<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title><![CDATA[Magento开发教程及电子商务最新动态]]></title>
    <link>https://www.360magento.com/blog/</link>
    <description><![CDATA[Magento开发教程及电子商务最新动态]]></description>
    <pubDate>Mon, 12 Oct 2026 06:36:45 +0000</pubDate>
    <generator>Zend_Feed</generator>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <item>
      <title><![CDATA[Magento 2 Sitemap定时任务重叠生成不完整XML]]></title>
      <link>https://www.360magento.com/blog/sitemap-cron-overlap-incomplete-xml/</link>
      <description><![CDATA[<p>搜索引擎偶尔抓到截断的Sitemap，服务器上同时存在临时文件。常见原因是多个Cron实例同时写同一目标文件。</p>
<h2>排查路径</h2>
<ul>
<li>对照cron_schedule、文件mtime与Web访问日志，确认同一Sitemap是否在上一任务未完成时再次启动。</li>
<li>为单个sitemap_id加互斥锁，生成到同目录临时文件，完成XML校验后再原子rename替换正式文件。</li>
</ul>
<h2>落地修复</h2>
<ol>
<li>检查磁盘空间、文件权限和Base URL，失败时保留上一份完整文件而不是先清空正式文件。</li>
<li>多节点部署时只允许一个调度节点生成，产物放共享存储或同步后再对外发布。</li>
</ol>
<pre><code>SELECT job_code,status,scheduled_at,executed_at,finished_at FROM cron_schedule WHERE job_code LIKE '%sitemap%' ORDER BY schedule_id DESC LIMIT 30;ls -lh --time-style=long-iso pub/sitemap*.xmlxmllint --noout pub/sitemap.xml</code></pre>
<h2>完成标准</h2>
<p>并发触发时只有一个任务写入，抓取过程中始终得到完整有效XML，索引文件中的子文件均可访问。</p>]]></description>
      <pubDate>Wed, 16 Sep 2026 03:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2切换币种后Varnish仍返回上一种价格]]></title>
      <link>https://www.360magento.com/blog/varnish-serves-wrong-currency-price/</link>
      <description><![CDATA[<p>客户从USD切到EUR，页面头部已是EUR，商品价格仍为USD。先比较X-Magento-Vary、Age和Cache命中。</p><h2>排查路径</h2><ul><li>用两个独立cookie jar请求同一URL并分别设置币种，确认错误只发生在HIT而源站MISS正确。</li><li>以后台导出的当前版本VCL为基线，自定义vcl_hash不能删除Magento vary上下文。</li></ul><h2>落地修复</h2><ol><li>检查前置CDN是否再次缓存HTML却忽略Cookie/Vary，Store与币种切换必须正确分区。</li><li>部署修正VCL后清受影响Host缓存并预热，不能把整站永久pass作为最终方案。</li></ol><pre><code>curl -sSI -c usd.jar -b usd.jar https://shop.example/product.html
curl -sSI -c eur.jar -b eur.jar https://shop.example/product.html
# 比较X-Magento-Cache-Debug、Age、X-Magento-Vary</code></pre><h2>完成标准</h2><p>两个cookie jar交替请求十次，价格与币种始终匹配；相同上下文仍能HIT，切币种不读取旧对象。</p>]]></description>
      <pubDate>Tue, 15 Sep 2026 03:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2维护模式设置允许IP后仍看到503]]></title>
      <link>https://www.360magento.com/blog/maintenance-allow-ip-behind-proxy-503/</link>
      <description><![CDATA[<p>执行maintenance:allow-ips加入办公公网IP后，自己访问仍是503。先确认请求到Magento时REMOTE_ADDR究竟是什么。</p><h2>解决方案</h2><ol><li>运行maintenance:status确认模式和允许列表已写入正确release。多节点若各自有独立var目录，设置可能只落在执行命令的节点。</li><li>在受控临时日志或Web服务器access log记录REMOTE_ADDR与代理传来的X-Forwarded-For。Magento维护判断通常不会无条件信任任意客户端伪造的XFF。</li><li>在负载均衡/Nginx层配置可信代理和real_ip_header，让应用获得真实客户端IP；set_real_ip_from只允许实际代理网段，不能信任0.0.0.0/0。</li><li>重新设置允许IP并滚动访问所有节点。若CDN在源站前，必要时在CDN边缘建立受认证的维护绕过，不要公开放行整个CDN出口网段。</li></ol><details open><summary>排查命令</summary><pre><code>bin/magento maintenance:status
bin/magento maintenance:allow-ips 203.0.113.25
cat var/.maintenance.ip 2&gt;/dev/null
# Nginx示例需替换为真实代理网段：
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;</code></pre></details><h2>回归测试</h2><p>允许IP访问首页和后台返回正常页面，未允许的外部网络仍503；伪造X-Forwarded-For不能绕过，切换每个Web节点结果一致。</p><p>测试结束后删除临时IP日志；不要记录完整Cookie、Authorization或后台URL密钥。</p>]]></description>
      <pubDate>Mon, 14 Sep 2026 03:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2上传商品图片时报413 Request Entity Too Large]]></title>
      <link>https://www.360magento.com/blog/product-image-upload-413-request-too-large/</link>
      <description><![CDATA[<p>后台选择图片后立即返回413，Magento日志没有记录，说明请求通常在Nginx或CDN层就被拒绝。</p>
<h2>解决记录</h2>
<p><strong>步骤1：</strong>用浏览器Network确认响应服务器与请求大小，先区分CDN、负载均衡、Nginx和PHP哪一层限制。</p>
<p><strong>步骤2：</strong>在对应admin location/server设置合理client_max_body_size，不能只改另一个虚拟主机。</p>
<p><strong>步骤3：</strong>同步检查PHP upload_max_filesize、post_max_size、max_file_uploads和临时目录空间，post_max_size应覆盖完整multipart请求。</p>
<p><strong>步骤4：</strong>重载配置并上传边界大小文件；仍失败时检查WAF策略和代理请求体限制。</p>
<p>命令与数据检查</p>
<pre><code>nginx -T | grep -n client_max_body_sizephp -i | grep -E 'upload_max_filesize|post_max_size|max_file_uploads|upload_tmp_dir'nginx -s reload</code></pre>
<h3>上线前验收</h3>
<p>允许范围内的JPG/PNG可上传并生成缩略图，超限文件显示友好错误，前台不会接受危险格式。</p>]]></description>
      <pubDate>Wed, 09 Sep 2026 02:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[测试站和生产共用Redis后Magento 2缓存互相污染]]></title>
      <link>https://www.360magento.com/blog/redis-cache-prefix-collision-environments/</link>
      <description><![CDATA[<p>测试站清缓存后生产突然MISS，或生产偶尔出现测试域名配置。先比较两个环境Redis database与id_prefix。</p><h2>解决记录</h2><p><strong>步骤1：</strong>分别检查default、page_cache和session配置；逻辑DB是否被托管Redis真正支持也要确认。</p><p><strong>步骤2：</strong>为每个环境配置唯一id_prefix，更稳妥是独立实例或独立DB；Session必须完全隔离。</p><p><strong>步骤3：</strong>切换后清本环境Magento缓存并预热，绝不能对共享Redis执行FLUSHALL。</p><p><strong>步骤4：</strong>用SCAN统计不同前缀键，验证测试cache:flush不会改变生产键数量，并检查锁和队列连接是否也共享。</p><details open><summary>命令与数据检查</summary><pre><code>grep -n 'id_prefix|database|session|page_cache' app/etc/env.php
redis-cli INFO keyspace
redis-cli --scan --pattern 'prod_*' | head
redis-cli --scan --pattern 'stage_*' | head</code></pre></details><h3>上线前验收</h3><p>两个环境交替清缓存、登录和部署互不影响，生产不出现测试配置，Session键完全隔离。</p>]]></description>
      <pubDate>Tue, 08 Sep 2026 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2多Store生成的Sitemap域名和路径错误]]></title>
      <link>https://www.360magento.com/blog/multistore-sitemap-wrong-domain-path/</link>
      <description><![CDATA[<p>英文站Sitemap里出现中文域名，或文件生成到pub却前台404。Sitemap记录本身带store_id，不能用一条记录服务所有Store。</p><h2>处理步骤</h2><p><strong>步骤1：</strong>查询sitemap表，确认每个Store有独立记录、sitemap_filename和sitemap_path。后台创建时必须选择正确Store View。</p><p><strong>步骤2：</strong>在对应Store Scope读取web/secure/base_url与web/unsecure/base_url。Cron/CLI运行时若自定义代码未模拟Store，可能总用默认域名。</p><p><strong>步骤3：</strong>sitemap_path是Magento安装目录下的可写相对目录，Web服务器URL必须能映射到该文件。生成成功但404时检查DocumentRoot、Nginx location和发布容器持久卷。</p><p><strong>步骤4：</strong>删除错误文件前先保留副本，按Store重新生成。robots.txt或搜索引擎提交的URL也要分别指向正确域名的Sitemap。</p><h2>命令与数据检查</h2><pre><code>SELECT sitemap_id,sitemap_filename,sitemap_path,store_id,sitemap_time FROM sitemap ORDER BY store_id;
bin/magento config:show web/secure/base_url --scope=stores --scope-code=zh_cn
find pub -maxdepth 3 -name '*sitemap*.xml' -ls
curl -I https://cn.example/sitemap.xml</code></pre><h3>上线前验证</h3><p>随机抽查商品、分类、CMS URL，全部属于该Store域名并返回200；XML位置可公开访问，另一个Store的URL不会混入。</p><blockquote><p>生成时间正确但内容旧时，还要检查Cron节点写入的文件系统是否与Web节点共享。</p></blockquote>]]></description>
      <pubDate>Mon, 07 Sep 2026 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2只有结账接口偶发502 Bad Gateway]]></title>
      <link>https://www.360magento.com/blog/checkout-api-intermittent-502-php-fpm-capacity/</link>
      <description><![CDATA[<h2>先确认问题层级</h2>
<p>普通页面正常，保存地址或提交支付时偶发502。应把Nginx错误、PHP-FPM容量和慢请求时间线对齐。</p>
<p>在同一request_id下关联Nginx access/error、PHP-FPM slowlog和Magento日志，判断upstream超时还是进程崩溃。</p>
<p>检查pm.max_children是否耗尽、listen queue与内存，不能只延长fastcgi_read_timeout掩盖容量问题。</p>
<h2>修复方法</h2>
<ul>
<li>用slowlog定位外部税费、运费或支付调用，为它们设置连接/读取超时和可控失败策略。</li>
<li>按单进程峰值内存计算max_children，调整后压测结账而不是只压首页，并监控队列长度。</li>
</ul>
<pre><code>grep -E 'upstream timed out|connect() failed|reset by peer' /var/log/nginx/error.logps -ylC php-fpm --sort:rssss -lntp | grep php-fpm# 开启request_slowlog_timeout与slowlog后复现</code></pre>
<h2>怎样才算解决</h2>
<p>持续结账压测无502，FPM队列与RSS在容量内，外部服务超时时用户收到可恢复错误而非网关错误。</p>]]></description>
      <pubDate>Wed, 02 Sep 2026 01:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 setup:upgrade后自定义数据库列被删除]]></title>
      <link>https://www.360magento.com/blog/declarative-schema-removes-custom-column/</link>
      <description><![CDATA[<h2>先确认问题层级</h2><p>手工添加的列在setup:upgrade后消失。Declarative Schema以启用模块声明为目标状态，数据库不是唯一事实来源。</p><p>从备份确认列定义和数据，明确哪个业务模块拥有字段，不立即重复ALTER生产。</p><p>在自定义模块db_schema.xml声明列、索引和约束；修改他人表也由自己的模块声明新增部分。</p><h2>修复方法</h2><ul><li>按版本流程生成db_schema_whitelist.json，并在预发布运行setup:db:status查看计划。</li><li>先部署声明创建列，再按主键从备份回填；必要迁移用幂等Data Patch。</li></ul><pre><code>bin/magento setup:db:status
bin/magento setup:db-declaration:generate-whitelist --module-name=Vendor_Module
SHOW CREATE TABLE target_table;
bin/magento setup:upgrade</code></pre><h2>怎样才算解决</h2><p>连续两次升级列都保留，全新安装结构一致，回填数量与备份相符，应用正常读写。</p>]]></description>
      <pubDate>Tue, 01 Sep 2026 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台导出CSV时内存溢出如何解决？]]></title>
      <link>https://www.360magento.com/blog/admin-grid-csv-export-memory-exhausted/</link>
      <description><![CDATA[<h2>先确认问题落在哪一层</h2><p>列表浏览正常，点击Export CSV就Allowed memory size exhausted。导出会遍历全部筛选结果，自定义列在每行load实体会迅速放大内存。</p><p>记录导出筛选条件、总行数和OOM堆栈。先用100、1000、10000行逐级测试，观察内存是否线性增长或突然跳升。</p><p>检查Grid Collection是否select了大字段、join造成重复行，Renderer/DataProvider是否在每行调用Repository getById。把所需字段一次join或批量预取。</p><pre><code>php -d memory_limit=512M bin/magento vendor:export --page-size=1000 --from-id=1
rg -n 'getCsvFile|getCsv|_prepareCollection|addFieldToFilter|getById' app/code
SELECT COUNT(*) FROM target_table WHERE created_at BETWEEN :from AND :to;</code></pre><h2>实际修复</h2><ul><li>大数据导出改为固定页大小读取并流式写临时文件/响应，每页clear集合与实体缓存。排序必须稳定（例如entity_id），避免翻页重复漏行。</li><li>若导出需要分钟级时间，改成队列任务并提供下载链接；限制用户可导出的最大范围和临时文件保留时间。</li></ul><h2>怎样才算修好</h2><p>用边界数据量导出，CSV行数与COUNT一致，首尾ID无缺失重复，内存峰值在分页增加后保持稳定；中文和公式开头字段正确转义。</p><aside><p>提高memory_limit只能作为诊断对照，不能替代流式设计。</p></aside>]]></description>
      <pubDate>Mon, 31 Aug 2026 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Composer更新后Magento 2补丁突然没有生效]]></title>
      <link>https://www.360magento.com/blog/composer-update-patch-no-longer-applied/</link>
      <description><![CDATA[<p><strong>现象：</strong>之前有效的Composer补丁在更新依赖后消失，生产问题重新出现。必须确认补丁工具是否执行、目标版本是否改变及hunk是否成功。</p>
<table>
<thead>
<tr><th>阶段</th><th>具体操作</th></tr>
</thead>
<tbody>
<tr>
<td>取证</td>
<td>检查composer install/update日志与lock文件，确认补丁插件仍安装并被allow-plugins允许。</td>
</tr>
<tr>
<td>定位</td>
<td>用composer show确认目标包版本；对照vendor源码测试patch --dry-run，旧补丁可能因上游代码变化而跳过。</td>
</tr>
<tr>
<td>修复</td>
<td>更新补丁基线与校验说明，把补丁文件纳入版本控制；失败必须让CI退出，不能只打印warning。</td>
</tr>
<tr>
<td>复核</td>
<td>删除目标vendor包后从干净lock重装，验证实际源码和自动化回归，避免本地残留造成假成功。</td>
</tr>
</tbody>
</table>
<h3>可执行检查</h3>
<pre><code>composer show vendor/packagecomposer why cweagans/composer-patchespatch --dry-run -p1 -d vendor/vendor/package &lt; patches/fix.patchrm -rf vendor/vendor/package &amp;&amp; composer install --no-interaction</code></pre>
<p><strong>通过标准：</strong>干净CI和生产构建都明确显示补丁成功，目标回归用例通过；上游已修复时安全移除补丁。</p>]]></description>
      <pubDate>Wed, 26 Aug 2026 03:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 patch_list已有记录但数据库字段不存在]]></title>
      <link>https://www.360magento.com/blog/patch-list-record-exists-column-missing/</link>
      <description><![CDATA[<p><strong>现象：</strong>setup:upgrade显示无更新，但模块所需列不存在，patch_list却有Patch类名。删除记录强制重跑可能产生副作用。</p><table><thead><tr><th>阶段</th><th>具体操作</th></tr></thead><tbody><tr><td>取证</td><td>确认变更来自db_schema.xml、Schema Patch还是Data Patch，Declarative Schema会先执行。</td></tr><tr><td>定位</td><td>核对代码版本、模块版本和数据库备份时间，数据库回滚但patch_list未同步很常见。</td></tr><tr><td>修复</td><td>阅读Patch是否幂等，在数据库副本删除对应记录并运行setup:upgrade观察实际SQL。</td></tr><tr><td>复核</td><td>不可安全重跑时写新的修复Patch，检测列或数据缺失后补齐，不篡改旧Patch历史。</td></tr></tbody></table><h3>可执行检查</h3><pre><code>SELECT patch_name FROM patch_list WHERE patch_name LIKE '%Vendor\Module%';
SHOW COLUMNS FROM vendor_table LIKE 'custom_column';
bin/magento setup:db:status
bin/magento setup:upgrade</code></pre><p><strong>通过标准：</strong>全新安装、正常升级和问题库修复得到同一Schema，再次setup:upgrade无重复副作用。</p>]]></description>
      <pubDate>Tue, 25 Aug 2026 03:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Consumer为什么会把同一消息处理两次？]]></title>
      <link>https://www.360magento.com/blog/consumer-processes-message-twice-idempotency/</link>
      <description><![CDATA[<p><strong>问题现象：</strong>同一消息导致两次发货、两封邮件或两次ERP调用，不一定是RabbitMQ故障。消费者完成业务后若在ack前断开，Broker会重新投递。</p><table><thead><tr><th>阶段</th><th>实际操作</th></tr></thead><tbody><tr><td>复现</td><td>在Publisher生成稳定message_id或业务event_id，Consumer日志只记录该ID、redelivered标志和处理结果，不记录完整敏感payload。</td></tr><tr><td>取证</td><td>在业务数据库建立event_id唯一记录，并在同一事务中检查/占用。已完成事件再次到达时直接返回成功；处理中超时需要有可恢复状态。</td></tr><tr><td>修复</td><td>外部API也应传幂等键。仅在本地去重但第一次外部调用成功、数据库写入失败，重试仍会重复调用外部系统。</td></tr><tr><td>回归</td><td>确认Consumer异常时正确抛出，让消息重试或进入失败处理；不要catch后既未完成业务又返回成功。设置最大重试与死信队列。</td></tr></tbody></table><h3>可直接执行的检查</h3><pre><code>bin/magento queue:consumers:list
bin/magento queue:consumers:start vendor.consumer --max-messages=100
# 业务表建议：UNIQUE(event_id, handler_name)，并记录 processing/completed/failed 状态</code></pre><p><strong>通过标准：</strong>在业务提交后、ack前主动终止Consumer，再启动处理；消息可以重投，但订单/发货/外部调用只产生一次最终副作用。</p><p>不要用消息正文哈希替代业务ID，字段顺序变化和合法重复事件会让哈希去重失真。</p>]]></description>
      <pubDate>Mon, 24 Aug 2026 03:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Declarative Schema添加外键时报Constraint violation]]></title>
      <link>https://www.360magento.com/blog/declarative-schema-foreign-key-orphan-rows/</link>
      <description><![CDATA[<blockquote>
<p>在db_schema.xml新增外键后setup:upgrade失败，通常是旧表已有孤儿数据或两列类型并不完全一致。</p>
</blockquote>
<h2>固定复现范围</h2>
<p>用LEFT JOIN找出子表中不存在父记录的值，并统计数量；不要先关闭foreign_key_checks强行建约束。</p>
<h2>定位真实原因</h2>
<p>比较两列数据类型、unsigned、长度与字符集，引用列必须有索引且定义兼容。</p>
<h2>执行修复</h2>
<p>制定孤儿数据处理规则：补父记录、归档或删除，并先在数据库副本验证影响。</p>
<h2>恢复后处理</h2>
<p>修正数据和Schema后运行setup:upgrade，再检查SHOW CREATE TABLE和级联删除策略是否符合业务。</p>
<pre><code>SELECT c.parent_id,COUNT(*) FROM child_table c LEFT JOIN parent_table p ON p.entity_id=c.parent_id WHERE p.entity_id IS NULL GROUP BY c.parent_id;SHOW CREATE TABLE child_table;SHOW CREATE TABLE parent_table;bin/magento setup:upgrade</code></pre>
<h2>回归测试</h2>
<p>升级成功且重复执行无变化，新增非法parent_id被数据库拒绝，删除父记录按预期RESTRICT或CASCADE。</p>]]></description>
      <pubDate>Wed, 19 Aug 2026 02:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Composer升级Magento 2时报Plugin is blocked by allow-plugins]]></title>
      <link>https://www.360magento.com/blog/composer-plugin-blocked-allow-plugins/</link>
      <description><![CDATA[<blockquote><p>composer install/update被allow-plugins阻止。这是Composer安全机制，删除vendor不能解决。</p></blockquote><h2>固定复现范围</h2><p>从错误取得完整package名，用composer show与why确认来源及是否必要。</p><h2>定位真实原因</h2><p>只允许经过审核的具体插件：composer config allow-plugins.vendor/package true，不允许通配所有插件。</p><h2>执行修复</h2><p>配置写入项目composer.json并提交，保证CI与生产一致，不只改个人全局配置。</p><h2>恢复后处理</h2><p>重新validate和install，检查composer.lock没有意外大范围升级；未知插件保持阻止。</p><pre><code>composer show vendor/package --all
composer why vendor/package
composer config allow-plugins.vendor/package true
composer validate
composer install --no-dev --prefer-dist --no-interaction</code></pre><h2>回归测试</h2><p>干净环境可非交互构建，只加载批准插件；删除本地vendor重建结果一致。</p>]]></description>
      <pubDate>Tue, 18 Aug 2026 02:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cron提示Could not acquire lock for cron job]]></title>
      <link>https://www.360magento.com/blog/cron-could-not-acquire-lock-job/</link>
      <description><![CDATA[<blockquote><p>日志反复出现Could not acquire lock for cron job，任务长期不执行。锁本身是在防止同一Job并发，先确认持锁进程是否真的还活着。</p></blockquote><h2>定位与修复记录</h2><h3>1. 固定复现范围</h3><p>从日志取得job_code和时间，查询cron_schedule最近记录。状态running且executed_at很早，才可能是遗留任务；短任务偶发抢锁通常只是另一个实例正在执行。</p><h3>2. 确认真实原因</h3><p>在所有Cron节点检查bin/magento cron:run进程、系统crontab与Supervisor。多台机器都跑default组而又使用不同锁后端，会互相看不见。</p><h3>3. 执行修复</h3><p>确认env.php锁提供者和缓存/数据库连接一致。先停止重复调度源，再处理确认已死亡的running记录；不要在活进程存在时改状态。</p><h3>4. 恢复后处理</h3><p>对耗时任务加业务级分页和超时监控，让单次在计划间隔内完成。必须并行时拆成不同job code或队列消息，而不是关闭锁。</p><pre><code>SELECT schedule_id,job_code,status,scheduled_at,executed_at,finished_at,messages FROM cron_schedule WHERE job_code='vendor_job' ORDER BY schedule_id DESC LIMIT 20;
ps -eo pid,lstart,etime,cmd | grep '[b]in/magento cron:run'
crontab -l
bin/magento cron:run --group default</code></pre><h2>验收清单</h2><ul><li>连续观察至少三个调度周期，每次只有一个running并能转success；无重复业务记录，下一周期可正常获取锁。</li><li>若任务涉及订单或库存，清遗留状态前先确认没有仍在执行的数据库事务。</li></ul>]]></description>
      <pubDate>Mon, 17 Aug 2026 02:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 RequireJS映射冲突导致同一组件加载两次]]></title>
      <link>https://www.360magento.com/blog/requirejs-map-conflict-component-loaded-twice/</link>
      <description><![CDATA[<p>前端组件事件执行两次，Network中出现两个不同路径的同名模块。通常是多个requirejs-config.js同时map或mixin同一目标。</p>
<h2>实际处理步骤</h2>
<ol>
<li>查看生成后的requirejs-config与Network Initiator，列出目标模块所有map、paths和mixins来源。</li>
<li>统一由一个模块负责替换；主题和模块不能分别把原模块映射到不同实现，路径名也要保持大小写一致。</li>
<li>Mixin返回目标组件且只注册一次，避免在initialize每次bind全局事件却不dispose。</li>
<li>删除目标静态目录并重新deploy，清浏览器与CDN缓存后用无痕窗口复测。</li>
</ol>
<h3>检查命令</h3>
<pre><code>rg -n "map:|mixins:|Vendor_Module/js/component" app/code app/designfind pub/static -name requirejs-config.js -printbin/magento setup:static-content:deploy -f</code></pre>
<h2>验证结果</h2>
<p>目标模块只请求一次、事件只触发一次，两个主题和生产模式下行为一致。</p>]]></description>
      <pubDate>Wed, 12 Aug 2026 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2只缺少一个Locale的JS和翻译文件]]></title>
      <link>https://www.360magento.com/blog/static-content-one-locale-files-missing/</link>
      <description><![CDATA[<p>en_US正常，zh_CN页面404 js-translation.json或组件JS。浏览器清缓存无效，因为服务器没有对应Locale产物。</p><h2>实际处理步骤</h2><ol><li>确认Store的general/locale/code与请求路径，zh_CN等代码不能混用。</li><li>检查部署命令是否只生成部分语言，或--area、--theme、--no-parent排除了主题依赖。</li><li>在维护窗口按目标主题和Locales完整重新deploy，不单独复制缺失JS。</li><li>多节点比较deployed_version.txt与Locale目录校验和，清CDN旧404并检查静态签名重写。</li></ol><h3>检查命令</h3><pre><code>bin/magento config:show general/locale/code --scope=stores --scope-code=zh_cn
find pub/static/frontend -maxdepth 4 -type d -name "zh_*"
bin/magento setup:static-content:deploy -f zh_CN en_US</code></pre><h2>验证结果</h2><p>目标Locale的JS、Knockout模板、翻译字典和CSS均200，切换节点不再404。</p>]]></description>
      <pubDate>Tue, 11 Aug 2026 01:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[部署后Magento 2提示Factory类不存在]]></title>
      <link>https://www.360magento.com/blog/missing-generated-factory-after-deployment/</link>
      <description><![CDATA[<p>发布后某些请求报Class Vendor\Module\Model\ThingFactory does not exist，刷新或切节点又恢复。生产模式不应依赖运行时临时生成类。</p><h2>按顺序解决</h2><ol><li>从报错节点检查源码中的Thing类是否存在、命名空间和大小写正确，再检查generated/code对应Factory。只有部分节点缺失时直接比较release版本。</li><li>确认部署顺序：安装依赖与代码完成后运行setup:di:compile，随后再打包并原子切换release。若compile后才复制app/code，新类不会被生成。</li><li>generated/code必须和本次源码、composer.lock一起发布；不要多个节点共享一个正在写入的generated目录。Web进程需要读取权限，但不应靠开放777解决。</li><li>清PHP OPcache或滚动重启FPM，使旧进程不再引用上一release路径。多节点逐台健康检查后再接流量。</li></ol><h3>检查命令</h3><pre><code>test -f app/code/Vendor/Module/Model/Thing.php
test -f generated/code/Vendor/Module/Model/ThingFactory.php
bin/magento setup:di:compile
find generated/code/Vendor/Module/Model -maxdepth 1 -type f -ls
sha256sum composer.lock app/etc/config.php</code></pre><h2>验证结果</h2><p>连续请求覆盖所有Web节点，目标类始终存在；重新发布一次也不复发，且部署期间没有节点读取半成品目录。</p><p><strong>注意：</strong>在Cloud或只读文件系统中更不能依赖运行时生成，构建产物缺失必须回滚release。</p>]]></description>
      <pubDate>Mon, 10 Aug 2026 01:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CSP阻止支付页面加载第三方脚本]]></title>
      <link>https://www.360magento.com/blog/csp-blocks-payment-third-party-script/</link>
      <description><![CDATA[<p>结账页控制台出现Refused to load script，支付组件空白。不能用全局unsafe-inline或关闭CSP解决，应精确授权资源来源。</p>
<h2>排查路径</h2>
<ul>
<li>从浏览器控制台记录被阻止的script、frame、connect或img来源，区分支付生产域与测试域。</li>
<li>在支付模块csp_whitelist.xml为对应policy添加精确host；内联脚本优先改为外部文件或使用Magento nonce/hash机制。</li>
</ul>
<h2>落地修复</h2>
<ol>
<li>支付iframe、API和风控像素可能属于不同policy，逐项添加且只允许HTTPS官方域名。</li>
<li>部署后清config/FPC并检查响应Content-Security-Policy，确认没有重复代理Header覆盖Magento配置。</li>
</ol>
<pre><code>rg -n 'csp_whitelist|content-security-policy' app/code app/designcurl -sSI https://shop.example/checkout/ | grep -i content-security-policybin/magento cache:clean config full_page</code></pre>
<h2>完成标准</h2>
<p>支付组件完整加载并可下单，控制台无相关CSP错误，未授权测试域和任意内联脚本仍被阻止。</p>]]></description>
      <pubDate>Wed, 05 Aug 2026 03:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 UI Component字段能显示但保存后为空]]></title>
      <link>https://www.360magento.com/blog/ui-component-field-displays-but-not-saved-datascope/</link>
      <description><![CDATA[<p>自定义字段能显示旧值，修改保存后数据库为空。显示只证明DataProvider读取成功，保存还依赖dataScope与POST路径。</p><h2>排查路径</h2><ul><li>查看保存请求payload，确认字段位于data[general][field]、field或其他实际路径。</li><li>检查form namespace、dataSource、fieldset和field dataScope，Provider getData结构与JS期待层级一致。</li></ul><h2>落地修复</h2><ol><li>Controller/Repository从同一路径取值，并写入模型允许字段或Extension Attribute，数据库列必须存在。</li><li>布尔字段配置valueMap，空值区分“清除”和“未提交”，避免0被过滤。</li></ol><pre><code>rg -n 'dataScope|namespace|provider' view/adminhtml/ui_component app/code
SHOW COLUMNS FROM vendor_entity LIKE 'custom_field';</code></pre><h2>完成标准</h2><p>新建、编辑、清空和值为0四种情况保存后重新打开均正确，Repository/API读取一致。</p>]]></description>
      <pubDate>Tue, 04 Aug 2026 03:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 setup:di:compile报Incompatible argument type]]></title>
      <link>https://www.360magento.com/blog/di-compile-incompatible-argument-type/</link>
      <description><![CDATA[<p>升级后di:compile提示Incompatible argument type，错误会给出类、参数位置、期望与实际类型。不要通过删除类型声明让编译通过。</p><h2>解决方案</h2><ol><li>完整保存第一条编译错误。找到生成目标类的constructor，并用Reflection或源码确认父类当前版本的参数顺序与类型。</li><li>自定义类继承核心类时，升级后父构造函数新增/调整参数最常见。同步子类签名和parent::__construct调用，优先避免复制整个父构造函数。</li><li>若错误来自di.xml，检查argument name是否仍与构造函数参数名一致，xsi:type=object指向的类是否实现期望接口；virtualType链中同名参数也会覆盖。</li><li>清除旧generated/code与generated/metadata后重新compile。生产构建必须使用与运行环境相同的composer.lock和PHP主次版本。</li></ol><details open><summary>排查命令</summary><pre><code>bin/magento setup:di:compile
rg -n '&lt;argument name="problemArg"|&lt;preference.*ExpectedInterface' app/code vendor
php -r "require 'app/bootstrap.php'; $r=new ReflectionClass('Vendor\Module\Model\Target'); foreach($r-&gt;getConstructor()-&gt;getParameters() as $p){echo $p,PHP_EOL;}"</code></pre></details><h2>回归测试</h2><p>di:compile无错误，相关页面/CLI实际实例化目标类成功；同时运行静态分析或最小集成测试，确保不是靠可空默认值掩盖缺失依赖。</p><p>generated目录应在构建阶段重新生成，不要把旧环境生成物复制进新版本。</p>]]></description>
      <pubDate>Mon, 03 Aug 2026 03:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2静态资源部署后仍引用旧版本文件]]></title>
      <link>https://www.360magento.com/blog/static-deploy-old-version-assets-served/</link>
      <description><![CDATA[<p>新JS已经部署，页面HTML却继续引用旧static version，或不同节点返回不同版本。问题多在部署顺序、共享存储和CDN缓存。</p>
<h2>解决记录</h2>
<p><strong>步骤1：</strong>比较所有Web节点pub/static/deployed_version.txt、HTML中的/version数字及文件校验和。</p>
<p><strong>步骤2：</strong>使用同一构建产物原子切换到各节点，代码、静态文件和版本号不能分批不一致暴露。</p>
<p><strong>步骤3：</strong>清Magento FPC后按Host和static路径清CDN，避免CDN缓存旧HTML或旧404。</p>
<p><strong>步骤4：</strong>检查Nginx static签名重写规则和symlink权限，不能用关闭静态签名长期规避。</p>
<p>命令与数据检查</p>
<pre><code>for h in web1 web2; do ssh $h 'cat pub/static/deployed_version.txt'; donecurl -sS https://shop.example/ | grep -o '/static/version[0-9]*/' | headsha256sum pub/static/frontend/Vendor/theme/*/*/js/app.js</code></pre>
<h3>上线前验收</h3>
<p>连续请求命中不同节点时HTML版本一致，新资源返回200，旧HTML不再引用已删除路径。</p>]]></description>
      <pubDate>Wed, 29 Jul 2026 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台Mass Action选择全部却只处理当前页]]></title>
      <link>https://www.360magento.com/blog/admin-mass-action-select-all-current-page-only/</link>
      <description><![CDATA[<p>Grid选择Select All显示几千条，执行后只有当前页改变。标准Mass Action不会把所有ID都放进selected参数。</p><h2>解决记录</h2><p><strong>步骤1：</strong>检查请求中的selected、excluded、filters和namespace；全选依赖筛选条件和excluded列表。</p><p><strong>步骤2：</strong>Controller使用MassAction Filter的getCollection应用UI筛选，不要只遍历request[selected]。</p><p><strong>步骤3：</strong>primaryFieldName、requestFieldName和indexField必须对应真实主键。</p><p><strong>步骤4：</strong>大批量改为分页或队列，并记录成功失败ID；执行前显示匹配总数避免误处理全表。</p><details open><summary>命令与数据检查</summary><pre><code>$collection = $this-&gt;filter-&gt;getCollection($this-&gt;collectionFactory-&gt;create());
foreach ($collection-&gt;getItems() as $item) { /* enqueue/process */ }</code></pre></details><h3>上线前验收</h3><p>当前页选择、跨页全选、排除3条及带筛选全选的处理数量都与界面一致。</p>]]></description>
      <pubDate>Tue, 28 Jul 2026 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2自定义Controller路由始终返回404如何排查？]]></title>
      <link>https://www.360magento.com/blog/custom-controller-route-always-404/</link>
      <description><![CDATA[<p>Controller类存在，访问/vendor/action/index仍404。Magento前端路由由etc/frontend/routes.xml注册，任一层名称不匹配都会落到noroute。</p><h2>处理步骤</h2><p><strong>步骤1：</strong>确认模块已启用且registration.php、module.xml名称一致。执行module:status和setup:upgrade后查看config缓存，不要只看代码目录。</p><p><strong>步骤2：</strong>routes.xml必须位于etc/frontend，router id通常为standard；route的id用于布局handle，frontName才是URL第一段。检查XML命名空间和模块name。</p><p><strong>步骤3：</strong>Action类路径应匹配Controller/Action/Index.php，并实现ActionInterface或继承正确Action。Linux文件名大小写不一致在本地macOS可能正常、生产会404。</p><p><strong>步骤4：</strong>在execute入口写临时脱敏日志。完全没有进入时检查前置路由冲突、URL Rewrite和Web服务器location；进入后返回404则查ResultFactory逻辑。</p><h2>命令与数据检查</h2><pre><code>bin/magento module:status Vendor_Module
php -l app/code/Vendor/Module/Controller/Action/Index.php
xmllint --noout app/code/Vendor/Module/etc/frontend/routes.xml
bin/magento cache:clean config full_page</code></pre><h3>上线前验证</h3><p>访问标准URL返回预期状态；不存在action仍404；开启/关闭Store Code和两个Store View时路由均稳定，日志只记录一次执行。</p><blockquote><p>不要把敏感参数直接写日志，自定义POST路由还需要正确处理CSRF。</p></blockquote>]]></description>
      <pubDate>Mon, 27 Jul 2026 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2清缓存后所有客户突然退出登录]]></title>
      <link>https://www.360magento.com/blog/cache-clean-logs-out-all-customers-redis-db/</link>
      <description><![CDATA[<h2>先确认问题层级</h2>
<p>执行cache:clean或部署后全站客户Session丢失。正常缓存清理不应删除Session，通常是Redis数据库或前缀配置重叠。</p>
<p>比较env.php中default cache、page_cache和session的host、port、database及前缀，Session必须独立。</p>
<p>检查部署脚本是否执行redis-cli FLUSHALL/FLUSHDB，或把cache:flush误当成安全的cache:clean。</p>
<h2>修复方法</h2>
<ul>
<li>迁移Session存储时设置独立数据库/实例并安排窗口；不要在高峰直接切换造成全部现有Session失效。</li>
<li>执行一次受控cache:clean，比较Session键数量和测试账号Cookie，确认没有被清除。</li>
</ul>
<pre><code>grep -n 'session|page_cache|default|database|id_prefix' app/etc/env.phpredis-cli -n 2 DBSIZEbin/magento cache:clean config layout block_html</code></pre>
<h2>怎样才算解决</h2>
<p>清理任意Magento缓存类型后已登录账号仍在线，Session过期只由自身生命周期控制。</p>]]></description>
      <pubDate>Wed, 22 Jul 2026 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台Grid筛选时报Column id is ambiguous]]></title>
      <link>https://www.360magento.com/blog/admin-grid-filter-column-ambiguous/</link>
      <description><![CDATA[<h2>先确认问题层级</h2><p>Grid能打开，一筛选ID或状态就报Column is ambiguous。join的多个表都有同名列，而Filter仍使用裸字段。</p><p>从异常SQL确认冲突列和表别名，明确UI字段属于主表还是join表。</p><p>在Collection用addFilterToMap映射到main_table.entity_id或目标别名，Select列使用唯一alias。</p><h2>修复方法</h2><ul><li>UI column name、filter与DataProvider字段保持一致，自定义addFilter保留condition type。</li><li>同时测试排序、范围筛选和导出；只修WHERE不修ORDER BY仍会报错。</li></ul><pre><code>$collection-&gt;addFilterToMap('entity_id', 'main_table.entity_id');
$collection-&gt;addFilterToMap('status', 'main_table.status');</code></pre><h2>怎样才算解决</h2><p>ID、状态、日期筛选与排序、CSV导出均正常，join不会造成重复行。</p>]]></description>
      <pubDate>Tue, 21 Jul 2026 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CMS页面只在一个Store View返回404]]></title>
      <link>https://www.360magento.com/blog/cms-page-404-one-store-view/</link>
      <description><![CDATA[<h2>先确认问题落在哪一层</h2><p>同一个CMS identifier在主站正常，切到另一个Store就404。缓存不是第一嫌疑，先验证页面是否真正分配给该Store。</p><p>查询cms_page_store，确认page_id关联目标store_id或store_id=0（All Store Views）。页面还必须is_active=1。</p><p>检查目标Store是否存在另一个相同identifier页面。多个可匹配页面会导致加载歧义，按语言拆分时每个页面只分配明确Store。</p><pre><code>SELECT page_id,identifier,title,is_active FROM cms_page WHERE identifier='shipping-policy';
SELECT cps.page_id,cps.store_id,s.code FROM cms_page_store cps JOIN store s ON s.store_id=cps.store_id WHERE cps.page_id IN (:page_ids);
bin/magento config:show web/url/use_store</code></pre><h2>实际修复</h2><ul><li>带Store Code的URL要确认web/url/use_store以及Base URL路径。反向代理若剥离或重复添加Store Code，会在CMS路由前得到错误path。</li><li>修正分配后清full_page和block_html；用Host与Store Cookie都固定的请求验证，避免浏览器残留Cookie把请求送到另一个Store。</li></ul><h2>怎样才算修好</h2><p>在每个目标Store用无痕请求页面，状态200、标题与语言正确；未分配的Store应保持404而不是错误回退。</p><aside><p>如果页面设置了自定义布局更新，也要确认该布局文件未在特定主题触发异常。</p></aside>]]></description>
      <pubDate>Mon, 20 Jul 2026 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2配置明明已保存却只在默认Store生效]]></title>
      <link>https://www.360magento.com/blog/config-saved-wrong-scope-default-store/</link>
      <description><![CDATA[<p><strong>现象：</strong>后台在某Store View保存配置后，前台仍读取默认值。需要核对保存Scope、路径和代码读取Scope是否一致。</p>
<table>
<thead>
<tr><th>阶段</th><th>具体操作</th></tr>
</thead>
<tbody>
<tr>
<td>取证</td>
<td>在后台切换到目标Website/Store View并确认没有勾选Use Default，再记录实际config path。</td>
</tr>
<tr>
<td>定位</td>
<td>查询core_config_data同一路径的default、websites与stores记录，确认scope_id映射正确且没有旧值覆盖。</td>
</tr>
<tr>
<td>修复</td>
<td>代码读取时传入正确ScopeInterface与storeId；Cron/CLI没有HTTP Store上下文，不能依赖当前Store。</td>
</tr>
<tr>
<td>复核</td>
<td>清config缓存后从目标Store输出解析值；敏感配置若加密，使用Config接口读取而不是直接查明文。</td>
</tr>
</tbody>
</table>
<h3>可执行检查</h3>
<pre><code>SELECT scope,scope_id,path,value FROM core_config_data WHERE path='vendor/module/setting' ORDER BY scope,scope_id;bin/magento config:show vendor/module/setting --scope=stores --scope-code=zh_cnbin/magento cache:clean config</code></pre>
<p><strong>通过标准：</strong>默认、Website和两个Store View分别返回预期值，后台保存与CLI、前台、Cron读取结果一致。</p>]]></description>
      <pubDate>Wed, 15 Jul 2026 03:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2重置密码链接刚收到就提示Token已过期]]></title>
      <link>https://www.360magento.com/blog/password-reset-token-immediately-expired/</link>
      <description><![CDATA[<p><strong>现象：</strong>新收到的密码重置链接立即过期。先比较Token创建时间、数据库UTC时间和应用服务器时间。</p><table><thead><tr><th>阶段</th><th>具体操作</th></tr></thead><tbody><tr><td>取证</td><td>查询rp_token_created_at，并核对数据库UTC、PHP时间和NTP，节点相差数小时会立即超过生命周期。</td></tr><tr><td>定位</td><td>检查重置链接有效期与Scope，避免单位误解或极小配置。</td></tr><tr><td>修复</td><td>连续请求会生成新Token并让旧邮件失效，页面要提示只使用最新邮件并做限速。</td></tr><tr><td>复核</td><td>异步邮件不能延迟到接近过期才发送；修复后重新生成Token，不复活旧Token。</td></tr></tbody></table><h3>可执行检查</h3><pre><code>SELECT email,rp_token_created_at FROM customer_entity WHERE email='test@example.com';
SELECT UTC_TIMESTAMP(),NOW();
date -u
bin/magento config:show customer/password/reset_link_expiration_period</code></pre><p><strong>通过标准：</strong>最新链接在有效期内可使用一次，旧链接和已使用Token失效，所有Web节点与数据库时间一致。</p>]]></description>
      <pubDate>Tue, 14 Jul 2026 03:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[修改分类URL Key后Magento 2出现循环跳转]]></title>
      <link>https://www.360magento.com/blog/category-url-key-change-redirect-loop/</link>
      <description><![CDATA[<p><strong>问题现象：</strong>浏览器提示too many redirects时，先用curl记录每一跳的Location。不要一上来清空url_rewrite，否则会丢失全部历史301。</p><table><thead><tr><th>阶段</th><th>实际操作</th></tr></thead><tbody><tr><td>复现</td><td>分别请求HTTP/HTTPS、带/不带尾斜杠和目标Store域名，使用curl -I -L --max-redirs 10记录跳转链，找出第一次回到已访问URL的位置。</td></tr><tr><td>取证</td><td>查询循环中两个request_path的url_rewrite。正常旧路径应custom redirect到新路径，新路径应指向catalog/category/view/id。若两条都是redirect或互指，就修复具体记录。</td></tr><tr><td>修复</td><td>检查“Create Permanent Redirect for URLs if URL Key Changed”及Store View覆盖。默认范围和子Store分别保存可能生成反向历史重写。</td></tr><tr><td>回归</td><td>Magento记录正确时再查Nginx、CDN和SEO扩展的尾斜杠/HTTP规则。每层只保留一个规范化责任，修改后清CDN 301缓存。</td></tr></tbody></table><h3>可直接执行的检查</h3><pre><code>curl -I -L --max-redirs 10 https://shop.example/old-category.html
SELECT url_rewrite_id,request_path,target_path,redirect_type,store_id,entity_id FROM url_rewrite WHERE request_path IN ('old-category.html','new-category.html') OR target_path IN ('old-category.html','new-category.html');</code></pre><p><strong>通过标准：</strong>旧URL只跳一次到新URL，新URL直接200；带参数、尾斜杠和两个Store域名都不会回跳。</p><p>301会被浏览器和CDN长时间缓存，验收应使用curl和新路径，不要只看原浏览器标签。</p>]]></description>
      <pubDate>Mon, 13 Jul 2026 03:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[更换Magento 2后台域名后无法通过2FA登录]]></title>
      <link>https://www.360magento.com/blog/admin-domain-change-2fa-login-loop/</link>
      <description><![CDATA[<blockquote>
<p>后台域名切换后账号密码和验证码都正确，却反复回到登录页。先区分2FA验证失败与Admin Session Cookie未保存。</p>
</blockquote>
<h2>固定复现范围</h2>
<p>浏览器检查登录响应的Set-Cookie、Domain、Path、Secure和SameSite，并清除旧域名同名Cookie。</p>
<h2>定位真实原因</h2>
<p>核对web/secure/base_url、cookie_domain、cookie_path及Offloader Header，反向代理必须把HTTPS状态传给Magento。</p>
<h2>执行修复</h2>
<p>服务器时间与手机时间保持NTP同步；若只是个别用户，按官方CLI流程重置该用户2FA提供器后重新绑定。</p>
<h2>恢复后处理</h2>
<p>清config缓存并在无痕窗口测试，不能通过关闭整个2FA模块作为长期解决方案。</p>
<pre><code>bin/magento config:show web/secure/base_urlbin/magento config:show web/cookie/cookie_domaintimedatectl statusbin/magento security:tfa:reset adminuser google</code></pre>
<h2>回归测试</h2>
<p>新域名连续登录、退出和Session过期均正常，旧域名Cookie不影响，其他管理员2FA保持有效。</p>]]></description>
      <pubDate>Wed, 08 Jul 2026 02:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2发票邮件显示了错误Store的Logo]]></title>
      <link>https://www.360magento.com/blog/invoice-email-wrong-store-logo/</link>
      <description><![CDATA[<blockquote><p>中文站Invoice邮件出现英文主站Logo。邮件Logo取决于订单Store环境和Transactional Email配置。</p></blockquote><h2>固定复现范围</h2><p>记录Invoice所属order.store_id、模板ID和异步发送配置，在目标Store Scope检查Logo和模板。</p><h2>定位真实原因</h2><p>自定义发送代码以订单Store构造Template Options，并用Environment Emulation包裹渲染，finally停止模拟。</p><h2>执行修复</h2><p>队列消息保存store_id，Consumer不能在默认Store渲染；图片URL使用订单Store的secure Base URL。</p><h2>恢复后处理</h2><p>清配置/模板缓存后发送两个Store测试邮件，不能在HTML硬编码主域名。</p><pre><code>SELECT i.increment_id,o.store_id FROM sales_invoice i JOIN sales_order o ON o.entity_id=i.order_id WHERE i.increment_id='INV-1';
bin/magento config:show design/email/logo --scope=stores --scope-code=zh_cn</code></pre><h2>回归测试</h2><p>两个Store的Logo、语言、发件人和链接域名均正确，交叉发送顺序不会串站。</p>]]></description>
      <pubDate>Tue, 07 Jul 2026 02:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[中文商品名称生成的Magento 2 URL Key为空怎么办？]]></title>
      <link>https://www.360magento.com/blog/chinese-product-name-empty-url-key/</link>
      <description><![CDATA[<blockquote><p>新建中文商品时URL Key为空，保存后出现重复或无法生成Rewrite。直接用随机字符串虽能保存，却会造成URL不稳定。</p></blockquote><h2>定位与修复记录</h2><h3>1. 固定复现范围</h3><p>确认url_key是否勾选Use Default，以及哪个Store范围为空。检查自定义Plugin是否在Product Url Key Generator之后再次过滤非ASCII字符。</p><h3>2. 确认真实原因</h3><p>确定稳定策略：使用人工维护的英文短名、拼音slug或SKU派生值。转换结果必须小写、仅允许安全字符、合并连续连字符并去掉首尾连字符。</p><h3>3. 执行修复</h3><p>当转换结果仍为空时回退到SKU；保存前按Store检查request_path唯一性，冲突时追加稳定短后缀，不能每次保存生成新随机值。</p><h3>4. 恢复后处理</h3><p>对已上线商品批量修复时保留旧URL的301重写。先导出entity_id、store_id、旧url_key和新slug，dry-run检测冲突后再分批执行。</p><pre><code>SELECT entity_id,sku FROM catalog_product_entity WHERE entity_id=:entity_id;
SELECT store_id,value FROM catalog_product_entity_varchar WHERE entity_id=:entity_id AND attribute_id=(SELECT attribute_id FROM eav_attribute WHERE attribute_code='url_key' AND entity_type_id=4);
SELECT request_path,target_path,store_id FROM url_rewrite WHERE request_path LIKE 'new-slug%';</code></pre><h2>验收清单</h2><ul><li>创建纯中文、中文加数字、重复名称三个商品；每个Store生成稳定且唯一URL，二次保存URL不变化，旧地址正确301。</li><li>SKU可能包含内部信息或不适合公开，采用SKU回退前先确认业务与SEO要求。</li></ul>]]></description>
      <pubDate>Mon, 06 Jul 2026 02:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单邮件偶尔重复发送两次]]></title>
      <link>https://www.360magento.com/blog/order-email-sent-twice-queue-race/</link>
      <description><![CDATA[<p>同一订单在几秒内收到两封完全相同的确认邮件。常见原因是同步发送与异步队列同时启用，或自定义重试没有幂等。</p>
<h2>实际处理步骤</h2>
<ol>
<li>按订单号对照邮件服务日志、cron_schedule和sales_order.email_sent，确认两次发送分别来自哪个入口。</li>
<li>使用Magento标准send_new_order_email流程；自定义Observer不能再直接调用TransportBuilder发送同一模板。</li>
<li>异步发送时只有成功后更新状态，重试前再次检查订单标记；队列消息以order_id和邮件类型做唯一幂等键。</li>
<li>并发Consumer必须原子领取任务，修复后清理重复调度但不删除待发送的其他订单。</li>
</ol>
<h3>检查命令</h3>
<pre><code>SELECT increment_id,email_sent,send_email,created_at FROM sales_order WHERE increment_id='000000123';SELECT job_code,status,messages,executed_at FROM cron_schedule WHERE job_code LIKE '%email%' ORDER BY schedule_id DESC LIMIT 50;rg -n 'sendNewOrderEmail|TransportBuilder|sales_order_place_after' app/code</code></pre>
<h2>验证结果</h2>
<p>普通下单、支付重试、Consumer重启和邮件服务超时场景中，每种邮件只发送一次且失败可恢复。</p>]]></description>
      <pubDate>Wed, 01 Jul 2026 01:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2支付Webhook验签失败但网关密钥正确]]></title>
      <link>https://www.360magento.com/blog/payment-webhook-signature-fails-raw-body-proxy/</link>
      <description><![CDATA[<p>密钥无误但Webhook仍报Invalid signature。多数签名基于原始字节，对解析后的JSON重新序列化一定会改变内容。</p><h2>实际处理步骤</h2><ol><li>从php://input或请求对象取得原始body并只读取一次；不能对decode后的对象再次encode再验签。</li><li>确认代理没有解压重压、转换字符集或把JSON包装成表单，Content-Type和签名头完整透传。</li><li>按网关文档组合timestamp与rawBody，用常量时间比较，并检查服务器时钟和允许窗口。</li><li>验签后再解析业务字段，按event_id/transaction_id幂等处理。</li></ol><h3>检查命令</h3><pre><code># PHP伪代码：$raw=$request-&gt;getContent(); verify($timestamp.'.'.$raw,$header,$secret)
timedatectl status</code></pre><h2>验证结果</h2><p>官方测试事件通过；重放同一事件只执行一次，篡改一个字节或过期timestamp均被拒绝。</p>]]></description>
      <pubDate>Tue, 30 Jun 2026 01:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[可配置商品属性标签在Store View显示错误]]></title>
      <link>https://www.360magento.com/blog/configurable-attribute-label-wrong-store-view/</link>
      <description><![CDATA[<p>中文Store仍显示Color/Red，后台明明配置了“颜色/红色”。要分别检查属性前端标签和option label，它们存放在不同表。</p><h2>按顺序解决</h2><ol><li>确认请求实际Store ID，查询eav_attribute_label中attribute_id+store_id的frontend_label；没有记录时会回退默认属性label。</li><li>再查eav_attribute_option_value。store_id=0是默认option label，目标Store应有对应记录；保存空字符串可能被当成没有覆盖。</li><li>自定义Configurable JSON或Swatch Resolver必须在目标Store环境下获取label。若Block cache key不含store_id，先访问英文站会把英文JSON缓存给中文站。</li><li>补齐标签并修正cache key后清block_html与FPC；GraphQL/PWA还要携带Store Header并清客户端缓存。</li></ol><h3>检查命令</h3><pre><code>SELECT attribute_id,store_id,value FROM eav_attribute_label WHERE attribute_id=:attribute_id;
SELECT option_id,store_id,value FROM eav_attribute_option_value WHERE option_id IN (:option_ids) ORDER BY option_id,store_id;
bin/magento cache:clean block_html full_page graphql</code></pre><h2>验证结果</h2><p>交叉访问两个Store的同一商品，每个属性名和选项值使用本Store翻译；连续切换访问顺序也不能串语言。</p><p><strong>注意：</strong>URL中的Store Code和Cookie可能覆盖预期Store，排查时同时看响应中的Store上下文。</p>]]></description>
      <pubDate>Mon, 29 Jun 2026 01:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Queue Consumer运行几小时后内存持续上涨]]></title>
      <link>https://www.360magento.com/blog/queue-consumer-memory-growth-restart-strategy/</link>
      <description><![CDATA[<p>Consumer启动时正常，数小时后占用数GB并被系统杀死。应先定位单条消息泄漏还是长期进程累积，再设置安全重启边界。</p>
<h2>排查路径</h2>
<ul>
<li>记录RSS随消息数变化，使用固定测试消息复现；同时检查未释放的大Collection、图片资源和静态缓存。</li>
<li>逐条处理时清理实体引用，避免把完整对象追加到进程级数组；异常路径也要关闭文件与外部连接。</li>
</ul>
<h2>落地修复</h2>
<ol>
<li>使用--max-messages让Consumer定期优雅退出，由Supervisor/systemd自动拉起，并设置停止超时。</li>
<li>限制重试和死信策略，单条毒消息不能在内存中无限失败重放。</li>
</ol>
<pre><code>ps -o pid,rss,etime,cmd -C php | grep consumers:startbin/magento queue:consumers:start async.operations.all --max-messages=1000# Supervisor: autorestart=true, stopwaitsecs=60</code></pre>
<h2>完成标准</h2>
<p>处理相同规模消息时RSS在区间内波动，进程轮换不丢消息、不重复业务写入，毒消息可追踪。</p>]]></description>
      <pubDate>Wed, 24 Jun 2026 03:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2完成3DS验证返回后购物车变空]]></title>
      <link>https://www.360magento.com/blog/3ds-return-cart-empty-samesite-session/</link>
      <description><![CDATA[<p>客户在银行完成3DS，返回后购物车为空或Session过期。先确认流程是跨站GET、POST还是iframe回传。</p><h2>排查路径</h2><ul><li>记录3DS前后quote_id、支付attempt_id以及返回请求是否带Cookie，不记录卡数据。</li><li>跨站POST时检查SameSite、Secure、HTTPS和Cookie域；Lax策略可能不携带原Session。</li></ul><h2>落地修复</h2><ol><li>state参数需签名并绑定Quote/attempt，不能只依赖Session；返回后先查询网关状态再恢复订单。</li><li>订单已创建时跳成功页；重复返回和刷新必须幂等，不能再次capture。</li></ol><pre><code>php bin/magento config:show web/cookie/cookie_domain
php bin/magento config:show web/cookie/cookie_path
# Network检查Set-Cookie的SameSite与Secure</code></pre><h2>完成标准</h2><p>成功、失败、取消、超时和重复返回均能定位原Quote/Order，只发生一次支付，伪造state被拒绝。</p>]]></description>
      <pubDate>Tue, 23 Jun 2026 03:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2重新下单后商品自定义选项丢失]]></title>
      <link>https://www.360magento.com/blog/reorder-loses-product-custom-options/</link>
      <description><![CDATA[<p>原订单显示刻字或尺寸，点击Reorder后购物车只有基础商品。先查看sales_order_item.product_options，不要从页面文本反推。</p><h2>解决方案</h2><ol><li>解码product_options，确认options与info_buyRequest都含option_id和选择值。只有additional_options显示文本但buyRequest为空，说明下单时只做了展示，没有保存可重建配置。</li><li>自定义加购代码应使用Product Type prepareForCartAdvanced或Cart addProduct并传完整buyRequest，不要直接new Quote Item后写name/price。</li><li>自定义选项值已被删除或option_id在新版本变化时，Reorder应给出可理解错误并要求重新选择，不能静默加入无选项商品。</li><li>修复后新订单会保存完整buyRequest。历史订单若有足够的additional_options，可建立受控映射恢复；无法确定时不要自动猜值。</li></ol><details open><summary>排查命令</summary><pre><code>SELECT item_id,sku,product_options FROM sales_order_item WHERE order_id=:order_id;
SELECT option_id,product_id,type,is_require FROM catalog_product_option WHERE product_id=:product_id;
SELECT option_type_id,option_id,sku FROM catalog_product_option_type_value WHERE option_id IN (:option_ids);</code></pre></details><h2>回归测试</h2><p>新建包含文本、下拉、日期和文件以外可重用选项的订单，再Reorder；购物车选项、价格附加值和最终订单完全一致。</p><p>文件上传选项通常不能安全复用原文件，应明确要求客户重新上传。</p>]]></description>
      <pubDate>Mon, 22 Jun 2026 03:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 cron_schedule表增长过快拖慢后台]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-table-growth-admin-slow/</link>
      <description><![CDATA[<p>cron_schedule累积数百万行后，Cron扫描和后台页面变慢。删除整张表会丢失正在执行与待执行任务，应先找出增长原因。</p>
<h2>解决记录</h2>
<p><strong>步骤1：</strong>按job_code和status统计数量、最老时间与执行耗时，识别重复调度、长期error或never finished任务。</p>
<p><strong>步骤2：</strong>确认cron:run没有被多个系统Cron以过高频率重复启动，并检查同一组锁是否正常。</p>
<p><strong>步骤3：</strong>修复异常Job后配置合理的history_success_lifetime、history_failure_lifetime与cleanup_every。</p>
<p><strong>步骤4：</strong>分批删除超过保留期的success/error/missed历史记录，控制事务大小并保留pending/running。</p>
<p>命令与数据检查</p>
<pre><code>SELECT job_code,status,COUNT(*) c,MIN(created_at),MAX(created_at) FROM cron_schedule GROUP BY job_code,status ORDER BY c DESC LIMIT 30;DELETE FROM cron_schedule WHERE status IN ('success','error','missed') AND finished_at &lt; UTC_TIMESTAMP()-INTERVAL 30 DAY LIMIT 5000;bin/magento config:show system/cron/default/history_success_lifetime</code></pre>
<h3>上线前验收</h3>
<p>表行数稳定，Cron查询恢复使用索引，新任务按时运行且清理任务不会阻塞业务写入。</p>]]></description>
      <pubDate>Wed, 17 Jun 2026 02:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[切换支付方式后Magento 2账单地址被重置]]></title>
      <link>https://www.360magento.com/blog/billing-address-resets-on-payment-method-change/</link>
      <description><![CDATA[<p>客户填写独立账单地址，切换支付方式后又恢复配送地址。通常是支付renderer重新初始化时覆盖了billingAddress Observable。</p><h2>解决记录</h2><p><strong>步骤1：</strong>记录切换前后checkoutProvider与set-billing-address请求，确认只丢UI还是Quote也被改写。</p><p><strong>步骤2：</strong>检查支付renderer的initialize、selectPaymentMethod和afterRender，不能每次显示都调用useShippingAddress。</p><p><strong>步骤3：</strong>same-as-shipping订阅只在用户操作时更新，并在组件销毁时解除，避免重复subscription反向写值。</p><p><strong>步骤4：</strong>保存Billing Address的Promise完成后再提交订单，后端以Quote最后地址为准。</p><details open><summary>命令与数据检查</summary><pre><code>rg -n 'isAddressSameAsShipping|billingAddress|selectPaymentMethod|setBillingAddress' app/code app/design
# Network检查/carts/*/billing-address与/payment-information</code></pre></details><h3>上线前验收</h3><p>三个支付方式来回切换，独立账单地址保持；只有勾选同配送时才同步，Order地址与页面一致。</p>]]></description>
      <pubDate>Tue, 16 Jun 2026 02:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[填写配送地址后Magento 2优惠码自动消失]]></title>
      <link>https://www.360magento.com/blog/coupon-removed-after-shipping-address/</link>
      <description><![CDATA[<p>购物车页优惠码已生效，结账填写地址后折扣归零。先检查规则条件，而不是在前端强行把coupon_code写回Quote。</p><h2>处理步骤</h2><p><strong>步骤1：</strong>保存应用优惠码前后的quote、quote_address和salesrule验证日志。记录customer_group_id、website_id、国家、地区、邮编、subtotal以及shipping_method。</p><p><strong>步骤2：</strong>在Sales Rule中逐层检查Website、客户组、有效期、Uses、Coupon Uses以及Conditions。配送国家条件在地址未知时可能暂时通过，填写后才会被正确判定失败。</p><p><strong>步骤3：</strong>若条件应当通过，检查自定义total collector或地址保存插件是否清空coupon_code、覆盖applied_rule_ids，或者错误地用billing address验证实体购物车。</p><p><strong>步骤4：</strong>修正规则或插件后重新collect totals。不要只修改discount_amount，折扣必须由规则重新计算并同步到base金额和item分摊。</p><h2>命令与数据检查</h2><pre><code>SELECT entity_id,coupon_code,customer_group_id,store_id,subtotal,grand_total,applied_rule_ids FROM quote WHERE entity_id=:quote_id;
SELECT address_type,country_id,region_id,postcode,shipping_method,subtotal,discount_amount FROM quote_address WHERE quote_id=:quote_id;
SELECT rule_id,name,is_active,from_date,to_date,conditions_serialized,actions_serialized FROM salesrule WHERE coupon_type&lt;&gt;1;</code></pre><h3>上线前验证</h3><p>测试允许/禁止国家、边界金额、访客/登录客户和切换配送方式；符合条件时优惠码保留，不符合时页面给出明确提示而非静默消失。</p><blockquote><p>多币种规则通常以base金额判断，验证时同时记录subtotal与base_subtotal。</p></blockquote>]]></description>
      <pubDate>Mon, 15 Jun 2026 02:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2搜索结果在不同Store显示错误语言]]></title>
      <link>https://www.360magento.com/blog/search-results-wrong-language-store-view/</link>
      <description><![CDATA[<h2>先确认问题层级</h2>
<p>中文Store搜索结果出现英文名称或英文属性标签，直接访问商品页却正常。搜索索引可能在错误Store上下文中构建。</p>
<p>对同一SKU查询默认范围与目标store_id的name、description和参与搜索属性值，确认源数据存在。</p>
<p>检查catalogsearch_fulltext为每个Store建立的索引/alias，Cron运行时不能被自定义代码强制切到默认Store。</p>
<h2>修复方法</h2>
<ul>
<li>自定义数据Mapper应使用传入的storeId加载属性标签，不能从全局StoreManager读取当前后台Store。</li>
<li>修复后仅重建catalogsearch_fulltext并清搜索/FPC缓存，分别用两个Store请求验证。</li>
</ul>
<pre><code>SELECT store_id,value FROM catalog_product_entity_varchar WHERE entity_id=:entity_id AND attribute_id=:name_attr ORDER BY store_id;bin/magento indexer:reindex catalogsearch_fulltextcurl -sS 'http://opensearch:9200/_cat/aliases?v'</code></pre>
<h2>怎样才算解决</h2>
<p>相同关键词在中英文Store返回各自名称和标签，切换Store不会读取上一站的搜索文档。</p>]]></description>
      <pubDate>Wed, 10 Jun 2026 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2邮编校验拒绝有效的国际地址]]></title>
      <link>https://www.360magento.com/blog/checkout-postcode-validation-rejects-valid-address/</link>
      <description><![CDATA[<h2>先确认问题层级</h2><p>合法英国、加拿大或无邮编地区地址被判格式错误。前端是否阻止请求和后端是否拒绝要分开检查。</p><p>在Network确认请求是否发出；未发出查前端validate，请求400读取后端字段错误。</p><p>country_id变化时动态更新postcode的required和正则，不能全局套用美国5位数字规则。</p><h2>修复方法</h2><ul><li>使用国家级规则；不要求邮编的国家允许空值，同时保留长度和安全过滤。</li><li>第三方地址服务超时不应等同地址非法，可提供受控的“使用原地址”路径并在服务端规范化。</li></ul><pre><code>rg -n 'postcode|zip.*validate|validate-postcode' app/code app/design
# 比较country_id切换前后的input class与validation配置</code></pre><h2>怎样才算解决</h2><p>美国、英国、加拿大、无邮编国家以及含空格/连字符格式均按国家正确判断，前后端规则一致。</p>]]></description>
      <pubDate>Tue, 09 Jun 2026 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单全部发货后仍停在Processing]]></title>
      <link>https://www.360magento.com/blog/order-stays-processing-after-full-shipment/</link>
      <description><![CDATA[<h2>先确认问题落在哪一层</h2><p>后台显示全部实体商品已发货，订单仍是Processing。不要直接UPDATE state/status为complete，先找出Magento为什么仍判断canInvoice或canShip。</p><p>查询每个order_item的qty_ordered、qty_invoiced、qty_shipped、qty_refunded、qty_canceled以及product_type。父子商品要看实际可发货行，不能简单相加。</p><p>若canInvoice仍为真，检查支付动作是Authorize还是Authorize and Capture，以及是否缺Invoice。虚拟商品不需要Shipment，但通常需要完成开票。</p><pre><code>SELECT item_id,parent_item_id,sku,product_type,qty_ordered,qty_invoiced,qty_shipped,qty_refunded,qty_canceled FROM sales_order_item WHERE order_id=:order_id;
SELECT increment_id,state,status,total_invoiced,total_paid FROM sales_order WHERE entity_id=:order_id;</code></pre><h2>实际修复</h2><ul><li>Shipment数量不足时，检查Bundle/Configurable父子行、自定义创建Shipment代码是否使用错误item_id，或小数数量被取整。</li><li>修复缺失业务单据后调用Order Repository保存，让状态机自行计算。只有所有可开票/可发货动作结束时才应Complete。</li></ul><h2>怎样才算修好</h2><p>覆盖纯实体、纯虚拟、可配置和Bundle订单；完成Invoice/Shipment后自动Complete，仍有未开票或未发货数量的订单继续保持Processing。</p><aside><p>状态只是结果，强改状态会让后续退款、发货和报表失真。</p></aside>]]></description>
      <pubDate>Mon, 08 Jun 2026 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2部分重建搜索索引后商品消失]]></title>
      <link>https://www.360magento.com/blog/opensearch-product-missing-after-partial-reindex/</link>
      <description><![CDATA[<p><strong>现象：</strong>商品后台启用且分类可见，执行局部更新后却从搜索结果消失。需要对比Magento可搜索条件与OpenSearch文档，而不是反复全量重建。</p>
<table>
<thead>
<tr><th>阶段</th><th>具体操作</th></tr>
</thead>
<tbody>
<tr>
<td>取证</td>
<td>确认商品在目标Store启用、分配Website、visibility包含Search，并且可售状态符合搜索配置。</td>
</tr>
<tr>
<td>定位</td>
<td>用SKU定位catalogsearch_fulltext索引状态及OpenSearch对应文档，检查store_id维度和alias指向。</td>
</tr>
<tr>
<td>修复</td>
<td>查看indexer changelog是否积压或丢失版本，修复消费者/cron后对单个测试商品保存触发增量更新。</td>
</tr>
<tr>
<td>复核</td>
<td>只有确认alias或索引结构损坏时才全量重建；重建期间监控磁盘水位，避免新索引分片只读。</td>
</tr>
</tbody>
</table>
<h3>可执行检查</h3>
<pre><code>bin/magento indexer:status catalogsearch_fulltextbin/magento indexer:show-mode catalogsearch_fulltextcurl -sS 'http://opensearch:9200/_cat/aliases?v'curl -sS 'http://opensearch:9200/_cluster/health?pretty'</code></pre>
<p><strong>通过标准：</strong>单品保存后能通过SKU和关键词搜索，两个Store结果符合各自可见性，后续增量更新无需全量重建。</p>]]></description>
      <pubDate>Wed, 03 Jun 2026 03:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2满额免邮为什么在结账时突然失效？]]></title>
      <link>https://www.360magento.com/blog/free-shipping-threshold-fails-at-checkout/</link>
      <description><![CDATA[<p><strong>现象：</strong>购物车显示已满免邮门槛，填写地址后又收运费。要先明确规则按折扣前后、含税或基础币种哪个金额判断。</p><table><thead><tr><th>阶段</th><th>具体操作</th></tr></thead><tbody><tr><td>取证</td><td>记录地址前后subtotal、base_subtotal、discount、tax和shipping_amount，多币种门槛通常按base金额。</td></tr><tr><td>定位</td><td>检查Free Shipping与Cart Price Rule的Website、客户组、国家、邮编和商品条件。</td></tr><tr><td>修复</td><td>确认是否有不可免邮商品、包裹重量或多地址拆包；Carrier门槛与Sales Rule不要形成两套冲突判断。</td></tr><tr><td>复核</td><td>统一策略后重新collect totals，不能只把shipping_amount手工改0。</td></tr></tbody></table><h3>可执行检查</h3><pre><code>SELECT subtotal,base_subtotal,subtotal_with_discount,base_subtotal_with_discount,shipping_amount,discount_amount FROM quote_address WHERE quote_id=:quote_id;
SELECT rule_id,name,conditions_serialized,actions_serialized,simple_free_shipping FROM salesrule WHERE is_active=1;</code></pre><p><strong>通过标准：</strong>门槛前后1分钱、优惠券前后、两个国家和两种币种下，页面、Quote与Order运费一致。</p>]]></description>
      <pubDate>Tue, 02 Jun 2026 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2退款完成后库存没有退回Source]]></title>
      <link>https://www.360magento.com/blog/creditmemo-refund-stock-not-returned-source/</link>
      <description><![CDATA[<p><strong>问题现象：</strong>Credit Memo已完成，商品仍缺货。先区分财务退款和实物入库：只有明确选择Return to Stock并能确定原Source时，库存才应增加。</p><table><thead><tr><th>阶段</th><th>实际操作</th></tr></thead><tbody><tr><td>复现</td><td>检查Credit Memo item的qty、back_to_stock以及订单是否创建过Shipment。未发货订单取消主要通过reservation补偿；已发货订单退货则涉及Source Item。</td></tr><tr><td>取证</td><td>记录Shipment使用的source_code。多Source订单不能把退货一律加回default Source；自定义ERP退款流程若绕过Creditmemo Management，也可能没触发库存回补。</td></tr><tr><td>修复</td><td>核对inventory_source_item当前数量和inventory_reservation累计值。不要同时手工加Source数量又创建reservation补偿，否则会双重增加可售量。</td></tr><tr><td>回归</td><td>对历史异常单，按订单、SKU、Source逐项计算应退数量，通过正式库存API补偿并保留业务备注。修复扩展后再处理批量历史数据。</td></tr></tbody></table><h3>可直接执行的检查</h3><pre><code>SELECT item_id,sku,qty,back_to_stock FROM sales_creditmemo_item WHERE parent_id=:creditmemo_id;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku='SKU-1';
SELECT stock_id,sku,SUM(quantity) FROM inventory_reservation WHERE sku='SKU-1' GROUP BY stock_id,sku;</code></pre><p><strong>通过标准：</strong>测试未发货取消、已发货全退、部分退且不回库、部分退并回库四种情况，Source quantity与salable quantity都只变化一次。</p><p>退款到支付平台成功不代表仓库已收货，业务上需要RMA时应让入库确认驱动回库存。</p>]]></description>
      <pubDate>Mon, 01 Jun 2026 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Catalog Price Rule过期后仍显示折扣价]]></title>
      <link>https://www.360magento.com/blog/catalog-price-rule-expired-still-discounted/</link>
      <description><![CDATA[<blockquote>
<p>促销结束时间已过，商品页和购物车仍显示规则价。价格规则依赖时区、Cron应用和价格索引，单纯清浏览器缓存没有作用。</p>
</blockquote>
<h2>固定复现范围</h2>
<p>确认规则Website、客户组、from_date/to_date以及后台配置时区，日期边界按商店时区解释。</p>
<h2>定位真实原因</h2>
<p>检查catalogrule_apply_all及相关Cron是否成功，cron_schedule不能长期pending或missed。</p>
<h2>执行修复</h2>
<p>执行规则应用与catalog_product_price重建，再清FPC/Varnish；先在预发布验证影响范围。</p>
<h2>恢复后处理</h2>
<p>若自定义价格服务缓存最终价，缓存键必须包含日期和客户组，并在规则失效时主动清理。</p>
<pre><code>bin/magento cron:run --group=defaultbin/magento indexer:reindex catalogrule_rule catalogrule_product catalog_product_priceSELECT job_code,status,scheduled_at,executed_at,finished_at FROM cron_schedule WHERE job_code LIKE 'catalogrule%' ORDER BY schedule_id DESC LIMIT 20;</code></pre>
<h2>回归测试</h2>
<p>在规则开始和结束边界前后测试，列表页、商品页、GraphQL与购物车价格同步切换。</p>]]></description>
      <pubDate>Wed, 27 May 2026 02:45:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2结账出现两个名称相同的配送方式]]></title>
      <link>https://www.360magento.com/blog/duplicate-shipping-methods-same-carrier-code/</link>
      <description><![CDATA[<blockquote><p>结账显示两条完全相同的配送方式。Magento依赖carrier_code + method_code唯一标识，不是靠标题区分。</p></blockquote><h2>固定复现范围</h2><p>保存shipping-methods接口原始rates，比较carrier_code、method_code、amount，判断重复来自后端还是前端。</p><h2>定位真实原因</h2><p>检查自定义Carrier的$_code和Method code，复制模块后必须更换code，同Carrier不同服务也要不同method。</p><h2>执行修复</h2><p>检查collectRates插件只调用proceed一次并且不会重复append，前端mixin不要重复push Observable。</p><h2>恢复后处理</h2><p>修复后清config/FPC并重新估算运费；已有Quote的冲突shipping_method应清除后重选。</p><pre><code>rg -n '$_code|setCarrier(|setMethod(|collectRates' app/code
SELECT carrier,method,price FROM quote_shipping_rate WHERE address_id=:address_id ORDER BY rate_id;</code></pre><h2>回归测试</h2><p>不同地址重复估算三次，每个carrier_method只有一条；保存到Quote和Order的配送方式正确。</p>]]></description>
      <pubDate>Tue, 26 May 2026 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付已Capture但Magento 2没有生成Invoice如何补救？]]></title>
      <link>https://www.360magento.com/blog/payment-captured-no-invoice-created/</link>
      <description><![CDATA[<blockquote><p>网关后台显示Capture成功，Magento订单仍Processing/Pending Payment且没有Invoice。第一原则是停止自动重试支付，避免二次扣款。</p></blockquote><h2>定位与修复记录</h2><h3>1. 固定复现范围</h3><p>用订单号、网关transaction_id和金额在两边对账。确认Capture确实settled/authorized-captured，而不是只创建了authorization。</p><h3>2. 确认真实原因</h3><p>查sales_payment_transaction与order_payment中的last_trans_id、amount_paid。已有capture交易但无Invoice，说明回调在保存Invoice前中断；完全无交易记录则先安全补录网关事实。</p><h3>3. 执行修复</h3><p>通过InvoiceService为可开票数量创建Invoice，设置capture case为NOT_CAPTURE并关联现有transaction_id，注册后在数据库事务中保存Invoice与Order。绝不能调用CAPTURE_ONLINE。</p><h3>4. 恢复后处理</h3><p>把补救脚本限制到一个明确订单，执行前输出dry-run信息并备份。随后修复Webhook幂等与事务边界，让重复回调只返回成功。</p><pre><code>SELECT entity_id,increment_id,state,status,total_paid,total_invoiced FROM sales_order WHERE increment_id='000000123';
SELECT txn_id,txn_type,parent_txn_id,is_closed,additional_information FROM sales_payment_transaction WHERE order_id=:order_id;
SELECT entity_id,increment_id,state,grand_total FROM sales_invoice WHERE order_id=:order_id;</code></pre><h2>验收清单</h2><ul><li>补建后total_paid、total_invoiced与网关Capture金额一致，只出现一个capture transaction；退款入口可用且客户只收到一次发票邮件。</li><li>金额或币种对不上时不要自动补Invoice，先交由财务和支付负责人确认。</li></ul>]]></description>
      <pubDate>Mon, 25 May 2026 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2优惠券使用次数被失败订单占用]]></title>
      <link>https://www.360magento.com/blog/coupon-usage-count-consumed-by-failed-orders/</link>
      <description><![CDATA[<p>支付失败或订单取消后，优惠券提示已达到使用上限。要确认订单是否真正创建、取消流程是否回滚以及自定义支付是否绕过事件。</p>
<h2>实际处理步骤</h2>
<ol>
<li>查询salesrule_coupon_usage、salesrule_customer和相关订单状态，按coupon_id、customer_id核对计数。</li>
<li>正常取消订单应通过Order Management执行；直接更新state/status不会触发优惠券使用次数回滚。</li>
<li>检查支付失败逻辑是否重复调用下单或重复派发sales_order_place_after，确保一次订单只增加一次。</li>
<li>历史数据先列出应回滚的订单并备份，再使用服务层或审计脚本逐单纠正，禁止无条件重置全部计数。</li>
</ol>
<h3>检查命令</h3>
<pre><code>SELECT coupon_id,customer_id,times_used FROM salesrule_coupon_usage WHERE coupon_id=:coupon_id;SELECT rule_id,customer_id,times_used FROM salesrule_customer WHERE rule_id=:rule_id AND customer_id=:customer_id;SELECT increment_id,state,status,coupon_code FROM sales_order WHERE coupon_code=:code;</code></pre>
<h2>验证结果</h2>
<p>成功订单占用一次，取消后按规则释放，支付重试不重复累计，客户与全局使用上限都正确。</p>]]></description>
      <pubDate>Wed, 20 May 2026 01:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2删除Source后发货页面仍显示旧仓库]]></title>
      <link>https://www.360magento.com/blog/deleted-source-still-shown-in-shipment/</link>
      <description><![CDATA[<p>后台已禁用仓库，创建Shipment时仍看到旧source_code。先确认是禁用、从Stock解绑，还是数据库实体真的删除。</p><h2>实际处理步骤</h2><ol><li>查询inventory_source和Stock-Source链接，确认enabled状态及是否仍属于当前Stock。</li><li>检查该Source是否仍有非零Source Item、未完成发货或自定义SSA缓存；先处理业务库存再解绑。</li><li>清config、block与FPC；API仍返回旧Source时检查自定义Provider缓存键是否包含Stock ID。</li><li>历史Shipment保留原source_code用于审计，新Shipment候选只过滤当前有效Source。</li></ol><h3>检查命令</h3><pre><code>SELECT source_code,name,enabled FROM inventory_source WHERE source_code='old_wh';
SELECT * FROM inventory_source_stock_link WHERE source_code='old_wh';
SELECT COUNT(*),SUM(quantity) FROM inventory_source_item WHERE source_code='old_wh';</code></pre><h2>验证结果</h2><p>新Shipment候选不再出现旧仓，新订单由有效仓推荐；历史Shipment仍显示原仓信息。</p>]]></description>
      <pubDate>Tue, 19 May 2026 01:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2创建订单时报Sequence table does not exist]]></title>
      <link>https://www.360magento.com/blog/sales-sequence-table-missing-order-create/</link>
      <description><![CDATA[<p>下单时报sequence_order_某ID不存在，不能把请求改去使用另一个Store的序列表。每个Store可能有独立订单、发票、发货和退款序列。</p><h2>按顺序解决</h2><ol><li>从异常表名确定store_id，再查store是否存在，以及sales_sequence_meta中order实体是否有该Store映射。</li><li>比较一个正常Store的meta、profile和实际sequence表结构。若只迁了业务表没迁序列表，应从同版本结构恢复，而不是手工创建只有一列但缺少自增设置的表。</li><li>若Store是后台新建后出现问题，检查创建Store时setup/observer异常。修复模块后通过Magento的Sequence建表逻辑补齐order、invoice、shipment、creditmemo，不只补当前报错表。</li><li>设置起始值前查询该Store现有最大increment_id，确保新序列不会与历史订单重复。操作前备份所有sales_sequence相关表。</li></ol><h3>检查命令</h3><pre><code>SELECT store_id,code,website_id FROM store ORDER BY store_id;
SELECT meta_id,entity_type,store_id,sequence_table FROM sales_sequence_meta ORDER BY store_id,entity_type;
SELECT MAX(increment_id) FROM sales_order WHERE store_id=:store_id;
SHOW CREATE TABLE sequence_order_1;</code></pre><h2>验证结果</h2><p>在目标Store依次创建订单、Invoice、Shipment和Credit Memo，编号前缀、步长与唯一性正确；另一个Store序列不受影响。</p><p><strong>注意：</strong>不要复制生产订单号到测试后再反向覆盖生产序列，迁移必须明确每个环境的编号边界。</p>]]></description>
      <pubDate>Mon, 18 May 2026 01:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2迷你购物车与结账页总金额不一致]]></title>
      <link>https://www.360magento.com/blog/minicart-checkout-totals-mismatch/</link>
      <description><![CDATA[<p>迷你购物车显示旧折扣或旧税额，进入结账页后金额才正确。先判断后端Quote已正确还是customer-data缓存没有失效。</p>
<h2>排查路径</h2>
<ul>
<li>对比cart section-data与totals-information接口，记录quote_id和更新时间，确认差异来自显示层还是Totals。</li>
<li>自定义加购、改数量、优惠券或地址接口完成后触发正确customer-data section失效，不要直接改DOM金额。</li>
</ul>
<h2>落地修复</h2>
<ol>
<li>在sections.xml声明会影响cart的Action；异步请求必须等待Quote保存和collectTotals完成再刷新section。</li>
<li>清浏览器localStorage仅用于复现，最终修复要保证多标签页和登录合并购物车也能自动更新。</li>
</ol>
<pre><code>rg -n '&lt;action name=|customer-data|invalidate(.*cart' app/code app/design# 浏览器检查 localStorage: mage-cache-storage 与 mage-cache-storage-section-invalidation</code></pre>
<h2>完成标准</h2>
<p>加购、改数量、用券、登录和切换地址后，迷你购物车与购物车页、结账页金额同步且无需手工刷新。</p>]]></description>
      <pubDate>Wed, 13 May 2026 03:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[取消订单后Magento 2 Reservation没有自动补偿]]></title>
      <link>https://www.360magento.com/blog/order-cancel-reservation-not-compensated/</link>
      <description><![CDATA[<p>订单已Canceled，可售数量却没回来。MSI不会修改原reservation，而是追加相反记录使累计值归零。</p><h2>排查路径</h2><ul><li>按订单号在metadata中定位原预留与补偿，按stock_id和SKU求和，不能只看最后一条。</li><li>确认订单经标准Order Management cancel执行；ERP直接改state/status不会触发完整补偿。</li></ul><h2>落地修复</h2><ol><li>运行list-inconsistencies，确认订单确已取消且未发货后，再将审核过的输出交给create-compensations。</li><li>修复ERP/API取消流程并做幂等；历史订单逐单补偿，避免部分发货单被错误加库存。</li></ol><pre><code>SELECT reservation_id,stock_id,sku,quantity,metadata FROM inventory_reservation WHERE metadata LIKE '%000000123%' ORDER BY reservation_id;
bin/magento inventory:reservation:list-inconsistencies -r</code></pre><h2>完成标准</h2><p>新订单预留为负，取消后累计归零且salable恢复；重复取消不会再增加补偿。</p>]]></description>
      <pubDate>Tue, 12 May 2026 03:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单邮件一直排队不发送怎么处理？]]></title>
      <link>https://www.360magento.com/blog/order-emails-queued-not-sent/</link>
      <description><![CDATA[<p>订单创建正常，后台重发也可能成功，但自动邮件长期不发。先确认是否启用了异步发送，再检查订单是否真的进入待发状态。</p><h2>解决方案</h2><ol><li>查询问题订单的send_email与email_sent。send_email=0表示业务流程根本没有安排发送；send_email=1且email_sent为空才是待发送。</li><li>在cron_schedule中查sales_send_order_email及对应时间窗口。success但邮件未到，需要查SMTP传输和退信；error/missed则先修Cron锁、PHP错误或执行频率。</li><li>自定义下单代码应通过Order Email Sender安排发送，不要只创建Order后假设Cron会自动发现。异步模式下也要保留正确Store环境和模板配置。</li><li>修复后只对确认未发送的订单重试，发送前再次检查email_sent，防止批量重发造成重复邮件。</li></ol><details open><summary>排查命令</summary><pre><code>SELECT increment_id,store_id,send_email,email_sent,created_at FROM sales_order WHERE increment_id='000000123';
SELECT job_code,status,messages,scheduled_at,executed_at,finished_at FROM cron_schedule WHERE job_code='sales_send_order_email' ORDER BY schedule_id DESC LIMIT 20;
bin/magento cron:run --group default</code></pre></details><h2>回归测试</h2><p>创建访客和登录客户订单各一笔，观察一轮Cron后email_sent变为1；模板语言、发件人、订单链接和重复发送控制均正确。</p><p>SMTP返回250只代表服务器接收，不代表最终进收件箱；需要结合退信和邮件服务事件。</p>]]></description>
      <pubDate>Mon, 11 May 2026 03:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2部分开票后税额被重复计算]]></title>
      <link>https://www.360magento.com/blog/partial-invoice-tax-calculated-twice/</link>
      <description><![CDATA[<p>一个订单分两次开票后，两张Invoice税额之和超过订单税额。问题常出在自定义Totals没有处理已开票金额和最后一张发票舍入。</p>
<h2>解决记录</h2>
<p><strong>步骤1：</strong>比较订单、order_item与两张invoice_item的qty、tax_amount、discount_tax_compensation_amount。</p>
<p><strong>步骤2：</strong>自定义Invoice Total只计算本次可开票行，扣除已开票金额；不要重新按订单小计完整算一次。</p>
<p><strong>步骤3：</strong>基础币种先计算并按Magento精度舍入，最后一张Invoice吸收舍入差，确保累计值等于订单。</p>
<p><strong>步骤4：</strong>修复后用新测试订单验证；历史已发送发票按财务流程冲销重开，不直接改账务表。</p>
<p>命令与数据检查</p>
<pre><code>SELECT increment_id,tax_amount,base_tax_amount,discount_amount,grand_total FROM sales_invoice WHERE order_id=:order_id ORDER BY entity_id;SELECT item_id,qty_invoiced,tax_invoiced FROM sales_order_item WHERE order_id=:order_id;</code></pre>
<h3>上线前验收</h3>
<p>按1+1、1+2和最后剩余数量开票，所有Invoice累计税、折扣和总额与Order完全相等。</p>]]></description>
      <pubDate>Wed, 06 May 2026 02:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Source有库存但Salable Quantity长期不更新]]></title>
      <link>https://www.360magento.com/blog/source-stock-salable-quantity-consumer-stopped/</link>
      <description><![CDATA[<p>Source Item数量已经保存，前台仍缺货，手工reindex后才恢复。MSI可售状态更新依赖消息消费与库存索引链。</p><h2>解决记录</h2><p><strong>步骤1：</strong>确认Source属于当前Website对应Stock，Source Item status启用，不能只看quantity。</p><p><strong>步骤2：</strong>检查inventory.reservations.updateSalabilityStatus消费者是否持续运行，并查看退出异常。</p><p><strong>步骤3：</strong>Consumer运行但单个SKU不更新时，比较SKU格式、队列消息和当前版本相关补丁。</p><p><strong>步骤4：</strong>恢复Consumer后只修改一个测试SKU，观察消息消费和inventory_stock_X变化，再决定是否全量reindex。</p><details open><summary>命令与数据检查</summary><pre><code>bin/magento queue:consumers:list | grep inventory.reservations.updateSalabilityStatus
bin/magento queue:consumers:start inventory.reservations.updateSalabilityStatus --max-messages=100
bin/magento indexer:status inventory</code></pre></details><h3>上线前验收</h3><p>连续修改数量与状态，无需手工全量索引即可在合理延迟内反映到前台，Consumer重启不重复改库存。</p>]]></description>
      <pubDate>Tue, 05 May 2026 02:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2重复点击Place Order生成两张订单如何修复？]]></title>
      <link>https://www.360magento.com/blog/double-click-place-order-creates-duplicate-orders/</link>
      <description><![CDATA[<p>网络慢时客户连续点击下单，出现两张订单或两次支付。只给按钮加disabled不够，因为重试、浏览器回放和网关回调仍可重复到达。</p><h2>处理步骤</h2><p><strong>步骤1：</strong>对重复订单比较customer/guest、quote_id、支付transaction_id、remote_ip和created_at。相同Quote产生两单说明订单提交并发保护失效；不同Quote则先查前端是否重复创建购物车。</p><p><strong>步骤2：</strong>前端在placeOrder Promise完成前禁用按钮并显示进度，失败时按明确错误恢复；不要在timeout后自动无条件重发。</p><p><strong>步骤3：</strong>服务端以cart_id加支付attempt_id生成幂等键，在提交前原子占用。相同键再次到达时返回原订单结果，不再次调用网关。数据库要有唯一约束或可靠锁，不能只用进程内变量。</p><p><strong>步骤4：</strong>支付回调按网关transaction_id幂等处理；创建Invoice、发送邮件和扣库存前检查是否已完成。已有重复单逐单核对支付后取消未付款单。</p><h2>命令与数据检查</h2><pre><code>SELECT entity_id,increment_id,quote_id,customer_email,created_at FROM sales_order WHERE quote_id=:quote_id ORDER BY entity_id;
SELECT payment_id,txn_id,txn_type,created_at FROM sales_payment_transaction WHERE order_id IN (:order_ids);</code></pre><h3>上线前验证</h3><p>使用浏览器双击、两个并发请求、客户端超时重试和重复Webhook测试，最终只能有一张订单、一次capture和一次库存扣减。</p><blockquote><p>不要通过关闭客户重试来掩盖问题；幂等返回应让客户能拿到已经创建的订单号。</p></blockquote>]]></description>
      <pubDate>Mon, 04 May 2026 02:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2克隆数据库后订单号出现重复]]></title>
      <link>https://www.360magento.com/blog/database-clone-duplicate-order-increment-id/</link>
      <description><![CDATA[<h2>先确认问题层级</h2>
<p>将预发布数据库恢复到生产或新增Store后，创建订单时报increment_id重复。订单号来自按Store维护的sequence表，不只看sales_order最大值。</p>
<p>确认出错订单的store_id以及对应sales_sequence_meta、sales_sequence_profile和sequence_order_N表。</p>
<p>比较sequence表当前AUTO_INCREMENT与该Store已有订单最大序号，先备份并暂停下单后再校正。</p>
<h2>修复方法</h2>
<ul>
<li>数据库克隆脚本必须连同sequence元数据一起迁移；新增Store应通过标准流程创建对应sequence表。</li>
<li>不要直接修改历史订单increment_id绕过唯一键，外部ERP和支付已引用这些号码。</li>
</ul>
<pre><code>SELECT store_id,MAX(entity_id),MAX(increment_id) FROM sales_order GROUP BY store_id;SELECT * FROM sales_sequence_meta WHERE entity_type='order';SHOW TABLE STATUS LIKE 'sequence_order_%';</code></pre>
<h2>怎样才算解决</h2>
<p>每个Store连续创建多张订单均唯一，Invoice、Shipment和Credit Memo各自序列也无冲突。</p>]]></description>
      <pubDate>Wed, 29 Apr 2026 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Group Price在子Website显示了主站价格]]></title>
      <link>https://www.360magento.com/blog/group-price-leaks-across-websites/</link>
      <description><![CDATA[<h2>先确认问题层级</h2><p>同一客户组在A站有折扣，B站不应有，但B站也显示A站价格。先核对价格作用域和原始高级价格行。</p><p>确认Catalog Price Scope是Website还是Global，并记录两个Store所属website_id。</p><p>查询website_id=0与具体Website的价格行；不需要的All Websites记录应通过正式接口删除。</p><h2>修复方法</h2><ul><li>自定义价格插件从当前Store获取Website，不能写死默认站；缓存键需包含客户组和Store维度。</li><li>修复数据与代码后全量重建价格索引，客户退出重登并清FPC/GraphQL缓存。</li></ul><pre><code>bin/magento config:show catalog/price/scope
SELECT website_id,customer_group_id,qty,value FROM catalog_product_entity_tier_price WHERE entity_id=:entity_id;
bin/magento indexer:reindex catalog_product_price</code></pre><h2>怎样才算解决</h2><p>同一SKU和客户组在两个Website分别显示各自价格，购物车、订单与API返回一致。</p>]]></description>
      <pubDate>Tue, 28 Apr 2026 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2新增客户地址属性后结账无法保存地址]]></title>
      <link>https://www.360magento.com/blog/customer-address-attribute-blocks-checkout-save/</link>
      <description><![CDATA[<h2>先确认问题落在哪一层</h2><p>结账页新增门牌号或税号字段后，前端能填写，但shipping-information返回400，或订单地址里为空。必须把显示、传输和持久化三层分别验证。</p><p>确认customer_address属性backend_type、is_required和used_in_forms。结账使用的表单代码与后台客户地址不同，属性没有分配到正确form时Repository可能忽略。</p><p>在浏览器Network检查字段位于shippingAddress.customAttributes还是extension_attributes，并与后端插件读取路径一致。字段名必须和attribute_code完全相同。</p><pre><code>SELECT attribute_id,attribute_code,backend_type,is_required FROM eav_attribute WHERE entity_type_id=(SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code='customer_address');
SELECT * FROM customer_form_attribute WHERE attribute_id=:attribute_id;
bin/magento setup:di:compile</code></pre><h2>实际修复</h2><ul><li>声明extension_attributes.xml并生成代码；保存前把扩展属性复制到Customer Address/Quote Address，提交订单时再明确复制到Order Address。不要依赖任意数组自动落库。</li><li>非必填字段要允许null和空字符串；下拉字段提交option value而不是显示label。清generated并重新compile后测试。</li></ul><h2>怎样才算修好</h2><p>测试访客新地址、登录客户新地址、已保存地址和账单地址同/不同四种路径，customer_address_entity、quote_address和sales_order_address值一致。</p><aside><p>不要把完整地址请求写入日志；只记录字段是否存在、类型和非敏感测试值。</p></aside>]]></description>
      <pubDate>Mon, 27 Apr 2026 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2在线退款成功但Credit Memo金额不一致]]></title>
      <link>https://www.360magento.com/blog/online-refund-creditmemo-amount-mismatch/</link>
      <description><![CDATA[<p><strong>现象：</strong>支付网关已退一笔金额，Magento Credit Memo却多退或少退。必须先区分基础币种、订单币种、税、运费和Adjustment。</p>
<table>
<thead>
<tr><th>阶段</th><th>具体操作</th></tr>
</thead>
<tbody>
<tr>
<td>取证</td>
<td>比对sales_creditmemo的base_grand_total/grand_total与网关退款币种和最小货币单位，确认没有把分当元。</td>
</tr>
<tr>
<td>定位</td>
<td>部分退款按订单行可退款数量创建，税与折扣使用Magento计算结果；不要在网关回调再次手工创建第二张Credit Memo。</td>
</tr>
<tr>
<td>修复</td>
<td>运费退款和Adjustment Positive/Negative分别记录业务原因，网关只发送最终允许的金额。</td>
</tr>
<tr>
<td>复核</td>
<td>以网关transaction_id做幂等；结果未知时先查询网关，不能超时就再次refund。</td>
</tr>
</tbody>
</table>
<h3>可执行检查</h3>
<pre><code>SELECT increment_id,base_grand_total,grand_total,shipping_amount,tax_amount,discount_amount,adjustment_positive,adjustment_negative FROM sales_creditmemo WHERE order_id=:order_id;SELECT txn_id,txn_type,parent_txn_id,is_closed FROM sales_payment_transaction WHERE order_id=:order_id;</code></pre>
<p><strong>通过标准：</strong>全额、部分、仅运费及重复回调测试中，Magento累计退款、网关累计退款和订单可退款余额完全一致。</p>]]></description>
      <pubDate>Wed, 22 Apr 2026 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Tier Price导入后旧客户组价格仍然存在]]></title>
      <link>https://www.360magento.com/blog/tier-price-import-does-not-replace-old-rows/</link>
      <description><![CDATA[<p><strong>现象：</strong>新的阶梯价导入成功，但旧客户组价格仍显示。缺失的CSV行通常不会自动代表删除旧价格。</p><table><thead><tr><th>阶段</th><th>具体操作</th></tr></thead><tbody><tr><td>取证</td><td>查询原始Tier Price，按Website、客户组和qty列出旧新记录，确认前台命中哪一行。</td></tr><tr><td>定位</td><td>核对导入行为是Add/Update、Replace还是Delete；清旧价格要使用版本支持的删除格式或Repository明确删除。</td></tr><tr><td>修复</td><td>检查website_id、all_groups与customer_group_id，All Websites + All Groups可能继续覆盖具体组价格。</td></tr><tr><td>复核</td><td>完成后重建catalog_product_price并让客户重新登录，清FPC后比较商品页与购物车。</td></tr></tbody></table><h3>可执行检查</h3><pre><code>SELECT website_id,all_groups,customer_group_id,qty,value,percentage_value FROM catalog_product_entity_tier_price WHERE entity_id=:entity_id ORDER BY website_id,customer_group_id,qty;
bin/magento indexer:reindex catalog_product_price</code></pre><p><strong>通过标准：</strong>访客、两个客户组、边界数量和两个Website只出现预期阶梯，购物车与商品页价格一致。</p>]]></description>
      <pubDate>Tue, 21 Apr 2026 03:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[客户登录后Magento 2访客购物车没有合并]]></title>
      <link>https://www.360magento.com/blog/guest-cart-not-merged-after-login/</link>
      <description><![CDATA[<p><strong>问题现象：</strong>访客加了商品，登录后购物车变空或只保留旧客户购物车。先保存登录前后的quote_id，不要只看前端mini cart数量。</p><table><thead><tr><th>阶段</th><th>实际操作</th></tr></thead><tbody><tr><td>复现</td><td>在测试账号中记录登录前Cookie、masked cart ID、quote_id、is_active和customer_id；登录后再次读取当前Quote。确认是否生成了第三个Quote。</td></tr><tr><td>取证</td><td>使用标准Customer Account登录时，Checkout Session会执行客户Quote加载和merge。自定义SSO、手机号登录或GraphQL登录若只设置客户Session，可能完全跳过这一步。</td></tr><tr><td>修复</td><td>修复流程应调用官方Quote合并服务，让访客Quote合并进客户活动Quote，再保存并停用旧Quote。不要用SQL直接改customer_id。</td></tr><tr><td>回归</td><td>若同SKU没有合并数量，检查custom_options、buyRequest和扩展属性是否导致两个item不等价；这是合并规则，不是Quote丢失。</td></tr></tbody></table><h3>可直接执行的检查</h3><pre><code>SELECT entity_id,is_active,customer_id,items_count,items_qty,updated_at FROM quote WHERE entity_id IN (:guest_quote,:customer_quote);
SELECT quote_id,sku,qty,product_type FROM quote_item WHERE quote_id IN (:guest_quote,:customer_quote);</code></pre><p><strong>通过标准：</strong>测试客户原购物车为空和非空两种情况，同SKU与带自定义选项商品都覆盖；登录、退出再登录后只保留一个活动Quote且金额正确。</p><p>PWA/GraphQL还要确认客户端在登录后改用customerCart返回的新cart_id。</p>]]></description>
      <pubDate>Mon, 20 Apr 2026 03:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2允许Backorder但购物车仍提示缺货]]></title>
      <link>https://www.360magento.com/blog/backorder-enabled-cart-still-out-of-stock/</link>
      <description><![CDATA[<blockquote>
<p>后台已允许缺货下单，商品页也显示可售，但加入购物车仍提示Requested qty is not available。需要同时检查Stock、Source和阈值配置。</p>
</blockquote>
<h2>固定复现范围</h2>
<p>在当前Website对应Stock下查询is_salable与salable quantity，不能只看默认Source的quantity。</p>
<h2>定位真实原因</h2>
<p>核对Manage Stock、Backorders、Out-of-Stock Threshold及Use Config Settings；负阈值决定可继续销售的下限。</p>
<h2>执行修复</h2>
<p>检查可配置商品的实际子SKU配置，父商品设置不会覆盖子商品的库存选项。</p>
<h2>恢复后处理</h2>
<p>清理不一致Reservation并重建库存索引；自定义数量校验插件必须使用MSI服务而非旧StockItem数量。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies -rbin/magento indexer:reindex inventorySELECT sku,quantity,is_salable FROM inventory_stock_1 WHERE sku='SKU-1';</code></pre>
<h2>回归测试</h2>
<p>数量跨越0和负阈值时行为符合设置，商品页、GraphQL加入购物车与后台订单结果一致。</p>]]></description>
      <pubDate>Wed, 15 Apr 2026 02:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[更换Attribute Set后Magento 2可配置商品组合消失]]></title>
      <link>https://www.360magento.com/blog/attribute-set-change-removes-configurable-combinations/</link>
      <description><![CDATA[<blockquote><p>给父商品或子商品换Attribute Set后，Edit Configurations为空，前台色板消失。Attribute Set变化不是单纯的界面分组调整。</p></blockquote><h2>固定复现范围</h2><p>导出父商品超级属性列表，确认新Attribute Set包含同一attribute_id，而不是同名新属性。</p><h2>定位真实原因</h2><p>检查属性为Select、允许用于可配置商品，并确认每个子商品仍保存有效option_id。</p><h2>执行修复</h2><p>在副本商品先把缺失属性加入新Set、保存子商品值，再切换父子商品Attribute Set。</p><h2>恢复后处理</h2><p>重建EAV、configurable、价格和库存索引；若关联已删除，使用官方Link Management按已验证组合恢复。</p><pre><code>SELECT product_id,attribute_id FROM catalog_product_super_attribute WHERE product_id=:parent_id;
SELECT attribute_set_id,attribute_id FROM eav_entity_attribute WHERE attribute_set_id=:new_set;
SELECT parent_id,product_id FROM catalog_product_super_link WHERE parent_id=:parent_id;</code></pre><h2>回归测试</h2><p>后台组合数量与迁移前一致，前台每个选项映射唯一子SKU，后续保存不会再次丢组合。</p>]]></description>
      <pubDate>Tue, 14 Apr 2026 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2发货时Source Selection总选错仓库]]></title>
      <link>https://www.360magento.com/blog/source-selection-chooses-wrong-warehouse/</link>
      <description><![CDATA[<blockquote><p>订单明明更靠近华东仓，创建Shipment时Magento却推荐默认仓。先确认使用的是Priority还是Distance算法，二者需要的配置完全不同。</p></blockquote><h2>定位与修复记录</h2><h3>1. 固定复现范围</h3><p>记录订单Website、stock_id、收货地址、SKU和推荐source_code。确认订单所属Website只绑定到预期Stock。</p><h3>2. 确认真实原因</h3><p>Priority算法按Stock配置中的Source顺序选择，不按Source名称或后台列表排序。重新拖动优先级并保存；禁用或无货Source会被跳过。</p><h3>3. 执行修复</h3><p>Distance Priority算法需要正确的经纬度、国家地区数据和距离提供者。地址缺邮编或Source坐标为空时可能回退。检查下载的geonames数据与API凭证。</p><h3>4. 恢复后处理</h3><p>如果ERP创建Shipment时自己传source_code，Magento推荐不会生效；修复ERP映射或在调用Source Deduction前使用正式Source Selection接口。</p><pre><code>SELECT stock_id,website_id FROM inventory_stock_sales_channel WHERE website_id=:website_id;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku='SKU-1';
SELECT source_code,name,latitude,longitude,enabled FROM inventory_source;</code></pre><h2>验收清单</h2><ul><li>用两个仓都有货、首选仓缺货、部分数量不足三种订单测试；推荐、实际扣减和Shipment中的source_code必须一致。</li><li>不要通过直接改inventory_source_item数量来强迫选仓，这会破坏ERP库存事实。</li></ul>]]></description>
      <pubDate>Mon, 13 Apr 2026 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2执行catalog:images:resize时内存耗尽]]></title>
      <link>https://www.360magento.com/blog/catalog-images-resize-memory-exhausted/</link>
      <description><![CDATA[<p>批量生成商品缩略图时CLI被Killed或报Allowed memory size exhausted。不要只无限提高memory_limit，要先找异常原图和并发压力。</p>
<h2>实际处理步骤</h2>
<ol>
<li>记录最后处理文件并用identify检查像素尺寸、色彩空间和文件是否损坏；小体积图片也可能解码占用数百MB。</li>
<li>隔离超大或损坏原图，重新压缩后再上传；同时确认GD或ImageMagick版本及临时目录空间。</li>
<li>在非高峰以单进程或受控批次执行，避免多个resize与部署任务同时争抢内存。</li>
<li>调整CLI memory_limit后监控峰值RSS，生成完成再清理旧缓存，不能删除catalog/product原图。</li>
</ol>
<h3>检查命令</h3>
<pre><code>find pub/media/catalog/product -type f -size +20M -printidentify -format '%w %h %m %f\n' pub/media/catalog/product/x/y/image.jpgphp -d memory_limit=2G bin/magento catalog:images:resize</code></pre>
<h2>验证结果</h2>
<p>全量命令正常结束，随机抽查各主题尺寸均可访问，日志无坏图且服务器未发生OOM Kill。</p>]]></description>
      <pubDate>Wed, 08 Apr 2026 01:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Media API重试后生成重复商品图片]]></title>
      <link>https://www.360magento.com/blog/media-api-retry-creates-duplicate-product-images/</link>
      <description><![CDATA[<p>ERP上传图片超时后重试，媒体库出现多张相同图片。HTTP超时不代表第一次请求失败，可能只是响应未送达。</p><h2>实际处理步骤</h2><ol><li>为图片记录外部ID、内容SHA-256和Magento entry_id；不能只按文件名判断。</li><li>上传前读取media_gallery_entries并比较外部ID或内容哈希；已存在则更新label、position和roles。</li><li>一次业务上传使用稳定幂等键，结果未知时先GET核对，再决定是否重试，禁止并发重放。</li><li>历史重复项先确认各Store图片角色，只删除内容相同且无独立角色的冗余entry，再重建图片缓存。</li></ol><h3>检查命令</h3><pre><code>GET /rest/V1/products/SKU/media
POST /rest/V1/products/SKU/media
# 客户端保存 external_image_id -&gt; entry_id 与 sha256(content) 映射</code></pre><h2>验证结果</h2><p>模拟服务器已保存但客户端超时，再重试同一图片；最终只有一个entry，图片角色和排序正确。</p>]]></description>
      <pubDate>Tue, 07 Apr 2026 01:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Bulk API部分失败后如何只重试失败项？]]></title>
      <link>https://www.360magento.com/blog/bulk-api-retry-failed-operations-only/</link>
      <description><![CDATA[<p>一批1000个商品更新后，部分Complete、部分Rejected。如果原样重发全部请求，成功项会再次执行，可能重复写媒体、库存或外部流水。</p><h2>按顺序解决</h2><ol><li>保存接口返回的bulk_uuid，并调用Bulk Status接口取得每个operation_key、status、result_message和serialized_data。先按错误类型分组。</li><li>401、字段校验、SKU不存在等确定性错误先修数据；队列连接中断、死锁、临时超时才适合自动重试。不要把所有Rejected都当成瞬时故障。</li><li>从原始业务数据按operation_key重建只包含失败项的新批次，不要直接执行数据库里的serialized_data。为每条业务操作保留外部幂等键，成功项不得重复创建资源。</li><li>确认async.operations.all消费者正在运行；提交新批次后分别记录旧、新bulk_uuid，直到所有操作进入最终状态。</li></ol><h3>检查命令</h3><pre><code>bin/magento queue:consumers:list | grep async.operations.all
bin/magento queue:consumers:start async.operations.all --max-messages=500
curl -H 'Authorization: Bearer ***' 'https://shop.example/rest/V1/bulk/BULK_UUID/status'</code></pre><h2>验证结果</h2><p>构造一条合法、一条字段错误和一条临时失败数据；修复后只重试后两条中的可重试项，已成功记录的updated_at和关联数据不应再次变化。</p><p><strong>注意：</strong>生产脚本应设置最大重试次数和死信报告，避免毒消息无限循环。</p>]]></description>
      <pubDate>Mon, 06 Apr 2026 01:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2生成URL Rewrite时报Duplicate entry store_id request_path]]></title>
      <link>https://www.360magento.com/blog/url-rewrite-duplicate-store-request-path/</link>
      <description><![CDATA[<p>保存商品或运行索引时出现store_id与request_path唯一键冲突。直接删除全部URL Rewrite会丢失自定义重定向，应先定位冲突来源。</p>
<h2>排查路径</h2>
<ul>
<li>按报错的store_id和request_path查询全部记录，区分系统生成、分类路径、商品路径和自定义重定向。</li>
<li>检查两个商品或分类是否在同一Store生成相同url_key；同时核对URL后缀、分类路径开关和历史重定向。</li>
</ul>
<h2>落地修复</h2>
<ol>
<li>先修正冲突实体的url_key或Store范围，再只删除可再生成的系统记录；保留is_autogenerated=0的人工重写。</li>
<li>对目标商品/分类重新生成并清FPC，检查旧地址的301链不能循环。</li>
</ol>
<pre><code>SELECT url_rewrite_id,entity_type,entity_id,request_path,target_path,redirect_type,is_autogenerated FROM url_rewrite WHERE store_id=:store_id AND request_path=:path;SELECT entity_id,store_id,value FROM catalog_product_entity_varchar WHERE attribute_id=:url_key_attr AND value=:url_key;</code></pre>
<h2>完成标准</h2>
<p>重复路径只保留一条有效目标，商品与分类保存成功，旧URL跳转一次后到正确新地址。</p>]]></description>
      <pubDate>Wed, 01 Apr 2026 03:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2商品导入的分类路径被拆成多个错误分类]]></title>
      <link>https://www.360magento.com/blog/product-import-category-path-separator-error/</link>
      <description><![CDATA[<p>本应进入“女装/上衣”的商品，却创建了两个根级分类。问题通常是Category path separator与Multiple value separator混用。</p><h2>排查路径</h2><ul><li>导出一个已关联两个分类的商品，观察categories列对层级和多个分类的实际表达。</li><li>固定不同的路径分隔符和多分类分隔符；分类名包含分隔符时先改名或使用版本支持的转义。</li></ul><h2>落地修复</h2><ol><li>确认导入所用根分类和目标Store根目录，路径字符串正确但根目录错误也会建到另一棵树。</li><li>先用一个SKU试导并核对分类树；清理错误分类前检查商品关联和URL Rewrite。</li></ol><pre><code>SELECT c.entity_id,c.path,c.level,v.value name FROM catalog_category_entity c JOIN catalog_category_entity_varchar v ON v.entity_id=c.entity_id WHERE v.attribute_id=(SELECT attribute_id FROM eav_attribute WHERE attribute_code='name' AND entity_type_id=3) ORDER BY c.path;</code></pre><h2>完成标准</h2><p>商品进入指定叶子分类且不创建多余根分类，面包屑、URL和分类商品数与导入文件一致。</p>]]></description>
      <pubDate>Tue, 31 Mar 2026 03:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL商品自定义属性返回null怎么处理？]]></title>
      <link>https://www.360magento.com/blog/graphql-product-custom-attribute-null/</link>
      <description><![CDATA[<p>Schema里能查询自定义字段，也没有报错，但所有商品都返回null。先确认字段是EAV自动暴露，还是自定义Resolver读取。两条链路的修复点不同。</p><h2>解决方案</h2><ol><li>在相同Store View下直接查catalog_product_entity对应backend表，确认目标entity_id、attribute_id、store_id确实有值；没有Store值时应验证是否正确回退到store_id=0。</li><li>若使用ProductInterface扩展字段，Resolver不要从$model数组猜数据。用value中的model或Repository按当前Store读取，并处理简单、可配置、虚拟等商品类型。</li><li>核对schema.graphqls的返回类型。属性是数组或对象却声明为String时，序列化会失败；Dropdown若需要文本，要通过选项源把option_id转为当前Store标签。</li><li>清理config与GraphQL缓存，重新请求一个有值和一个无值商品。若Varnish/FPC参与GraphQL GET缓存，自定义Resolver还要返回正确Identity。</li></ol><details open><summary>排查命令</summary><pre><code>SELECT attribute_id,attribute_code,backend_type FROM eav_attribute WHERE attribute_code='vendor_code';
SELECT entity_id,attribute_id,store_id,value FROM catalog_product_entity_varchar WHERE attribute_id=:attribute_id AND entity_id=:entity_id;
bin/magento cache:clean config graphql full_page</code></pre></details><h2>回归测试</h2><p>使用default与第二语言Store Header查询，同一SKU分别返回对应值；无值商品返回明确的null而不是导致整个products查询报错。</p><p>不要在每个商品Resolver里单独load一次实体，列表查询会形成N+1；批量加载或使用已提供的数据。</p>]]></description>
      <pubDate>Mon, 30 Mar 2026 03:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2保存商品时反复触发Observer导致死循环]]></title>
      <link>https://www.360magento.com/blog/product-save-observer-recursive-loop/</link>
      <description><![CDATA[<p>保存一次商品却持续触发catalog_product_save_after，最终超时或内存耗尽。通常是Observer内部再次调用save造成递归。</p>
<h2>解决记录</h2>
<p><strong>步骤1：</strong>从异常堆栈和临时计数日志确认同一SKU、同一请求重复进入哪个Observer或Plugin。</p>
<p><strong>步骤2：</strong>Observer中不要再次执行$product-&gt;save()；只改当前对象可在合适的before事件设置数据，跨实体写入改用Repository并加边界。</p>
<p><strong>步骤3：</strong>确需二次更新时使用请求级guard并比较旧新值，只在值真正变化时执行；guard不能掩盖无限业务循环。</p>
<p><strong>步骤4：</strong>检查aroundSave必须且只能调用一次proceed，修复后移除临时日志并重新编译。</p>
<p>命令与数据检查</p>
<pre><code>rg -n 'catalog_product_save_|aroundSave|-&gt;save(' app/code# 临时记录sku、事件名与debug_backtrace摘要bin/magento setup:di:compile</code></pre>
<h3>上线前验收</h3>
<p>单次保存只进入预期次数，CLI导入和后台保存都能完成，索引与扩展字段仍正确更新。</p>]]></description>
      <pubDate>Wed, 25 Mar 2026 02:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2导入Multiselect属性时部分选项被跳过]]></title>
      <link>https://www.360magento.com/blog/import-multiselect-values-partially-skipped/</link>
      <description><![CDATA[<p>CSV写了三个值，导入后只保存一个或整行跳过。先确认Multiple value separator，不能默认逗号同时承担列分隔与多值分隔。</p><h2>解决记录</h2><p><strong>步骤1：</strong>导出一个已有多选值的商品，以系统格式确认列名、标签和多值分隔符。</p><p><strong>步骤2：</strong>CSV字段包含逗号时用双引号包裹；选项标签也含逗号时改用明确的多值分隔符并保持导入设置一致。</p><p><strong>步骤3：</strong>核对目标Store选项标签的大小写、空格和语言，先创建缺失选项，避免导入器无法映射。</p><p><strong>步骤4：</strong>用Validate Data检查Skipped Rows，先导入一个SKU并重新导出验证，再执行批量。</p><details open><summary>命令与数据检查</summary><pre><code>SELECT a.attribute_code,o.option_id,v.store_id,v.value FROM eav_attribute a JOIN eav_attribute_option o ON o.attribute_id=a.attribute_id JOIN eav_attribute_option_value v ON v.option_id=o.option_id WHERE a.attribute_code='features';</code></pre></details><h3>上线前验收</h3><p>单值、多值、标签含逗号及第二语言Store均能完整保存，重新导出不丢值也不生成重复option。</p>]]></description>
      <pubDate>Tue, 24 Mar 2026 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API指定fields后SearchCriteria筛选失效]]></title>
      <link>https://www.360magento.com/blog/rest-fields-parameter-breaks-searchcriteria/</link>
      <description><![CDATA[<p>单独传searchCriteria能过滤，加入fields精简响应后却返回全部记录。问题通常出在查询字符串结构，不是Repository突然忽略过滤器。</p><h2>处理步骤</h2><p><strong>步骤1：</strong>从服务器access log复制实际收到的完整query string，对比客户端发送内容。重点检查第一个参数后是否使用&，方括号是否被HTTP库二次编码。</p><p><strong>步骤2：</strong>fields只描述返回结构，例如items[sku,name],total_count；searchCriteria仍是独立顶级参数。不要把&searchCriteria拼进fields值，也不要对整条URL一次urlencode。</p><p><strong>步骤3：</strong>用curl的--get与--data-urlencode分别传参数，确认服务端解析结果。若curl正常、SDK异常，修复SDK的query builder而不是改Magento Repository。</p><p><strong>步骤4：</strong>自定义接口还要确认方法参数名为searchCriteria且类型是SearchCriteriaInterface；实现层调用getList时必须传入收到的对象。</p><h2>命令与数据检查</h2><pre><code>curl --get 'https://shop.example/rest/V1/products'   --data-urlencode 'searchCriteria[filter_groups][0][filters][0][field]=status'   --data-urlencode 'searchCriteria[filter_groups][0][filters][0][value]=1'   --data-urlencode 'searchCriteria[filter_groups][0][filters][0][condition_type]=eq'   --data-urlencode 'fields=items[sku,name,status],total_count'</code></pre><h3>上线前验证</h3><p>确认total_count与不带fields时一致，items只保留指定字段；再测试空结果、第二页以及包含空格和加号的过滤值。</p><blockquote><p>记录请求时隐藏Authorization头和客户数据，但保留原始参数顺序与编码形式。</p></blockquote>]]></description>
      <pubDate>Mon, 23 Mar 2026 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST保存客户地址时报Custom attribute is invalid]]></title>
      <link>https://www.360magento.com/blog/rest-customer-address-custom-attribute-invalid/</link>
      <description><![CDATA[<h2>先确认问题层级</h2>
<p>REST创建客户地址时标准字段正常，自定义字段却返回Custom attribute is invalid。先核对属性实体、输入代码和前后台表单配置。</p>
<p>确认属性创建在customer_address实体而不是customer实体，并检查attribute_code拼写与数据类型。</p>
<p>请求体按custom_attributes数组提交attribute_code/value；多选值按接口要求传字符串或数组，不能直接发送后台标签。</p>
<h2>修复方法</h2>
<ul>
<li>检查属性已加入正确Attribute Set/Group并允许用于相应表单；API写入还需Service Contract可见。</li>
<li>清EAV和config缓存后用GET读回地址；若只在某Website失败，核对客户Website与地址归属。</li>
</ul>
<pre><code>GET /rest/V1/attributeMetadata/customerAddressPOST /rest/V1/customers/123/addressesSELECT attribute_id,attribute_code,backend_type FROM eav_attribute WHERE entity_type_id=(SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code='customer_address');</code></pre>
<h2>怎样才算解决</h2>
<p>同一地址可通过REST新增、修改和清空该属性，后台打开后值一致，非法选项返回明确错误。</p>]]></description>
      <pubDate>Wed, 18 Mar 2026 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST自定义接口接收对象数组时报Class does not exist]]></title>
      <link>https://www.360magento.com/blog/rest-custom-api-object-array-class-does-not-exist/</link>
      <description><![CDATA[<h2>先确认问题层级</h2><p>自定义REST接口传入items数组时，反序列化阶段报Class does not exist，业务方法甚至没有执行，根因通常在Service Contract类型声明。</p><p>接口DocBlock使用完整的\Vendor\Module\Api\Data\ItemInterface[]，参数名与JSON字段一致。</p><p>为Data Interface提供getter/setter，并在di.xml配置preference到实现类。</p><h2>修复方法</h2><ul><li>不要只声明array后期待Magento推断内部对象，也不要把具体Model作为公共接口类型。</li><li>清generated和config缓存后重新compile，先用一个最小对象跑通，再增加嵌套数组。</li></ul><pre><code>/** @param \Vendor\Module\Api\Data\ItemInterface[] $items */
public function save(array $items);
# di.xml配置ItemInterface到Data实现类
bin/magento setup:di:compile</code></pre><h2>怎样才算解决</h2><p>单个和多个对象都能反序列化为Data Interface；缺字段或错误类型返回明确400，Swagger结构正确。</p>]]></description>
      <pubDate>Tue, 17 Mar 2026 01:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2导入客户时报Invalid website_id如何修复？]]></title>
      <link>https://www.360magento.com/blog/customer-import-invalid-website-id/</link>
      <description><![CDATA[<h2>先确认问题落在哪一层</h2><p>客户CSV在验证阶段提示Invalid website_id，常见原因不是客户数据坏了，而是把Store ID、Store Code或旧环境的Website ID填进了新环境。</p><p>先导出一条当前环境的测试客户，确认该版本客户导入使用的网站字段名和格式。不要直接照搬另一套环境的数字ID。</p><p>查询store_website与store表建立映射。CSV若使用_website字段，填Website Code；若明确要求website_id，则填当前环境的数字ID。Default Website也不要凭经验假设为1。</p><pre><code>SELECT website_id,code,name,is_default FROM store_website ORDER BY website_id;
SELECT store_id,code,website_id,is_active FROM store ORDER BY website_id,store_id;
SELECT email,website_id,COUNT(*) c FROM customer_entity GROUP BY email,website_id HAVING c&gt;1;</code></pre><h2>实际修复</h2><ul><li>检查Customer Account Sharing Options。按Website共享时，同一email可存在于不同website；全局共享时，导入到第二个website会触发重复邮箱而不是website错误。</li><li>先用两行CSV验证：一个新客户、一个更新客户。验证通过后再批量导入，并保留Import History与失败行文件。</li></ul><h2>怎样才算修好</h2><p>在目标Website前台分别执行登录、忘记密码和下单，后台客户记录的website_id、store_id与邮件域名均正确。</p><aside><p>绝不要用UPDATE把全部客户强行改到同一website；先确认账号共享策略和历史订单归属。</p></aside>]]></description>
      <pubDate>Mon, 16 Mar 2026 01:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单Extension Attribute保存后再次读取为空]]></title>
      <link>https://www.360magento.com/blog/order-extension-attribute-saved-but-read-empty/</link>
      <description><![CDATA[<p><strong>现象：</strong>下单时Extension Attribute里有值，订单也保存成功，但再次通过Repository或REST读取却变成空。字段必须同时打通写入、持久化和读回三条链路。</p>
<table>
<thead>
<tr><th>阶段</th><th>具体操作</th></tr>
</thead>
<tbody>
<tr>
<td>取证</td>
<td>确认extension_attributes.xml声明在Magento\Sales\Api\Data\OrderInterface，并完成setup:di:compile生成接口方法。</td>
</tr>
<tr>
<td>定位</td>
<td>在下单或Repository保存前把值落到明确的订单列或独立表；只setExtensionAttributes不会自动持久化。</td>
</tr>
<tr>
<td>修复</td>
<td>为OrderRepository的get/getList读回路径补充after插件，批量列表要一次加载映射，避免逐订单N+1查询。</td>
</tr>
<tr>
<td>复核</td>
<td>检查数据库列与Service Contract类型一致，分别测试新订单、旧订单空值、REST列表和单条接口。</td>
</tr>
</tbody>
</table>
<h3>可执行检查</h3>
<pre><code>rg -n 'OrderInterface|extension_attributes|OrderRepository' app/code/VendorSHOW COLUMNS FROM sales_order LIKE 'external_reference';bin/magento setup:di:compilebin/magento cache:clean config</code></pre>
<p><strong>通过标准：</strong>保存后Repository get、getList、REST与后台页面读取同一值，未设置的历史订单返回约定的空值。</p>]]></description>
      <pubDate>Wed, 11 Mar 2026 03:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2关联可配置子商品时报Child product attributes mismatch]]></title>
      <link>https://www.360magento.com/blog/configurable-child-attributes-mismatch/</link>
      <description><![CDATA[<p><strong>现象：</strong>通过REST或脚本关联子SKU时返回属性不匹配，不能跳过校验直接写catalog_product_super_link，否则前台组合会损坏。</p><table><thead><tr><th>阶段</th><th>具体操作</th></tr></thead><tbody><tr><td>取证</td><td>读取父商品catalog_product_super_attribute，列出全部超级属性；确认子商品Attribute Set包含的是同一个attribute_id。</td></tr><tr><td>定位</td><td>检查子商品默认范围属性值，可配置属性必须为Select且保存有效option_id，不能写显示标签。</td></tr><tr><td>修复</td><td>确认父子商品分配到兼容Website，子商品类型与启用状态符合要求。</td></tr><tr><td>复核</td><td>修复属性并保存子商品后，再调用ConfigurableProductLinkManagement或标准REST接口关联并重建相关索引。</td></tr></tbody></table><h3>可执行检查</h3><pre><code>SELECT product_id,attribute_id FROM catalog_product_super_attribute WHERE product_id=:parent_id;
SELECT entity_id,attribute_set_id,sku,type_id FROM catalog_product_entity WHERE sku IN ('PARENT','CHILD-1');</code></pre><p><strong>通过标准：</strong>父商品variants包含新子SKU，前台每个属性组合唯一，价格和可售状态均来自正确子商品。</p>]]></description>
      <pubDate>Tue, 10 Mar 2026 03:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2保存大分类时超时，URL Rewrite应该怎么处理？]]></title>
      <link>https://www.360magento.com/blog/large-category-save-timeout-url-rewrite/</link>
      <description><![CDATA[<p><strong>问题现象：</strong>分类挂了大量商品后，点击保存长时间转圈甚至504。提高max_execution_time只能延后失败，真正要定位保存请求卡在哪一段。</p><table><thead><tr><th>阶段</th><th>实际操作</th></tr></thead><tbody><tr><td>复现</td><td>保存前记录分类ID、关联商品数量、是否修改URL Key，以及请求开始时间。查看Nginx access、PHP-FPM slowlog和exception.log，用相同时间定位最后执行的方法。</td></tr><tr><td>取证</td><td>只改分类名称能成功、改URL Key失败，重点统计该分类现有url_rewrite数量并检查重复request_path；不要先批量删除全站重写。</td></tr><tr><td>修复</td><td>不改URL也超时，则检查请求是否提交了完整商品选择网格，以及自定义Observer是否在catalog_category_save_after再次调用save。移除递归保存，把批量关联改为Repository/资源模型的一次性更新。</td></tr><tr><td>回归</td><td>先在预发布复制该分类并验证修复。生产处理冲突重写时，只删除明确属于目标entity且可重新生成的记录，保留备份并重建catalog_url。</td></tr></tbody></table><h3>可直接执行的检查</h3><pre><code>SELECT COUNT(*) FROM catalog_category_product WHERE category_id=:category_id;
SELECT request_path,store_id,COUNT(*) c FROM url_rewrite WHERE entity_type='category' AND entity_id=:category_id GROUP BY request_path,store_id HAVING c&gt;1;
rg -n 'catalog_category_save_(before|after)|-&gt;save(' app/code
bin/magento indexer:reindex catalog_category_product catalog_product_category catalog_url</code></pre><p><strong>通过标准：</strong>分别保存名称、描述、URL Key和100个商品关联；每项都在代理超时前完成，前台旧URL按配置跳转，新URL返回200且无重复重写。</p><p>若必须修改上万商品关联，优先拆分后台操作或使用受控批处理，不要让一个HTTP请求承担全部工作。</p>]]></description>
      <pubDate>Mon, 09 Mar 2026 03:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL分类翻页时商品重复或遗漏怎么修复？]]></title>
      <link>https://www.360magento.com/blog/graphql-category-pagination-duplicate-missing-products/</link>
      <description><![CDATA[<blockquote>
<p>分类第一页和第二页出现同一SKU，或者翻到后面漏商品。常见原因不是pageSize，而是排序字段不唯一或翻页期间索引结果发生变化。</p>
</blockquote>
<h2>固定复现范围</h2>
<p>保存每页返回的SKU、position和排序字段，使用同一Store、客户组、筛选及search参数复现。</p>
<h2>定位真实原因</h2>
<p>自定义Collection排序时追加entity_id等稳定的唯一次序；只按相同价格或相同position排序会导致数据库任意换序。</p>
<h2>执行修复</h2>
<p>确认客户端没有把currentPage从0开始，也没有在筛选变化后继续使用旧页码和旧结果。</p>
<h2>恢复后处理</h2>
<p>大量商品更新期间完成相关分类与价格索引后再做一致性验收，缓存键要包含排序和筛选变量。</p>
<pre><code>query { products(filter:{category_id:{eq:"12"}},pageSize:20,currentPage:2,sort:{position:ASC}) { total_count items { sku } page_info { current_page total_pages } } }</code></pre>
<h2>回归测试</h2>
<p>固定数据下连续读取全部页，SKU集合无重复无遗漏，总数与分类索引一致；同分值商品顺序保持稳定。</p>]]></description>
      <pubDate>Wed, 04 Mar 2026 02:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2客户Token刚生成就提示The current customer is not authorized]]></title>
      <link>https://www.360magento.com/blog/graphql-customer-token-immediately-unauthorized/</link>
      <description><![CDATA[<blockquote><p>generateCustomerToken成功返回Token，紧接着查询customer却提示未授权。先确认第二个请求真的把同一个Token发送到了Magento，而不是先延长Token寿命。</p></blockquote><h2>固定复现范围</h2><p>核对请求头为Authorization: Bearer TOKEN，Bearer与Token之间只有一个空格，不能包含引号或响应字段名。</p><h2>定位真实原因</h2><p>比较生成和使用Token时的域名、环境及Store Header；测试站Token不能在生产站使用。</p><h2>执行修复</h2><p>确认反向代理保留Authorization头，customer与customerCart响应不得进入公共缓存。</p><h2>恢复后处理</h2><p>确认客户账号启用且Website范围正确，修复后重新生成Token，不继续使用已吊销或错误环境的旧Token。</p><pre><code>curl -sS https://shop.example/graphql -H 'Store: default' -H 'Authorization: Bearer ***' -H 'Content-Type: application/json' --data '{"query":"{customer{email firstname}}"}'</code></pre><h2>回归测试</h2><p>同一Token可读取customer与customerCart；去掉头、错误Store或吊销Token时明确失败，且客户响应不会串会话。</p>]]></description>
      <pubDate>Tue, 03 Mar 2026 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Bundle商品选择数量后Magento 2价格不更新]]></title>
      <link>https://www.360magento.com/blog/bundle-option-qty-price-not-refreshing/</link>
      <description><![CDATA[<blockquote><p>Bundle详情页能勾选选项，但修改数量后总价不变。先区分后端选项价格是否正确，还是浏览器没有重新计算。</p></blockquote><h2>定位与修复记录</h2><h3>1. 固定复现范围</h3><p>在页面源代码中找到 bundleConfig，确认选项ID、selectionID、基础价格和canApplyMsrp等数据存在。若这里价格已错，先重建 catalog_product_price 并检查子商品价格。</p><h3>2. 确认真实原因</h3><p>bundleConfig正确时，在Console观察数量输入框是否触发change。自定义主题若删除 data-selector、改写name或把输入框复制成另一个节点，Magento_Bundle/js/price-bundle就找不到原字段。</p><h3>3. 执行修复</h3><p>恢复核心模板中的data-role和name结构；自定义JS应触发标准change事件，不要直接修改页面上的价格文本。确认priceBox只初始化一次，避免两个组件互相覆盖。</p><h3>4. 恢复后处理</h3><p>清理目标主题静态目录并按实际语言重新部署，随后清FPC。不要只在developer模式下验证，因为生产合并后的RequireJS路径可能不同。</p><pre><code>bin/magento indexer:reindex catalog_product_price
find app/design app/code -path '*Magento_Bundle*' -type f
rg -n 'price-bundle|bundleConfig|data-selector' app/design app/code
bin/magento setup:static-content:deploy -f zh_CN en_US</code></pre><h2>验收清单</h2><ul><li>依次测试单选、多选、可输入数量和默认数量；页面价、加入购物车后的item price以及订单金额必须一致。</li><li>固定价Bundle与动态价Bundle走的价格数据不同，排查时先确认商品Price Type。</li></ul>]]></description>
      <pubDate>Mon, 02 Mar 2026 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL自定义字段能查询却无法通过Mutation保存]]></title>
      <link>https://www.360magento.com/blog/graphql-custom-field-query-works-mutation-not-save/</link>
      <description><![CDATA[<p>GraphQL查询能返回自定义字段，但Mutation提交后数据库没有变化。Resolver收到值并不代表值已经进入Service Contract和保存链。</p>
<h2>实际处理步骤</h2>
<ol>
<li>在浏览器Network或GraphQL日志中确认变量类型、字段名与schema完全一致，先排除前端根本没提交。</li>
<li>给输入对象配置对应Input类型，在Resolver中把值写入Data Interface或Extension Attribute，不能只修改临时数组。</li>
<li>检查extension_attributes.xml、接口getter/setter以及Repository保存插件；保存后重新从Repository读取，不直接依赖Model状态。</li>
<li>清GraphQL与config缓存并重新编译，分别测试新增、修改、空值清除和权限不足。</li>
</ol>
<h3>检查命令</h3>
<pre><code>rg -n 'type .*Input|extension_attributes|setExtensionAttributes' app/code/Vendorbin/magento setup:di:compilebin/magento cache:clean config graphql</code></pre>
<h2>验证结果</h2>
<p>Mutation响应与再次查询、REST读取及数据库结果一致，空值和非法值都有明确行为。</p>]]></description>
      <pubDate>Wed, 25 Feb 2026 01:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL加入可配置商品时报Selected option is not valid]]></title>
      <link>https://www.360magento.com/blog/graphql-configurable-selected-option-invalid/</link>
      <description><![CDATA[<p>调用addProductsToCart时商品存在，却返回Selected option is not valid。这个错误通常发生在购物车写入前，说明选项UID与当前父商品、Store或变体不匹配。</p><h2>实际处理步骤</h2><ol><li>使用与购物车相同的Store Header查询父SKU，从configurable_options.values读取uid和value_index，不要把attribute_id或option_id自行编码。</li><li>selected_options必须包含组成真实子SKU所需的全部超级属性；只传颜色、不传尺码时无法解析唯一变体。</li><li>属性选项重建、环境迁移或Store切换后清除客户端保存的旧UID，再用本次products查询返回值提交。</li><li>自定义选项应使用其自己的selected_options或entered_options UID，不能混入可配置属性UID。</li></ol><h3>检查命令</h3><pre><code>query { products(filter:{sku:{eq:"CONF-1"}}){items{... on ConfigurableProduct{configurable_options{attribute_code values{uid label value_index}} variants{product{sku}}}}}}</code></pre><h2>验证结果</h2><p>有效组合可加入购物车且SKU对应正确子商品；缺属性、禁用子SKU和其他Store的旧UID必须明确失败。</p>]]></description>
      <pubDate>Tue, 24 Feb 2026 01:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2可配置商品有库存但色板仍显示禁用如何解决？]]></title>
      <link>https://www.360magento.com/blog/configurable-swatch-disabled-with-stock/</link>
      <description><![CDATA[<p>后台看到子商品 quantity 大于0，前台颜色仍灰掉，不能只重建价格索引。色板是否可选取决于当前 Website 对应 Stock 中每个简单商品的可售状态。</p><h2>按顺序解决</h2><ol><li>先记录问题页面的 Store、Website、父SKU和被禁用的子SKU。确认子商品已启用、分配到同一 Website，并且必选属性值没有为空。</li><li>检查 Website 绑定的 stock_id，再核对子SKU所在 Source 是否属于该 Stock、Source Item 的 status 是否为1。数量大于0但 status 为0仍会被判为不可售。</li><li>查询 reservation 汇总；若存在取消或失败订单留下的负数，使用官方 list-inconsistencies 输出确认后再创建补偿，不要直接删除 inventory_reservation。</li><li>修复来源或 reservation 后，只重建 inventory、configurable 与价格相关索引并清理 block/FPC；随后重新请求产品 JSON 配置，确认该 option 对应的 salableProducts 已恢复。</li></ol><h3>检查命令</h3><pre><code>SELECT stock_id,website_id FROM inventory_stock_sales_channel WHERE website_id=:website_id;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku IN ('CHILD-RED-S','CHILD-RED-M');
SELECT stock_id,sku,SUM(quantity) reserved FROM inventory_reservation WHERE sku='CHILD-RED-S' GROUP BY stock_id,sku;
bin/magento inventory:reservation:list-inconsistencies -r
bin/magento indexer:reindex inventory catalog_product_price</code></pre><h2>验证结果</h2><p>用同一Store分别测试有货、无货两个子SKU；有货色板可选并能加入购物车，无货项仍保持禁用。再切换另一个Website，确认库存范围没有串站。</p><p><strong>注意：</strong>如果数据库状态正确但只有某台Web节点异常，检查各节点 generated、静态资源版本和FPC是否一致。</p>]]></description>
      <pubDate>Mon, 23 Feb 2026 01:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2定时索引只更新部分Indexer如何解决？]]></title>
      <link>https://www.360magento.com/blog/scheduled-index-updates-only-some-indexers/</link>
      <description><![CDATA[<p><strong>现象：</strong>价格索引会自动更新，Catalog Search或库存索引却停在旧版本。每个Indexer都有独立模式、MView订阅和状态，不能用“Cron正常”概括全部。</p><p><strong>判断：</strong>列出未更新的Indexer，确认它们是schedule模式；再查对应changelog是否增长以及indexer_update_all_views最近一次运行结果。</p><pre><code>bin/magento indexer:show-mode
bin/magento indexer:status</code></pre><p><strong>复核：</strong>某个Indexer异常时，Cron可能继续处理其他任务，形成只更新部分的现象。修复后修改一条只影响该Indexer的测试数据，观察version_id推进。</p><h3>完成标准</h3><p>原问题可以稳定消失，相关边界场景仍能正常工作，而且不需要依赖手工清缓存或重复执行命令。</p>]]></description>
      <pubDate>Thu, 19 Feb 2026 08:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台验证商品属性时返回302]]></title>
      <link>https://www.360magento.com/blog/admin-product-attribute-validate-302-session/</link>
      <description><![CDATA[<blockquote><p>点击保存属性没有明确报错，Network里validate请求返回302并最终得到后台登录HTML。表单期待JSON，所以页面看起来像没有反应。</p></blockquote><h2>处理记录</h2><p>检查重定向目标与Admin Cookie的Domain、Path、Secure和SameSite，并对比主表单请求是否使用同一后台路径。反向代理协议识别错误也可能造成域名跳转。</p><p>修复后validate应直接返回JSON，不经过登录页。再保存一个文本属性和一个下拉属性，确认两种验证路径都正常。</p><p>多节点站点还应在不同Web节点各请求一次，确认代码、缓存与共享文件一致；单台节点恢复不能代表整个站点已经恢复。</p>]]></description>
      <pubDate>Wed, 18 Feb 2026 01:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API调用成功但响应字段全部为空]]></title>
      <link>https://www.360magento.com/blog/rest-api-success-empty-response-fields/</link>
      <description><![CDATA[<p>接口返回200且数组长度正确，但对象字段都是空。数据库查询可能正常，丢失发生在实体转换为Service Contract对象的过程。</p><ol><li>序列化器根据getter生成字段。实现类若直接写成员变量，getter却从DataObject的另一个key读取，最终就是空；还要确认工厂创建的是正确实现类。</li><li>比较Repository原始行、DTO调用setter后和返回前getter三个位置。先让一个字段跑通，再增加嵌套对象与数组。</li></ol><h3>检查命令</h3><pre><code>public function getCode();
public function setCode($code);</code></pre><ul><li>先在测试环境复现；</li><li>每次只改一个变量；</li><li>恢复后再检查日志没有产生新的异常。</li></ul>]]></description>
      <pubDate>Tue, 17 Feb 2026 07:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2结账页面一直停在支付步骤]]></title>
      <link>https://www.360magento.com/blog/checkout-stuck-payment-step-loader/</link>
      <description><![CDATA[<p>点击下一步后加载动画不消失，支付方式没有出现。先查看Network中的最后一个请求，而不是先重装支付模块。</p><table><thead><tr><th>阶段</th><th>检查内容</th></tr></thead><tbody><tr><td>定位</td><td>shipping-information返回400或500时查地址、配送方式和后端异常；请求200但JS报错时查响应结构、mixin与Knockout；根本没请求则查前端校验和点击事件。</td></tr><tr><td>验证</td><td>第三方mixin覆盖setShippingInformation却不返回原Promise，也会让loader一直存在。修复后测试访客、登录客户、虚拟和实体购物车。</td></tr></tbody></table><h3>避免误判</h3><p>测试时固定同一个Store、客户状态和输入数据，并记录修改前后的请求与数据库结果，避免把作用域差异当成随机故障。</p>]]></description>
      <pubDate>Mon, 16 Feb 2026 02:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL自定义筛选返回空结果如何排查？]]></title>
      <link>https://www.360magento.com/blog/graphql-custom-filter-empty-results/</link>
      <description><![CDATA[<p>不带筛选时products能返回商品，加上自定义字段后items变空。先用同一个Store Header和最小查询确认商品本身可见。</p><h2>排查重点</h2><p>检查Schema filter input、字段到真实attribute_code的映射，以及Filter Processor是否向集合加入正确条件。Dropdown还要分清传选项文本还是option_id。</p><pre><code>{ products(filter: { vendor_code: { eq: 'A01' } }) { total_count items { sku name } } }</code></pre><p>先在集合SQL中确认条件，再测试eq、in与match。不要返回全部商品后用PHP过滤，这会破坏分页并拖慢查询。</p><p>验收时要重新打开后台页面，并从前台或接口读取一次最终数据；只看到保存成功提示，不能证明缓存、索引和展示层已经同步。</p>]]></description>
      <pubDate>Fri, 13 Feb 2026 06:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[删除商品后唯一属性值仍提示已被占用]]></title>
      <link>https://www.360magento.com/blog/deleted-product-unique-attribute-value-occupied/</link>
      <description><![CDATA[<p><strong>现象：</strong>旧商品已删除，新商品使用相同序列号时仍提示该值必须唯一。先确认旧商品是彻底删除、被归档，还是仅禁用。</p><p><strong>判断：</strong>查询EAV值表是否仍有对应实体。若记录存在，检查删除事务与外键；若不存在，检查唯一校验插件是否维护自己的索引或缓存。</p><pre><code>SELECT e.entity_id, e.sku, v.store_id, v.value FROM catalog_product_entity_varchar v JOIN catalog_product_entity e ON e.entity_id=v.entity_id WHERE v.attribute_id=:attribute_id AND v.value='SERIAL-001';</code></pre><p><strong>复核：</strong>不要直接关闭unique标记录入重复值。修复数据和删除流程后，完整验证创建、删除、重新使用同一值。</p><h3>完成标准</h3><p>原问题可以稳定消失，相关边界场景仍能正常工作，而且不需要依赖手工清缓存或重复执行命令。</p>]]></description>
      <pubDate>Thu, 12 Feb 2026 03:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台编辑商品提示无权修改Design Attributes]]></title>
      <link>https://www.360magento.com/blog/admin-product-design-attributes-permission-error/</link>
      <description><![CDATA[<blockquote><p>管理员只改商品名称，保存时却提示无权修改Design Attributes，因为表单同时提交了页面布局、主题等设计字段。</p></blockquote><h2>处理记录</h2><p>检查请求中的custom_design、page_layout、custom_layout_update与设计日期。用户不应修改时，字段应禁用并避免提交；业务确需修改时才补充最小必要ACL。</p><p>第三方表单Modifier也可能把隐藏字段重新加入payload。用管理员和受限角色分别保存同一商品，确认普通字段可改而设计字段仍受控。</p><p>多节点站点还应在不同Web节点各请求一次，确认代码、缓存与共享文件一致；单台节点恢复不能代表整个站点已经恢复。</p>]]></description>
      <pubDate>Wed, 11 Feb 2026 08:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级Magento 2后Checkout读取不到quoteData]]></title>
      <link>https://www.360magento.com/blog/checkout-config-quotedata-missing-after-upgrade/</link>
      <description><![CDATA[<p>升级后控制台报window.checkoutConfig.quoteData is undefined，结账页停在加载状态。quoteData来自Checkout Config Provider合并结果，不是静态JS变量。</p><ol><li>先查看HTML中的window.checkoutConfig是否包含quoteData。服务端已缺失时，检查自定义ConfigProvider或Plugin是否用自己的数组替换原结果，以及旧主题layout是否删除核心block。</li><li>HTML中有quoteData但JS读取不到，再查脚本执行顺序与CSP。修复后测试空购物车、访客购物车和登录客户。</li></ol><h3>检查命令</h3><pre><code>grep -Rni 'getConfig' app/code/*/*/Plugin app/code/*/*/Model</code></pre><ul><li>先在测试环境复现；</li><li>每次只改一个变量；</li><li>恢复后再检查日志没有产生新的异常。</li></ul>]]></description>
      <pubDate>Tue, 10 Feb 2026 01:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2清理Catalog Images Cache后前台图片消失]]></title>
      <link>https://www.360magento.com/blog/catalog-image-cache-clean-images-missing/</link>
      <description><![CDATA[<p>清理Catalog Images Cache后大量商品图404。正常情况下，请求会从pub/media/catalog/product中的原图重新生成派生文件。</p><pre><code>namei -l pub/media/catalog/product/a/b/image.jpg
df -h pub/media</code></pre><table><thead><tr><th>阶段</th><th>检查内容</th></tr></thead><tbody><tr><td>定位</td><td>原图不存在时从备份或对象存储恢复；多节点环境确认各节点共享media；原图存在却不生成时检查PHP-FPM权限、图像库、磁盘空间和错误日志。</td></tr><tr><td>验证</td><td>选择不同尺寸与格式的三张商品图访问，确认缓存目录重新出现，并检查CDN没有继续缓存旧404。不要把整个media长期设成777。</td></tr></tbody></table><h3>避免误判</h3><p>测试时固定同一个Store、客户状态和输入数据，并记录修改前后的请求与数据库结果，避免把作用域差异当成随机故障。</p>]]></description>
      <pubDate>Mon, 09 Feb 2026 06:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[可配置商品点击Edit Configurations后无法保存]]></title>
      <link>https://www.360magento.com/blog/configurable-edit-configurations-save-failed/</link>
      <description><![CDATA[<p>配置向导能走完，最终保存却返回通用错误。先从Network与日志找到具体SKU或字段，再把组合缩小到一个颜色和两个尺码。</p><h2>排查重点</h2><p>小组合成功而大组合失败，检查请求体大小、执行时间和重复选项；最小组合也失败，则检查超级属性是否为Dropdown且允许用于可配置商品。</p><p>若异常出现在图片角色保存，取消批量应用图片再试。修复后核对子商品数量、关联表与前台选项，不只看父商品是否保存成功。</p><p>验收时要重新打开后台页面，并从前台或接口读取一次最终数据；只看到保存成功提示，不能证明缓存、索引和展示层已经同步。</p>]]></description>
      <pubDate>Fri, 06 Feb 2026 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[保存商品时Magento 2频繁清空Full Page Cache]]></title>
      <link>https://www.360magento.com/blog/product-save-invalidates-full-page-cache-often/</link>
      <description><![CDATA[<p><strong>现象：</strong>每次保存一个商品后全站首屏都变慢，Varnish命中率瞬间下降。商品变更需要失效相关页面，但不应等同于清空全部FPC。</p><p><strong>判断：</strong>检查自定义Observer是否调用flush或cleanType，以及Block的getIdentities是否返回过宽的全局标签。所有URL同时MISS通常是全量flush，只有商品和分类页MISS多为正常标签失效。</p><pre><code>rg -n 'cacheManager-&gt;flush|cleanType|getIdentities' app/code</code></pre><p><strong>复核：</strong>记录保存前后的缓存标签与BAN请求，修正扩展后比较命中率。不要通过禁止商品变更失效缓存来换取命中率。</p><h3>完成标准</h3><p>原问题可以稳定消失，相关边界场景仍能正常工作，而且不需要依赖手工清缓存或重复执行命令。</p>]]></description>
      <pubDate>Thu, 05 Feb 2026 07:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2索引设为Update by Schedule后长期不更新]]></title>
      <link>https://www.360magento.com/blog/indexer-update-schedule-not-running/</link>
      <description><![CDATA[<blockquote><p>索引器显示Ready且模式为Update by Schedule，商品改价后前台仍不更新。Ready不代表MView增量链路正常推进。</p></blockquote><h2>处理记录</h2><p>检查mview_state.version_id、对应changelog、数据库触发器和indexer_update_all_views任务。changelog有数据但version_id不动，重点看index Cron与锁。</p><pre><code>bin/magento indexer:show-mode
bin/magento cron:run --group index
bin/magento indexer:status</code></pre><p>恢复后只修改一个测试商品，观察增量记录是否被消费。一次全量reindex成功不能证明定时增量已经修好。</p><p>多节点站点还应在不同Web节点各请求一次，确认代码、缓存与共享文件一致；单台节点恢复不能代表整个站点已经恢复。</p>]]></description>
      <pubDate>Wed, 04 Feb 2026 01:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API报Property does not have corresponding setter]]></title>
      <link>https://www.360magento.com/blog/rest-property-no-corresponding-setter/</link>
      <description><![CDATA[<p>请求中的delivery_note会被映射到setDeliveryNote。接口只有getter、方法拼写不同或参数指向另一个DTO时，会在InputParamsResolver阶段失败。</p><ol><li>实现类必须实现同名getter和setter，di.xml的preference也要指向该实现。对象数组还需在DocBlock中声明正确接口类型。</li><li>先用只含必填字段的请求跑通，再逐个增加字段。不要在控制器中静默忽略未知字段，否则客户端契约错误会进入业务层。</li></ol><h3>检查命令</h3><pre><code>public function getDeliveryNote();
public function setDeliveryNote($value);</code></pre><ul><li>先在测试环境复现；</li><li>每次只改一个变量；</li><li>恢复后再检查日志没有产生新的异常。</li></ul>]]></description>
      <pubDate>Tue, 03 Feb 2026 05:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Swagger显示Failed to load API definition如何修复？]]></title>
      <link>https://www.360magento.com/blog/swagger-failed-load-api-definition-schema/</link>
      <description><![CDATA[<p>Swagger UI只显示Failed to load API definition时，直接请求rest/all/schema通常能看到真正的500异常或报告ID。</p><pre><code>curl -sS https://shop.example/rest/all/schema -H 'Authorization: Bearer ***'</code></pre><table><thead><tr><th>阶段</th><th>检查内容</th></tr></thead><tbody><tr><td>定位</td><td>常见原因包括webapi.xml指向不存在的方法、接口类型不是有效Service Contract、DocBlock与PHP类型冲突，以及第三方模块生成无法序列化的schema。</td></tr><tr><td>验证</td><td>修改接口声明后清config缓存，确认schema返回完整JSON，再打开Swagger。不要只修改前端Swagger页面掩盖后端错误。</td></tr></tbody></table><h3>避免误判</h3><p>测试时固定同一个Store、客户状态和输入数据，并记录修改前后的请求与数据库结果，避免把作用域差异当成随机故障。</p>]]></description>
      <pubDate>Mon, 02 Feb 2026 02:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品属性已加入Attribute Set，Magento 2仍无法保存属性值]]></title>
      <link>https://www.360magento.com/blog/attribute-in-set-value-not-saving-eav-cache/</link>
      <description><![CDATA[<p>Data Patch创建属性并加入Attribute Set，后台也能看到字段，但保存后值为空。页面可见并不代表运行时EAV元数据已经刷新。</p><h2>排查重点</h2><p>确认属性关联落在商品实际使用的Attribute Set，而不是Default Set；清理EAV和config缓存，再检查backend type与输入值是否匹配。</p><pre><code>SELECT attribute_set_id, attribute_group_id, attribute_id FROM eav_entity_attribute WHERE attribute_id=:attribute_id;</code></pre><p>不要在每次商品保存时动态加入属性。结构变更应在Patch中完成。用default scope和一个Store View各保存一次，可快速识别作用域问题。</p><p>验收时要重新打开后台页面，并从前台或接口读取一次最终数据；只看到保存成功提示，不能证明缓存、索引和展示层已经同步。</p>]]></description>
      <pubDate>Fri, 30 Jan 2026 08:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级Magento 2后Checkout无法加载shipping模板]]></title>
      <link>https://www.360magento.com/blog/checkout-failed-load-shipping-template-after-upgrade/</link>
      <description><![CDATA[<p><strong>现象：</strong>升级后结账页空白，控制台出现Failed to load Magento_Checkout/shipping template。这不是运费配置问题，而是Knockout模板没有加载。</p><p><strong>判断：</strong>从Network查看失败请求是404、403还是返回HTML。若路径落在自定义主题，检查旧版本复制的web/template/shipping.html；再核对RequireJS map和mixin。</p><pre><code>find app/design app/code -path '*Magento_Checkout*shipping*.html'
bin/magento setup:static-content:deploy -f zh_CN en_US</code></pre><p><strong>复核：</strong>生产模式按实际locale重新部署，并确保所有Web节点使用同一release。修复后确认模板返回正确内容，再测试访客和登录客户。</p><h3>完成标准</h3><p>原问题可以稳定消失，相关边界场景仍能正常工作，而且不需要依赖手工清缓存或重复执行命令。</p>]]></description>
      <pubDate>Thu, 29 Jan 2026 03:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2结账提示The shipping method is missing如何处理？]]></title>
      <link>https://www.360magento.com/blog/checkout-shipping-method-is-missing-fix/</link>
      <description><![CDATA[<blockquote><p>配送步骤已选中某个方式，点击下单仍报The shipping method is missing。不能只看页面状态，Magento最终验证的是Quote Shipping Address里的shipping_method。</p></blockquote><h2>处理记录</h2><p>修改邮编、切换账单地址或应用优惠码都会重新收集rates。第三方承运商若在此时超时，旧方式从rates消失，前端却可能仍显示选中。</p><pre><code>SELECT country_id, region_id, postcode, shipping_method FROM quote_address WHERE quote_id=:quote_id AND address_type='shipping';</code></pre><p>记录carrier code、method code与重算前后的rate列表。修复后依次测试修改地址、切换币种和应用优惠码再下单。</p><p>多节点站点还应在不同Web节点各请求一次，确认代码、缓存与共享文件一致；单台节点恢复不能代表整个站点已经恢复。</p>]]></description>
      <pubDate>Wed, 28 Jan 2026 06:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台无法删除商品图片角色]]></title>
      <link>https://www.360magento.com/blog/product-image-role-cannot-remove-store-scope/</link>
      <description><![CDATA[<p>商品图片从媒体库移除后，保存时仍提示被角色使用，通常是某个Store View还保留Base、Small或Thumbnail覆盖值。</p><ol><li>先在All Store Views记录三个角色，再逐个检查子范围；把目标范围角色改为No Image后保存，最后删除媒体记录并重建图片缓存。</li><li>不要直接从pub/media删除文件。数据库引用仍在时，后台会继续认为图片存在，前台还可能产生404。批量操作前先用一个SKU验证。</li></ol><ul><li>先在测试环境复现；</li><li>每次只改一个变量；</li><li>恢复后再检查日志没有产生新的异常。</li></ul>]]></description>
      <pubDate>Tue, 27 Jan 2026 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2商品保存时报Unique constraint violation found]]></title>
      <link>https://www.360magento.com/blog/product-save-unique-constraint-eav-duplicate/</link>
      <description><![CDATA[<p>错误文本本身信息有限，真正有用的是异常中的表名、索引名和Duplicate entry值。先完整保存异常SQL，不要看到1062就随机删除记录。</p><pre><code>SELECT entity_id, attribute_id, store_id, COUNT(*) c FROM catalog_product_entity_varchar GROUP BY entity_id, attribute_id, store_id HAVING c &gt; 1;</code></pre><table><thead><tr><th>阶段</th><th>检查内容</th></tr></thead><tbody><tr><td>定位</td><td>冲突在商品主表时检查序列和迁移数据；冲突在EAV值表时检查entity、attribute、store组合；冲突在媒体表时检查图片关联是否被重复插入。</td></tr><tr><td>验证</td><td>若数据库没有历史重复行，检查自定义Observer是否在一次请求里再次调用商品保存。修正递归保存后，用新商品、旧商品和含图片商品分别验证。</td></tr></tbody></table><h3>避免误判</h3><p>测试时固定同一个Store、客户状态和输入数据，并记录修改前后的请求与数据库结果，避免把作用域差异当成随机故障。</p>]]></description>
      <pubDate>Mon, 26 Jan 2026 07:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2商品属性保存后自动恢复原值如何解决？]]></title>
      <link>https://www.360magento.com/blog/product-attribute-save-reverts-old-value/</link>
      <description><![CDATA[<p>先确认修改落在哪个范围。属性配置通常是全局数据，商品属性值则可能按Website或Store View保存。切换到目标范围，检查“使用默认值”是否仍被勾选。</p><h2>排查重点</h2><p>若数据库值刚保存就被改回，检查保存事件、Repository Plugin和同步模块；数据库已是新值但页面显示旧值，则清理EAV与配置缓存，并确认各后台节点使用同一缓存。</p><pre><code>SELECT attribute_id, attribute_code, is_global FROM catalog_eav_attribute JOIN eav_attribute USING(attribute_id) WHERE attribute_code='vendor_code';</code></pre><p>用一个无第三方插件的测试属性复现，再比较系统属性和自定义属性。这样能区分缓存、作用域与扩展代码问题。</p><p>验收时要重新打开后台页面，并从前台或接口读取一次最终数据；只看到保存成功提示，不能证明缓存、索引和展示层已经同步。</p>]]></description>
      <pubDate>Fri, 23 Jan 2026 02:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[同一SKU在不同Store View使用不同URL Key]]></title>
      <link>https://www.360magento.com/blog/product-url-key-store-view-scope-boundary/</link>
      <description><![CDATA[<p>英文店希望使用 <code>red-shirt</code>，德文店希望使用 <code>rotes-hemd</code>。后台字段看似保存成功，前台却仍跳到默认 URL。</p><h2>先看属性作用域与保存范围</h2><p>切到目标 Store View，取消“使用默认值”后再保存 URL Key。若导入脚本总在 default scope 写入，它会覆盖不到店铺级值；反过来，错误的 store_id 也会产生看似存在却永远不被当前店铺读取的数据。</p><pre><code>SELECT store_id, request_path, target_path, redirect_type
FROM url_rewrite
WHERE entity_type='product' AND entity_id=:product_id
ORDER BY store_id, request_path;</code></pre><p>最终 URL 还受到商品 URL 后缀、是否包含分类路径、历史重定向和同店铺唯一性限制。不要只查 EAV 属性值。</p><h2>验收矩阵</h2><ul><li>直接访问两个语言的新 URL 都返回 200；</li><li>旧 URL 只做一次预期 301；</li><li>切换语言不会落回默认 Store；</li><li>canonical 指向当前语言的规范地址。</li></ul><p>若批量改大量 URL Key，应先用少量 SKU 生成重写并检查冲突，再扩大范围。</p>]]></description>
      <pubDate>Thu, 22 Jan 2026 02:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2价格索引临时表锁住商品保存]]></title>
      <link>https://www.360magento.com/blog/price-index-temp-table-lock-product-save/</link>
      <description><![CDATA[<p>后台保存商品一直等待，<code>indexer:status</code> 全部是 Ready。MySQL 却显示请求在等待价格索引临时表的 metadata lock。</p><pre><code>SHOW FULL PROCESSLIST;
SELECT trx_id, trx_started, trx_mysql_thread_id, trx_query
FROM information_schema.innodb_trx
ORDER BY trx_started;</code></pre><p>Ready 只说明 Magento 记录的索引状态，不代表某次被中断的 CLI、导入脚本或数据库会话已经提交。先定位最老事务对应的应用进程、主机和操作，再决定是否终止；不要看到 lock 就批量 kill 连接。</p><p>常见起因包括手工脚本开启事务后异常退出、部署时同时运行全量 reindex，以及监控工具长时间保持未提交查询。处理持锁会话后，单独执行价格索引并观察是否正常完成。</p><p>预防措施是给发布流程加互斥锁，避免商品批量更新与全量索引重叠；自定义脚本使用 try/finally 回滚。复测除了保存速度，还要检查价格、分组价和网站范围价格。</p>]]></description>
      <pubDate>Wed, 21 Jan 2026 08:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[GraphQL购物车更新后仍显示旧数据]]></title>
      <link>https://www.360magento.com/blog/graphql-mutation-success-stale-cart-client-cache/</link>
      <description><![CDATA[<p>修改购物车数量的 mutation 返回成功，响应中 qty 已是 3，刷新页面后也正确；只有当前界面仍显示 1。这个证据把范围缩到前端状态。</p><p>先看客户端缓存如何识别 CartItem。若查询返回的对象缺少稳定 ID，或 type policy 使用了错误 keyFields，Apollo 可能把新对象与旧对象当成两条记录。mutation 也可能没有返回页面实际读取的字段，导致缓存无法覆盖。</p><h3>三种更新方式</h3><ul><li>让 mutation 返回购物车组件需要的完整字段；</li><li>在 update 函数中按稳定标识更新缓存；</li><li>对关键操作执行一次精确 refetch，而不是清空全部缓存。</li></ul><p>若 mutation 响应本身就是旧数据，再回到 Magento Resolver、Cart ID 和后端缓存排查。修复后连续执行加数量、删商品、应用优惠码，不刷新页面也应与服务端结果一致。</p>]]></description>
      <pubDate>Tue, 20 Jan 2026 05:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台日期筛选少一天]]></title>
      <link>https://www.360magento.com/blog/admin-grid-date-filter-one-day-off/</link>
      <description><![CDATA[<p>筛选“1月10日到1月10日”少了当天早上的订单，而数据库记录明明存在。把 MySQL 时区改成本地只会让核心表和扩展表更加混乱。</p><h2>画出同一时间的三种表示</h2><ol><li>数据库字段：通常为 UTC；</li><li>筛选输入：管理员看到的本地日期；</li><li>SQL 边界：转换后的 UTC 起止时间。</li></ol><pre><code>SELECT @@global.time_zone, @@session.time_zone, UTC_TIMESTAMP(), NOW();</code></pre><p>自定义 UI Component 列若同时设置 date filter，又在 collection 的 addFieldToFilter 中手工减 8 小时，就会重复转换。结束日期还应覆盖本地当天的完整范围，而不是当天 00:00:00。</p><table><thead><tr><th>测试</th><th>必须命中</th></tr></thead><tbody><tr><td>当天00:00本地时间</td><td>第一条边界记录</td></tr><tr><td>当天23:59:59</td><td>最后一条边界记录</td></tr><tr><td>夏令时切换日</td><td>按实际时区偏移换算</td></tr></tbody></table>]]></description>
      <pubDate>Mon, 19 Jan 2026 01:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Page Builder保存后正文出现多余反斜杠]]></title>
      <link>https://www.360magento.com/blog/page-builder-content-extra-backslashes/</link>
      <description><![CDATA[<p>第一次保存正常，第二次编辑后正文出现 <code>&quot;</code>、<code>\</code>，每保存一次反斜杠继续增加。这种“递增”是重复编码的典型信号。</p><pre><code>SELECT page_id, LENGTH(content), LEFT(content, 300)
FROM cms_page
WHERE page_id=:page_id;</code></pre><p>先判断多余字符已经写进数据库，还是仅在后台编辑器显示。若数据库内容每次都变长，搜索自定义 CMS 保存 Plugin、Observer 和导入脚本中的 <code>addslashes</code>、<code>json_encode</code>、手工实体转换。</p><p>Page Builder 自己负责其内容格式。扩展如果先把 HTML 变成 JSON 字符串，再交给已经会序列化的层，就会编码两次。修复时从原始备份恢复一份页面，在进入 repository 前后各比较一次内容；不要对线上全部页面执行不加条件的 <code>stripslashes</code>，合法的代码示例也可能被破坏。</p><p>验收采用“打开—保存—再打开—再保存”两轮，数据库内容长度与前台渲染应保持稳定。</p>]]></description>
      <pubDate>Fri, 16 Jan 2026 07:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Checkout返回400 Bad Request]]></title>
      <link>https://www.360magento.com/blog/checkout-form-key-present-still-400/</link>
      <description><![CDATA[<p>Network 面板能看到 <code>form_key</code>，所以开发者认定校验没问题。但服务端校验的不是“有没有这个字段”，而是它是否与当前 Session 中的值一致。</p><h2>对比请求链路</h2><ul><li>加载结账页时使用的域名与提交域名是否一致；</li><li>POST 是否带上同一个 Session Cookie；</li><li>结账 HTML 是否被 CDN 或错误的 Full Page Cache 缓存；</li><li>登录、切换店铺后页面里的 form_key 是否已刷新。</li></ul><p>不要把完整 Cookie 或 token 贴进日志。可以在测试环境只记录 form_key 的哈希前几位和 Session ID 哈希，用来判断两次请求是否属于同一会话。</p><p>如果站点为了“恢复下单”直接关闭 Checkout Form Key Validation，风险会被转移而不是消失。应修正缓存排除、Cookie Domain 或前端取值逻辑。最后在访客、登录客户、跨 Store 切换和长时间停留后提交四种场景复测。</p>]]></description>
      <pubDate>Thu, 15 Jan 2026 02:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Source有库存但商品不可售]]></title>
      <link>https://www.360magento.com/blog/msi-source-qty-positive-status-disabled/</link>
      <description><![CDATA[<p>仓库导入把某 SKU 的数量改为 25，前台仍显示缺货。数据库里 quantity 没错，但 <code>status</code> 仍是 0。</p><table><thead><tr><th>字段</th><th>含义</th></tr></thead><tbody><tr><td>quantity</td><td>该 Source 的物理数量</td></tr><tr><td>status</td><td>该 Source Item 是否启用</td></tr><tr><td>salable quantity</td><td>Stock 聚合后再扣除 Reservation 的结果</td></tr></tbody></table><pre><code>SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku='SKU-001';</code></pre><p>通过 SourceItemsSaveInterface 保存时，导入程序要明确设置状态；不要直接写表。还要确认 Source 已分配到当前 Website 使用的 Stock。若 status 和映射都正确，再检查库存索引以及未补偿的 Reservation。</p><p>本次修复在导入映射中加入“数量大于零并且 ERP 可销售”才设为 in stock 的业务规则。零库存、冻结库存、恢复库存三组样本都通过后才重新跑全量导入。</p>]]></description>
      <pubDate>Wed, 14 Jan 2026 06:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2部署后PHP-FPM仍加载旧类]]></title>
      <link>https://www.360magento.com/blog/php-fpm-old-class-after-deploy-realpath-opcache/</link>
      <description><![CDATA[<p>命令行执行新代码正常，浏览器请求却仍报旧方法不存在。清 Magento cache、重新部署静态文件都无效，因为问题不在前端资源。</p><pre><code>readlink -f /var/www/shop/current
ps -ef | grep php-fpm
php -i | grep -E 'opcache.validate_timestamps|realpath_cache_ttl'</code></pre><p>使用 <code>current -&gt; releases/20260113</code> 这类软链接发布时，PHP-FPM worker 可能继续持有旧 release 的真实路径或 OPcache 字节码。CLI 每次启动新进程，所以看起来已经更新。</p><p>正确动作是按部署方案平滑重载对应 FPM pool，让新 worker 接管；不要粗暴杀光进程造成正在结账的请求中断。若 OPcache 关闭时间戳校验，发布流程必须显式 reset 或 reload。</p><p>验证时在不泄露绝对路径的诊断端点记录 release 版本号，连续请求多次，确保负载均衡后的每个节点都返回同一版本。随后移除临时端点。</p>]]></description>
      <pubDate>Tue, 13 Jan 2026 00:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台媒体库拒绝上传SVG]]></title>
      <link>https://www.360magento.com/blog/admin-media-gallery-svg-disallowed-type/</link>
      <description><![CDATA[<p>PNG、JPG 都能上传，只有 SVG 提示 <code>Disallowed file type</code>。目录可写已经被前两个成功案例证明，继续 chmod 777 没有意义。</p><p>SVG 是 XML 文档，不只是“另一种图片”。它可能包含脚本、事件属性、外部资源和嵌入内容，因此 Magento 或安全模块拒绝它通常是有意设计。</p><h2>可接受的处理方式</h2><ol><li>优先把装饰图转换成 WebP 或 PNG；</li><li>确需 SVG 时，只对指定后台字段或目录开放；</li><li>在服务端做 SVG 清洗，移除 script、事件属性和外部引用；</li><li>同时校验扩展名、MIME 与实际文件内容。</li></ol><blockquote><p>仅在前端 JavaScript 增加 <code>.svg</code> 后缀不会增加安全性，攻击者可以绕开浏览器直接请求上传接口。</p></blockquote><p>放行后用普通图标、带脚本测试样本和伪装成 SVG 的文本各验证一次。安全样本应成功，危险与伪装文件必须被拒绝。</p>]]></description>
      <pubDate>Mon, 12 Jan 2026 08:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Nginx报upstream sent too big header]]></title>
      <link>https://www.360magento.com/blog/upstream-too-big-header-cookie-debug/</link>
      <description><![CDATA[<p>只有部分老客户打开账户页会 502，Nginx error log 记录 <code>upstream sent too big header</code>。无痕窗口正常，说明差异在 Cookie 或会话。</p><h3>抓响应头而不是复制客户Cookie</h3><pre><code>curl -skD headers.txt -o /dev/null https://shop.example/customer/account/
awk 'BEGIN{IGNORECASE=1}/^Set-Cookie:/{print length($0),$0}' headers.txt</code></pre><p>生产排查只统计名称与长度，不把完整 Cookie 值写进工单。重点找同名 Cookie 被多个 Path 或 Domain 重复设置，以及第三方模块把 JSON、追踪参数塞进响应头。</p><h3>缓冲区调整只能基于测量</h3><p><code>fastcgi_buffer_size</code> 和 <code>fastcgi_buffers</code> 可以临时缓解，但无限加大掩盖了响应持续膨胀。先删除错误 Cookie 写入逻辑，再让受影响浏览器清理旧项。最后测试登录、退出、切换 Store 和加入购物车，确认头大小保持稳定。</p>]]></description>
      <pubDate>Fri, 09 Jan 2026 03:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2多店铺URL Rewrite出现301循环]]></title>
      <link>https://www.360magento.com/blog/multistore-url-rewrite-redirect-loop/</link>
      <description><![CDATA[<p>中文店把 <code>/shoes.html</code> 跳到 <code>/cn/shoes.html</code>，下一次请求又被英文店规则送回原地址，浏览器最终提示重定向次数过多。</p><pre><code>SELECT url_rewrite_id, store_id, request_path, target_path, redirect_type
FROM url_rewrite
WHERE request_path IN ('shoes.html','cn/shoes.html')
ORDER BY store_id, url_rewrite_id;</code></pre><p>排查时把每次响应的 <code>Location</code> 和 Store Cookie 记录下来。只看最终错误页会漏掉中间切换了哪个 Store View。</p><h2>不要混淆三类规则</h2><ul><li>系统生成的商品、分类 canonical rewrite；</li><li>管理员创建的 301/302 重定向；</li><li>Nginx、CDN 或语言切换模块的外层跳转。</li></ul><p>同一个 request path 在不同 <code>store_id</code> 下可以有不同目标。清理冲突前先备份目标记录，不要按 request_path 跨店铺一把删除。重建后分别用无 Cookie、中文 Cookie、英文 Cookie 请求，确认每条链路最多发生预期的一次跳转。</p>]]></description>
      <pubDate>Thu, 08 Jan 2026 07:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台保存商品耗时过长]]></title>
      <link>https://www.360magento.com/blog/product-save-slow-observer-profile/</link>
      <description><![CDATA[<p><strong>现象：</strong>同一商品原来 3 秒保存完，安装营销扩展后稳定需要 110 秒，Nginx 最终偶尔 504。</p><p><strong>第一刀：</strong>记录请求开始、数据库提交和响应结束时间。若数据库更新很早完成，后面的耗时多半在保存后的 Observer、Plugin 或同步接口。</p><pre><code>grep -RniE 'catalog_product_save_(before|after)|catalog_product_save_commit_after' app/code
bin/magento dev:profiler:enable html</code></pre><p><strong>第二刀：</strong>在测试环境用相同商品和数据，逐个停用最近增加的模块。不要在生产环境随机关模块，也不要把 <code>max_execution_time</code> 调到十分钟后就宣布修好。</p><p>本次根因是 <code>catalog_product_save_after</code> 中同步调用远程 ERP，并且连接超时设为 90 秒。改为提交后写入队列，消费者负责重试；后台保存只记录任务 ID。复测简单、可配置、含大量图片三类商品，同时确认索引状态和 ERP 最终数据一致。</p>]]></description>
      <pubDate>Wed, 07 Jan 2026 01:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2消费者被Supervisor反复重启]]></title>
      <link>https://www.360magento.com/blog/queue-consumer-exit-zero-supervisor-restart/</link>
      <description><![CDATA[<p>监控每隔十几分钟报警“进程退出”，但队列持续下降，日志里也没有异常。启动命令使用了：</p><pre><code>bin/magento queue:consumers:start async.operations.all --max-messages=1000</code></pre><p><code>--max-messages</code> 的目的就是让长驻 PHP 进程定期结束，释放累积内存并加载新代码。它完成 1000 条后以正常状态退出，不等同于崩溃。</p><table><thead><tr><th>Supervisor项</th><th>建议</th></tr></thead><tbody><tr><td>autorestart</td><td>允许正常退出后重新拉起</td></tr><tr><td>exitcodes</td><td>包含实际正常退出码</td></tr><tr><td>startsecs</td><td>避免瞬时启动被误判</td></tr><tr><td>stopwaitsecs</td><td>给当前消息留出收尾时间</td></tr></tbody></table><p>若进程每处理一条就退出，才应检查消息异常、内存限制或消费者名称。验收时同时看退出码、处理数量和队列深度，不能只追求进程 PID 永远不变。</p>]]></description>
      <pubDate>Tue, 06 Jan 2026 05:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[REST响应因extension_attributes.xml类型错误返回500]]></title>
      <link>https://www.360magento.com/blog/extension-attributes-wrong-type-rest-500/</link>
      <description><![CDATA[<p>接口已经把数据写进数据库，客户端却收到 500。堆栈最后停在 ServiceOutputProcessor，这通常不是保存失败，而是返回值无法按服务契约转换。</p><pre><code>&lt;extension_attributes for="MagentoSalesApiDataOrderInterface"&gt;
  &lt;attribute code="warehouse_note" type="string" /&gt;
&lt;/extension_attributes&gt;</code></pre><p>如果插件实际给 <code>warehouse_note</code> 塞进数组，序列化阶段就会与声明冲突。返回对象列表时，类型应写成完整接口数组，例如 <code>VendorModuleApiDataItemInterface[]</code>，不能写实现类的随意缩写。</p><h2>核对三处</h2><ol><li><code>extension_attributes.xml</code> 的 for 与 type；</li><li>插件调用的 setter、getter以及真实返回值；</li><li>生成的 Extension 接口是否来自当前配置。</li></ol><p>修正 XML 后重新编译并清理旧生成代码，再分别请求单对象与搜索列表接口。若操作具有写入副作用，还要检查客户端是否因 500 自动重试，避免同一业务被执行两次。</p>]]></description>
      <pubDate>Mon, 05 Jan 2026 02:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单详情与订单列表状态不一致]]></title>
      <link>https://www.360magento.com/blog/sales-order-grid-stale-status-sync/</link>
      <description><![CDATA[<p>订单详情已经是 Processing，后台列表仍显示 Pending。刷新缓存没有用，因为两个页面读取的表不同。</p><pre><code>SELECT entity_id, increment_id, state, status, updated_at
FROM sales_order WHERE increment_id='000001234';

SELECT entity_id, increment_id, status, updated_at
FROM sales_order_grid WHERE increment_id='000001234';</code></pre><p>若站点启用了异步 Grid 更新，保存订单后会由任务把数据同步到 <code>sales_order_grid</code>。先查对应消费者或 Cron 是否运行，再查队列积压；不要用定时 SQL 直接覆盖 grid 表，这会遗漏扩展增加的列。</p><h3>只有一单异常</h3><p>确认第三方模块是否绕过 Order Repository 直接更新数据库。直接 SQL 改 <code>sales_order.status</code> 不会触发正常保存链路。</p><h3>所有新订单都延迟</h3><p>检查异步配置、消息队列连接和消费者管理。修复后创建一张测试订单，观察详情与列表状态的时间差，并确认筛选、导出结果也已同步。</p>]]></description>
      <pubDate>Fri, 02 Jan 2026 08:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST接口上传文件收到413 Request Entity Too Large]]></title>
      <link>https://www.360magento.com/blog/rest-upload-413-request-entity-too-large/</link>
      <description><![CDATA[<p>小图片上传成功，换成 12MB 文件立即返回 413，Magento 的 <code>var/log</code> 没有任何记录。这个证据说明请求还没进入应用。</p><ol><li>用响应头判断返回 413 的服务器；</li><li>检查入口代理、Nginx 虚拟主机和 location 覆盖；</li><li>再核对 PHP-FPM 的上传与 POST 限制；</li><li>最后确认 Magento 字段本身允许该扩展名和大小。</li></ol><pre><code>nginx -T 2&gt;/dev/null | grep -n client_max_body_size
php-fpm -i | grep -E 'upload_max_filesize|post_max_size'
curl -i -X POST https://shop.example/rest/V1/vendor/upload   -H 'Authorization: Bearer ***' -F 'file=@sample.bin'</code></pre><p><code>post_max_size</code> 应大于实际 multipart 请求体，因为边界和其他字段也占空间。改完 Nginx 配置要 reload，改 FPM 配置要重载对应 pool。不要用无限制大小代替容量设计；API 仍应在业务层校验类型、尺寸并避免把整个文件长期留在内存。</p>]]></description>
      <pubDate>Thu, 01 Jan 2026 03:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台Grid因ui_bookmark损坏而加载失败]]></title>
      <link>https://www.360magento.com/blog/admin-grid-broken-ui-bookmark-reset/</link>
      <description><![CDATA[<p>订单列表在管理员 A 的账号下一直转圈，管理员 B 却完全正常。服务器日志没有 SQL 异常，换浏览器也无效，这时不应先改数据源。</p><h2>判断依据</h2><ul><li>故障跟着后台用户走，而不是跟着浏览器走；</li><li>Network 中 mui/index/render 请求返回正常结构；</li><li>页面控制台提示某个列名或筛选组件不存在。</li></ul><p><code>ui_bookmark</code> 会保存用户自己的列顺序、显示状态、过滤条件和视图。模块升级删除了一列，旧 bookmark 仍可能引用它。</p><pre><code>SELECT bookmark_id, user_id, namespace, identifier
FROM ui_bookmark
WHERE user_id=:admin_user_id
  AND namespace='sales_order_grid';</code></pre><p>先导出目标记录留档，只删除这个用户、这个 namespace 的 bookmark。重新打开列表后，Magento 会按当前 XML 创建默认视图。若所有管理员都坏，问题更可能在 UI Component XML、DataProvider 或集合查询；批量清整张表只会抹掉其他人的个人设置。</p>]]></description>
      <pubDate>Wed, 31 Dec 2025 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[自定义Grid导出CSV时报Invalid UI Component element name]]></title>
      <link>https://www.360magento.com/blog/custom-grid-export-invalid-ui-component-name/</link>
      <description><![CDATA[<p>列表分页、筛选都正常，点击“导出 CSV”才报 <code>Invalid UI Component element name</code>。导出控制器会重新创建 UI Component，它比页面渲染更依赖组件名称和 provider 路径。</p><table><thead><tr><th>位置</th><th>应当一致的值</th></tr></thead><tbody><tr><td>文件名</td><td><code>vendor_item_listing.xml</code></td></tr><tr><td>listing name</td><td><code>vendor_item_listing</code></td></tr><tr><td>dataSource</td><td><code>vendor_item_listing_data_source</code></td></tr><tr><td>selectProvider</td><td><code>vendor_item_listing.vendor_item_listing.columns.ids</code></td></tr></tbody></table><p>最常见的错误是复制了别的 Grid，把 <code>selectProvider</code> 的 namespace 留成旧值；也有人给 selectionsColumn 改名，却没有同步导出按钮。</p><pre><code>&lt;exportButton name="export_button"&gt;
  &lt;settings&gt;
    &lt;selectProvider&gt;vendor_item_listing.vendor_item_listing.columns.ids&lt;/selectProvider&gt;
  &lt;/settings&gt;
&lt;/exportButton&gt;</code></pre><p>清除配置与页面缓存后，用“无筛选、单个筛选、勾选部分记录”三种方式导出。CSV 行数和页面条件一致，才算修复完整。</p>]]></description>
      <pubDate>Tue, 30 Dec 2025 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cron报No callbacks found]]></title>
      <link>https://www.360magento.com/blog/cron-no-callbacks-orphan-schedule-row/</link>
      <description><![CDATA[<p>扩展已经从代码库移除，日志却每分钟出现一次：</p><pre><code>No callbacks found for cron job vendor_sync</code></pre><p>这里不是“Cron 没启动”，而是调度表里仍有旧 job code。Magento 读取当前合并配置时找不到它的 instance 和 method，于是无法执行。</p><pre><code>SELECT schedule_id, job_code, status, scheduled_at
FROM cron_schedule
WHERE job_code='vendor_sync'
ORDER BY schedule_id DESC;</code></pre><p>先确认新版本代码中确实没有同名 <code>crontab.xml</code>，并检查模块是否只是被临时禁用。若任务属于已永久卸载的扩展，可清理该 job code 尚未执行的历史行；不要直接清空整张表，以免误删正在运行的其他任务。</p><blockquote><p>若同一个报错持续重新生成，说明配置缓存或某个节点仍保留旧代码。只删数据库记录不会解决。</p></blockquote><p>多节点部署要比较各节点的 <code>app/etc/config.php</code> 和 release 目录，再清理配置缓存。下一轮 Cron 运行后应确认该 job 不再生成，其他任务的 success、missed 数量没有异常变化。</p>]]></description>
      <pubDate>Mon, 29 Dec 2025 07:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[维护模式放行IP后IPv6访问仍显示503]]></title>
      <link>https://www.360magento.com/blog/maintenance-ip-whitelist-ipv6-503/</link>
      <description><![CDATA[<p>办公室公网 IPv4 已写入 <code>var/.maintenance.ip</code>，同一台电脑通过公司网络访问仍是 503。查看 Nginx 日志才发现，请求实际以 IPv6 到达源站。</p><h2>先确认 Magento 看到的地址</h2><pre><code>tail -f /var/log/nginx/access.log
cat var/.maintenance.ip
bin/magento maintenance:status</code></pre><p>不要照抄“查询 IP”网站的结果。站点经过 CDN 或负载均衡时，源站可能看到代理地址；双栈网络还会优先使用 IPv6。白名单中的 <code>203.0.113.10</code> 与 <code>::ffff:203.0.113.10</code> 也不是同一个字符串。</p><h2>处理顺序</h2><ol><li>从站点访问日志确认真实客户端地址；</li><li>让受信代理正确覆盖真实地址 Header，不能信任任意来源；</li><li>用 <code>bin/magento maintenance:allow-ips 地址</code> 写入；</li><li>分别用 IPv4、IPv6 和手机网络复测。</li></ol><p>如果运维层也配置了维护页，Magento 的白名单不会越过 Nginx 或 CDN 的拦截。此时应先判断 503 由哪一层返回，再改对应规则。</p>]]></description>
      <pubDate>Fri, 26 Dec 2025 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch报Limit of total fields exceeded]]></title>
      <link>https://www.360magento.com/blog/opensearch-total-fields-limit-product-attributes/</link>
      <description><![CDATA[<p>商品索引重建失败：</p>
<pre><code>Limit of total fields [1000] has been exceeded</code></pre>
<p>把上限从 1000 改成 5000 可能立刻成功，也可能让集群内存和 mapping 状态继续膨胀。先回答&ldquo;这些字段为什么进入索引&rdquo;。</p>
<h2>查看实际Mapping规模</h2>
<pre><code>curl -s 'http://opensearch:9200/magento_product_*/_mapping' &gt; mapping.json
curl -s 'http://opensearch:9200/_cluster/stats?filter_path=indices.mappings'</code></pre>
<p>按属性代码统计字段，尤其找带随机后缀、Store ID、选项 ID 的动态字段。正常的 Magento 属性增长是可解释的；第三方扩展把 JSON 每个键展开成新字段，会让数量随商品数据无限增长。</p>
<h2>属性配置也要做减法</h2>
<p>检查大量历史属性是否仍被标记为可搜索、用于分层导航或参与搜索权重。禁用不需要的搜索用途不会删除业务数据，却能减少新索引文档和 mapping 负担。先在测试索引验证查询功能，再调整生产。</p>
<h2>什么时候可以提高上限</h2>
<p>确认字段都属于真实业务需要、节点有足够 heap、集群状态稳定时，可以适度提高 index 级限制，并记录容量依据。但它应与清理动态 mapping、属性治理一起完成。</p>
<p>Magento 重建索引通常创建新索引再切 alias。修复后确认新索引 mapping 数量下降、alias 已切换、旧索引按保留策略清理。最后测试全文搜索、筛选、多 Store 和增量更新；一次全量 reindex 成功不代表动态字段不会再次增长。</p>]]></description>
      <pubDate>Thu, 25 Dec 2025 07:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[部署Magento 2时Composer要求输入用户名]]></title>
      <link>https://www.360magento.com/blog/composer-deploy-prompts-credentials-auth-json/</link>
      <description><![CDATA[<p>发布脚本卡在 <code>composer install</code>，日志最后一行是 Username。开发机不复现，因为凭据早已保存在个人全局配置中。</p>
<p>先看 Composer 正在访问哪个域名。Magento Marketplace、私有 Satis、GitHub 和公司 Git 需要的认证方式不同，不能把一对 key 填到所有仓库。</p>
<pre><code>composer config --global --list --auth
composer diagnose
composer install --no-interaction --no-dev --prefer-dist -vvv
</code></pre>
<p>日志分享前删除 Authorization、token 和带凭据 URL。</p>
<h2>CI里用受控秘密注入</h2>
<p>把凭据放在部署平台的 Secret 中，通过 <code>COMPOSER_AUTH</code> 或构建时生成的临时 auth 配置提供；不要提交 <code>auth.json</code> 到 Git，也不要复制开发者的整个 Composer Home。密钥权限只覆盖需要的仓库，并设置轮换。</p>
<p>如果锁文件引用已经下线的私有 dist URL，即使 package 仍在缓存里，干净构建也会失败。用全新容器、空 Composer cache 执行一次 install，才能证明仓库与凭据完整。</p>
<p>最后验证非交互命令不会等待 stdin，失败时能快速返回明确的 401/403；成功构建产物中不包含 auth.json、环境变量转储或 Composer 调试日志中的秘密。</p>]]></description>
      <pubDate>Wed, 24 Dec 2025 01:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2付款成功后成功页空白]]></title>
      <link>https://www.360magento.com/blog/checkout-success-page-blank-order-created/</link>
      <description><![CDATA[<p>客户已扣款，后台订单也在 Processing，但支付平台回跳后只看到空白成功页，没有订单号。刷新不会恢复。</p>
<h2>这不是&ldquo;再创建一次订单&rdquo;的场景</h2>
<p>先用支付交易号确认订单已经存在。成功页通常从 Checkout Session 读取 last quote/order 信息；信息丢了，页面不能展示，不代表应该重新 submit quote。</p>
<h2>按回跳时间线查</h2>
<ol>
<li>place order 后是否设置 last order ID；</li>
<li>跳到支付域名前 Session Cookie 的 Domain、SameSite、Secure 是否允许返回；</li>
<li>return controller 是否提前 clearQuote 或清整个 checkout session；</li>
<li>webhook 与浏览器 return 是否竞争修改状态；</li>
<li>自定义成功页 Block 是否从错误 session key 取值。</li>
</ol>
<p>我会对比正常支付方式与问题支付方式的 Cookie 和重定向链。若只在跨域支付失败，优先查 SameSite/Secure 与 HTTPS 终止；若同域模拟也失败，就读支付模块 return action。</p>
<pre><code># 日志只记录哈希后的session标识、quote_id、order_id与request_id
place_order  quote=812 order=1042 session=ab12...
return       quote=?   order=?    session=cd34...</code></pre>
<p>两段 session 标识不同，说明回跳没有带回原会话。标识相同但 order 为空，则是应用过早清理。</p>
<p>修复时让 webhook 负责幂等更新支付状态，让 return 只负责用户体验；成功页只读取已创建订单，不执行二次业务。验收覆盖成功、取消、浏览器关闭后仅 webhook 到达、return 与 webhook 乱序四种情况。每个支付交易只能对应一张订单。</p>]]></description>
      <pubDate>Tue, 23 Dec 2025 06:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2保存商品自定义属性时报输入值无效]]></title>
      <link>https://www.360magento.com/blog/product-attribute-invalid-value-backend-model/</link>
      <description><![CDATA[<p>只有一个自定义属性导致商品保存失败，错误却只有&ldquo;输入值无效&rdquo;。我先复制商品并逐项移除字段，确定问题属性 code 为 <code>external_codes</code>。</p>
<p>数据库显示它的 <code>backend_model</code> 指向多年前扩展中的类。这个类在 <code>beforeSave</code> 中假定输入永远是逗号字符串，但新后台组件提交的是数组，于是把合法值当成非法。</p>
<pre><code>SELECT attribute_id, attribute_code, backend_type,
       backend_model, source_model, frontend_input
FROM eav_attribute
WHERE attribute_code='external_codes';</code></pre>
<p>排查顺序：</p>
<ol>
<li>保存请求里的原始类型；</li>
<li>UI组件是否把空值传成 <code>[]</code>、<code>null</code> 或空字符串；</li>
<li>backend_type能否容纳转换后的值；</li>
<li>backend model是否仍存在且兼容当前PHP；</li>
<li>Store View保存时是否错误覆盖默认值。</li>
</ol>
<p>不要直接在数据库里删除 backend_model 名称。它可能还负责序列化、唯一性或同步副表。应先为旧数据建立测试样本，再修改模型兼容数组/字符串并给出明确异常消息；如果确实不再需要，通过 Data Patch 安全迁移配置与现有值。</p>
<p>修复后测试新商品、已有商品、空值、多个值和 Store View 覆盖。再跑一次批量导入，因为导入调用同一属性后端模型，却不经过后台 UI 的数据整理。</p>]]></description>
      <pubDate>Mon, 22 Dec 2025 02:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2索引器状态变为Suspended]]></title>
      <link>https://www.360magento.com/blog/indexer-suspended-repeats-after-reset/</link>
      <description><![CDATA[<p>值班时看到索引器 Suspended，执行 reset、reindex 后恢复；第二天又停。反复 reset 相当于把报警灯按灭，并没有修导致任务中断的异常。</p>
<h3>先取证，再改变状态</h3>
<pre><code>bin/magento indexer:status
bin/magento indexer:show-mode
SELECT * FROM indexer_state WHERE status='suspended';
SELECT * FROM mview_state ORDER BY updated DESC;</code></pre>
<p>按索引器更新时间向前查看 Cron、system、exception 和数据库日志。磁盘满、临时表空间不足、OpenSearch只读、数据库连接中断，都可能让任务被保护性挂起。</p>
<h3>检查锁是否真的跨进程共享</h3>
<p>Application Lock 配置错误时，一个索引任务可能认为已有实例运行，或者多节点同时处理同一 changelog。确认所有节点使用一致的锁提供方、前缀和后端；如果使用数据库锁，再检查长事务与连接中断。</p>
<h3>恢复顺序</h3>
<ol>
<li>停止制造积压或冲突的任务；</li>
<li>修复磁盘、搜索集群、数据库或锁根因；</li>
<li>记录 changelog 位置；</li>
<li>只 reset 受影响索引器；</li>
<li>低峰执行重建并观察下一个增量周期。</li>
</ol>
<p>不要一上来 truncate changelog，它是增量索引的事实记录。验收不是 status 变 Ready，而是新增、改价、改库存都能由下一轮 Cron 推进版本，且 24 小时内不再进入 Suspended。</p>]]></description>
      <pubDate>Fri, 19 Dec 2025 07:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2支付Webhook签名校验失败]]></title>
      <link>https://www.360magento.com/blog/payment-webhook-signature-raw-body-mismatch/</link>
      <description><![CDATA[<p>支付平台后台显示回调已送达，Magento 却每次记录 signature mismatch。最关键的证据不是解析后的数组，而是应用收到的原始字节。</p>
<h2>一次失败回调要保留什么</h2>
<ul>
<li>请求 ID、到达时间和来源 IP；</li>
<li>签名头名称与算法版本；</li>
<li>原始 body 的 SHA-256，仅在安全环境短期保留脱敏样本；</li>
<li>用于签名的时间戳；</li>
<li>代理是否解压、改写或转换编码。</li>
</ul>
<p>不要在日志中输出密钥、完整银行卡数据或未经脱敏的请求体。</p>
<p>常见错误是先 <code>json_decode()</code>，业务处理后再 <code>json_encode()</code> 去算 HMAC。键顺序、斜杠、空白和 Unicode 转义任何一个变化，摘要都不同。签名必须用框架读取到的原始 body 按支付平台规定拼接。</p>
<pre><code>$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($expected, $received)) {
    throw new LocalizedException(__('Invalid signature.'));
}</code></pre>
<p>示例中的拼接格式只是结构说明，实际必须严格使用该支付平台当前协议。</p>
<h2>验证通过也不能直接处理两次</h2>
<p>校验时间戳允许窗口，保存 event ID 并做唯一约束。平台重试同一事件时应返回成功但不重复开票、发货或改状态。密钥轮换期间可同时验证新旧密钥，但必须记录命中哪一把，并在窗口结束后移除旧密钥。</p>
<p>最终用官方测试事件验证：正常签名成功、改一个字节失败、过期时间戳失败、同一 event 重放不产生第二次业务动作。</p>]]></description>
      <pubDate>Thu, 18 Dec 2025 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL自定义字段返回旧值]]></title>
      <link>https://www.360magento.com/blog/graphql-custom-field-stale-cache-identity/</link>
      <description><![CDATA[<p>后台把品牌说明从 A 改成 B，REST 立即返回 B，GraphQL 仍是 A；清全站缓存后恢复。这个对比已经说明数据保存没问题，缺的是精准失效。</p>
<p>我先用完全相同的 query 连续请求并记录响应头，再换 SKU、Store 和客户组。结果显示自定义字段被缓存，却没有关联到品牌实体的 cache tag。</p>
<h2>Identity必须描述&ldquo;这段结果依赖谁&rdquo;</h2>
<p>Resolver 返回品牌说明，它不仅依赖产品，还依赖品牌实体。只返回产品 ID 的 Identity，保存品牌时就不会让这份 GraphQL 结果失效。实现 Identity 时使用实体本身定义的缓存标签格式，避免自己拼出一个永远没人清理的字符串。</p>
<p>另一个维度是上下文：字段若按 Store View、客户组或币种变化，缓存键也要区分这些上下文。Identity负责实体变更失效，context负责不同请求之间不串数据，二者不能互相替代。</p>
<pre><code># 复现时保存两次响应与缓存头
curl -sS -D headers-1.txt -o body-1.json https://shop.example.com/graphql ...
curl -sS -D headers-2.txt -o body-2.json https://shop.example.com/graphql ...</code></pre>
<p>修复后更新品牌实体，只清对应 tag，旧查询应返回 B；另一个无关品牌仍可保持命中。再用两个 Store 与两个客户组交叉测试，防止为了修&ldquo;旧值&rdquo;引入跨站或跨客户价格泄漏。</p>]]></description>
      <pubDate>Wed, 17 Dec 2025 06:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2后台Grid新增列筛选时报Unknown column]]></title>
      <link>https://www.360magento.com/blog/admin-grid-filter-unknown-column-filterindex/</link>
      <description><![CDATA[<p>列表加载正常，新列&ldquo;供应商名称&rdquo;也有值；一输入筛选条件就报：</p>
<pre><code>SQLSTATE[42S22]: Column not found: 1054 Unknown column 'supplier_name' in 'where clause'</code></pre>
<p>显示值可能是 DataProvider 后处理出来的，或者 SQL 中只是 select alias。筛选器会把字段放进 WHERE，此时数据库需要知道它属于哪张表。</p>
<h2>先看最终SQL</h2>
<p>确认 supplier 表是否已 join、真实列名是什么、join 发生在 addFieldToFilter 之前还是之后。若真实字段是 <code>s.name</code>，把筛选映射到它：</p>
<pre><code>$collection-&gt;addFilterToMap('supplier_name', 's.name');</code></pre>
<p>映射应放在 collection/data provider 的合适位置，而不是在控制器里解析筛选参数。多个表都有 <code>name</code> 时必须带 alias，避免从 Unknown column 变成 Ambiguous column。</p>
<p>如果一件商品可能关联多个供应商，普通 join 会让 Grid 行重复，筛选和分页数量都不准确。这时要先决定展示规则：主供应商、聚合文本，还是子查询。不能只加 <code>GROUP BY</code> 压掉重复，因为 count SQL 和导出仍可能错。</p>
<h2>验证范围</h2>
<p>文本包含、精确值、空值筛选各测一次，再测试排序、分页、导出和 Mass Action。Grid 列&ldquo;能看到&rdquo;只是第一关，所有基于 collection 的动作都必须使用同一字段语义。</p>]]></description>
      <pubDate>Tue, 16 Dec 2025 02:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2客户地址保存时报省份无效]]></title>
      <link>https://www.360magento.com/blog/customer-address-region-id-text-conflict/</link>
      <description><![CDATA[<p>故障只发生在一批导入客户：账户中心地址能看到&ldquo;California&rdquo;，结账切换到该地址却提示省份无效。请求里同时出现：</p>
<pre><code>{"country_id":"US","region":"California","region_id":999}</code></pre>
<p>文字看起来正确，但 999 并不是 US 下的 California。承运商和税务规则通常更信任 <code>region_id</code>，因此页面能展示不代表数据有效。</p>
<h3>查字典与异常地址</h3>
<pre><code>SELECT d.region_id, d.country_id, d.code, n.name
FROM directory_country_region d
LEFT JOIN directory_country_region_name n ON n.region_id=d.region_id
WHERE d.country_id='US' AND (d.code='CA' OR n.name='California');</code></pre>
<p>再筛出 country_id 与 region_id 所属国家不一致的客户地址。先导出清单并按客户确认，不能只根据 region 文本模糊匹配后批量写库；不同国家可能存在同名地区。</p>
<h3>入口修复</h3>
<p>CSV 导入、ERP 接口和自定义地址组件只能选择一种明确策略：有目录地区的国家传正确 ID；自由文本国家传 region 并让 region_id 为空。国家变化时必须清掉旧 ID，不能只更新文字。</p>
<p>历史数据通过受控脚本使用 Region Factory/Repository 映射并保存，保留变更日志。修复后验证账户编辑、默认配送地址、运费估算、税费和下单生成的 order_address 五处一致。</p>]]></description>
      <pubDate>Mon, 15 Dec 2025 07:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2下载类商品链接返回403]]></title>
      <link>https://www.360magento.com/blog/downloadable-product-link-403-nginx/</link>
      <description><![CDATA[<p>订单已经付款，客户账户中也出现下载链接，点击后却是 Nginx 403。直接给 <code>pub/media/downloadable</code> 加公开 location 虽然能下载，但任何猜到路径的人都可能绕过订单权限。</p>
<h2>分清403是谁返回的</h2>
<p>响应是 Magento 页面，先查客户、订单、链接购买记录和允许下载次数；响应是 Nginx 默认页，查 Web 服务器 location 命中。保存 access log 中的 URI 与最终内部重写路径：</p>
<pre><code>curl -I -b cookies.txt 'https://shop.example.com/downloadable/customer/products/'
nginx -T | grep -n -A8 -B3 'downloadable|media'</code></pre>
<p>不要把带签名或密钥的完整下载 URL 写进共享工单。</p>
<h2>安全的请求链</h2>
<ol>
<li>客户通过 Magento 路由发起下载；</li>
<li>应用校验客户、订单状态、次数与链接有效性；</li>
<li>校验通过后由应用流式输出，或通过内部重定向让 Nginx 发送文件；</li>
<li>媒体真实目录仍禁止外部直接访问。</li>
</ol>
<p>如果使用 X-Accel-Redirect，内部 location 必须标记 <code>internal</code>，应用生成的内部路径与 alias 要一致。容器部署还要确认 PHP 和 Nginx 看到的是同一挂载点。</p>
<p>文件权限只需让运行用户可读，不要 777。验收时分别使用已付款客户、未购买客户、达到下载次数的客户和直接文件 URL；只有第一种应成功。</p>]]></description>
      <pubDate>Fri, 12 Dec 2025 03:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Grouped商品无法加入购物车]]></title>
      <link>https://www.360magento.com/blog/grouped-product-children-in-stock-cannot-add-cart/</link>
      <description><![CDATA[<p>这类问题先准备一个表，不要在后台来回点：</p>
<table>
<thead>
<tr><th>对象</th><th>检查值</th></tr>
</thead>
<tbody>
<tr>
<td>父商品</td>
<td>状态、网站、分类、可见性</td>
</tr>
<tr>
<td>每个子商品</td>
<td>状态、网站、价格、Stock下可售量</td>
</tr>
<tr>
<td>关联</td>
<td>position、默认数量、是否仍存在</td>
</tr>
<tr>
<td>请求</td>
<td>super_group[子商品ID]数量</td>
</tr>
</tbody>
</table>
<p>Grouped 商品自己不承载可售数量，真正加入购物车的是用户输入数量大于零的子商品。模板改造后若输入框 name 丢了，页面看得到子项，POST 却没有 <code>super_group</code>，后台只会认为没有选择商品。</p>
<h2>后端证据</h2>
<p>用当前 Website 对应的 Stock 查询每个子 SKU 的 salable quantity，不要只看 Default Source。子商品被禁用、未分配到当前网站或只在另一个 Stock 可售时，父页面可能仍被缓存显示，但提交会失败。</p>
<p>然后用原生主题临时对照一次。如果原生主题可以加入，检查自定义模板是否保留 add-to-cart form、form_key 和数量字段；如果原生也失败，再查关联与库存。</p>
<p>修复后至少测试：只选一个子项、同时选两个、输入零、输入超过可售量，以及一个子项缺货。报错应准确落在失败子项，不能让一个缺货子项阻塞其他可购买子项。</p>]]></description>
      <pubDate>Thu, 11 Dec 2025 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2发票PDF缺少Logo]]></title>
      <link>https://www.360magento.com/blog/invoice-pdf-logo-missing-cli-context/</link>
      <description><![CDATA[<p>后台页头 Logo 正常，不代表 PDF 能读取它。浏览器可以从 CDN URL 请求图片，PDF 生成器通常需要在服务器上直接读取文件。</p>
<p>先记录问题订单的 Store ID，因为 Sales PDF Logo 可以按网站或商店视图配置。再到生成 PDF 的那个节点检查真实文件，而不是在 Web 节点看：</p>
<pre><code>bin/magento config:show sales/identity/logo
find pub/media/sales/store/logo -maxdepth 2 -type f -ls
</code></pre>
<p>如果发票由队列或 Cron 生成，Consumer 节点没有挂载同一份 <code>pub/media</code>，就会出现后台能看、邮件附件没图。另一个常见问题是文件扩展名为 PNG，实际内容却是 WebP，浏览器能识别，PDF 图片库不能。</p>
<p>我用三步收尾：重新上传一张标准 RGB PNG；确认 Web 与 Consumer 节点文件校验值一致；分别从后台下载和异步邮件生成 PDF。两份文件都出现 Logo，且不同 Store 使用各自配置，才算修复。</p>]]></description>
      <pubDate>Wed, 10 Dec 2025 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2商品图产生重复记录]]></title>
      <link>https://www.360magento.com/blog/product-media-gallery-duplicate-images/</link>
      <description><![CDATA[<p>ERP 每晚同步商品后，后台图库会多出一张肉眼完全相同的图片：<code>/a/b/photo.jpg</code>、<code>/a/b/photo_1.jpg</code>、<code>/a/b/photo_2.jpg</code>。清图片缓存没有用，因为数据库确实新增了 Gallery 记录。</p>
<h2>先确认重复的是文件、记录还是商店视图</h2>
<pre><code>SELECT mg.value_id, mg.value, mg.media_type,
       v.store_id, v.position, v.disabled
FROM catalog_product_entity_media_gallery mg
JOIN catalog_product_entity_media_gallery_value v
  ON v.value_id = mg.value_id
WHERE v.entity_id = :product_id
ORDER BY mg.value, v.store_id;</code></pre>
<p>同一个 <code>value_id</code> 有多条 store 记录属于作用域数据，不一定重复；不同 value_id 指向不同后缀文件，才是反复新增。</p>
<h2>同步代码不要每次都addImage</h2>
<p>常见代码只判断远程 URL 是否变化，却没有按 Magento 中的规范化媒体路径找现有图片。URL 带时间参数、大小写不同或前导斜杠不同，比较都会失败。</p>
<p>我的修复是先计算稳定的源图片业务键，查询商品已有 Gallery，内容未变时更新 label、position、角色，不重新复制文件；内容改变才替换。同步任务重复执行两次，图库行数必须保持不变。</p>
<p>历史数据清理前先确认 image、small_image、thumbnail 是否引用准备删除的文件，并核对其他商品是否共享同一路径。不要按文件名后缀直接批量删。先在副本库生成保留/删除清单，后台抽查角色图，再通过服务层做清理。</p>
<p>修复后连续跑三次同步，并分别在 All Store Views 和一个子视图查看排序、标签和禁用状态。这样才能确认&ldquo;去重&rdquo;没有把商店级配置一起抹掉。</p>]]></description>
      <pubDate>Tue, 09 Dec 2025 07:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Varnish把Magento 2游客购物车缓存给登录用户]]></title>
      <link>https://www.360magento.com/blog/varnish-hit-logged-customer-guest-cart/</link>
      <description><![CDATA[<p>页面右上角显示&ldquo;登录&rdquo;，迷你购物车是空的，但访问账户中心又确认用户 Session 存在。刷新几次后偶尔恢复，而且响应头一直是 Varnish HIT。</p>
<p>我用同一浏览器连续保存三类证据：HTML 文档请求、<code>customer/section/load</code> 请求、Cookie。结果是 HTML 可以公共缓存，客户姓名和购物车应由 private content 再加载；问题页面的 section/load 也被 CDN 缓存了。</p>
<h3>快速判断</h3>
<pre><code>curl -sSI https://shop.example.com/
curl -sSI 'https://shop.example.com/customer/section/load/?sections=cart,customer'</code></pre>
<ul>
<li>HTML HIT 不一定错；</li>
<li>带客户私有数据的 section 响应不应成为跨用户公共缓存；</li>
<li><code>X-Magento-Vary</code> Cookie 被代理删除，会让页面上下文失去区分；</li>
<li>把所有 Cookie 都加入 cache key 又会把命中率打到很低。</li>
</ul>
<p>最终修改的是 CDN 对 private-content 路径的缓存规则，并恢复必要 Cookie 的转发。没有通过&ldquo;登录页面全部 bypass&rdquo;粗暴规避，因为那会让大量可缓存 HTML 失去价值。</p>
<p>验收用三个无痕会话：游客、客户A、客户B。三者请求同一商品页可以共享公共 HTML，但 customer-data 必须分别返回自己的姓名和购物车；退出登录后本地 section 也要被正确失效。</p>]]></description>
      <pubDate>Mon, 08 Dec 2025 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[多台服务器运行Magento 2 Cron导致任务重复执行]]></title>
      <link>https://www.360magento.com/blog/cron-duplicate-execution-multi-node-lock/</link>
      <description><![CDATA[<p>凌晨促销同步执行了两遍，外部系统收到两次推送。排查时先别把责任全推给&ldquo;Magento Cron不可靠&rdquo;，我会按时间线还原：</p>
<ol>
<li>两条记录是否拥有不同的 <code>schedule_id</code>？</li>
<li>两台机器是否在同一秒启动？</li>
<li>第一次是否仍在运行，第二次就开始了？</li>
<li>外部接口是否因超时重试，而服务端其实已处理成功？</li>
</ol>
<pre><code>SELECT schedule_id, job_code, status, created_at,
       scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE job_code='vendor_sync'
ORDER BY schedule_id DESC LIMIT 20;</code></pre>
<h2>三种常见根因</h2>
<p><strong>系统crontab重复：</strong>同一节点被 root 与 Magento 用户各配置一份，或旧发布目录的任务没有移除。</p>
<p><strong>锁不共享：</strong>两台节点使用本地文件锁，各自都认为自己拿到了锁。多节点应使用项目支持的共享锁后端，并确认节点连接到同一数据库/Redis。</p>
<p><strong>任务超过调度间隔：</strong>上一轮还没结束，下一轮又被标记为可执行。任务需要合理的超时、批次和互斥，而不是单纯把执行频率调低。</p>
<h2>业务动作必须自己幂等</h2>
<p>即使调度层只有一次，网络超时也可能触发重试。向 ERP 推送订单时应带稳定的业务键，让接收方识别重复；发送优惠券、扣款和库存更新更不能依赖&ldquo;Cron理论上只跑一次&rdquo;。</p>
<p>修复后连续观察至少两个完整调度周期。对照主机名、PID、schedule_id 和业务键，确认第二个进程拿不到锁时会安全退出，并且人为重放同一任务不会产生第二份业务结果。</p>]]></description>
      <pubDate>Fri, 05 Dec 2025 05:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2修改Data Patch后setup:upgrade没有重新执行]]></title>
      <link>https://www.360magento.com/blog/data-patch-changed-not-running-again/</link>
      <description><![CDATA[<p><code>setup:upgrade</code> 显示完成，但我刚改过的 Data Patch 一行日志都没有。原因不是缓存：Magento 记录的是&ldquo;这个补丁类是否执行过&rdquo;，不会计算文件内容哈希。</p>
<pre><code>SELECT patch_name FROM patch_list
WHERE patch_name LIKE 'Vendor\Module%';</code></pre>
<p>只要类名已经在 <code>patch_list</code>，修改 <code>apply()</code> 后再运行也不会重放。</p>
<h2>不要在生产库直接删除patch_list记录</h2>
<p>删除记录会让原补丁从头再来。若它创建属性、移动数据或发送业务事件，不具备幂等性时可能产生重复选项、覆盖人工数据，甚至在中途失败。</p>
<p>正确方式是新建第二个补丁类，把&ldquo;这次新增的变化&rdquo;写进去，并通过 <code>getDependencies()</code> 声明它依赖第一个补丁。新环境会按顺序执行两个补丁，旧环境只执行新的一个。</p>
<blockquote>
<p>补丁是已经发生过的数据库历史，不是可以随意改写的初始化脚本。</p>
</blockquote>
<p>本地确实需要反复调试未发布补丁时，可以重建一次性开发数据库；不要把删除 patch_list 当成上线步骤。新补丁还应先判断目标状态，尽量做到重复运行也安全。</p>
<p>验收很简单：全新数据库安装一次，从旧版本升级一次，两条路径得到相同 schema 与数据；再次执行 <code>setup:upgrade</code> 不应产生额外变化。</p>]]></description>
      <pubDate>Thu, 04 Dec 2025 03:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2结账页的自定义手续费没有写入订单]]></title>
      <link>https://www.360magento.com/blog/checkout-custom-fee-missing-from-order/</link>
      <description><![CDATA[<p>这次的现象很具体：结账右侧有&ldquo;包装费 10 元&rdquo;，应付总额也增加了 10 元，支付成功后后台订单却没有包装费，发票金额又少了 10 元。</p>
<p>前端组件不是事实来源。它只把 Quote Totals 中的一段数据显示出来；订单创建时并不会自动猜测哪个自定义 segment 需要持久化。</p>
<table>
<thead>
<tr><th>环节</th><th>需要存在的内容</th></tr>
</thead>
<tbody>
<tr>
<td>Quote计算</td>
<td>Total Collector设置base与display金额</td>
</tr>
<tr>
<td>数据库</td>
<td>quote、sales_order及需要的invoice/creditmemo字段</td>
</tr>
<tr>
<td>转换</td>
<td>Quote到Order显式传值</td>
</tr>
<tr>
<td>后续单据</td>
<td>开票、退款、邮件和PDF读取同一规则</td>
</tr>
</tbody>
</table>
<p>先查支付前 Quote 与创建后的 Order：</p>
<pre><code>SELECT entity_id, grand_total, base_grand_total, custom_fee, base_custom_fee
FROM quote WHERE entity_id = :quote_id;

SELECT entity_id, grand_total, base_grand_total, custom_fee, base_custom_fee
FROM sales_order WHERE quote_id = :quote_id;</code></pre>
<p>Quote 正确而 Order 为空，问题在字段声明或转换；Quote 自己就为空，前端可能只是临时拼了显示值。</p>
<p>金额字段必须同时处理基础币种与订单币种，并明确税前、税后及折扣顺序。只加到 grand_total 会造成明细和总额对不上；只保存展示币种会让多币种退款无法还原。</p>
<h2>我会这样验收</h2>
<ul>
<li>费用适用与不适用的商品各下一单；</li>
<li>切换币种后核对 base/display 两组金额；</li>
<li>部分开票、部分退款，确认费用是否按设计分摊；</li>
<li>重复 collectTotals 不得把费用累加两次。</li>
</ul>
<p>最后再看支付网关请求。如果 Magento 订单总额与网关捕获金额不同，不能只在后台补一列，而要重新核对费用进入 grand total 的时点。</p>]]></description>
      <pubDate>Wed, 03 Dec 2025 08:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2自定义后台表单保存后字段变空]]></title>
      <link>https://www.360magento.com/blog/admin-ui-form-field-not-saving-datascope/</link>
      <description><![CDATA[<p>这个故障最容易浪费时间，因为编辑页看起来完全正常：数据库里的值能显示，输入新值也没有校验错误，点击保存还提示成功；再次打开却恢复为空。</p>
<p>我不先看资源模型，而是直接保存一次 Network 里的 POST。假设请求实际是：</p>
<pre><code>general[name]=New Name</code></pre>
<p>控制器却读取 <code>$request-&gt;getParam('name')</code>，拿到的自然是空值。页面回显来自 DataProvider，提交来自 UI Component；两条链路可以一条正确、一条错误。</p>
<h2>四个名字必须形成同一条路径</h2>
<ol>
<li>form 的 namespace；</li>
<li>fieldset 的 dataScope；</li>
<li>field 的 source/dataScope；</li>
<li>DataProvider 返回数组的根节点。</li>
</ol>
<p>如果 DataProvider 返回 <code>[$id =&gt; ['general' =&gt; ['name' =&gt; 'A']]]</code>，XML 与保存逻辑就应按 general.name 对齐。不要为了让页面显示而在 <code>getData()</code> 中复制两份值，这会把读取问题藏起来。</p>
<pre><code>&lt;item name="dataScope" xsi:type="string"&gt;general.name&lt;/item&gt;</code></pre>
<p>保存时先记录经过白名单后的 payload 键，不要记录敏感值。字段完全没进请求，查组件绑定；请求中有值但控制器读不到，查层级；控制器读到而数据库没变，再看 repository、resource model 和事务。</p>
<h2>一个容易忽略的覆盖</h2>
<p><code>prepareMeta()</code>、Modifier Pool 或另一个模块可以在运行时改字段配置。浏览器中的 UI registry 才是最终结果，不能只看自己模块的 XML。修复后分别测试新建和编辑，因为两者的 provider 数据结构经常不同；再提交空值，确认系统按业务规则清空或拒绝，而不是悄悄保留旧值。</p>]]></description>
      <pubDate>Tue, 02 Dec 2025 01:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级PHP 8.2后Magento 2接口的JSON被Deprecated污染]]></title>
      <link>https://www.360magento.com/blog/php82-deprecated-breaks-json-response/</link>
      <description><![CDATA[<p>移动端报&ldquo;JSON parse error&rdquo;，抓包后发现响应最前面多了一行：</p>
<pre><code>Deprecated: Creation of dynamic property VendorModuleModelClient::$token is deprecated</code></pre>
<p>后面的 JSON 本身完全正确，但客户端从第一个字节开始解析，当然会失败。这类问题在 PHP 升级后很常见，根因是旧扩展动态创建属性；<code>display_errors</code> 又被误开，最终把诊断信息送给了 API 调用方。</p>
<h3>应急处理</h3>
<p>生产环境关闭错误直接展示，把错误留在 PHP-FPM 日志中。修改的是实际 FPM pool 使用的配置，不要只改 CLI 的 php.ini：</p>
<pre><code>php --ini
php -i | grep -E 'display_errors|error_reporting'
</code></pre>
<p>CLI 输出只能帮助确认命令行环境。FPM 配置修改后需要平滑重载，并用接口再次确认 <code>Content-Type</code> 与响应首字节。</p>
<h3>真正的修复</h3>
<p>在报错类中声明属性并给出合适类型，或者升级扩展到支持当前 PHP 的版本。不要长期从 <code>error_reporting</code> 中屏蔽所有 Deprecated，因为同一批日志里可能还藏着下一次 PHP 大版本会直接失败的问题。</p>
<p>我会抽查 REST、GraphQL、后台保存和 Cron 四条入口：它们可能由不同 SAPI 或 pool 执行。验收标准是浏览器响应无杂字、日志能记录兼容性警告、修正后的模块不再产生该警告。</p>]]></description>
      <pubDate>Mon, 01 Dec 2025 06:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 RabbitMQ连接报ACCESS_REFUSED]]></title>
      <link>https://www.360magento.com/blog/rabbitmq-access-refused-vhost-permission/</link>
      <description><![CDATA[<p>部署新环境后，Magento 页面能打开，消费者却不断退出：</p>
<pre><code>ACCESS_REFUSED - access to vhost '/' refused for user 'magento'</code></pre>
<p>密码并没有写错。问题是运维创建了用户，也允许它登录 RabbitMQ 管理页，却没有给 Magento 实际使用的 vhost 授权。管理界面登录权限与队列读写权限不是一回事。</p>
<h2>先把连接目标逐项对齐</h2>
<p>查看 <code>app/etc/env.php</code> 中的 host、port、user、virtualhost 和 ssl，不要只验证账号。vhost 名称里的斜杠需要正确转义；集群环境还要确认每个 Web、Cron、Consumer 节点读取的是同一份配置。</p>
<pre><code>rabbitmqctl list_vhosts
rabbitmqctl list_user_permissions magento
rabbitmqctl list_permissions -p /magento</code></pre>
<p>如果 Magento 配置使用 <code>/magento</code>，授权也必须落在这个 vhost：</p>
<pre><code>rabbitmqctl set_permissions -p /magento magento ".*" ".*" ".*"</code></pre>
<p>生产环境应按实际交换机和队列缩小正则范围，上面的全权限更适合作为短暂验证。改完后重新启动一个消费者并观察是否能声明 exchange、写消息和 ack；只做到 TCP 连接成功还不够。</p>
<h2>错误文本不同，排查方向也不同</h2>
<ul>
<li><code>PLAIN login refused</code>：优先检查凭据或认证方式；</li>
<li><code>access to vhost refused</code>：检查 vhost 是否存在及权限；</li>
<li><code>NOT_FOUND - no queue</code>：连接已经成功，继续查拓扑声明；</li>
<li>TLS 握手失败：核对证书、端口与 ssl 配置。</li>
</ul>
<p>最后我会发送一条测试消息，确认队列数量先增加再减少，并检查消费者日志没有继续重连。这样能证明权限覆盖了完整收发链路，而不是仅让报错暂时消失。</p>]]></description>
      <pubDate>Fri, 28 Nov 2025 02:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2自定义模块安装后setup:upgrade成功，后台菜单点进去却提示Access denied]]></title>
      <link>https://www.360magento.com/blog/custom-admin-menu-access-denied-acl/</link>
      <description><![CDATA[<p>菜单已经显示，点击却 Access denied，说明路由大概率是通的，问题落在 ACL：菜单 resource、Controller 的 <code>ADMIN_RESOURCE</code> 和 <code>acl.xml</code> 没指向同一个 ID。</p><h3>把三个resource ID并排对照</h3><p><code>etc/adminhtml/menu.xml</code>：</p><pre><code>&lt;add id="Vendor_Module::records"
     title="Records"
     module="Vendor_Module"
     sortOrder="20"
     parent="Magento_Backend::content"
     action="vendor_module/record/index"
     resource="Vendor_Module::records"/&gt;</code></pre><p>Controller：</p><pre><code>class Index extends MagentoBackendAppAction
{
    public const ADMIN_RESOURCE = 'Vendor_Module::records';
}</code></pre><p><code>etc/acl.xml</code> 中也必须存在完全相同的 ID，并挂在合适的父资源下。大小写、下划线和模块前缀只要有一个字符不同，管理员就会被拒绝。</p><h3>超级管理员能进，普通角色不能进，就刷新角色资源</h3><p>修改 ACL 后执行：</p><pre><code>php bin/magento cache:clean config</code></pre><p>然后在后台重新保存一次角色权限，让新 resource 写入角色规则。不要直接修改 <code>authorization_rule</code> 表，因为层级变化后很容易留下错误授权。</p><p>用两个账号验证：超级管理员应能访问，受限角色只有勾选 <code>Records</code> 后才能访问；取消权限后再次请求应返回 Access denied。这样既证明功能可用，也证明 ACL 没被为了省事设置成过宽的父级资源。</p>]]></description>
      <pubDate>Thu, 27 Nov 2025 02:20:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2部署后首页正常，checkout页面却报require is not defined怎么恢复？]]></title>
      <link>https://www.360magento.com/blog/checkout-require-is-not-defined-after-deploy/</link>
      <description><![CDATA[<p>发布后首页看起来没事，结账页却白屏并报 <code>require is not defined</code>，通常不是 checkout 业务代码坏了，而是 RequireJS 主文件没加载成功或加载顺序被合并工具改乱。</p><h3>先检查requirejs/require.js的请求状态</h3><p>Network 过滤 <code>require.js</code>，看它是 404、403、HTML 响应还是被 CDN 返回了旧内容。如果响应 Content-Type 是 <code>text/html</code>，经常是静态资源没部署，Nginx 又把 404 fallback 到首页。</p><p>确认文件：</p><pre><code>pub/static/frontend/Vendor/theme/zh_Hans/requirejs/require.js</code></pre><p>并检查页面 source 中 <code>require.js</code> 是否出现在依赖它的 bundle 之前。</p><h3>暂时关闭合并功能定位，不要直接长期绕过</h3><p>如果启用了第三方 JS 合并、defer 或 CDN 优化，先在测试环境关闭它，重新部署：</p><pre><code>php bin/magento config:set dev/js/merge_files 0
php bin/magento config:set dev/js/enable_js_bundling 0
php bin/magento setup:static-content:deploy -f   --theme Vendor/theme zh_Hans
php bin/magento cache:flush</code></pre><p>恢复后再逐项打开优化配置，找出哪个步骤改变了脚本顺序。Cloudflare Rocket Loader 一类功能也要对 Magento 的 RequireJS 页面排除。</p><p>最后用无痕窗口打开首页、商品页和 checkout，确认 <code>require</code> 在第一个自定义模块执行前已经存在，并检查所有静态 JS 都返回 200，而不是只看到结账界面出现就结束。</p>]]></description>
      <pubDate>Wed, 26 Nov 2025 02:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2邮件模板里插入的图片收件人看不到，为什么后台预览却正常？]]></title>
      <link>https://www.360magento.com/blog/email-template-image-not-showing-absolute-url/</link>
      <description><![CDATA[<p>邮件模板后台预览能看到 Logo，真正发到 Gmail 或 Outlook 后图片破图，最常见的是模板里用了相对地址。后台预览和邮件客户端不是同一个页面环境，<code>/media/...</code> 在邮件里没有可解析的站点域名。</p><h3>先查看邮件原文里的img src</h3><p>不要只看邮件客户端渲染。查看原始邮件，找到：</p><pre><code>&lt;img src="/media/wysiwyg/mail/logo.png"&gt;</code></pre><p>这就是问题。模板里用 Magento 指令生成绝对地址：</p><pre><code>&lt;img src="https://www.360magento.com/media/wysiwyg/mail/logo.png" alt="Store"&gt;</code></pre><p>主题静态资源则用：</p><pre><code>&lt;img src="{{view url='images/email/logo.png'}}" alt="Store"&gt;</code></pre><h3>检查生成出来的是不是内部域名</h3><p>如果最终地址是 <code>http://nginx/media/...</code> 或内网主机名，说明 Store View 的 Base URL 或反向代理协议仍有问题。用实际发送邮件所属的 Store View 检查 secure/unsecure Base URL，而不是只看 Default Config。</p><p>图片 URL 还必须允许公网匿名访问，不能依赖后台 Cookie，也不要被防盗链规则按 Referer 拦截。发一封测试邮件后，从无登录状态的浏览器直接打开邮件原文中的完整图片 URL；返回 200 且 Content-Type 正确，邮件客户端才有机会正常显示。</p>]]></description>
      <pubDate>Tue, 25 Nov 2025 02:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台Grid筛选日期后报SQL错误，时区转换和字段名哪里写错了？]]></title>
      <link>https://www.360magento.com/blog/admin-grid-date-filter-sql-timezone-error/</link>
      <description><![CDATA[<p>自定义 Grid 平时能打开，一选日期范围就报 SQL ambiguous column 或格式错误，常见原因是 collection join 后同名字段没有映射，或者 UI Component 把日期按 UTC 转换后传给了不合适的表达式字段。</p><h3>先把失败请求里的filters参数留下来</h3><p>在 <code>mui/index/render</code> 请求中找到 <code>filters[created_at][from]</code> 和 <code>to</code>，再把 collection 生成的 SQL 打到日志：</p><pre><code>$this-&gt;logger-&gt;debug((string) $collection-&gt;getSelect());</code></pre><p>如果 join 的两张表都有 <code>created_at</code>，给 filter 建立明确映射：</p><pre><code>$collection-&gt;addFilterToMap('created_at', 'main_table.created_at');</code></pre><p>Grid XML 中也让列名对应 collection 可过滤字段，不要显示别名 A，却让 DataProvider 对不存在的别名 B 做 <code>WHERE</code>。</p><h3>日期列的dataType和timezone要按存储值设置</h3><p>Magento 数据库里的标准时间通常按 UTC 保存，UI 日期列可配置：</p><pre><code>&lt;column name="created_at" class="MagentoUiComponentListingColumnsDate"&gt;
    &lt;settings&gt;
        &lt;filter&gt;dateRange&lt;/filter&gt;
        &lt;dataType&gt;date&lt;/dataType&gt;
        &lt;label translate="true"&gt;Created At&lt;/label&gt;
    &lt;/settings&gt;
&lt;/column&gt;</code></pre><p>如果字段保存的是商店本地时间或纯日期，就不要照抄带时区转换的配置。测试时用跨午夜的数据，分别筛选单日和跨日范围，检查边界记录是否被错误排除。SQL 不报错只是第一步，日期范围与后台显示的时区一致才算完成。</p>]]></description>
      <pubDate>Mon, 24 Nov 2025 02:59:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2自定义维护页面不显示，只看到Unable to proceed堆栈怎么办？]]></title>
      <link>https://www.360magento.com/blog/custom-maintenance-page-shows-exception-stack/</link>
      <description><![CDATA[<p>已经改了 <code>pub/errors/default/503.phtml</code>，开启维护模式却看到异常堆栈，这通常是因为站点还在 developer mode。开发模式优先暴露异常，和生产环境展示维护页的行为不同。</p><h3>先确认当前模式和维护状态</h3><pre><code>php bin/magento deploy:mode:show
php bin/magento maintenance:status</code></pre><p>自定义错误皮肤放在：</p><pre><code>pub/errors/mytheme/503.phtml
pub/errors/mytheme/css/styles.css</code></pre><p>并创建 <code>pub/errors/local.xml</code>：</p><pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;skin&gt;mytheme&lt;/skin&gt;
&lt;/config&gt;</code></pre><h3>在生产模式下再验证503响应</h3><pre><code>php bin/magento deploy:mode:set production
php bin/magento maintenance:enable
curl -I https://shop.example.com/</code></pre><p>应返回 503，并显示自定义页面。不要只在浏览器看，因为 CDN 可能缓存旧的 500/503 页面。还要测试白名单 IP：</p><pre><code>php bin/magento maintenance:allow-ips 203.0.113.10</code></pre><p>白名单来源如果经过代理，Magento 看到的客户端 IP 可能不是你的公网 IP，需要同时核对可信代理和转发头。验证完成后执行 <code>maintenance:disable</code>，再确认首页恢复 200。</p>]]></description>
      <pubDate>Fri, 21 Nov 2025 02:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2搜索有时返回0条，重建索引后又恢复，是OpenSearch索引还是别名丢了？]]></title>
      <link>https://www.360magento.com/blog/opensearch-empty-results-index-alias-missing/</link>
      <description><![CDATA[<p>搜索偶发空白但分类页正常，重建 <code>catalogsearch_fulltext</code> 后马上恢复，我会先查 Magento 当前索引别名指向的物理索引，而不是直接把问题归咎于缓存。</p><h3>先在OpenSearch里看alias和index是否同时存在</h3><pre><code>curl -s 'http://opensearch:9200/_cat/aliases?v'
curl -s 'http://opensearch:9200/_cat/indices?v'</code></pre><p>正常情况下，Magento 使用的 alias 应指向一个存在且 health 正常的索引。若 alias 指向的索引刚被外部清理任务删除，应用查询会失败；若多个部署同时重建，也可能出现别名切换竞争。</p><h3>对照Magento日志里的真实索引名</h3><p>打开搜索请求对应的 <code>exception.log</code>，记录 <code>index_not_found_exception</code> 或 429 的索引名，再检查配置：</p><pre><code>php bin/magento config:show catalog/search/engine
php bin/magento indexer:status catalogsearch_fulltext</code></pre><p>确认不同环境没有共用同一个 OpenSearch index prefix。测试、预发布和生产共用前缀时，一个环境重建或清理会误伤另一个环境。</p><p>修正前缀或外部生命周期策略后，只让一个发布任务执行完整 reindex：</p><pre><code>php bin/magento indexer:reindex catalogsearch_fulltext</code></pre><p>随后再次查看 alias，确认它稳定指向新索引，并连续请求多个关键词。不要把“重建一次恢复”当永久修复，必须找到是谁删除索引或抢着切 alias。</p>]]></description>
      <pubDate>Thu, 20 Nov 2025 02:45:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台商品图片上传成功，保存后缩略图却404怎么处理？]]></title>
      <link>https://www.360magento.com/blog/product-image-saved-thumbnail-404/</link>
      <description><![CDATA[<p>上传时能看到临时预览，保存商品后图片变成 404，说明临时文件上传没问题，故障多半发生在从 <code>media/tmp/catalog/product</code> 移到正式目录或生成缓存图的阶段。</p><h3>对着404地址检查原图和缓存图</h3><p>假设页面请求：</p><pre><code>/media/catalog/product/cache/.../a/b/abc.jpg</code></pre><p>先找原图：</p><pre><code>find pub/media/catalog/product -path '*a/b/abc.jpg' -ls</code></pre><p>原图不存在，就看保存商品时的 <code>exception.log</code>，以及 PHP-FPM 用户是否能写 <code>pub/media/catalog/product</code>。原图存在而 cache 路径没有，则测试：</p><pre><code>php bin/magento catalog:images:resize</code></pre><h3>权限要按运行用户修，不要chmod 777</h3><p>确认 CLI 用户、PHP-FPM 用户和部署用户的组关系，再设置目录组写权限与 setgid。例如实际用户组为 <code>www-data</code> 时：</p><pre><code>chgrp -R www-data pub/media
find pub/media -type d -exec chmod 2775 {} +
find pub/media -type f -exec chmod 664 {} +</code></pre><p>命令里的用户组必须按服务器实际情况调整。还要确认 ImageMagick/GD 可用，以及 Nginx 的 <code>/media/</code> 规则没有把不存在的缓存图直接永久缓存成 404。</p><p>最后重新保存同一商品，确认原图已移动、resize 命令无异常、前台缩略图 200。只清浏览器缓存而没检查文件落盘，不算修好。</p>]]></description>
      <pubDate>Wed, 19 Nov 2025 02:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 REST API带了Bearer Token还是401，先查ACL还是Nginx？]]></title>
      <link>https://www.360magento.com/blog/rest-api-bearer-token-401-acl-nginx/</link>
      <description><![CDATA[<p>同一个 Token 在本机 curl 可用，经过正式域名就 401，这时我不会立刻重建 Integration。先判断 Magento 有没有收到 <code>Authorization</code> 头。</p><h3>用最小请求对比直连和域名</h3><pre><code>curl -i   -H 'Authorization: Bearer YOUR_TOKEN'   https://shop.example.com/rest/V1/store/storeViews</code></pre><p>如果直连 PHP-FPM 前的测试正常，而走 Nginx/Apache/CDN 失败，检查 Web Server 是否丢了认证头。PHP-FPM 常见配置是：</p><pre><code>fastcgi_param HTTP_AUTHORIZATION $http_authorization;</code></pre><p>Apache 环境则确认 rewrite 或 FastCGI 配置没有清掉 <code>Authorization</code>。</p><h3>头已收到再查Integration权限</h3><p>后台打开对应 Integration，确认 API Resources 里勾选了实际 endpoint 需要的 ACL；更改资源后重新激活并使用新 Token。自定义 <code>webapi.xml</code> 的 resource 也要指向真实存在的 <code>acl.xml</code> ID：</p><pre><code>&lt;resources&gt;
    &lt;resource ref="Vendor_Module::api"/&gt;
&lt;/resources&gt;</code></pre><p>401 多半是认证失败，403 更像已识别身份但没有权限。结合 <code>var/log/exception.log</code> 与响应码判断，不要把所有问题都归到 ACL。最终分别测试一个公共接口和目标受限接口，确认 Token 被识别且只有授权范围内的资源能访问。</p>]]></description>
      <pubDate>Tue, 18 Nov 2025 02:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2禁用模块后还报找不到它的Proxy类，generated/code为什么没有更新？]]></title>
      <link>https://www.360magento.com/blog/disabled-module-proxy-class-generated-code/</link>
      <description><![CDATA[<p>模块已经 <code>module:disable</code>，页面仍报 <code>Class VendorModule...Proxy does not exist</code>，通常不是模块真的还启用，而是生产模式的 DI 元数据仍保留着旧依赖。</p><h3>先确认配置状态而不是只看app/code目录</h3><pre><code>php bin/magento module:status Vendor_Module
grep -n "Vendor_Module" app/etc/config.php</code></pre><p>再搜索到底是谁还引用旧类：</p><pre><code>rg "Vendor\Module" app/code app/etc vendor/composer</code></pre><p>有时另一个自定义模块在 <code>di.xml</code>、构造函数或 preference 中仍依赖被禁用模块，这种情况下重新编译也应该失败，不能靠删生成代码掩盖。</p><h3>确认没有真实依赖后再重建DI</h3><p>维护窗口内执行：</p><pre><code>php bin/magento maintenance:enable
rm -rf generated/code/* generated/metadata/*
php bin/magento setup:di:compile
php bin/magento cache:clean config
php bin/magento maintenance:disable</code></pre><p>多节点环境要在构建阶段生成一次，再把同一 <code>generated</code> 产物发布到所有节点，不能只清当前机器。验证时用 <code>setup:di:compile</code> 的成功退出码作为第一道标准，再请求原报错页面，确认日志没有继续加载旧 Proxy。</p>]]></description>
      <pubDate>Mon, 17 Nov 2025 02:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2翻译CSV已经改了，结账页JS提示为什么还是英文？]]></title>
      <link>https://www.360magento.com/blog/checkout-js-translation-still-english/</link>
      <description><![CDATA[<p>PHP 模板里的文字能翻译，结账页 Knockout 提示却还是英文，说明 CSV 本身不一定有问题，JS 翻译字典可能没有重新生成，或者原代码根本没走 <code>$t()</code>。</p><h3>先看js-translation.json里有没有这句话</h3><p>打开当前 locale 的：</p><pre><code>pub/static/frontend/Vendor/theme/zh_Hans/js-translation.json</code></pre><p>搜索英文原文。没有的话先确认 CSV 编码为 UTF-8、引号正确，并位于主题或模块的 <code>i18n/zh_Hans.csv</code>。</p><p>前端 JS 必须这样调用：</p><pre><code>define(['mage/translate'], function ($t) {
    'use strict';
    return $t('The requested quantity is not available.');
});</code></pre><p>字符串拼接会导致字典匹配失败，动态变量用占位符，不要先拼成完整英文。</p><h3>删除当前locale的字典后重新部署</h3><pre><code>rm -f pub/static/frontend/Vendor/theme/zh_Hans/js-translation.json
php bin/magento setup:static-content:deploy -f   --theme Vendor/theme zh_Hans
php bin/magento cache:clean translate full_page</code></pre><p>浏览器里还要清 <code>mage-translation-storage</code> 和 <code>mage-translation-file-version</code>，否则 Local Storage 会继续使用旧字典。刷新后在控制台执行 <code>$.mage.__('英文原文')</code> 或通过模块加载 <code>mage/translate</code> 验证返回值，再检查结账实际提示。</p>]]></description>
      <pubDate>Fri, 14 Nov 2025 02:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2修改LESS后前台还是旧样式，怎么确认浏览器拿到的是哪份CSS？]]></title>
      <link>https://www.360magento.com/blog/less-changes-not-updated-static-content/</link>
      <description><![CDATA[<p>改了 <code>_extend.less</code>，清缓存后页面一点变化都没有，先别继续改选择器。Magento 生产模式下访问的是 <code>pub/static</code> 里的编译结果，源文件改对了不代表当前 theme、locale 的 CSS 已重新生成。</p><h3>在DevTools里反查实际CSS文件</h3><p>选中元素，看命中的 CSS URL，例如：</p><pre><code>/static/version123/frontend/Vendor/theme/zh_Hans/css/styles-l.css</code></pre><p>这里已经告诉了当前 area、theme 和 locale。部署时如果只生成了 <code>en_US</code>，中文 Store View 当然还在用旧文件或直接 404。</p><h3>只清当前主题的生成结果再部署</h3><p>先确认当前主题继承关系没有写错，然后执行：</p><pre><code>rm -rf pub/static/frontend/Vendor/theme/zh_Hans
rm -rf var/view_preprocessed/pub/static/frontend/Vendor/theme
php bin/magento setup:static-content:deploy -f   --area frontend --theme Vendor/theme zh_Hans
php bin/magento cache:clean full_page</code></pre><p>不要删除 <code>pub/static/.htaccess</code>。多节点部署时还要确认静态资源是共享存储，或者同一构建产物已经同步到每个节点；否则刷新几次时新旧样式会交替出现。</p><p>最后直接打开生成后的 <code>styles-l.css</code> 搜索刚改的规则，再回到页面确认响应命中的是这份文件。如果文件里都没有规则，问题在 LESS 编译或主题继承；文件里有但页面没用，才继续查 CDN、FPC 和选择器优先级。</p>]]></description>
      <pubDate>Thu, 13 Nov 2025 02:10:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2放到Cloudflare或负载均衡后后台反复跳登录页，Cookie该怎么查？]]></title>
      <link>https://www.360magento.com/blog/admin-login-loop-behind-cloudflare-load-balancer/</link>
      <description><![CDATA[<p>站点直连服务器能登录，一走 Cloudflare 或负载均衡就回到登录页，这类问题大多不是管理员密码错，而是 Magento 设置的后台 Cookie 没有在下一次请求带回来。</p><h3>在登录请求里对比Set-Cookie和下一跳Cookie</h3><p>Network 里看后台登录 POST 响应有没有 <code>Set-Cookie: admin=...</code>，然后看随后的 dashboard 请求是否带上同一个 Cookie。没带时检查四项：</p><ul><li>Cookie Domain 是否写成了旧域名。</li><li>Cookie Path 是否限制在错误的后台路径。</li><li>前端实际是 HTTPS，但 Magento 认为当前请求是 HTTP。</li><li>SameSite / Secure 属性是否与浏览器访问方式冲突。</li></ul><h3>让代理把真实协议传给Magento</h3><p>Nginx 反代至少要正确传递：</p><pre><code>proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</code></pre><p>如果 TLS 在负载均衡终止，后端 <code>$scheme</code> 可能永远是 http，这时应使用上游提供的协议头，不能盲目硬编码。Magento 的 Secure Base URL 也要与用户实际访问地址一致。</p><p>配置修正后清理旧浏览器 Cookie 再测。只清 Magento 缓存往往没用，因为浏览器还在带旧 domain/path 的会话。登录后连续打开三个后台页面并观察 session Cookie 没有变化、请求不再 302 回 login，才表示代理协议和 Cookie 已经对齐。</p>]]></description>
      <pubDate>Wed, 12 Nov 2025 02:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2分类保存报URL key for specified store already exists，重复地址藏在哪里？]]></title>
      <link>https://www.360magento.com/blog/category-url-key-already-exists-url-rewrite/</link>
      <description><![CDATA[<p>后台保存分类时报 URL Key 已存在，界面通常不告诉你冲突记录是哪一条。尤其做过数据迁移、批量导入或改过根分类后，<code>url_rewrite</code> 里可能留着旧路径。</p><h3>用报错里的request_path直接查</h3><p>假设冲突路径是 <code>sale.html</code>：</p><pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE request_path = 'sale.html';</code></pre><p>一定要带 store_id 看。不同 Store View 可以有同名路径，但同一个 store 内不能有两条相同 <code>request_path</code>。</p><p>再确认这条记录对应的商品或分类是否还存在：</p><pre><code>SELECT entity_id, parent_id, path
FROM catalog_category_entity
WHERE entity_id = 42;</code></pre><h3>先判断是正常占用还是孤儿记录</h3><p>如果路径已被另一个有效分类使用，就应该改当前分类 URL Key，而不是删 rewrite。只有确认 entity 已不存在、路径是迁移残留时，才考虑先备份该行再清理。</p><p>自动生成的分类 URL Rewrite 可以通过重新保存实体或相关索引恢复，但自定义 301 跳转不能随便删。生产库操作前先导出冲突行：</p><pre><code>SELECT * FROM url_rewrite
WHERE url_rewrite_id = 1234;</code></pre><p>清理后保存分类，再访问新路径和旧路径各一次，确认新地址 200、需要保留的历史地址仍按预期 301，而不是只看后台“保存成功”。</p>]]></description>
      <pubDate>Tue, 11 Nov 2025 02:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2自定义Controller路由一直404，routes.xml和文件都在为什么进不去？]]></title>
      <link>https://www.360magento.com/blog/custom-controller-route-404-frontname/</link>
      <description><![CDATA[<p>自定义前台 Controller 访问 404，我一般不先清十遍缓存，而是把 URL 拆成 frontName、controller、action 三段逐个对。</p><h3>先用最短路径排除目录层级问题</h3><p><code>etc/frontend/routes.xml</code>：</p><pre><code>&lt;router id="standard"&gt;
    &lt;route id="vendor_module" frontName="tools"&gt;
        &lt;module name="Vendor_Module"/&gt;
    &lt;/route&gt;
&lt;/router&gt;</code></pre><p>访问 <code>/tools/ping/index</code> 时，类应是：</p><pre><code>VendorModuleControllerPingIndex</code></pre><p>文件为：</p><pre><code>app/code/Vendor/Module/Controller/Ping/Index.php</code></pre><p>Linux 文件系统区分大小写。目录写成 <code>controller/ping</code>，本机 macOS 可能没事，上服务器就会 404。</p><h3>action类要满足当前版本的接口要求</h3><pre><code>class Index implements MagentoFrameworkAppActionHttpGetActionInterface
{
    public function __construct(
        private MagentoFrameworkControllerResultJsonFactory $jsonFactory
    ) {}

    public function execute()
    {
        return $this-&gt;jsonFactory-&gt;create()-&gt;setData(['ok' =&gt; true]);
    }
}</code></pre><p>如果这是 POST 接口，则实现 <code>HttpPostActionInterface</code>，并处理 Form Key 或明确实现合适的 CSRF 逻辑。不要为了让请求通过就全局关闭 CSRF。</p><p>再运行：</p><pre><code>php bin/magento module:status Vendor_Module
php bin/magento cache:clean config</code></pre><p>先让最短的 JSON Action 返回，再逐步加依赖和业务逻辑。这样能清楚区分“路由没命中”和“Controller 构造失败后被错误页接管”。</p>]]></description>
      <pubDate>Mon, 10 Nov 2025 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2自定义后台Mass Action提示没有选择记录，勾选框明明已经选了]]></title>
      <link>https://www.360magento.com/blog/admin-grid-mass-action-no-selected-records/</link>
      <description><![CDATA[<p>后台列表加批量操作后，勾选几行再提交却提示没有选择记录，通常不是控制器收不到参数，而是 UI Grid 用来标识行的字段不一致。</p><h3>在请求里看selected传来的到底是什么</h3><p>Network 中打开 Mass Action 请求，正常应包含：</p><pre><code>selected[]=12
selected[]=15
excluded=false</code></pre><p>如果 <code>selected</code> 是空，先对比 <code>storageConfig</code>、<code>selectionsColumn</code> 和主键字段：</p><pre><code>&lt;storageConfig&gt;
    &lt;param name="indexField" xsi:type="string"&gt;entity_id&lt;/param&gt;
&lt;/storageConfig&gt;

&lt;selectionsColumn name="ids"&gt;
    &lt;settings&gt;
        &lt;indexField&gt;entity_id&lt;/indexField&gt;
    &lt;/settings&gt;
&lt;/selectionsColumn&gt;</code></pre><p>数据源返回的每条 item 也必须包含 <code>entity_id</code>。数据库主键叫 <code>rule_id</code>，XML 却抄成 <code>entity_id</code>，页面仍会显示勾选框，但前端没有稳定的行 ID。</p><h3>控制器别自己拼where in</h3><p>批量操作用 <code>MagentoUiComponentMassActionFilter</code> 处理“选择全部”和 excluded：</p><pre><code>$collection = $this-&gt;filter-&gt;getCollection(
    $this-&gt;collectionFactory-&gt;create()
);

foreach ($collection as $item) {
    $item-&gt;setIsActive(false)-&gt;save();
}</code></pre><p>这样既支持逐条勾选，也支持跨页“全选后排除几条”。修完后分别测试选两条、全选当前页、Select All，再看真正被修改的 ID 是否一致，避免页面不报错但误处理整张表。</p>]]></description>
      <pubDate>Fri, 07 Nov 2025 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2写了requirejs mixin却完全没执行，是文件没加载还是配置名写错？]]></title>
      <link>https://www.360magento.com/blog/requirejs-mixin-not-working-debug/</link>
      <description><![CDATA[<p>Mixin 没生效时最浪费时间的做法，是不断在 JS 文件里加 <code>console.log</code>。如果 RequireJS 根本没合并到那份配置，日志写再多也不会出现。</p><h3>先在控制台确认目标模块有没有注册mixin</h3><p>打开页面后执行：</p><pre><code>require.s.contexts._.config.config.mixins</code></pre><p>找到目标模块，例如：</p><pre><code>Magento_Checkout/js/action/place-order</code></pre><p>如果这里没有你的 mixin，问题在 <code>requirejs-config.js</code> 的位置、作用域或模块名，而不是 mixin 函数本身。前台文件应放在：</p><pre><code>app/code/Vendor/Module/view/frontend/requirejs-config.js</code></pre><p>后台则是 <code>view/adminhtml</code>，全局才用 <code>view/base</code>。</p><h3>模块名要写AMD名称，不要写磁盘路径</h3><pre><code>var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/action/place-order': {
                'Vendor_Module/js/action/place-order-mixin': true
            }
        }
    }
};</code></pre><p>Mixin 文件返回的函数还要包住原目标：</p><pre><code>define([], function () {
    'use strict';
    return function (target) {
        return target.extend({
            // override here
        });
    };
});</code></pre><p>如果目标导出的是普通函数而不是 UI Component，就要返回一个包装函数，不能机械地 <code>target.extend()</code>。</p><p>生产模式下重新部署对应 area、theme 和 locale 的静态资源，然后清浏览器缓存。最后不仅要看到 mixin 文件 200，还要在 <code>mixins</code> 配置中看到它，并确认目标方法确实走进覆盖逻辑。</p>]]></description>
      <pubDate>Thu, 06 Nov 2025 02:35:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台自定义列表一直Loading，数据接口明明返回200还差什么？]]></title>
      <link>https://www.360magento.com/blog/admin-ui-grid-stuck-loading-data-provider/</link>
      <description><![CDATA[<p>自定义 Admin Grid 卡在 Loading 时，我以前总先怀疑 SQL。后来发现很多时候接口已经 200，真正卡住的是 UI Component 找不到它等待的组件，spinner 就永远不会被替换掉。</p><h3>先在浏览器里把UI组件日志打开</h3><p>控制台执行：</p><pre><code>require([
    'Magento_Ui/js/lib/logger/console-logger',
    'Magento_Ui/js/lib/logger/levels-pool'
], function (logger) {
    logger.setDisplayLevel(5);
});</code></pre><p>刷新页面后，重点看 provider、deps 或 columns 组件未加载的警告。这比只看 <code>var/log</code> 快，因为 XML 能通过服务端解析，不代表前端组件名能对上。</p><h3>把provider、dataSource和spinner三个名字逐字对齐</h3><p>一个可工作的结构至少要保证：</p><pre><code>&lt;item name="provider" xsi:type="string"&gt;
    vendor_module_listing.vendor_module_listing_data_source
&lt;/item&gt;
&lt;item name="spinner" xsi:type="string"&gt;vendor_module_columns&lt;/item&gt;</code></pre><p>并且下面真实存在同名的：</p><pre><code>&lt;dataSource name="vendor_module_listing_data_source" component="Magento_Ui/js/grid/provider"&gt;
    &lt;settings&gt;
        &lt;updateUrl path="mui/index/render"/&gt;
    &lt;/settings&gt;
&lt;/dataSource&gt;
&lt;columns name="vendor_module_columns"&gt;</code></pre><p>Grid 不要直接复用编辑表单的 DataProvider。列表需要返回 <code>items</code> 和 <code>totalRecords</code>，Collection 还要正确注册到 <code>CollectionFactory</code>。Network 虽然是 200，但返回结构不对时，provider 仍然无法完成初始化。</p><p>修改后清 <code>config</code>、<code>layout</code> 缓存，删除浏览器 Local Storage 中这个 listing 的旧 bookmark 再测试。看到 <code>mui/index/render</code> 返回正确 JSON、Loading 消失并能翻页，才算真正修好。</p>]]></description>
      <pubDate>Wed, 05 Nov 2025 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2登录后结账突然报No such entity with cartId，刷新购物车也没用怎么办？]]></title>
      <link>https://www.360magento.com/blog/checkout-no-such-entity-cart-id-after-login/</link>
      <description><![CDATA[<p>我遇到的场景是：客户在结账页停留着，又在另一个标签页登录账户，回来继续提交就报 <code>No such entity with cartId</code>。这不是 quote 表一定丢了，而是前端还握着旧的 guest cart 标识，登录动作已经把购物车合并到 customer quote。</p><h3>先确认报错用的是旧masked_id还是新quote_id</h3><p>在浏览器 Network 里看失败的 GraphQL 或 REST 请求。如果请求里还是登录前的 <code>maskedCartId</code>，再查：</p><pre><code>SELECT quote_id, masked_id
FROM quote_id_mask
WHERE masked_id = '请求里的ID';</code></pre><p>然后确认对应 quote 是否仍然 active：</p><pre><code>SELECT entity_id, customer_id, is_active, updated_at
FROM quote
WHERE entity_id = 12345;</code></pre><p>如果登录后生成或激活了另一个 customer quote，旧 masked ID 继续请求自然会找不到有效购物车。</p><h3>登录完成后必须让checkout重新取customer-data</h3><p>自定义登录弹窗或单页应用最常漏掉这一段：登录成功只改了页面上的用户状态，却没有失效 <code>cart</code>、<code>customer</code> 等 section，也没有重新初始化 checkout。</p><pre><code>define(['Magento_Customer/js/customer-data'], function (customerData) {
    'use strict';
    customerData.invalidate(['customer', 'cart']);
    customerData.reload(['customer', 'cart'], true);
});</code></pre><p>如果是 Headless 前端，登录或合并购物车成功后要丢弃旧 cart token，以服务端返回的新 cart ID 为准。不要捕获异常后无限重试原 ID，那只会把同一个无效请求打很多遍。</p><p>验证时打开两个标签页复现完整过程：游客加购、打开结账、另一页登录、回到结账。页面应主动重新加载购物车，而不是继续提交旧 masked ID。</p>]]></description>
      <pubDate>Tue, 04 Nov 2025 02:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2库存明明大于0，加购物车却提示The requested qty is not available怎么查？]]></title>
      <link>https://www.360magento.com/blog/requested-qty-not-available-msi-salable-qty/</link>
      <description><![CDATA[<p>这个问题最容易被“后台数量还有几十个”带偏。Magento 2.3 以后用了 MSI，页面上的 Source Item 数量并不等于前台可售数量。真正参与加购判断的是库存、来源分配、缺货阈值和 reservation 共同计算出来的 salable quantity。</p><h3>先让Magento自己报出可售数量</h3><p>不要只查 <code>inventory_source_item.quantity</code>。先运行：</p><pre><code>php bin/magento inventory:reservation:list-inconsistencies -r</code></pre><p>再用 SKU 查可售数量。不同版本可用的 CLI 命令并不完全一致，我一般直接在一个临时 PHP 脚本里调用 <code>GetProductSalableQtyInterface</code>，并明确传入当前 website 对应的 stock ID。这样能避免查错库存范围。</p><h3>数量有货但salable为0，就逐项对账</h3><p>我会按这个顺序看：</p><ol><li>当前 Website 是否真的分配到了这个 Stock。</li><li>Stock 下是否包含保存该 SKU 的 Source。</li><li>Source Item 的状态是不是 <code>In Stock</code>，不是只看 quantity。</li><li><code>Out-of-Stock Threshold</code> 是否大于或等于现有数量。</li><li><code>inventory_reservation</code> 里是否残留了没有补偿回来的负数。</li></ol><p>查 reservation：</p><pre><code>SELECT stock_id, sku, SUM(quantity) AS reserved
FROM inventory_reservation
WHERE sku = 'TEST-SKU'
GROUP BY stock_id, sku;</code></pre><p>不要直接删表里的 reservation。先用 <code>list-inconsistencies</code> 找异常订单，再生成补偿：</p><pre><code>php bin/magento inventory:reservation:list-inconsistencies -r |
php bin/magento inventory:reservation:create-compensations</code></pre><p>处理完重新索引 <code>inventory</code>，再用同一 website、同一 SKU 查询 salable quantity。只有接口返回值恢复并且前台实际能加入购物车，才说明不是表面上“改了库存”，而是可售库存链路真的恢复了。</p>]]></description>
      <pubDate>Mon, 03 Nov 2025 02:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台保存商品提示No data to save，为什么请求会先跳转一次？]]></title>
      <link>https://www.360magento.com/blog/admin-product-save-no-data-301-redirect/</link>
      <description><![CDATA[<p>后台改商品时遇到过一个很怪的问题：页面没有明确报错，保存后内容还是旧的，日志里只有 <code>No data to save</code>。刚开始一直盯着商品 Repository 和插件，后来才发现代码根本没机会处理表单数据&mdash;&mdash;保存请求先返回了 301，浏览器跟着跳到新地址时，POST body 已经没了。</p>
<h3>不看页面提示，先在Network里找catalog/product/save</h3>
<p>正常保存大致会看到这几步：</p>
<pre><code>catalog/product/validate  200
catalog/product/save      302
catalog/product/edit      200</code></pre>
<p>出问题时则是：</p>
<pre><code>catalog/product/save      301
catalog/product/save      302</code></pre>
<p>第二次 save 已经变成重定向后的请求，没有原来的表单数据，所以 Magento 才说没有数据可保存。这个现象和 PHP 的 <code>post_max_size</code> 超限不一样；超限时通常能看到请求大小异常，而这里最明显的证据就是多出来的 301。</p>
<h3>顺着Location头查是谁改了后台地址</h3>
<p>点开 301 响应，看 <code>Location</code> 到底多了什么。常见情况是少了 Store Code、HTTP 被强制跳到 HTTPS，或者反向代理传进来的 Host 与后台 Base URL 不一致。</p>
<p>如果启用了 Add Store Code to URLs，还要检查 Web Server / Nginx 配置是否把后台请求重写到了另一个不带 Store Code 的地址。站点放在负载均衡后面时，再确认代理有没有正确传递：</p>
<pre><code>proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;</code></pre>
<p>不要先改 Product Save 控制器。先把保存请求的最终 URL 调整成一次就能命中的地址，再清配置缓存并重新登录后台。Network 中 <code>catalog/product/save</code> 直接返回 302，商品内容也能重新读出来，这个问题才算处理完。</p>]]></description>
      <pubDate>Fri, 31 Oct 2025 02:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2执行setup:di:compile报Class Factory does not exist，到底是没生成还是类名写错？]]></title>
      <link>https://www.360magento.com/blog/factory-class-does-not-exist-di-compile/</link>
      <description><![CDATA[<p>编译时报
<code>Class Vendor\Module\Model\SomethingFactory does not exist</code>，很多人的第一反应是删除
<code>generated</code>
再编译。这个办法只对“生成目录不可写或旧代码残留”有效。如果源类名称、命名空间或
Composer
自动加载本身就有问题，清十次生成目录也不会好。先分清报错的是“应该由
Magento 生成的 Factory”，还是“项目里本来就该存在的普通类”。</p>
<h3
id="先去掉factory后缀确认源类能被自动加载">先去掉Factory后缀，确认源类能被自动加载</h3>
<p>例如报错是：</p>
<pre class="text"><code>Class Vendor\Catalog\Model\FeedFactory does not exist</code></pre>
<p>Magento 能生成 <code>FeedFactory</code> 的前提是
<code>Vendor\Catalog\Model\Feed</code> 可以被 Composer
找到。依次检查：</p>
<pre class="bash"><code>test -f app/code/Vendor/Catalog/Model/Feed.php &amp;&amp; echo found
php -l app/code/Vendor/Catalog/Model/Feed.php
composer dump-autoload -o
php -r &quot;require &#39;app/bootstrap.php&#39;; var_dump(class_exists(&#39;Vendor\\Catalog\\Model\\Feed&#39;));&quot;</code></pre>
<p>最后一条如果返回
false，问题还没到代码生成阶段。检查文件名大小写、namespace、类名以及模块是否真的存在。Linux
区分大小写，本地 macOS 能跑不代表服务器也能加载。</p>
<h3
id="连续大写缩写最容易让文件名和类名对不上">连续大写缩写最容易让文件名和类名对不上</h3>
<p>像 <code>WeatherDataDBDetails</code>
这种命名，看起来没有拼错，但文件、类型声明、构造参数和引用处只要有一处写成
<code>WeatherDataDbDetails</code>，开发机上可能侥幸通过，Linux
编译就会失败。不要靠肉眼来回看，直接搜索所有声明和引用：</p>
<pre class="bash"><code>rg -n &#39;WeatherData(DB|Db)Details&#39; app/code</code></pre>
<p>比较稳的做法是按项目约定统一缩写写法，例如把 <code>DB</code> 当作
<code>Db</code>，然后让文件名、类名、<code>use</code>、XML
和构造参数完全一致。修改大小写时，Git
在不区分大小写的文件系统上可能不记录变化，可以通过中间文件名完成
rename。</p>
<h3
id="源类能加载再查generated目录的属主和残留">源类能加载，再查generated目录的属主和残留</h3>
<p>Magento 2.2 及以后通常在 <code>generated/code</code> 生成
Factory、Proxy 和 Interceptor。先看运行编译的用户是否有权限：</p>
<pre class="bash"><code>id
namei -l generated/code
find generated/code -maxdepth 3 ! -user deploy -ls | head</code></pre>
<p>不要直接
<code>chmod -R 777 generated</code>。应该让固定的部署用户拥有目录，并让
Web 用户按部署模型获得需要的读取权限。确认当前没有其他发布或 PHP
进程正在生成代码后，再清理旧产物并重新编译：</p>
<pre class="bash"><code>find generated/code generated/metadata -mindepth 1 -delete
php bin/magento setup:di:compile</code></pre>
<h3
id="如果报错类属于已经卸载的模块查配置和缓存残留">如果报错类属于已经卸载的模块，查配置和缓存残留</h3>
<p>第三方模块从 Composer
移除后，<code>app/etc/config.php</code>、其他模块的
<code>di.xml</code>、插件声明或编译缓存可能仍引用旧类。用完整类名搜索代码和配置：</p>
<pre class="bash"><code>rg -n &#39;OldVendor\\OldModule|OldClass&#39; app/code app/etc vendor composer.*</code></pre>
<p>确认模块确实已卸载后，修正模块列表和依赖，再按当前环境清配置缓存。Redis
是共享缓存时只删除本项目使用的 cache database 或 key
前缀，不要在一台承载多个站点的 Redis 上随手 <code>FLUSHALL</code>。</p>
<p>最终判断很直接：源类 <code>class_exists()</code> 为
true、生成目录可写、旧模块引用已清干净，<code>setup:di:compile</code>
才有可能稳定通过。Factory
不存在只是结果，真正要修的是它为什么没法被生成。</p>]]></description>
      <pubDate>Thu, 30 Oct 2025 06:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2升级后报Unable to unserialize value，怎么找到数据库里的旧序列化数据？]]></title>
      <link>https://www.360magento.com/blog/unable-to-unserialize-find-legacy-data/</link>
      <description><![CDATA[<p>Magento 老版本和一些扩展曾把 PHP serialize
字符串写进数据库，新版本改用 JSON 反序列化后，读取旧值就会报
<code>Unable to unserialize value</code> 或
<code>Syntax error</code>。最危险的“修复”是直接改
<code>vendor/magento/framework/Serialize/Serializer/Json.php</code>，让它失败后自动尝试
PHP
<code>unserialize()</code>。这样会把脏数据问题扩散到整个系统，也让后续升级更难判断。</p>
<h3 id="先从堆栈找到是谁在读这段值">先从堆栈找到是谁在读这段值</h3>
<p>异常最后落在 <code>Json.php</code>
不代表根因在那里。从调用栈向上找第一个具体模块、配置路径或数据模型。例如错误只在编辑客户时出现，就优先查客户扩展属性；只在结账页出现，则查支付、配送或营销模块读取的配置和缓存。</p>
<p>临时调试可以在调用方记录字段主键和原始值长度，但不要把客户数据直接写入日志。拿到疑似值后分别验证：</p>
<pre class="bash"><code>php -r &#39;$v=$argv[1]; json_decode($v, true); var_dump(json_last_error_msg());&#39; &#39;待检查内容&#39;</code></pre>
<p>PHP 序列化字符串常以
<code>a:</code>、<code>s:</code>、<code>i:</code>、<code>O:</code>
开头，但不能只靠前缀批量判断，更不能对不可信内容使用允许对象实例化的
<code>unserialize()</code>。</p>
<h3 id="确认字段后先统计再迁移">确认字段后，先统计再迁移</h3>
<p>假设已定位到某扩展表的 <code>options</code>
字段，先查总量、空值和样本：</p>
<pre class="sql"><code>SELECT COUNT(*) AS total,
       SUM(options IS NULL OR options = &#39;&#39;) AS empty_values
FROM vendor_module_item;

SELECT entity_id, LEFT(options, 120)
FROM vendor_module_item
WHERE options IS NOT NULL AND options &lt;&gt; &#39;&#39;
LIMIT 20;</code></pre>
<p>不要因为某个回答说“truncate
这张表”就照做。表中可能同时保存业务状态或订阅关系。最稳妥的是由扩展升级脚本逐行读取旧格式，使用受限的
<code>unserialize($value, ['allowed_classes' =&gt; false])</code>
转成数组，再编码为 JSON，并记录成功、跳过和失败数量。</p>
<h3 id="数据迁移要能停能重跑能核对">数据迁移要能停、能重跑、能核对</h3>
<p>先备份目标表；按主键分批处理；每批提交；转换前后保留行数和校验信息。遇到无法解析的值不要写成空数组掩盖问题，而是把主键放进失败清单，确认它究竟是截断数据、双重序列化还是扩展版本不匹配。</p>
<h3 id="修完数据再清相关缓存">修完数据再清相关缓存</h3>
<p>如果错误值来自 <code>core_config_data</code>，清 config
cache；来自模块缓存，则清对应 cache type。不要把“全站
cache:flush”当成数据修复。最终要重复触发原页面或命令，并在日志中确认没有新的反序列化异常。正确结果是数据库里的旧格式被一次性迁移，而不是框架从此默默兼容所有坏值。</p>]]></description>
      <pubDate>Wed, 29 Oct 2025 02:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2多个Data Patch有先后依赖，怎么保证setup:upgrade按正确顺序执行？]]></title>
      <link>https://www.360magento.com/blog/data-patch-dependency-execution-order/</link>
      <description><![CDATA[<p>一个模块里有三个 Data
Patch：先创建默认数据，再补关联关系，最后迁移旧配置。只把类名写成
<code>Patch01</code>、<code>Patch02</code>
并不能保证执行顺序，文件时间也不可靠。Magento 判断顺序看的是 patch
之间声明的依赖。</p>
<h3
id="后执行的patch明确返回它依赖的类">后执行的Patch明确返回它依赖的类</h3>
<pre class="php"><code>use Magento\Framework\Setup\Patch\DataPatchInterface;

class AssignDefaultGroup implements DataPatchInterface
{
    public static function getDependencies(): array
    {
        return [
            CreateDefaultGroup::class,
        ];
    }

    public function apply(): void
    {
        // CreateDefaultGroup 已完成后再写关联数据
    }

    public function getAliases(): array
    {
        return [];
    }
}</code></pre>
<p>如果 Patch C 必须在 A、B
都完成之后执行，就同时返回两个类。依赖可以跨模块，但对方模块也应该在
<code>module.xml</code> 的 sequence 或 Composer
依赖中体现安装关系，避免代码根本未安装。</p>
<h3 id="只给真正的数据依赖排序">只给真正的数据依赖排序</h3>
<p>两个 Patch
操作互不相关的表，就不必为了“看起来整齐”串成一条长链。依赖越多，循环依赖和后续重构越麻烦。判断标准很简单：前一个
Patch 没有执行，后一个是否必然失败或产生错误数据？只有答案为是，才写进
<code>getDependencies()</code>。</p>
<h3
id="patch_list有记录后改apply不会重新执行">patch_list有记录后，改apply不会重新执行</h3>
<pre class="sql"><code>SELECT patch_name
FROM patch_list
WHERE patch_name LIKE &#39;Vendor\\Module\\Setup\\Patch\\Data\\%&#39;;</code></pre>
<p>Data Patch 成功后会记录类名。你后来修改 <code>apply()</code>，Magento
不会再次执行它。开发环境可以在确认数据可回滚后删除对应记录重测；生产环境不要随便删
<code>patch_list</code>，应该新增一个 Patch 来做后续变更。</p>
<p>如果只是给类改名，需要通过 <code>getAliases()</code>
返回旧类名，避免升级站点把同一份变更再跑一次。</p>
<h3 id="在空库和升级库各跑一遍">在空库和升级库各跑一遍</h3>
<p>空库测试能验证完整依赖排序，已有数据库升级测试能验证历史 patch
记录、类重命名和新增 patch
的组合。执行后除了看命令成功，还要核对业务表和
<code>patch_list</code>。Patch
的目标是可重复部署同一个结果，不是依赖某台服务器恰好按文件名顺序扫描。</p>]]></description>
      <pubDate>Tue, 28 Oct 2025 07:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2怎么把支付模块日志单独写到payment.log，不要全塞进system.log？]]></title>
      <link>https://www.360magento.com/blog/separate-payment-module-log-file/</link>
      <description><![CDATA[<p>调支付接口时，如果请求、回调和状态变化都写进
<code>system.log</code>，定位一笔订单很痛苦。临时用
<code>file_put_contents()</code>
虽然快，但绕过日志级别、异常处理和轮转。比较稳的方式是给模块配置独立的
Monolog Handler，再把这个 Logger 只注入需要的类。</p>
<h3
id="handler只负责文件和最低日志级别">Handler只负责文件和最低日志级别</h3>
<pre class="php"><code>namespace Vendor\Payment\Logger;

use Magento\Framework\Logger\Handler\Base;
use Monolog\Level;

class Handler extends Base
{
    protected $loggerType = Level::Debug;
    protected $fileName = &#39;/var/log/payment.log&#39;;
}</code></pre>
<p>不同 Magento/Monolog 版本对 level
常量的类型要求可能不同。如果项目仍使用 Monolog 1/2，就按当前
<code>Magento\Framework\Logger\Handler\Base</code> 的属性定义使用
<code>Logger::DEBUG</code>。不要从网上复制一段代码后跳过编译检查。</p>
<h3
id="用dixml组装一个只带这个handler的logger">用di.xml组装一个只带这个Handler的Logger</h3>
<pre class="xml"><code>&lt;virtualType name=&quot;VendorPaymentLogger&quot; type=&quot;Magento\Framework\Logger\Monolog&quot;&gt;
    &lt;arguments&gt;
        &lt;argument name=&quot;name&quot; xsi:type=&quot;string&quot;&gt;payment&lt;/argument&gt;
        &lt;argument name=&quot;handlers&quot; xsi:type=&quot;array&quot;&gt;
            &lt;item name=&quot;payment&quot; xsi:type=&quot;object&quot;&gt;Vendor\Payment\Logger\Handler&lt;/item&gt;
        &lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/virtualType&gt;

&lt;type name=&quot;Vendor\Payment\Model\GatewayClient&quot;&gt;
    &lt;arguments&gt;
        &lt;argument name=&quot;logger&quot; xsi:type=&quot;object&quot;&gt;VendorPaymentLogger&lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/type&gt;</code></pre>
<p>业务类仍然依赖 <code>Psr\Log\LoggerInterface</code>，不用把自定义
Logger 类写死：</p>
<pre class="php"><code>public function __construct(private LoggerInterface $logger) {}

$this-&gt;logger-&gt;info(&#39;payment request started&#39;, [
    &#39;order_id&#39; =&gt; $orderId,
    &#39;request_id&#39; =&gt; $requestId,
]);</code></pre>
<h3
id="日志能定位问题但不能把敏感数据原样落盘">日志能定位问题，但不能把敏感数据原样落盘</h3>
<p>支付日志至少要过滤卡号、CVV、Authorization、Cookie、完整 access token
和客户密码。请求体最好建立白名单，只记录订单号、网关请求号、金额、币种、HTTP
状态和耗时。失败响应也不要整包输出，第三方接口有时会回显用户资料。</p>
<h3 id="用一笔可控测试订单验证四件事">用一笔可控测试订单验证四件事</h3>
<p>编译并清配置缓存后，检查 <code>var/log/payment.log</code>
是否由正确用户创建、正常请求是否写入、异常是否包含 correlation
id、<code>system.log</code> 是否没有重复一份。最后配置 logrotate
或容器日志采集，避免高峰期把磁盘写满。独立日志的价值是快速串起一笔交易，而不是把所有对象
dump 得越多越好。</p>]]></description>
      <pubDate>Mon, 27 Oct 2025 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2执行setup:upgrade提示pub/static没有写权限，别再直接chmod 777了]]></title>
      <link>https://www.360magento.com/blog/pub-static-write-permission-without-777/</link>
      <description><![CDATA[<p><code>Missing write permissions to the following directories: pub/static</code>
看起来是权限不足，但把目录改成 777 仍可能报错。Magento
会递归检查目录中的文件和符号链接；旧 release
留下的失效软链、文件属主混乱、只读挂载，都可能让整个检查失败。先找出具体是哪一个节点不可写，比整站放开权限可靠得多。</p>
<h3 id="先确认现在是谁在执行命令">先确认现在是谁在执行命令</h3>
<pre class="bash"><code>id
ps -eo user,group,cmd | rg &#39;php-fpm|apache2|httpd&#39;
namei -l pub/static
find pub/static -maxdepth 3 \( ! -user deploy -o ! -group www-data \) -ls | head -50</code></pre>
<p>示例里的 <code>deploy</code> 和 <code>www-data</code>
要换成服务器真实用户。重点是发布用户能创建文件，PHP-FPM
用户能读取；如果运行时也需要生成静态文件，则双方要通过同一组获得写权限。不要混用
root、部署账号和 Web 用户轮流跑 Magento
命令，否则下一次发布还会反复变属主。</p>
<h3
id="777也无效时检查失效软链和挂载">777也无效时，检查失效软链和挂载</h3>
<pre class="bash"><code>find -L pub/static -type l -print
findmnt -T pub/static
getfacl -p pub/static | sed -n &#39;1,40p&#39;</code></pre>
<p>旧版本或开发模式可能留下指向已删除源文件的软链。权限检查递归走到这里会失败，即使父目录是
777 也没用。容器环境还要看 <code>pub/static</code> 是否被只读 volume
覆盖，宿主机权限和容器内 uid 是否一致。</p>
<h3 id="确认可以重建后再清静态产物">确认可以重建后再清静态产物</h3>
<p><code>pub/static</code> 属于生成内容，但 <code>.htaccess</code> 在
Apache
环境中可能仍需要保留。不要无脑删除整个目录。可以先备份并仅清生成内容：</p>
<pre class="bash"><code>find pub/static -mindepth 1 ! -name &#39;.htaccess&#39; -delete
find var/view_preprocessed -mindepth 1 -delete</code></pre>
<p>如果目录里混入了人工上传文件，先停下来确认发布流程，不能因为它“理论上可生成”就直接清空。</p>
<h3 id="把属主和组一次修到发布模型上">把属主和组一次修到发布模型上</h3>
<p>常见做法是代码归部署用户、可写目录归共享组，并设置 setgid
让新文件继承组：</p>
<pre class="bash"><code>chown -R deploy:www-data pub/static var generated
find pub/static var generated -type d -exec chmod 2775 {} +
find pub/static var generated -type f -exec chmod 0664 {} +</code></pre>
<p>上面只是模型，具体权限要按主朸隔离策略调整。修完后用部署用户依次跑
<code>setup:upgrade</code> 和静态资源部署，再用 PHP-FPM
用户做一次只读访问验证。问题解决的标准不是命令暂时通过，而是下一次发布不会再次产生
root 属主文件。</p>]]></description>
      <pubDate>Fri, 24 Oct 2025 06:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2自定义CLI报Area code is not set，为什么不能在构造函数里setAreaCode？]]></title>
      <link>https://www.360magento.com/blog/cli-area-code-not-set-constructor/</link>
      <description><![CDATA[<p>自定义命令里调用客户、税率或订单服务时，常见异常是
<code>Area code is not set</code>。把
<code>$state-&gt;setAreaCode('adminhtml')</code>
塞进构造函数，当前命令也许能跑，但随后执行任意 <code>bin/magento</code>
命令又可能变成 <code>Area code is already set</code>。原因是 Magento
启动 CLI
时会实例化命令列表，构造函数不是“只有执行这条命令时才运行”。</p>
<h3
id="先看是哪条依赖在构造阶段启动了session">先看是哪条依赖在构造阶段启动了Session</h3>
<p>从异常栈往上找第一个自定义类。如果命令构造函数直接注入了重量级服务，该服务的依赖链可能创建
customer session，而 session 必须知道当前 area。此时问题不只是少一行
<code>setAreaCode</code>，而是对象创建得太早。</p>
<p>容易触发的写法类似：</p>
<pre class="php"><code>public function __construct(
    private TaxCalculationInterface $taxCalculation,
    AppState $appState
) {
    $appState-&gt;setAreaCode(Area::AREA_ADMINHTML);
    parent::__construct();
}</code></pre>
<h3
id="把area设置移到execute构造函数只保存依赖">把area设置移到execute，构造函数只保存依赖</h3>
<pre class="php"><code>protected function execute(InputInterface $input, OutputInterface $output): int
{
    $this-&gt;appState-&gt;setAreaCode(Area::AREA_ADMINHTML);
    $this-&gt;runImport();
    return Command::SUCCESS;
}</code></pre>
<p>area 要按实际业务选择。读取前台价格、客户组上下文时未必应该用
<code>adminhtml</code>；纯全局处理也不要为了消掉异常随便选一个
area。</p>
<h3
id="这段逻辑可能被别处调用就用emulateareacode包住">这段逻辑可能被别处调用，就用emulateAreaCode包住</h3>
<pre class="php"><code>return $this-&gt;appState-&gt;emulateAreaCode(
    Area::AREA_ADMINHTML,
    fn () =&gt; $this-&gt;runImport()
);</code></pre>
<p>emulation
的好处是执行完成后恢复原状态，适合共享服务或测试。但如果依赖在构造阶段已经启动
session，emulation 仍然来不及，这时要把该依赖改成 Proxy 或
Factory，让真实对象到 <code>execute()</code> 里才创建。</p>
<h3 id="修完要跑的不只是这条命令">修完要跑的不只是这条命令</h3>
<p>先执行目标命令，再跑：</p>
<pre class="bash"><code>php bin/magento list
php bin/magento cache:status
php bin/magento setup:di:compile</code></pre>
<p><code>list</code>
很重要，因为它会加载全部命令，最容易暴露“构造函数里抢先设置
area”的问题。真正稳定的修复是控制初始化时机，而不是捕获
<code>Area code is already set</code> 后假装没事。</p>]]></description>
      <pubDate>Thu, 23 Oct 2025 02:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2报Required parameter theme_dir was not passed，怎么找到残留的旧主题？]]></title>
      <link>https://www.360magento.com/blog/required-theme-dir-find-removed-theme/</link>
      <description><![CDATA[<p>这个错误经常出现在删掉一个旧主题、切换分支或从另一台服务器恢复数据库之后。文件系统里已经没有主题目录，但数据库仍保留主题注册记录，或者商店配置仍指向旧的
<code>theme_id</code>。Magento
解析主题继承关系时找不到物理目录，最后只抛出 <code>theme_dir</code>
参数缺失。</p>
<h3 id="先从异常栈里拿到theme-id或theme-path">先从异常栈里拿到theme
id或theme path</h3>
<p>不要一上来清整张 <code>theme</code> 表。先看
<code>var/log/exception.log</code>、部署命令输出以及错误前后的 theme
信息，再查询：</p>
<pre class="sql"><code>SELECT theme_id, parent_id, theme_path, theme_title, area, type, code
FROM theme
ORDER BY theme_id;</code></pre>
<p>然后把 <code>theme_path</code> 与
<code>app/design/frontend</code>、<code>app/design/adminhtml</code>
下的实际目录逐一对上。还要检查 <code>registration.php</code> 和
<code>theme.xml</code> 是否在，文件夹存在不等于主题注册完整。</p>
<h3
id="再查哪个scope还指着这个theme_id">再查哪个scope还指着这个theme_id</h3>
<pre class="sql"><code>SELECT config_id, scope, scope_id, path, value
FROM core_config_data
WHERE path = &#39;design/theme/theme_id&#39;;</code></pre>
<p>如果旧主题 ID 只出现在某个 Store View，首页可能正常，而那个 Store
View 一打开就报错。先明确 scope，不能只改 default 级配置。</p>
<h3
id="主题本来就该存在就把代码和依赖补回来">主题本来就该存在，就把代码和依赖补回来</h3>
<p>如果是发布漏文件或 Composer
包没有安装完整，正确处理是恢复主题代码，再运行：</p>
<pre class="bash"><code>php bin/magento setup:upgrade
php bin/magento cache:clean config layout</code></pre>
<p>同时确认父主题也存在。只把数据库里的 <code>parent_id</code> 改成
NULL，虽然可能暂时不报错，但会破坏继承链，CSS
和模板随后会出现更隐蔽的问题。</p>
<h3
id="确认主题已经下线才清配置和注册记录">确认主题已经下线，才清配置和注册记录</h3>
<p>先在后台或配置表把相关 Store View 切到仍然存在的主题，再备份
<code>theme</code> 表，最后删除明确无用的那一条注册记录。不要按
<code>theme_title</code> 模糊删除，也不要清空整表。处理后清配置与 layout
缓存，再执行一次静态资源部署。</p>
<p>验证时除了前台，还要运行
<code>php bin/magento setup:di:compile</code>
或计划中的正式发布命令。因为有些残留只会在编译、静态资源收集阶段触发，浏览几个页面正常并不能证明主题注册已经干净。</p>]]></description>
      <pubDate>Wed, 22 Oct 2025 07:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2只改了一个前台主题，static-content:deploy怎么只部署这个主题？]]></title>
      <link>https://www.360magento.com/blog/deploy-only-one-frontend-theme/</link>
      <description><![CDATA[<p>生产站改了一点 CSS，如果直接运行不带参数的
<code>setup:static-content:deploy</code>，Magento
会把后台主题、Luma、多个语言包和所有自定义主题一起编译。站点越大，发布时间越长。实际只改一个主题时，部署范围可以收得很小，但
theme、area 和 locale 最好一起写清楚。</p>
<h3 id="先确认主题代码和商店语言">先确认主题代码和商店语言</h3>
<p>主题名不是目录最后一级，而是注册时的
<code>Vendor/theme</code>。语言也要以商店实际 locale 为准：</p>
<pre class="bash"><code>php bin/magento config:show general/locale/code
php bin/magento theme:uninstall --help</code></pre>
<p>第二条只是利用命令帮助确认当前版本的主题相关能力，不要真的执行卸载。多
Store View 环境还应从后台配置或数据库确认各 scope 的
locale，不能假设全部是 <code>en_US</code>。</p>
<h3 id="生产模式下把范围写完整">生产模式下把范围写完整</h3>
<p>例如只部署 <code>Acme/shop</code> 的中文和英文前台资源：</p>
<pre class="bash"><code>php bin/magento setup:static-content:deploy \
  --area frontend \
  --theme Acme/shop \
  zh_Hans_CN en_US \
  --jobs 4</code></pre>
<p>如果服务器 CPU 和内存不宽裕，<code>--jobs</code>
不要盲目开大。主题继承的父主题资源会由依赖关系处理，通常不需要再把 Luma
单独列一遍。</p>
<h3
id="开发模式不要拿生产命令反复硬跑">开发模式不要拿生产命令反复硬跑</h3>
<p>开发模式下静态资源可以按请求生成。此时 CSS
改动看不到，先检查浏览器拿到的文件路径、静态文件签名和预处理缓存，而不是每次都全量
deploy。生产模式才把静态资源部署当作发布步骤，并尽量在维护窗口或新
release 目录里完成。</p>
<h3 id="部署完成后别只看命令返回0">部署完成后别只看命令返回0</h3>
<p>检查目标目录是否真的生成：</p>
<pre class="bash"><code>find pub/static/frontend/Acme/shop -maxdepth 2 -type d</code></pre>
<p>再用浏览器 Network 查看 CSS URL 对应的 theme 和
locale。若启用了静态内容版本号，还要刷新页面缓存和 CDN，避免 HTML
仍引用旧版本。只部署一个主题能缩短发布时间，但前提是本次改动没有同时影响后台资源、共享语言包或其他主题；涉及模块级
<code>view/frontend</code>
文件时，也要确认所有使用该模块资源的主题是否都需要重新部署。</p>]]></description>
      <pubDate>Tue, 21 Oct 2025 01:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2迁移网站后一直ERR_TOO_MANY_REDIRECTS，先查Cookie还是HTTPS配置？]]></title>
      <link>https://www.360magento.com/blog/too-many-redirects-cookie-domain-https-proxy/</link>
      <description><![CDATA[<p>网站从正式域名复制到测试域名后，前台和后台都可能陷入重定向循环。这个问题不能靠反复清缓存碰运气，先看清楚到底是哪两个地址在互相跳。Cookie
域名、Base URL、反向代理传来的 HTTPS 标记，都会造成同一个表象。</p>
<h3 id="先把跳转链打印出来">先把跳转链打印出来</h3>
<p>浏览器只显示“重定向次数过多”，信息不够。先在服务器外执行：</p>
<pre class="bash"><code>curl -I -L --max-redirs 10 https://staging.example.com/</code></pre>
<p>如果 <code>http</code> 和 <code>https</code> 来回切换，优先查代理和
secure 配置；如果 URL 没变但不断返回 302，通常更像 Cookie、Store Code
或后台会话问题。也可以去掉 <code>-L</code>，逐次看 <code>Location</code>
和 <code>Set-Cookie</code>。</p>
<h3
id="数据库是从旧站导入的先查cookie域名">数据库是从旧站导入的，先查Cookie域名</h3>
<pre class="sql"><code>SELECT scope, scope_id, path, value
FROM core_config_data
WHERE path IN (
  &#39;web/cookie/cookie_domain&#39;,
  &#39;web/unsecure/base_url&#39;,
  &#39;web/secure/base_url&#39;,
  &#39;web/secure/use_in_frontend&#39;,
  &#39;web/secure/use_in_adminhtml&#39;,
  &#39;web/secure/offloader_header&#39;
)
ORDER BY path, scope, scope_id;</code></pre>
<p><code>web/cookie/cookie_domain</code>
如果还写着旧域名，浏览器不会把会话 Cookie 发给新站。这里还要留意
website/store 级配置是否覆盖 default 值。测试环境没有特殊要求时，可以把
Cookie Domain 留空，让 Magento 按当前 Host
生成；需要显式设置时，只填域名，不要带协议、路径或端口。</p>
<h3
id="https在负载均衡器终止就核对offloader-header">HTTPS在负载均衡器终止，就核对offloader
header</h3>
<p>常见架构是用户访问 HTTPS，但 Nginx、Ingress 或 CDN 回源 Magento
时使用 HTTP。Magento 如果不知道外层请求本来是 HTTPS，就会再次跳到
HTTPS，代理又回源 HTTP，于是形成循环。</p>
<p>先确认代理实际传的是哪个头：</p>
<pre class="nginx"><code>proxy_set_header X-Forwarded-Proto $scheme;</code></pre>
<p>Magento 的 <code>web/secure/offloader_header</code>
要与之匹配，通常是
<code>X-Forwarded-Proto</code>。不要因为看到别人配置了
<code>SSL_OFFLOADED</code> 就直接照搬，关键是 Web 服务器交给 PHP
的请求头名称和 Magento 配置必须一致。</p>
<h3
id="修改后只清配置缓存再删旧cookie">修改后只清配置缓存，再删旧Cookie</h3>
<pre class="bash"><code>php bin/magento cache:clean config full_page</code></pre>
<p>用无痕窗口重新访问，避免旧域名 Cookie
干扰判断。如果后台仍循环，再检查 <code>env.php</code> 中的后台前缀、Web
服务器是否额外做了 www 跳转，以及 CDN 是否也配置了一层 HTTP 到 HTTPS
规则。把每一跳的 <code>Location</code>
记录下来，通常两三次就能看出是谁在重复改协议或域名。</p>]]></description>
      <pubDate>Mon, 20 Oct 2025 06:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2不需要商品对比和Wishlist，怎么关掉才不会影响其他功能？]]></title>
      <link>https://www.360magento.com/blog/disable-compare-wishlist-without-breaking-modules/</link>
      <description><![CDATA[<p>有些站只卖很少几个产品，商品对比和Wishlist基本用不上。最容易想到的做法是直接禁用
<code>Magento_Catalog</code> 或
<code>Magento_Wishlist</code>，但前者根本不能动，后者也可能被主题、客户中心或第三方模块依赖。我的处理原则是：业务只是“不显示”，就只处理前台入口，不把整个模块从系统里拔掉。</p>
<h3
id="先把页面上的入口找全别只删右侧栏">先把页面上的入口找全，别只删右侧栏</h3>
<p>商品对比不只出现在一个位置。分类列表、搜索结果、商品详情、顶部链接和
compare sidebar 都可能有入口；Wishlist
还会出现在客户中心、商品卡片和详情页。先在当前主题及父主题里查 block
名称：</p>
<pre class="bash"><code>rg &#39;catalog\.compare|product\.compare|wishlist&#39; app/design/frontend vendor/magento/module-*/view/frontend/layout</code></pre>
<p>这里不要直接改 <code>vendor</code>。搜索的目的只是确认当前 Magento
版本使用了哪些 block 名，真正的覆盖文件放到自定义主题。</p>
<h3
id="只是隐藏功能时用layout-remove掉对应block">只是隐藏功能时，用layout
remove掉对应block</h3>
<p>例如在主题的 <code>Magento_Catalog/layout/default.xml</code>
中处理公共区域：</p>
<pre class="xml"><code>&lt;?xml version=&quot;1.0&quot;?&gt;
&lt;page xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
      xsi:noNamespaceSchemaLocation=&quot;urn:magento:framework:View/Layout/etc/page_configuration.xsd&quot;&gt;
    &lt;body&gt;
        &lt;referenceBlock name=&quot;catalog.compare.sidebar&quot; remove=&quot;true&quot;/&gt;
        &lt;referenceBlock name=&quot;catalog.compare.link&quot; remove=&quot;true&quot;/&gt;
        &lt;referenceBlock name=&quot;wishlist_sidebar&quot; remove=&quot;true&quot;/&gt;
    &lt;/body&gt;
&lt;/page&gt;</code></pre>
<p>商品卡片里的“加入对比”和“加入愿望单”不一定都是独立
block。有的主题在模板或 UI component 中直接输出按钮，所以公共 layout
清完之后还要检查分类页、搜索页和商品详情页。自定义主题如果继承了第三方主题，也要以实际渲染出来的
layout handle 为准，不能照抄一组 block 名就认为结束了。</p>
<h3 id="不要用css把按钮盖住">不要用CSS把按钮盖住</h3>
<p><code>display:none</code>
只能让用户看不见，HTML、初始化脚本以及相关接口仍然存在。后续换主题、做无障碍检查或让搜索引擎抓页面时，很容易再次暴露。能在
layout 阶段移除就不要用
CSS；模板中直接输出的入口，则在自定义主题内覆盖最小模板片段。</p>
<h3
id="清完缓存后按游客和登录用户各走一遍">清完缓存后按游客和登录用户各走一遍</h3>
<pre class="bash"><code>php bin/magento cache:clean layout block_html full_page</code></pre>
<p>然后至少检查首页、分类页、搜索页、商品详情、客户中心和购物车。浏览器里再搜一次
<code>compare</code>、<code>wishlist</code>，确认没有遗留链接和 JS
报错。这样做保留了模块依赖关系，只收掉用户入口，后面换主题或恢复功能也容易回滚。</p>]]></description>
      <pubDate>Fri, 17 Oct 2025 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2消息队列Consumer显示running，为什么RabbitMQ里的消息一直不减少？]]></title>
      <link>https://www.360magento.com/blog/consumer-running-rabbitmq-messages-not-decreasing/</link>
      <description><![CDATA[<p>Supervisor 显示 consumer 是 RUNNING，RabbitMQ 队列里的 Ready 消息却一直上涨。RUNNING 只表示进程没退出，不表示它正在消费正确队列，也不表示消息处理能完成。</p>
<h2>先确认这个进程监听的是哪一个consumer</h2>
<pre><code>ps -ef | grep '[q]ueue:consumers:start'
bin/magento queue:consumers:list
supervisorctl status</code></pre>
<p>对照 Supervisor 配置里的 consumer 名称、Magento 配置和 RabbitMQ 实际队列绑定。配置改过但旧进程没重启时，它仍可能运行旧 consumer 或旧 release。多套环境共用 RabbitMQ vhost，也可能看错队列。</p>
<h2>在RabbitMQ里分开看Ready和Unacked</h2>
<p>Ready 高、Unacked 为 0，通常是没有消费者真正订阅；Unacked 持续很高，说明消息已取走但处理没完成或没有 ack。结合 connection、channel、consumer tag 和 hostname，确认是哪台机器占着消息。</p>
<p>如果 Ready 在下降但业务完全没有结果，别只看队列曲线，继续查消息是不是被路由到错误 consumer 或失败队列。交换机、routing key 与 queue binding 任何一个不一致，都会让“有消费者、也有消息”这两个事实彼此无关。</p>
<p>如果只有一条消息长期 unacked，抓 consumer 的 PHP 调用栈或打开针对性日志。外部 API 没超时、数据库锁等待、图片处理卡住，都会让进程看着 alive，实际上停在同一条消息上。</p>
<p>Unacked 数量刚好等于 worker 数乘以 prefetch 时，通常是所有 worker 都卡在处理阶段。此时继续加进程只会拿走更多消息并占用内存，应该先找到单条消息为什么不结束。</p>
<h2>消息反复回队列时，先保存失败原因</h2>
<p>消费者抛异常后立即 nack/requeue，Ready 数可能几乎不变，但日志会重复同一消息。记录 message ID、topic、重试次数和异常，设置合理的重试与失败队列，避免毒消息无限占满 worker。</p>
<h2>重启前先判断会不会重复执行</h2>
<p>直接 kill 卡住的 consumer 会让未确认消息重新投递。如果处理过程已经调用外部系统，只是 ack 前卡住，重投可能产生重复订单、重复邮件或重复库存动作。业务处理必须使用稳定键做幂等。</p>
<p>修复后观察 Ready、Unacked 和 ack rate，而不是只看 Supervisor 变绿。再投一条可识别的测试消息，确认正确 consumer 在预期时间处理，并完成一次滚动重启测试。这样才能证明进程管理和消费链路都正常。</p>
<p>最后把 Supervisor 的退出码、启动目录、PHP 路径和最大消息数写清楚。发布后主动滚动重启长期 consumer，确保它们加载的是新 release；否则 Web 已经运行新代码，队列进程还在执行旧类，问题会表现得非常随机。</p>]]></description>
      <pubDate>Thu, 16 Oct 2025 06:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2执行setup:upgrade报Duplicate column name，数据库已经加过字段怎么办？]]></title>
      <link>https://www.360magento.com/blog/setup-upgrade-duplicate-column-name-schema-patch/</link>
      <description><![CDATA[<p>部署执行 <code>setup:upgrade</code> 报 <code>Duplicate column name</code>，数据库里确实已经有这个字段。看到重复列不要立刻删字段，先弄清楚列是上一次部署加了一半、人工提前加的，还是两个模块都在声明同名字段。</p>
<h2>先把报错补丁和真实列定义对上</h2>
<p>从异常栈找到具体 Schema Patch、UpgradeSchema 或 declarative schema 文件，再查看数据库列类型、长度、nullable、默认值和索引。字段同名不等于定义一致。</p>
<pre><code>SHOW CREATE TABLE target_tableG
SELECT patch_name
FROM patch_list
WHERE patch_name LIKE '%Vendor\Module%';</code></pre>
<p>patch_list 没记录，但列已经存在，常见原因是补丁执行到 addColumn 后进程中断，事务没有覆盖 DDL，或者有人手工执行了 SQL。此时盲目删除列可能把已经写入的业务数据一起删掉。</p>
<h2>再查有没有第二个模块也在加同名列</h2>
<pre><code>grep -R "column_name" app/code vendor/*/*/etc/db_schema.xml -n
grep -R "addColumn.*column_name" app/code vendor -n</code></pre>
<p>如果两个自定义模块声明同一列，应该确定列归属并合并设计，而不是靠模块加载顺序碰运气。Declarative schema 与旧 UpgradeSchema 同时维护同一字段，也容易在迁移阶段重复。</p>
<h2>处理方式取决于列里有没有数据</h2>
<p>列为空、定义错误且确认没有代码使用时，可以在备份和测试验证后删除，让正式补丁重建。列已有数据且定义与代码一致，更安全的做法通常是让补丁先检测列是否存在，或修复补丁登记状态，但必须确认该补丁除了加列之外没有其他步骤。</p>
<p>不要随便往 patch_list 插一条记录跳过补丁。它可能还创建索引、迁移数据或增加约束，只标记完成会留下半套结构。</p>
<h2>在数据库副本上完整跑一次升级</h2>
<p>修复后从生产结构副本执行 setup:upgrade，检查 db_schema_whitelist、索引和外键，再跑应用回归。最后把人工处理写进部署记录。目标是让下一套相同旧版本数据库也能自动升级，不是只让当前库绕过这一行。</p>]]></description>
      <pubDate>Wed, 15 Oct 2025 01:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2支付平台已经扣款成功，订单为什么还停在Pending Payment？]]></title>
      <link>https://www.360magento.com/blog/payment-captured-order-stuck-pending-payment/</link>
      <description><![CDATA[<p>支付平台后台显示扣款成功，Magento 订单却一直是 Pending Payment。最危险的处理是直接把订单状态改成 Processing，因为这会让页面看起来正常，却可能没有 transaction、invoice，也没有完成后续库存和邮件动作。</p>
<h2>按时间把四段日志拼起来</h2>
<p>我会用 increment_id、支付平台 transaction ID 和 quote/order ID，把“创建支付请求、用户返回页、异步 webhook、Magento 状态更新”放在同一条时间线上。用户关闭返回页不应该影响异步回调，所以不要只查 success URL。</p>
<p>如果网关能看到 webhook 已发送，记录它的 HTTP 状态和响应体。404 是路由不对，401/403 多半是签名或 WAF，500 才进入 Magento 代码异常。返回 200 也不代表业务成功，有些插件捕获异常后仍然响应 200。</p>
<h2>Webhook进来了，就查它为什么没认出这张订单</h2>
<p>对照 merchant account、store scope、订单号字段、金额、币种和签名使用的原始 body。反向代理修改 body、读取流后没有重置、测试与正式密钥混用，都会导致验签失败。</p>
<p>再看 sales_payment_transaction 和 order payment additional information。支付成功事件如果没有保存外部 transaction ID，后续重复回调无法幂等判断，也无法正确 capture 或开票。</p>
<p>有些网关先发 authorized，再发 captured；两个事件可能乱序到达。处理 captured 时如果代码要求订单仍处于某个固定状态，早到或晚到的事件就会被丢弃。应该按外部交易的状态与唯一 ID 判断是否可以推进，而不是只依赖当前 Magento status 文本。</p>
<h2>别把Pending Payment只当成status文本</h2>
<p>检查订单内部 state/status、payment action 是 Authorize 还是 Authorize and Capture，以及插件成功分支实际调用了什么。Authorize 只授权时不一定立即生成发票；Capture 成功却仍 pending，才说明状态机或回调处理断了。</p>
<pre><code>SELECT entity_id, increment_id, state, status, updated_at
FROM sales_order
WHERE increment_id = '000000123';</code></pre>
<h2>修复后重放同一个Webhook</h2>
<p>第一次回放应把订单推进到正确状态并写入交易；第二次回放必须安全返回，不能重复开票、扣库存或发邮件。再测金额不一致、签名错误和回调延迟。旧订单的数据修复要根据支付平台真实交易逐单处理，不能批量把 Pending Payment 全改成 Processing。</p>]]></description>
      <pubDate>Tue, 14 Oct 2025 07:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2执行composer update后后台白屏，怎么确认到底更新坏了哪个包？]]></title>
      <link>https://www.360magento.com/blog/composer-update-admin-white-screen-find-broken-package/</link>
      <description><![CDATA[<p><code>composer update</code> 没报错，后台却直接白屏。Composer 只保证依赖约束能解出来，不保证新版本扩展一定兼容当前 Magento、PHP 和其他插件。这个时候一直清缓存通常没有信息增量，先把真实异常拿出来。</p>
<h2>先确认是500、502还是200空页面</h2>
<pre><code>curl -I https://shop.example.com/admin-path/
tail -f var/log/exception.log var/log/system.log
journalctl -u php-fpm --since "10 minutes ago"</code></pre>
<p>500 重点看 PHP 异常；502 看 PHP-FPM 是否崩溃或超时；200 但 body 为空，检查 fatal error 是否被输出配置吞掉。生产环境不要打开公开报错页面，日志里按请求时间找。</p>
<h2>直接diff更新前后的composer.lock</h2>
<p>如果目标只是升级一个支付模块，lock 却变了几十个框架包，问题范围已经失控。列出新增、删除和变更版本，再按异常中的类名回到具体包。</p>
<pre><code>composer show --direct
composer why vendor/package
composer why-not vendor/package target-version
composer validate</code></pre>
<p><code>Class not found</code> 先查包、autoload 和模块状态；方法签名不兼容或参数类型错误，通常是扩展与框架版本不匹配。不要直接改 vendor 里的方法，应该锁回兼容版本、升级扩展或应用正式 patch。</p>
<h2>依赖确认没问题，再重建generated和静态资源</h2>
<p>旧 interceptor/proxy 引用了更新前构造函数时，重新编译确实能修。但如果 <code>setup:di:compile</code> 自己报错，就继续修 DI 或依赖，不能删除 generated 后绕过编译上线。</p>
<p>多节点还要滚动重载 PHP-FPM/opcache。代码已经切到新 release，旧 worker 仍执行旧字节码时，会出现某些节点正常、某些节点白屏。</p>
<p>恢复后在干净目录用 lock 文件执行 <code>composer install</code>，再完成编译和基础回归。把这次确切的包版本和修复提交到版本控制，保证下一台机器能重复部署，而不是只在出问题的服务器上手工修好。</p>]]></description>
      <pubDate>Mon, 13 Oct 2025 02:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2商品页价格正常，加进购物车后为什么突然变成0元？]]></title>
      <link>https://www.360magento.com/blog/product-price-normal-cart-item-price-zero/</link>
      <description><![CDATA[<p>商品页显示 199 元，加进购物车后变成 0 元。价格索引当然要看，但我不会先 reindex，因为商品页已经拿到了正确价格，问题更可能发生在“商品加入 quote”或“重新计算 totals”这两步。</p>
<h2>先保存故障quote里这一行的价格字段</h2>
<p>记录 quote item 的 product_type、price、base_price、custom_price、original_custom_price、row_total 和父子 item 关系。普通商品这些值不该无缘无故变成 0；动态价格 bundle 的父行是 0、金额放在子行，则可能是正常数据结构，只是模板显示错了对象。</p>
<h2>普通加购正常，自定义入口为0，就搜setCustomPrice</h2>
<pre><code>grep -R "setCustomPrice" app/code -n
grep -R "setOriginalCustomPrice" app/code -n
grep -R "setIsSuperMode" app/code -n</code></pre>
<p>快速下单、ERP 下单和自定义 Controller 经常把空字符串、缺失价格转换成 0，再调用 custom price。还有代码为了允许手工价打开 super mode，却没有限制调用场景。先让标准商品页加购和自定义入口各生成一个新 quote，对比差异。</p>
<h2>加购时有价格，collectTotals后才归零，就按collector顺序查</h2>
<p>在测试环境记录 collectTotals 前后 item 和 address total。折扣、税、积分、礼品卡及自定义 collector 都可能改金额。Around plugin 忘记调用 proceed，或返回了错误对象，也会让后续 collector 读到不完整数据。</p>
<p>同时看 base_currency_code、quote_currency_code 和 conversion rate。汇率服务返回 0 时，base_price 可能仍正确，显示币种金额却归零。</p>
<h2>修完一定用新购物车测试</h2>
<p>旧 quote 已经保存了 custom_price，清缓存不会自动恢复。删除测试 Session 或创建新客户购物车，再测游客、登录客户、优惠券、目标币种和不同产品类型。最后核对订单金额与支付请求，不能只看购物车页面重新显示了 199 元。</p>]]></description>
      <pubDate>Fri, 10 Oct 2025 05:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2刚创建的管理员一登录就提示账户已锁定，怎么查是谁在反复试密码？]]></title>
      <link>https://www.360magento.com/blog/new-admin-account-locked-repeated-login-attempts/</link>
      <description><![CDATA[<p>刚创建一个后台账号，第一次手工登录就提示账户被锁。直接解锁能暂时进去，但几分钟后又锁上，说明还有别的请求在持续提交错误密码。先找请求来源，再解锁。</p>
<h2>先把锁定时间和访问日志对上</h2>
<p>只查询这个管理员的失败次数、锁定到期时间和状态，不要把整张管理员表导出来。然后在 Nginx/Apache 日志里按后台登录路径、用户名相关请求时间和来源 IP 对照。Magento 不一定把用户名明文写入访问日志，可以结合 Session、IP、User-Agent 和请求频率判断。</p>
<p>常见来源包括浏览器密码管理器自动提交旧密码、可用性监控把登录页当表单探测、旧自动化脚本，以及另一位管理员还开着保存旧凭据的窗口。</p>
<p>如果来源 IP 是公司出口，继续按 User-Agent 和请求间隔区分具体客户端。固定每 30 秒一次更像监控，打开页面马上连续数次更像浏览器自动填充或脚本重试。必要时在受控时间短暂增加登录失败审计字段，但不要把密码、验证码或完整 Cookie 写进日志。</p>
<h2>确认没有重试后再解锁这个用户</h2>
<pre><code>bin/magento admin:user:unlock username
bin/magento admin:user:create --help</code></pre>
<p>优先使用当前版本 CLI 解锁指定用户，不要批量清空所有管理员的 failures。完全无法进入后台时，可以按应急流程创建临时高强度账号，处理完成后立即禁用，并保留审计记录。</p>
<h2>一台节点正常、一台节点总锁，就查时间和Session</h2>
<p>负载均衡环境里，应用节点与数据库时间不一致会让锁定到期判断异常。检查 NTP、PHP 时间和数据库 UTC 时间。若后台 Session 分散在本地文件，登录请求切节点也可能表现异常，但它通常还会伴随掉线或 Form Key 问题。</p>
<p>解锁后分别测试密码、2FA 和退出重登。再故意输错一次，失败计数应该只增加一次；一次点击增加多次，就继续查代理重试或前端重复提交。把真正的自动重试源停掉，才算解决，不是把锁定阈值改得更大。</p>
<p>还要确认失败发生在哪一步。密码错误会增加登录失败计数，2FA 验证失败属于后续认证流程；如果界面统一显示“锁定”，日志里仍应能分开。把 2FA 问题误当密码爆破处理，解锁多少次都会再次失败。</p>]]></description>
      <pubDate>Thu, 09 Oct 2025 03:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2商品图片上传时能预览，保存商品后为什么又不见了？]]></title>
      <link>https://www.360magento.com/blog/product-image-preview-disappears-after-save/</link>
      <description><![CDATA[<p>后台上传商品图时能看到缩略图，点保存再打开商品，图片栏空了。上传预览读取的通常是临时文件，保存商品时才会把文件移动到正式目录并写入媒体库关系，所以我会把这两段分开查。</p>
<h2>保存前后盯住同一个文件名</h2>
<p>上传完成先在 <code>pub/media/catalog/product/tmp</code> 找到文件，保存后再看它有没有进入正式的 catalog/product 分散目录。tmp 有、正式目录没有，先看文件移动、磁盘和权限；正式文件存在但后台没有记录，再查数据库。</p>
<pre><code>df -h
df -i
find pub/media/catalog/product/tmp -type f -mmin -10
tail -f var/log/system.log var/log/exception.log</code></pre>
<p>inode 用完时磁盘容量可能仍显示有空间。跨挂载点移动、SELinux、安全扫描占用文件，也会让 rename 或 copy 失败。不要直接把 media 改成 777，先确认 PHP-FPM 与部署用户的 owner、group 和 umask。</p>
<h2>文件已经进正式目录，就查媒体库三层关系</h2>
<p>对照一个正常商品，检查 media gallery 主记录、store view 的 value 记录和商品关联。只写了文件名但没关联 entity，文件会一直躺在磁盘上，后台却看不到。不同 Magento 版本表结构不同，先用当前库的 schema 确认字段再查询。</p>
<p>图库里有图片但前台角色图空白时，再看 image、small_image、thumbnail 是否在当前 store view 被覆盖为 <code>no_selection</code>。这和整张图库记录丢失不是同一个问题。</p>
<h2>多节点环境要确认tmp和正式media是不是同一份</h2>
<p>上传请求落在 A 节点，保存请求落在 B 节点，而 tmp 目录没有共享，就会随机消失。使用对象存储时还要看上传、复制和读取是否都走同一套 remote storage 配置。靠 sticky session 只能暂时遮住问题，不能替代共享媒体设计。</p>
<p>修复后分别上传小 JPG、大 PNG、同名文件，并从两台后台节点各测一次。后台图库、数据库关系、原图 URL 和缓存图 URL 都正常，才算完整通过。</p>]]></description>
      <pubDate>Wed, 08 Oct 2025 07:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台保存配置提示成功，刷新页面为什么又变回原来的值？]]></title>
      <link>https://www.360magento.com/blog/admin-config-save-success-value-reverts-after-refresh/</link>
      <description><![CDATA[<p>后台改了一个配置，提示保存成功，刷新页面却还是旧值。这个问题不要先清全站缓存，我通常先回答两个问题：POST 请求提交了什么，数据库刚保存完到底有没有新值。</p>
<h2>保存前把scope和配置路径记下来</h2>
<p>同一个字段在 Default、Website、Store View 可以有三份值。先确认左上角当前作用域，以及“Use Default”是否勾选。然后从页面字段或 system.xml 找到真实配置路径。</p>
<pre><code>bin/magento config:show section/group/field
SELECT scope, scope_id, path, value
FROM core_config_data
WHERE path = 'section/group/field';</code></pre>
<p>保存后立刻查数据库。新值从来没写进去，就看 backend model 校验、ACL、POST 参数和异常日志；数据库里已经是新值，页面却显示旧值，再查读取作用域、config cache 和应用连的是不是同一个数据库。</p>
<p>读写分离环境要从处理保存请求的节点和处理刷新请求的节点分别确认数据库连接。写入主库后立刻从延迟副本读取，会短暂看到旧值；如果刷新几秒后又恢复新值，就是明显信号。后台配置读取通常不应该在不保证一致性的副本上完成。</p>
<h2>数据库里刚改好，几秒后又变回去，就找覆盖源</h2>
<p>容器启动脚本、部署任务、配置同步程序都有可能把旧值重新写回。连续查询该 path，并对照部署和 cron 时间。不要一直在后台重复保存，否则只会让覆盖动作更难看清。</p>
<p>自定义 backend model 也可能在 <code>afterSave</code> 中把一个可视字段拆成多个配置值，或者根据另一个开关强制清空。Network 里的 POST 有新值、数据库从未出现新值时，把该字段配置类和保存事件一起搜出来，比继续怀疑浏览器缓存有效。</p>
<p>再检查 <code>app/etc/config.php</code>、<code>env.php</code> 和环境变量。被配置管理锁定的 path 应该从代码或部署变量修改，后台不是它的事实来源。使用 Magento 的配置状态命令确认是否被锁，不要直接删配置文件里的节点。</p>
<h2>修完后必须走一次正常发布</h2>
<p>我会在正确 scope 保存或更新部署配置，清理 config cache，再从另一台 Web 节点读取一次。随后执行一次完整部署或重启容器，确认值没有被旧变量覆盖。</p>
<p>最终记录这个配置到底由数据库、config.php 还是环境变量维护。下次再改时团队知道去哪里动手，比“这次刷新终于没变回去”更重要。</p>
<p>多网站配置还要拿两个 store view 交叉验证：目标站点读到新值，未修改站点继续继承原值。这样能证明 scope_id 没写错，也不会为了修一个站点把全局配置一起覆盖。</p>]]></description>
      <pubDate>Tue, 07 Oct 2025 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2同一订单确认邮件发了两次，到底是Cron重复还是代码调用了两遍？]]></title>
      <link>https://www.360magento.com/blog/order-confirmation-email-sent-twice-debug/</link>
      <description><![CDATA[<p>客户同一订单收到了两封确认邮件。以前我也会第一时间检查 cron，后来发现不少重复邮件根本还没走到 cron 就已经生成了两次。先把两封邮件的 Message-ID、到达时间和正文放在一起比较，别凭感觉判断。</p>
<h2>两封邮件先比这三个值</h2>
<p>Message-ID 不同、模板生成时间也不同，通常是 Magento 发送流程执行了两次；Message-ID 相同但邮箱收到两次，继续查 SMTP 服务商或下游转发。再对照订单状态历史，看重复邮件是否紧跟两次支付回调或两次状态变更。</p>
<p>数据库里检查订单的 <code>email_sent</code>、创建时间和更新时间，但不要为了测试直接把 email_sent 改回 0，这会主动制造下一封邮件。</p>
<h2>在自定义代码里搜第二个OrderSender</h2>
<pre><code>grep -R "OrderSender" app/code -n
grep -R "->send(.*order" app/code -n</code></pre>
<p>核心下单流程已经安排发送时，自定义 observer 又监听 checkout success 调一次，是最直接的重复来源。支付插件也可能在 webhook 里再次调用发送。网关重复投递回调是正常现象，回调处理必须按交易号或事件 ID 做幂等，不能假设只会收到一次。</p>
<p>我会在发送入口临时记录 order_id、调用栈的自定义类、消息 ID 和 hostname，不记录客户敏感信息。两封邮件分别由哪个入口产生，很快就能看出来。</p>
<p>如果项目开启异步销售邮件，还要分清“入队两次”和“同一条消息消费两次”。在发送进入队列的位置与真正调用邮件传输的位置分别加一次关联 ID：前面已经出现两条，去查业务事件；前面一条、后面两次，才把注意力放到消费者确认与重投。</p>
<h2>只有证据指向队列，才查Cron和Consumer</h2>
<p>异步邮件模式下，同一条消息可能因为 consumer 发送成功后未及时确认而被重新投递。两台节点重复运行任务、进程被强杀、连接在 ack 前中断，都需要结合消息 ID 和 worker hostname 判断。</p>
<p>修复后我会故意重放一次支付回调，再在发送过程中重启一个测试 consumer。订单状态可以重复查询，但确认邮件只能生成一次。如果只是把某个 cron 停掉后不再重复，却没有解释第二次调用从哪里来，问题还没有解决。</p>
<p>另外核对邮件模板与发件配置作用域，避免把“订单确认”和自定义的“支付成功通知”做成几乎相同的正文。两封不同业务邮件看起来一样，不属于重复投递，应该从模板和主题上明确区分，而不是删除其中一个发送流程。</p>]]></description>
      <pubDate>Mon, 06 Oct 2025 06:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2结账页自定义地址字段明明填了，为什么还提示This is a required field？]]></title>
      <link>https://www.360magento.com/blog/checkout-custom-address-field-required-after-filled/</link>
      <description><![CDATA[<p>给结账地址加了一个门牌号字段，页面能输入，点“下一步”却一直报 <code>This is a required field</code>。这类问题我不会先改 validation 规则，因为 input 里看得到文字，不等于 Knockout 正在校验的那份数据里也有值。</p>
<h2>先在Console里看checkoutProvider有没有值</h2>
<p>打开浏览器开发者工具，找到这个 UI Component 的 <code>dataScope</code> 和 <code>provider</code>。字段如果声明在 <code>shippingAddress.custom_attributes.house_number</code>，就检查 checkoutProvider 的同一路径，不要只看 DOM 的 value。</p>
<p>常见情况是 LayoutProcessor 注入时用了 <code>customAttributes</code>，mixin 读取时却写成 <code>custom_attributes</code>；页面显示组件和校验组件实际绑定了两个对象。还有一种是同名字段被注入两次，用户填了可见的那个，隐藏的副本仍为空。</p>
<h2>点下一步，直接看shipping-information请求</h2>
<p>Network 里找到保存配送信息的请求，搜索字段代码。请求里没有值，问题还在前端数据转换；请求里有值而接口报必填，再查后端 extension attribute 或地址属性声明。</p>
<pre><code>{
  "shipping_address": {
    "custom_attributes": [
      {"attribute_code": "house_number", "value": "8-2"}
    ]
  }
}</code></pre>
<p>项目有时把字段放在 <code>extension_attributes</code>，有时使用 customer address EAV 的 <code>custom_attributes</code>。两种方式都能做，但前端 payload、extension_attributes.xml、接口和保存插件必须选同一条路径。字段代码差一个下划线也不会自动映射。</p>
<h2>值传到了，就查quote_address有没有落库</h2>
<p>在测试环境对照请求和 quote_address。接口返回成功但数据库没有值，检查保存插件是否执行、数据库列是否存在、setter 是否写到正确对象。quote 有值而 order_address 没值，则漏了 quote 转 order 的字段复制。</p>
<p>修复后我会测四条路径：游客新地址、登录用户新地址、从地址簿选择旧地址、账单地址与配送地址不同。最后下一个测试订单，后台订单地址必须看到该字段。只让红色必填提示消失不算修好，发货环节真正拿得到值才算。</p>]]></description>
      <pubDate>Fri, 03 Oct 2025 02:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 OpenSearch偶发429 Too Many Requests，搜索页空白怎么处理？]]></title>
      <link>https://www.360magento.com/blog/opensearch-429-too-many-requests-search-empty/</link>
      <description><![CDATA[<p>搜索页偶尔空白，Magento 日志里出现 OpenSearch 429。429 不是“接口不存在”，而是集群在当前压力下主动拒绝请求。先分清被拒绝的是前台 search、批量 bulk 索引，还是触发了内存保护，处理方式完全不同。</p>
<h2>保留429响应体，它会告诉你拒绝类型</h2>
<p>日志不要只截状态码。响应中的 <code>rejected_execution_exception</code>、线程池名称或 circuit breaker 信息能直接指向资源。同步记录当时节点 CPU、JVM heap、磁盘水位、pending tasks 和 thread pool rejected 计数。</p>
<pre><code>curl -s http://opensearch:9200/_cluster/health?pretty
curl -s http://opensearch:9200/_cat/thread_pool/search,write?v
curl -s http://opensearch:9200/_cat/nodes?v&amp;h=name,cpu,heap.percent,ram.percent,disk.avail</code></pre>
<p>命令应在受控网络并使用正确认证。不要把管理端口暴露到公网。</p>
<h2>看429发生在reindex还是用户搜索高峰</h2>
<p>如果每次全量 reindex 都出现 write/bulk rejected，降低批次并错峰执行，检查是否同时有多个索引任务。若是 search 线程池拒绝，分析慢查询、聚合字段和机器人流量。商品属性大量设置为 searchable/filterable，会显著放大查询与索引成本。</p>
<p>再查看索引数量、主分片和副本分布。小目录拆成大量分片会浪费 heap，大目录只有一个热点分片又会让单节点吃满。不要直接照搬别人的 shard 数，先看当前文档量、分片大小和节点数，再规划新索引并通过 Magento 的重建流程切换 alias。</p>
<p>磁盘接近水位、分片过多或副本不可分配时，简单增加重试只会把更多请求压回集群。先恢复集群健康，再决定扩节点、调 shard、清理旧索引或优化查询。</p>
<h2>应用重试必须有边界</h2>
<p>对可重试的查询使用短暂指数退避和随机抖动，限制次数；不要立即无限重试。前台还应给出可理解的降级结果，而不是把异常吞掉后展示“没有商品”，否则业务会误判为搜索索引为空。</p>
<p>扩容后也要复测同等负载，观察 rejected 计数是否继续增长、P95 查询延迟和 reindex 用时。真正解决 429，是让峰值请求量、查询成本和集群容量重新匹配，而不是把日志级别改低。</p>
<p>最后把前台搜索和后台索引的容量指标分开设告警：集群健康为 green 也可能持续拒绝高峰查询。至少监控 heap、GC、磁盘水位、search/write rejected、队列长度和慢查询。这样下一次接近极限时能提前扩容或限流，而不是等客户看到空白页才发现。</p>]]></description>
      <pubDate>Thu, 02 Oct 2025 07:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台已经修改URL Key，前台为什么还一直跳回旧地址？]]></title>
      <link>https://www.360magento.com/blog/product-url-key-changed-still-redirects-old-url/</link>
      <description><![CDATA[<p>商品 URL Key 从 <code>old-name</code> 改成 <code>new-name</code>，后台保存成功，前台访问新地址却又 301 回旧地址。继续点保存通常只会生成更多 rewrite，先把跳转链画出来。</p>
<h2>用curl看每一跳，不要相信浏览器地址栏</h2>
<pre><code>curl -IL --max-redirs 10 https://shop.example.com/new-name.html
curl -I https://shop.example.com/old-name.html</code></pre>
<p>记录每个 Location 和状态码。浏览器会缓存永久重定向，测试时用 curl 或无痕窗口更可靠。如果第一跳就来自 CDN，先绕过外层缓存确认 Magento 本身返回什么。</p>
<h2>查当前Store View的Rewrite，而不是全库模糊搜索</h2>
<p>按 request_path、target_path、entity_id 和 store_id 查询 <code>url_rewrite</code>。新路径如果被一条 custom rewrite 指向旧路径，而旧路径又指回新路径，就会形成循环。也要区分系统生成记录和管理员创建的自定义重定向。</p>
<p>后台保存 URL Key 时“Create Permanent Redirect for Old URL”会保留旧地址跳向新地址，这是正常 SEO 行为；方向应是旧到新。如果方向相反，多半有历史自定义 rewrite、导入脚本或扩展重建了错误记录。</p>
<h2>分类路径与Canonical不是同一个问题</h2>
<p>开启分类路径后，同一商品可能有多个 request_path。你改的是商品主 URL Key，但分类 URL rewrite 仍在旧路径，或者菜单缓存还输出旧链接。Canonical 标签只告诉搜索引擎首选地址，不会负责浏览器 301。</p>
<p>不要直接 <code>TRUNCATE url_rewrite</code>。先导出相关商品和 store 的记录，删掉确认有冲突的自定义项，再让 Magento 对该实体重新生成。全表重建会影响 CMS、自定义重定向和正在收录的页面。</p>
<p>修复后验证新地址 200、旧地址单跳 301 到新地址、分类页链接已经更新，并检查两个 store view 不互相串域。跳转少一层和方向正确，对用户与 SEO 都比“最终能打开”更重要。</p>]]></description>
      <pubDate>Wed, 01 Oct 2025 01:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2清了缓存CMS Block还是旧内容，Varnish到底缓存了哪一层？]]></title>
      <link>https://www.360magento.com/blog/cms-block-stale-after-cache-clean-varnish/</link>
      <description><![CDATA[<p>后台改了 CMS Block，也执行了 cache:clean，页面还是昨天的内容。缓存层多的时候，“我清过缓存”没有诊断意义，先确认当前响应究竟从哪一层返回。</p>
<h2>用响应头判断谁在回答</h2>
<pre><code>curl -sI https://shop.example.com/page | egrep -i 'age|x-cache|x-magento-cache-debug|x-magento-tags|via'
curl -s https://shop.example.com/page -o /tmp/page.html</code></pre>
<p>连续请求比较 Age、HIT/MISS 和 Magento 缓存调试头。绕过 CDN 直连 Varnish，再绕过 Varnish 直连源站，直到看到新内容。在哪一跳从新变旧，就查那一层，而不是从浏览器一路清到 Redis。</p>
<h2>缓存Tag有没有传到Varnish很关键</h2>
<p>Magento 更新 Block 时依赖相关 identity/tag 失效页面。如果自定义 Block 没实现正确 identity，或者 Nginx/CDN 删除了 <code>X-Magento-Tags</code>、PURGE/BAN 没到 Varnish，后台清理只能影响 Magento 自身缓存，外层对象仍然存活。</p>
<p>检查该页面缓存对象是否带有 CMS Block 对应标签，以及保存 Block 后 invalidation 请求是否成功。不要把标签头直接暴露给公网，但内部代理链要能使用它。</p>
<h2>同名Block和Store View也会制造“缓存没清”的错觉</h2>
<p>多商店里可能有相同 identifier 的不同 Block。后台改的是 Default Store View，页面实际读取另一个 store scope；或者 Page Builder 内容嵌入了另一块。直接在页面 HTML 找一段唯一文本，再回后台确认具体 block_id。</p>
<p>浏览器 Service Worker、CDN Edge 和 Varnish 的 TTL 也要分开。用 curl 得到新内容而用户浏览器仍旧，再查浏览器缓存；公网 CDN 旧、源站新，则做精确 URL purge，避免全站清缓存造成无谓回源峰值。</p>
<p>修复后保存同一 Block 两次，每次用唯一标记验证各层在合理时间内更新，并确认其他页面没有被全部驱逐。目标不是“清得越彻底越好”，而是让正确的 Tag 精准失效。</p>]]></description>
      <pubDate>Tue, 30 Sep 2025 05:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2静态资源部署成功，新增主题的CSS为什么还是404？]]></title>
      <link>https://www.360magento.com/blog/static-content-deploy-success-new-theme-css-404/</link>
      <description><![CDATA[<p>命令最后显示 Deployment complete，打开新主题页面却有一批 CSS 404。这里的“成功”只代表你要求部署的组合成功了，不代表当前页面使用的主题、语言和 area 包含在命令里。</p>
<h2>从404 URL反推缺的是哪一组产物</h2>
<p>把 URL 拆成 static version、frontend/adminhtml、Vendor/theme、locale 和文件路径。然后到发布产物里按同样层级找文件。不要直接搜索整个 pub/static，因为旧版本目录或 symlink 可能让你找到一份页面根本不会访问的文件。</p>
<pre><code>bin/magento theme:uninstall --help
bin/magento setup:static-content:deploy -f zh_Hans en_US   --area frontend --theme Vendor/theme</code></pre>
<p>上面的部署参数只是示例。先用当前商店 locale 和实际主题代码替换。新增主题必须有正确的 registration.php、theme.xml 以及父主题声明，后台选择的 Design Configuration 作用域也要对应当前 store view。</p>
<h2>多节点发布时，命令可能跑在用户看不到的磁盘上</h2>
<p>如果每个 Web 节点有独立 pub/static，只在发布机执行成功不够。确认产物被打包并分发到所有节点，静态资源 CDN 的源站也读取同一版本。请求偶发 200/404 通常就是节点内容不一致。</p>
<p>检查静态签名。HTML 引用了新的 version 路径，但 CDN 或 Nginx 仍映射旧 release 时，文件实际存在也会 404。对照页面源代码版本号、部署后的 <code>deployed_version.txt</code> 和当前 symlink。</p>
<h2>别用777掩盖生成和读取用户不一致</h2>
<p>部署用户需要写入生成目录，Web 用户需要读取。确认 owner、group、umask 与发布流程一致。若 LESS 编译或某个源文件失败，查看完整命令输出，不要只看最后一行。</p>
<p>修复后请求具体 CSS URL 并检查 Content-Type，再刷新一个使用父主题的页面和一个使用新主题的页面。最后清 CDN 的精确路径。能够访问文件只是第一步，样式内容属于正确 release、所有节点一致，才算部署完成。</p>]]></description>
      <pubDate>Mon, 29 Sep 2025 02:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2的cron_schedule堆满missed，手动执行cron又正常是什么原因？]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-missed-but-manual-run-works/</link>
      <description><![CDATA[<p><code>cron_schedule</code> 里一片 missed，但 SSH 下执行 <code>bin/magento cron:run</code> 又能成功。这个现象反而说明 PHP 和 Magento 命令本身大概率可用，差异在“谁、什么时候、用什么环境自动执行”。</p>
<h2>先证明系统Cron真的每分钟触发</h2>
<p>检查运行 Magento 的系统用户 crontab，不要只看 root。确认路径是当前 release，标准输出和错误没有被静默丢弃。部署切换软链接后，旧 crontab 指向过期目录也是常见原因。</p>
<pre><code>crontab -u www-data -l
journalctl -u cron --since "30 minutes ago"
ps -ef | grep '[c]ron:run'</code></pre>
<p>在 crontab 中使用绝对 PHP 路径和 Magento 根目录。交互 Shell 里可用的 PHP 版本、PATH、内存限制和环境变量，cron 用户不一定有。把 <code>php -v</code> 和必要环境写入临时诊断日志，很快能看出差异。</p>
<h2>missed表示错过调度窗口，不等于任务代码报错</h2>
<p>查看 scheduled_at、executed_at 和 finished_at。某个任务运行太久或锁未释放，会让后续任务来不及在允许窗口内启动。按 job_code 分组统计 pending、running、missed 数量，比只看最新十行更有用。</p>
<pre><code>SELECT job_code, status, COUNT(*)
FROM cron_schedule
WHERE created_at &gt; UTC_TIMESTAMP() - INTERVAL 2 HOUR
GROUP BY job_code, status;</code></pre>
<p>如果总是同一个 job_code 长时间 running，就查它的业务和外部依赖。不要先批量把 running 改成 success，那只会隐藏锁和重复执行风险。</p>
<h2>多节点只能让正确的节点负责调度</h2>
<p>Web 节点都装了相同 crontab 时，若没有合适锁机制可能重复跑；发布时所有节点又同时停 cron，则会集体漏跑。明确 cron 主机、消费者主机和共享数据库，并记录每次执行的 hostname。</p>
<p>修复后至少观察两个调度周期，确认 schedule 记录按预期提前生成、到点执行、状态 success。手动跑通一次只能证明当前命令可运行，持续没有 missed 才说明自动调度恢复。</p>]]></description>
      <pubDate>Fri, 26 Sep 2025 08:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 Redis报READONLY You can't write against a read only replica，切主后还要改什么？]]></title>
      <link>https://www.360magento.com/blog/redis-readonly-replica-after-failover-magento/</link>
      <description><![CDATA[<p>Redis 做完故障切换，监控显示新主已经正常，Magento 仍不断报 <code>READONLY You can't write against a read only replica</code>。这说明应用当前连接的节点角色是 replica。问题不在 Magento 缓存内容，而在连接发现或旧连接没有刷新。</p>
<h2>从报错的PHP节点确认它实际连到了谁</h2>
<p>不要只在 Redis 管理机上看。登录发生错误的 Web、cron 和 consumer 节点，解析配置里的主机名，并连接同一个地址查询 role。</p>
<pre><code>getent hosts redis.internal
redis-cli -h redis.internal -p 6379 ROLE
redis-cli -h redis.internal -p 6379 INFO replication</code></pre>
<p>多节点环境可能只有部分机器缓存了旧 DNS，表现为请求随机报错。也可能 cache、page_cache、session 使用三套不同 Redis 配置，首页正常但登录失败，或者后台正常而 cron 报错。</p>
<p>先按报错上下文判断是哪一个用途：前台随机退出多半是 session 写失败；配置保存或缓存清理时报错多半是 cache；整页缓存刷新失败则看 page_cache。三套连接逐个做最小读写测试，能避免只修首页缓存而客户仍然掉线。</p>
<h2>切主机制要和Magento连接方式匹配</h2>
<p>如果使用云 Redis 的主节点 endpoint，配置应指向会随故障切换更新的写端点，而不是某台实例 IP。使用 Sentinel 或代理时，要确认 Magento 所用客户端和配置确实支持主节点发现，不能把 Sentinel 地址当普通 Redis 地址直连。</p>
<p>检查 <code>app/etc/env.php</code> 中 cache、page_cache、session 的 server、port、database 和持久连接设置。不要在三处共用同一 database 后靠前缀勉强区分，故障排查会非常混乱。</p>
<h2>旧的PHP长连接不会因为DNS更新立刻消失</h2>
<p>解析已经指向新主，但 PHP-FPM worker 仍持有到旧副本的 persistent connection 时，需要按发布流程平滑重载 PHP-FPM，并重启长期运行的 consumer。先摘流量再处理，避免直接重启造成结账请求中断。</p>
<p>修复后分别写入 cache、session，并跑一条 cron/consumer 任务。再做一次受控切换，观察应用恢复时间、DNS TTL 和连接重建。真正的解决不是手工改一次 IP，而是让下次故障切换时所有写连接都能自动跟随主节点。</p>
<p>受控切换时我会保留一条已登录客户会话并持续请求，同时监控新登录、购物车写入和后台保存。缓存可以短暂 MISS，但 Session 不能在主从切换时被写到两边形成分叉。如果架构无法保证会话一致性，至少要明确故障窗口和用户影响，而不是仅凭 Redis 监控变绿宣布恢复。</p>]]></description>
      <pubDate>Thu, 25 Sep 2025 01:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2多仓库存总是从错误仓库扣减，Source Selection Algorithm怎么排查？]]></title>
      <link>https://www.360magento.com/blog/msi-source-selection-wrong-warehouse/</link>
      <description><![CDATA[<p>客户离上海仓很近，订单却总建议从广州仓发货。排查前要先澄清一个常见误区：Magento 下单时通常生成的是 Stock 级别 reservation，不是立刻从某个 Source 实物库存扣减；具体来源往往在创建 Shipment、执行 Source Selection 时才确定。</p>
<h2>先确认订单属于哪个Stock</h2>
<p>Website 会映射到 Stock，Stock 再包含多个 Source。网站如果挂错 Stock，后面的算法再聪明也只能在错误的仓库集合里选。后台逐层核对 Website → Stock → Source，并确认每个 Source 已启用、商品 Source Item 状态为 in stock。</p>
<h2>Priority算法不会理解“离客户最近”</h2>
<p>默认 Source Priority 按后台配置顺序扣减，它不知道地理距离。Distance Priority 才会结合地址与距离提供方，但还依赖完整的发货地址、国家地区代码、经纬度或距离服务配置。看到“选错仓”先确认当前使用的是哪个算法。</p>
<p>在创建发货页面记录系统给出的 source 和 qty 建议，然后对照各 Source 的可用数量。不要只查 inventory_source_item 的 quantity，reservation 会影响 salable quantity，而算法还可能考虑是否能完整满足发货。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies
bin/magento indexer:status inventory</code></pre>
<h2>自定义算法要检查输入，而不只是排序代码</h2>
<p>如果项目按省份、邮编或仓库成本自定义选择策略，先把订单地址、候选 Source、可用数量和排序分数写入结构化日志。地址字段为空、邮编格式不同或地区名称被翻译，都可能让算法走默认仓。</p>
<p>还要区分“推荐来源”和“实际发货来源”。管理员可以手动改 Source，ERP 也可能忽略 Magento 建议自行分仓。最终库存从哪扣，要看 Shipment 和 Source Deduction 执行记录，而不是只看下单页面。</p>
<p>如果订单已经发货却扣错仓，沿消息队列检查 source deduction message 使用的 source_code 和 sales_channel。异步消费者停掉时，后台可能已经生成 Shipment，但 Source Item 数量尚未更新；这时重复创建补偿脚本反而会二次扣减。先确认消息是否仍在队列、是否失败以及 reservation 是否已释放。</p>
<p>距离算法还要留意地址质量。国家、省份和邮编缺一项时，距离服务可能无法计算并回退到优先级。把算法返回的候选列表、距离和回退原因记下来，才能解释为什么某笔订单去了远仓，而不是凭地图肉眼判断。</p>
<p>修复后用同一 SKU 测试单仓可满足、需要拆仓、最近仓缺货和虚拟商品四种订单。只测试库存充足的一单，很容易把优先级调整误认为距离算法已经正常。</p>]]></description>
      <pubDate>Wed, 24 Sep 2025 06:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2导入可配置商品后，子商品为什么没有自动关联？]]></title>
      <link>https://www.360magento.com/blog/configurable-product-import-children-not-linked/</link>
      <description><![CDATA[<p>CSV 导入显示 Completed，父商品和简单商品在后台也都存在，可配置商品页面却没有任何 Variations。导入“成功”只代表每一行能被处理，不保证父子关系描述正确。</p>
<h2>先确认用于配置的属性本身合格</h2>
<p>颜色、尺寸等属性必须是合适的 Catalog Input Type，作用域通常为 Global，并启用用于创建可配置商品。父商品和所有子商品要使用包含这些属性的同一个属性集。属性代码、选项 label 和导入值要完全对应，注意前后空格与大小写。</p>
<h2>子商品应先存在，再让父商品引用SKU</h2>
<p>我通常把流程拆成两次：先导入简单商品，确认 SKU 和属性值；再导入可配置父商品及关联字段。这样失败时能明确是商品创建问题还是关系问题。</p>
<pre><code>sku,product_type,attribute_set_code,color,size
shirt-red-s,simple,Default,Red,S
shirt-blue-m,simple,Default,Blue,M</code></pre>
<p>父行的 <code>configurable_variations</code> 需要按 Magento 当前导出样例的格式列出每个子 SKU 及其属性组合，<code>configurable_variation_labels</code> 则负责前台显示名称。不要凭印象手写分隔符，先从同版本后台创建一个最小商品并导出，拿它作为模板。</p>
<h2>导入行为和多网站字段也会影响结果</h2>
<p>Add/Update、Replace 的处理方式不同。Replace 可能先删除再重建关系，缺少某一列时结果和 Add/Update 不一样。子商品如果不属于父商品所在 website，或者状态、可见性、库存不合理，后台关系可能存在但前台组合仍不可选。</p>
<p>导入后先在父商品后台看关联，再检查前台初始化 JSON。必要时重建 configurable、product EAV、price 和 stock 相关索引，但只有关系表已经正确写入时重建才有意义。</p>
<p>批量文件上线前，我会用两个属性、两个子商品做十行以内的小样，确认格式后再扩大。最终检查父商品的每个组合、子商品独立 SKU、网站分配和价格库存。比起反复导入几万行，这种最小样本更快找到具体是哪一列把关联吃掉了。</p>]]></description>
      <pubDate>Tue, 23 Sep 2025 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 REST API翻到第2页就出现重复数据，searchCriteria应该怎么传？]]></title>
      <link>https://www.360magento.com/blog/rest-api-pagination-duplicate-items-searchcriteria/</link>
      <description><![CDATA[<p>对接 ERP 时按每页 100 条拉商品，第一页正常，第二页开始出现重复 SKU，最后总数还对不上。很多人只检查 currentPage，其实分页没有稳定排序时，数据库并不保证两次请求返回一致顺序。</p>
<h2>先把最终请求URL完整记录下来</h2>
<p>数组参数经过 SDK、网关和 URL 编码后很容易变形。确认服务端实际收到的是 <code>searchCriteria[pageSize]</code> 和 <code>searchCriteria[currentPage]</code>，页码从 1 开始。响应中的 total_count 是匹配总数，不是当前页条数。</p>
<pre><code>?searchCriteria[pageSize]=100
&searchCriteria[currentPage]=2
&searchCriteria[sortOrders][0][field]=entity_id
&searchCriteria[sortOrders][0][direction]=ASC</code></pre>
<p>稳定排序字段必须尽量唯一。只按 updated_at 排序时，同一秒更新的多条记录顺序可能变化；可以把 entity_id 作为第二排序，或者直接采用“上次最大 ID”方式做游标式增量。</p>
<h2>同步期间数据在变化，offset分页天然会漂移</h2>
<p>第一页拉完后有人新增或删除商品，第二页的 offset 已经对应另一组数据，于是产生重复或漏项。对实时变化大的订单接口尤其明显。可行做法是固定时间窗口，例如只取 updated_at 小于任务开始时间的数据，并保存最后成功同步的时间和 ID。</p>
<p>筛选条件也要正确分组：同一个 filter_group 内通常是 OR，不同组之间是 AND。把“更新时间大于 X”和“小于 Y”放错组，会让数据集远大于预期，表现得像分页失效。</p>
<h2>客户端要以主键去重，但不能靠去重掩盖漏数</h2>
<p>接收端用 entity_id 或业务唯一键做幂等写入是必要的，不过任务结束仍应核对拉取的唯一 ID 数与预期窗口 total_count。若不一致，保存每页的首尾 ID，便于重跑和定位。</p>
<p>最后用三种场景验证：静态数据全集、同步过程中新增一条、同步过程中更新同一秒的多条。只有在数据变化时也不漏不重，分页方案才适合生产集成。</p>]]></description>
      <pubDate>Mon, 22 Sep 2025 07:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 GraphQL带了Bearer Token，为什么接口返回的还是游客数据？]]></title>
      <link>https://www.360magento.com/blog/graphql-bearer-token-returning-guest-data/</link>
      <description><![CDATA[<p>前端请求里明明写了 <code>Authorization: Bearer ...</code>，Magento GraphQL 返回的 customer 却是未登录，价格也按游客组计算。先不要怀疑 Token 内容，最常见的情况是它根本没有到达 PHP。</p>
<h2>用同一个Token绕过每一层测试</h2>
<p>从浏览器复制请求为 curl，分别请求公网域名、CDN 后的源站地址和本机 upstream。响应在哪一层开始变化，就查那一层的头转发。日志只记录 Authorization 是否存在和长度，不要打印完整 Token。</p>
<pre><code>curl -i https://shop.example.com/graphql   -H 'Content-Type: application/json'   -H 'Authorization: Bearer REDACTED'   --data '{"query":"{customer{firstname}}"}'</code></pre>
<p>Nginx、Apache、负载均衡和 WAF 都可能过滤 Authorization。PHP-FPM 环境还要确认该头以预期变量传入。修配置后在应用入口做一次临时的“是否收到”日志，比重复生成 Token 更快。</p>
<p>如果公网请求丢头而直连 PHP 正常，要沿代理链一段一段加回。Nginx 常见的是 FastCGI 参数没有传递 HTTP_AUTHORIZATION；Apache 可能被 rewrite 或安全模块处理；CDN 则可能没有把该头加入允许转发列表。修改任何一层后都用同一条 curl 复测，避免同时改三处后无法判断真正原因。</p>
<h2>确认Token属于客户，而不是集成或后台用户</h2>
<p>Magento 的 customer、admin 和 integration token 用途不同。用生成客户 Token 的 mutation 重新生成一枚，在没有 CDN 缓存的环境直接查询 customer。还要带正确 Store 头，多网站共享邮箱时，Token 的网站上下文不一致会产生权限或数据差异。</p>
<h2>缓存不能只按GraphQL正文区分</h2>
<p>如果游客先请求相同 query，CDN 随后把缓存响应发给登录客户，看起来就像 Token 被忽略。检查 GraphQL POST/GET 的缓存规则、Vary 信息以及 Magento 返回的缓存标识。包含 customer 私有数据的请求不应该命中公共游客缓存。</p>
<p>我会在响应头里记录 cache HIT/MISS，并用两个不同客户的 Token 交叉测试：A 不能看到 B 的数据，登录请求也不能复用游客响应。这比只验证“终于返回 firstname 了”更重要。</p>
<p>对于只查询公开商品的请求，也别简单地把 Authorization 从缓存键删掉。登录客户可能有专属客户组价格、共享目录或可见性。可以先对照 Magento 返回的缓存上下文标识，再配置 Varnish/CDN；自己拼一个只按 query hash 的键，最容易造成跨客户数据污染。</p>
<p>修好后再测试 Token 过期、空 Authorization、错误 Store 头和并发请求。最终结论应明确是代理丢头、Token 类型、网站上下文还是缓存键，而不是把所有 GraphQL 401 都归到“重新登录”。</p>]]></description>
      <pubDate>Fri, 19 Sep 2025 03:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2升级到2.4后，邮件模板里的订单变量为什么全是空白？]]></title>
      <link>https://www.360magento.com/blog/email-template-order-variables-empty-after-upgrade/</link>
      <description><![CDATA[<p>升级 Magento 2.4 后，订单邮件能发出，订单号也有，但旧模板里客户名、付款方式或自定义字段变成空白。很多旧模板直接调用对象方法，过去能工作不代表现在仍被允许。2.4 默认更严格地限制模板可执行内容，这是安全边界，不建议为了兼容旧写法把它关掉。</p>
<h2>先把“邮件没数据”和“模板取不到”分开</h2>
<p>临时切回当前版本自带的订单模板发送测试。如果默认模板正常，发送流程、订单对象和队列基本没问题；只需迁移自定义模板。若默认模板也缺值，再检查调用 Sender 时传入的 template vars。</p>
<p>在后台加载默认模板，查看页面列出的可用变量。新模板常使用已经整理好的变量，例如 order_data 中的 customer_name，而不是在模板里层层调用订单对象。</p>
<h2>不要继续在模板里调用getData和任意方法</h2>
<p>旧写法可能类似从 order 对象继续取 payment、address，再调用方法。严格模式下这些访问会被拦截或返回空。正确做法是在发送邮件的 PHP 代码里先把需要的数据整理为标量或安全对象，再作为命名变量传给模板。</p>
<pre><code>$transport = [
    'order' => $order,
    'order_data' => [
        'customer_name' => $order->getCustomerName(),
        'custom_reference' => (string)$order->getData('custom_reference')
    ]
];</code></pre>
<p>示例只说明思路。实际项目应尽量扩展现有 transport，而不是复制整个 Sender。自定义字段还要做合适的 HTML 转义；只有确实是可信 HTML 的内容才使用 raw。</p>
<h2>队列会让你一直看到修改前的结果</h2>
<p>异步发送开启时，测试邮件可能是队列里旧任务生成的。记录订单号、模板 ID 和入队时间，清楚地区分新订单与旧消息。也要确认配置作用域选中了你刚修改的模板，多商店经常仍引用另一份副本。</p>
<p>我最后会测试游客订单、注册客户、缺少自定义字段和包含特殊字符的客户名。模板不报错只是最低要求，还要保证空值有合理兜底、HTML 没被意外转义，并且不重新开放任意方法调用。这样升级后的模板才是真正兼容，而不是暂时绕过限制。</p>]]></description>
      <pubDate>Thu, 18 Sep 2025 06:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台订单列表明明有数据，导出的CSV为什么是空的？]]></title>
      <link>https://www.360magento.com/blog/admin-order-grid-export-csv-empty/</link>
      <description><![CDATA[<p>管理员在订单列表能看到几百条记录，点 Export CSV 下载出来却只有表头。这种情况别先怀疑 Excel，CSV 已经生成，只是导出使用的数据源没有取到行。</p>
<h2>先看导出请求带了哪些筛选条件</h2>
<p>打开 Network，点击导出，保存请求参数。UI Grid 的筛选、选择方式和 namespace 会一起传给导出控制器。页面上看似已经清空筛选，用户 bookmark 里可能仍保存着日期、store 或状态条件。</p>
<p>用 Reset Filters 后再导一次，并换一个从未打开过该 Grid 的管理员账号测试。如果新账号正常，优先清理或重建该用户的 UI bookmark，而不是改订单表。</p>
<pre><code>SELECT bookmark_id, user_id, namespace, identifier
FROM ui_bookmark
WHERE namespace = 'sales_order_grid';</code></pre>
<p>不要直接删除所有人的 bookmark。先备份并只处理故障用户和对应 namespace，否则别的后台列表布局也会被重置。</p>
<h2>有自定义列时检查导出用的collection</h2>
<p>页面数据有时来自插件改过的 DataProvider，而导出请求走另一条 collection 链路。自定义 join 使用 inner join、重复 alias 或只在普通请求下注入条件，都可能让导出 collection 变成空集。</p>
<p>临时去掉自定义列并不能证明字段本身有问题，要对照生成 SQL。记录普通 Grid 和 export 请求的 where、join、store scope 差异，尤其检查批量选择参数是 selected 还是 excluded。</p>
<h2>异步导出还要看消费者和文件权限</h2>
<p>部分版本或扩展会把大批量导出交给消息队列。请求立即成功但文件为空或迟迟不生成，就检查对应 consumer、队列记录和 var/export 的写权限。Web 节点与 consumer 节点使用不同共享目录时，也会发生任务写完但下载节点找不到文件。</p>
<p>修复后分别验证：无筛选导出、按日期筛选、只勾选两单、排除一单以及非超级管理员。CSV 行数应该和 Grid 当前条件一致，自定义金额列也要核对一两条原始订单，避免“有数据了”却导出错行。</p>]]></description>
      <pubDate>Wed, 17 Sep 2025 01:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2订单状态正常，后台为什么没有“创建发票”按钮？]]></title>
      <link>https://www.360magento.com/blog/order-missing-create-invoice-button/</link>
      <description><![CDATA[<p>订单能在后台打开，付款看起来也成功，却找不到“创建发票”按钮。按钮不是由订单状态标签简单控制的，Magento 最终会调用订单的 <code>canInvoice()</code>。只要其中一个条件不满足，界面就不会显示。</p>
<h2>先确认订单是不是已经被自动开票</h2>
<p>进入 Invoices 标签，看是否已有发票。很多网关配置 Capture 时，会在回调成功后自动创建发票；管理员再找按钮属于重复操作。对照每个 order item 的 qty_ordered、qty_invoiced 和 qty_canceled，剩余可开票数量为零时按钮本来就不该出现。</p>
<h2>状态标签正常，不代表内部state允许开票</h2>
<p>自定义 status 可以挂在错误的 state 下。页面显示“已付款”只是文本，内部如果是 canceled、closed、holded 或 payment review，<code>canInvoice()</code> 仍会返回 false。用订单 ID 对照 sales_order 的 state/status，并检查是否处于 hold 或支付审核。</p>
<pre><code>SELECT entity_id, increment_id, state, status,
       total_qty_ordered, total_invoiced
FROM sales_order
WHERE increment_id = '000000123';</code></pre>
<p>不要直接在数据库里把 state 改成 processing。订单、支付、发票和库存是一组状态机，手改一列可能让按钮出现，却留下金额和交易记录不一致。</p>
<h2>Payment Action决定什么时候生成发票</h2>
<p>Authorize Only 通常保留后续 Capture；Authorize and Capture 往往由支付模块自动开票。第三方网关若在回调里只改订单状态、没有正确登记 transaction 或 invoice，也会产生“看似支付成功但不能开票”的半状态。</p>
<p>查看 payment additional_information、authorization transaction 和网关回调日志，确认是否还有可捕获金额。退款、部分开票和虚拟商品也要分别计算，不要只看 grand_total。</p>
<p>定位时我会在测试环境记录 <code>canInvoice()</code> 返回前各项条件，而不是用插件强行让按钮显示。修复支付回调或订单状态映射后，新订单应能按预期自动开票或显示按钮；旧订单则需要按真实交易状态做数据修复。最终拿全新订单测试，避免历史脏数据让结论失真。</p>]]></description>
      <pubDate>Tue, 16 Sep 2025 05:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2可配置商品切换颜色后价格不变，是索引问题还是前端JS没更新？]]></title>
      <link>https://www.360magento.com/blog/configurable-product-option-price-not-updating/</link>
      <description><![CDATA[<p>同一个可配置商品，红色子商品比蓝色贵 20 元，但前台切换颜色后价格一直不动。这个问题不要一上来重写 swatch 组件，先判断浏览器拿到的价格数据是不是就已经错了。</p>
<h2>先在页面源码里找子商品价格</h2>
<p>查看可配置商品初始化 JSON，重点看 attributes、optionPrices 和子商品 ID 的对应关系。两种颜色的 optionPrices 本来就相同，问题在服务端价格计算或索引；JSON 里价格不同但页面不变，才是前端事件没有驱动 priceBox。</p>
<p>同时确认子商品的 website、客户组价格、special price 日期和货币。后台看到的基础价格不一定等于当前客户组最终价格。</p>
<pre><code>bin/magento indexer:reindex catalog_product_price
bin/magento cache:clean block_html full_page</code></pre>
<p>只在索引确实缺失时执行，不要把这两条当成固定仪式。重建前后都应该对比初始化 JSON，否则无法证明是索引修好的。</p>
<h2>JSON正确时，跟着change事件往下查</h2>
<p>在浏览器 Console 观察选择颜色后是否选中了对应 simple product，页面有没有 JavaScript 异常。第三方主题经常复制旧版 <code>configurable.js</code> 或 <code>swatch-renderer.js</code>，升级 Magento 后方法签名变了，错误被其他脚本吞掉，只剩价格不更新。</p>
<p>检查 priceBox 节点的 data-role 是否仍然存在，是否出现两个相同 ID 的价格容器。快速购买、Sticky Header 或自定义图库可能克隆了表单，事件更新的是隐藏区域，用户看到的那一块自然不变。</p>
<h2>别把所有差价都写进前端脚本</h2>
<p>有人为了赶进度在 onchange 里手工加 20 元，这会绕过客户组价格、税、货币格式和促销规则。正确修复应该让前端使用 Magento 输出的最终价格结构，只修复选项到商品 ID 的解析或 priceBox 更新链路。</p>
<p>最后测试不仅要点颜色，还要覆盖颜色+尺寸组合、缺货组合、登录客户组和含税显示。若只有某个组合不更新，通常是允许组合索引或子商品数据问题；若所有组合都不更新，才集中查主题 JS。这样排查比“索引和静态资源全清一遍”更容易留下可复现的结论。</p>]]></description>
      <pubDate>Mon, 15 Sep 2025 02:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2 Catalog Price Rule已经启用，前台商品价格为什么没有变化？]]></title>
      <link>https://www.360magento.com/blog/catalog-price-rule-enabled-price-not-changing/</link>
      <description><![CDATA[<p>目录价格规则在后台显示 Active，商品页还是原价。以前遇到这种情况我也会直接跑全量 reindex，后来发现这只能覆盖一部分原因：索引可以成功生成一份“没有匹配商品”的结果，命令照样返回成功。</p>
<h2>先证明这件商品真的命中规则</h2>
<p>把条件缩到最小，只保留一个可明确验证的 SKU 或属性。确认 Website、Customer Group、生效日期和商品在当前 store view 的属性值。用于规则的属性如果刚改过“Use for Promo Rule Conditions”，也需要让相关索引和缓存认识到新配置。</p>
<p>特殊价格和目录规则同时存在时，前台通常取可用的最低价格。商品本来就有更低的 special price，会让人误以为规则没执行。测试时记录 regular、special、rule 三种价格，不要只盯最终数字。</p>
<h2>看价格索引状态和Cron，不要只看命令最后一行</h2>
<pre><code>bin/magento indexer:status catalogrule_rule catalogrule_product catalog_product_price
bin/magento indexer:reindex catalogrule_rule catalogrule_product catalog_product_price
bin/magento cron:run --group=index</code></pre>
<p>Update by Schedule 模式依赖 cron 和 changelog。索引显示 Ready 不代表刚修改的规则已被消费，还要看 mview_state 的版本是否推进、cron_schedule 中相关任务是否成功。生产环境不要习惯性把所有索引切成 Update on Save，它可能把后台保存规则变成一个很重的同步操作。</p>
<h2>直接对照索引表比反复清缓存更快</h2>
<p>用产品 ID、website ID、customer group 和日期查询规则索引，确认是否产生记录以及 rule_price 是多少。没有记录就回到匹配和索引链路；有正确记录但页面错误，才检查价格缓存、全页缓存和第三方价格插件。</p>
<p>多网站项目尤其容易把规则建在默认网站，却在另一个网站测试。Catalog Price Rule 的作用范围不是仅靠 store view 名称判断，数据库里的 website_id 才是关键。</p>
<p>修复后我会用游客和目标客户组各打开一次商品页、分类页和购物车，并等跨过一个日期边界再确认 cron 能自动切换。一次手工 reindex 能让价格出现，不等于线上调度已经恢复。</p>]]></description>
      <pubDate>Fri, 12 Sep 2025 08:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2优惠券提示使用成功，为什么购物车一分钱都没减？]]></title>
      <link>https://www.360magento.com/blog/coupon-code-success-but-no-discount-cart/</link>
      <description><![CDATA[<p>购物车提示“优惠券代码已应用”，总价却完全没变化。这里的“成功”通常只表示系统找到了可用规则并把 code 写进 quote，不代表购物车里一定存在满足折扣 Action 的商品。</p>
<h2>用一辆最简单的购物车复现</h2>
<p>我会先清空购物车，只放一个确认应该参与活动的简单商品，并用无痕窗口登录正确客户组。复杂购物车里混着 bundle、赠品、虚拟商品和免折 SKU，很难看出是哪条条件排除了折扣。</p>
<p>后台逐项核对 Website、Customer Groups、起止日期、Uses per Customer 和 Coupon Uses。日期要按商店时区理解，不要拿服务器 UTC 直接判断。规则过期或次数用尽时通常不会正常应用，但自定义模块可能保留前端成功提示，所以仍要查。</p>
<h2>Conditions和Actions不是一回事</h2>
<p>Conditions 决定整辆购物车是否进入规则，Actions 下方的条件决定哪些行真正打折。最常见的是上面按分类判断通过，下面又把该分类排除了；或者配置“仅匹配以下条件的商品”，但用的是不可用于促销规则的属性。</p>
<p>检查商品在当前 store view 的真实属性值，不要只看 All Store Views。可配置商品还要确认条件落在父商品还是子商品，购物车里的实际 item 对应哪个 SKU。</p>
<h2>优先级和Stop Further Rules会让后面的规则看似失效</h2>
<p>临时停掉其他购物车规则，只留这一条测试。如果折扣出现，就按 sort order 逐个恢复，并检查前一条是否开启 Discard subsequent rules。多张优惠同时存在时，也要确认系统是否允许叠加。</p>
<p>代码层我会观察 quote 的 coupon_code、applied_rule_ids 以及各 item 的 discount_amount。coupon_code 有值而 applied_rule_ids 为空，说明规则校验没通过；规则 ID 已应用但金额为零，则继续看 Action 计算和商品行。</p>
<pre><code>bin/magento cache:clean config full_page
bin/magento indexer:status</code></pre>
<p>购物车规则本身不像目录价格规则那样只靠一次 reindex 就能解决。修复后要重新触发 collect totals，最好新建购物车验证，避免旧 quote 保存的金额干扰。最终至少测试游客、目标客户组、临界金额和被排除 SKU 四种情况，确认规则不是只在“刚好那辆购物车”里有效。</p>]]></description>
      <pubDate>Thu, 11 Sep 2025 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2执行setup:di:compile报Cannot instantiate interface，应该先查哪个di.xml？]]></title>
      <link>https://www.360magento.com/blog/setup-di-compile-cannot-instantiate-interface-debug/</link>
      <description><![CDATA[<p><code>setup:di:compile</code> 报 Cannot instantiate interface 时，不要直接给报错接口随便写一个 preference。这个异常只说明 Object Manager 在当前作用域无法把接口变成具体类，根因可能是模块没加载、配置被覆盖，甚至是构造函数写错了类型。</p>
<h2>先沿着异常栈找到是谁需要这个接口</h2>
<p>报错最后一行常常只有接口名，真正有价值的是上面第一个自定义类。查看它的构造函数，确认参数类型是不是你预期的接口。有时 IDE 自动导入了同名但不同命名空间的 Interface，怎么改 di.xml 都不会对。</p>
<pre><code>bin/magento setup:di:compile -vvv
bin/magento module:status Vendor_Module
grep -R "完整接口名" app/code vendor/*/*/etc -n</code></pre>
<p>搜索结果里重点看 preference、type argument 和 virtualType。一个接口可以在全局 <code>etc/di.xml</code> 有实现，但某个 <code>etc/adminhtml/di.xml</code> 或 <code>etc/frontend/di.xml</code> 又改了参数。CLI 编译读取的配置范围和浏览器请求并不完全一样，所以“后台能用”不能证明全局 DI 正确。</p>
<p>再看异常发生在 application code generation 的哪一步。Repositories、Factories、Proxies 和 Interceptors 的错误上下文不同：Factory 生成失败经常是目标类或构造函数不可用；Interceptor 失败则要检查被插件的方法是否允许拦截、插件类本身能否实例化。不要只复制异常最后一句去搜索。</p>
<h2>检查提供实现的模块是否真的在依赖链里</h2>
<p>如果实现来自另一个模块，调用方的 <code>module.xml</code> 应通过 sequence 表明加载关系，<code>composer.json</code> 也应声明包依赖。只依赖服务器上碰巧安装的模块，换一套环境就会在编译阶段暴露出来。</p>
<p>另外核对具体类是否可实例化：是不是 abstract、构造函数又依赖了同一个接口形成循环、类文件大小写是否和 Linux 文件系统一致。开发机在不区分大小写的文件系统上能跑，并不代表生产机也能自动找到。</p>
<h2>用生成后的DI信息验证，不靠清缓存碰运气</h2>
<p>修改后删除的应该是可重新生成的编译产物，并按照项目部署流程重新编译；不要把 vendor 和配置文件一起删掉。编译通过后，再用 DI 信息命令确认接口最终解析到哪个类：</p>
<pre><code>bin/magento dev:di:info 'VendorModuleApiSomeInterface'</code></pre>
<p>如果这个命令得到的实现和设计不一致，继续查覆盖顺序。只有确认“谁请求接口、哪个配置提供实现、最终合并结果是什么”，这个问题才算解决。临时把接口改成具体类虽然可能过编译，却会破坏可替换性，也容易在下次升级时再次爆掉。</p>
<p>发布前还要在一套干净目录执行 <code>composer install</code> 后重新编译。开发机残留的 generated 文件可能让错误暂时消失，CI 的全新工作区更能证明依赖声明与 DI 配置完整。若只有生产报错，比较启用模块列表和 composer.lock，而不是把生产生成目录复制回开发机。</p>]]></description>
      <pubDate>Wed, 10 Sep 2025 07:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台保存商品一直转圈，页面不报错到底卡在哪里？]]></title>
      <link>https://www.360magento.com/blog/admin-product-save-spinner-no-error-debug/</link>
      <description><![CDATA[<p>后台点“保存”后遮罩一直不消失，最没用的做法就是反复点按钮。商品保存不是一个小请求，它会触发 EAV 写入、图片处理、索引失效、插件和事件。页面没有弹错误，只能说明前端没有拿到可识别的响应。</p>
<h2>第一步看那条保存请求究竟处于什么状态</h2>
<p>打开浏览器 Network，重新保存一次，找到 product/save 请求。Pending 说明服务端还没结束；500 要看响应体和 exception.log；302 跳登录页多半是 Session 或 Form Key；200 却返回整页 HTML，则可能被 WAF、登录重定向或 PHP Warning 污染。</p>
<p>我会把请求开始时间记下来，再按同一时间段查日志，避免在几百 MB 的文件里盲搜：</p>
<pre><code>tail -f var/log/system.log var/log/exception.log
journalctl -u php-fpm --since "5 minutes ago"</code></pre>
<p>如果 PHP-FPM 日志显示 worker 超时或内存耗尽，先记录商品 SKU、图片数量和属性集。只有特定商品失败，通常是数据或媒体问题；所有商品都慢，才更像全局插件、数据库或基础设施。</p>
<h2>Pending请求要查数据库正在等什么</h2>
<pre><code>SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUSG</code></pre>
<p>长时间处于 Waiting for table metadata lock、更新价格索引表或 URL Rewrite 表，说明请求不是“死了”，而是在等锁。此时重启 PHP 只能让请求消失，锁的来源仍然存在。找到持锁事务和对应业务后再决定结束连接，别直接清空进程。</p>
<p>若数据库没有等待，我会在测试环境打开一次 Magento profiler，或者用 PHP-FPM slowlog 抓正在执行的调用栈。保存耗时稳定在同一个 Observer 或 Plugin，才有资格继续读那段代码。耗时飘忽且集中在远程域名，则检查 DNS、HTTP 超时和失败重试。很多“商品保存很慢”其实是在同步图片或通知 ERP，Magento 只是同步等待它返回。</p>
<p>图片较多的商品还要观察临时目录、磁盘 inode 和图片处理进程。上传预览成功并不代表保存时从 tmp 移动、生成角色图和缓存图都能完成。拿一个无图片的简单商品做对照，能快速把 EAV 保存与媒体处理拆开。</p>
<h2>临时绕开插件时要一次只缩小一层</h2>
<p>商品保存周围经常有 ERP 同步、自动生成 URL、图片压缩和审计插件。用 profiler 或插件日志确认耗时；在测试环境按模块逐个验证，不要在线上一次性禁用几十个模块。尤其检查 afterSave、aroundSave 中是否调用外部 HTTP 接口且没有超时。</p>
<p>还有一种情况是保存已经成功，前端在等待后续 Ajax 或页面跳转。刷新后若数据已落库，就检查返回内容是否混入调试输出，以及后台 JS Console 是否报错。最终修复标准不是“转圈没了”，而是保存请求耗时稳定、响应码正确、同类商品和大图商品都能完成，并且没有生成重复 URL 或半套索引数据。</p>]]></description>
      <pubDate>Tue, 09 Sep 2025 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2客户刚收到重置密码邮件，点击链接为什么就提示已过期？]]></title>
      <link>https://www.360magento.com/blog/customer-password-reset-link-expired-immediately/</link>
      <description><![CDATA[<p>客户反馈“重置密码链接已过期”时，我第一反应不是把有效期改成 24 小时。刚收到就失效和真正超时是两类问题，延长有效期只会掩盖 Token 为什么对不上。</p>
<h2>先只申请一次，然后保留原始链接</h2>
<p>连续点击“忘记密码”会生成新的重置 Token，之前邮件里的链接随即失效。测试时只提交一次，等队列发出邮件后复制完整 URL，不要让邮箱安全扫描器截断参数。重点确认链接里是否同时带有客户标识、Token 和正确的网站域名。</p>
<p>可以在测试账号上对照数据库中的时间与 Token 字段，但不要把 Token 发到工单或群里。线上排查只记录是否变化、生成时间和客户 ID 即可。</p>
<pre><code>SELECT entity_id, email, website_id,
       rp_token_created_at,
       CASE WHEN rp_token IS NULL THEN 'empty' ELSE 'set' END AS token_state
FROM customer_entity
WHERE email = 'test@example.com';</code></pre>
<p>提交一次后刷新查询，如果 Token 很快又变化，说明有第二次请求、自动化脚本或客服后台操作覆盖了它。邮件发送延迟也会造成旧邮件晚于新邮件到达，客户点开的其实是已经被替换的那一封。</p>
<h2>自定义邮件模板最容易丢参数</h2>
<p>升级后沿用很老的模板时，不要凭记忆拼重置地址。先临时切回当前版本自带模板发一封测试邮件。如果默认模板可用，自定义模板不可用，问题就在变量或转义方式，而不是控制器。</p>
<p>还要检查配置作用域。多网站允许相同邮箱属于不同 website，生成 Token 的网站和打开链接的域名必须一致。反向代理把 Host 改错、邮件 Base URL 使用主站域名，也可能把客户带到另一套 website 上校验。</p>
<h2>时间要比较数据库、PHP和应用节点</h2>
<pre><code>date -u
php -r 'echo gmdate("c"), PHP_EOL;'
mysql -e "SELECT UTC_TIMESTAMP(), NOW();"</code></pre>
<p>Magento 保存的时间、PHP 默认时区和数据库会话时区如果混在一起，日志看着只差几分钟，校验时却可能已经超过配置窗口。先统一 UTC 基准，再检查后台 Password Recovery Link Expiration Period 的网站级配置。</p>
<p>修好后我会做两组验证：同一账号申请两次，确认第一封确实失效、第二封可用；不同 website 上的同邮箱各申请一次，确认链接只在所属站点生效。这样才能证明修的是 Token 流程，而不是碰巧让某一封邮件通过。</p>]]></description>
      <pubDate>Mon, 08 Sep 2025 06:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2后台能正常登录，换了手机后验证码一直不对，2FA怎么重置？]]></title>
      <link>https://www.360magento.com/blog/admin-2fa-code-invalid-after-changing-phone/</link>
      <description><![CDATA[<p>同事换了手机，重新安装 Google Authenticator 后，Magento 2 后台账号和密码都能通过，但六位验证码怎么输都提示无效。这个问题最容易被误判成后台密码错误，实际上密码校验和 2FA 是两步，第一步通过并不代表新手机已经继承旧手机上的密钥。</p>
<h2>先确认不是30秒时间窗的问题</h2>
<p>TOTP 验证码依赖服务器与手机时间。如果只有一台手机失败，先让手机开启自动日期和自动时区；如果所有管理员突然一起失败，就检查服务器时间，而不是逐个重置账号。</p>
<pre><code>date -u
timedatectl status
chronyc tracking</code></pre>
<p>我会同时看应用节点的时间。多节点环境里，某一台机器慢一分钟，就可能表现为验证码偶发成功、偶发失败。NTP 修好后再试一次，避免把一个基础设施问题改成账号问题。</p>
<h2>换手机并不会自动迁移Magento里的密钥</h2>
<p>旧手机没有导出验证器账号，新手机扫描的如果不是当前后台用户对应的二维码，生成的数字当然永远不匹配。还能用另一位超级管理员登录时，直接到用户管理中找到该账号，在 2FA 页面执行 Reset。下次登录会重新出现配置流程。</p>
<p>后台没人能登录时，可以从 Magento 根目录只重置这个用户，不要为了省事关闭整个 2FA 模块：</p>
<pre><code>bin/magento security:tfa:reset admin_username google</code></pre>
<p>具体 provider 名称先根据当前版本和已启用模块确认。重置成功后，用无痕窗口重新登录并扫描新二维码。原窗口可能还保存着旧的登录状态和 2FA Cookie，继续在原页面刷新会制造“命令没生效”的假象。</p>
<h2>仍然无效时看账号和请求落在哪台机器</h2>
<p>检查执行命令的数据库是否就是线上后台使用的数据库，也要确认负载均衡后所有节点读取同一份加密配置。若迁移环境时更换了加密 key，旧的加密数据可能无法正确读取，这时日志里通常不只出现验证码错误，还会伴随解密异常。</p>
<p>最终验证不要只看能否进首页。我会退出后台、清掉该域名 Cookie，再完成一次完整登录，随后确认用户的 2FA 记录已经重新生成。这样可以排除当前 Session 恰好还有效的情况。核心思路是：先校准时间，再重置单个用户，最后才考虑模块和加密配置，别上来就禁用 2FA。</p>]]></description>
      <pubDate>Fri, 05 Sep 2025 02:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 退款后库存没有回来，Credit Memo 到底在什么条件下回补？]]></title>
      <link>https://www.360magento.com/blog/credit-memo-stock-not-returned-msi/</link>
      <description><![CDATA[<p>客服完成 Credit Memo，款也退了，但商品可销售数量没有增加。有人直接把 Source Quantity 加回去，第二天 ERP 同步又覆盖。退款、退货和库存回补是相关但不同的业务动作，必须先确认这张 Credit Memo 是否要求 Return to Stock。</p><h2>先还原订单履约状态</h2><p>记录 order、invoice、shipment、credit memo 的 ID 与时间，商品是否已发货、从哪个 Source 发货、退款数量和是否勾选 Return to Stock。未发货订单的取消与已发货订单的退货，库存事件不同；虚拟商品也不存在物理回库。</p><p>部分退款尤其要按 item 检查。订单买 5 件、发 3 件、退 2 件时，系统不能凭总数猜回哪个仓库。后台操作界面可能只显示数量，但 MSI 需要明确 Source 上下文。</p><h2>MSI 中 Source Quantity 与 Salable Quantity 分开变化</h2><p>下单 reservation 先影响 salable，发货再扣 Source Quantity 并做补偿。退款回库可能增加具体 Source 的物理数量，同时通过事件影响可销售状态。用服务接口或只读查询按 SKU、stock、source 和订单 reservation 对账，避免只看商品编辑页总数。</p><pre><code>php bin/magento inventory:reservation:list-inconsistencies
php bin/magento queue:consumers:list
php bin/magento indexer:status inventory</code></pre><p>若回库事件已产生但前台未变化，检查库存消费者与索引；若根本没有事件，回到 Credit Memo 参数、插件和订单状态。</p><h2>ERP/WMS 集成决定谁是物理库存事实源</h2><p>部分项目规定 Magento 只申请退货，仓库验收入库后由 WMS 增加数量。此时退款当刻不回库存可能是正确设计。必须和业务确认“退款即回库”还是“验收后回库”，并保证两边不会各加一次。</p><p>Webhook 和队列要用 creditmemo_id、order_item_id 等稳定键保证幂等。外部回调重放时，不能重复增加库存。失败消息应可重试且保留状态。</p><h2>完整验收要覆盖四条路径</h2><p>未发货取消、已发货全额退货、部分退货、不回库退款分别测试。每条路径对比 Source Quantity、Salable Quantity、reservation 合计、订单状态和 ERP 记录。最后再下一个测试订单，确认恢复的库存确实可售且不会超卖。退款金额正确只是财务闭环，库存还需要自己的闭环。</p>]]></description>
      <pubDate>Thu, 04 Sep 2025 06:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 税额差一分钱：购物车、订单和支付平台为什么会出现舍入差异？]]></title>
      <link>https://www.360magento.com/blog/tax-rounding-one-cent-cart-order-payment/</link>
      <description><![CDATA[<p>三个单价 9.99 的商品，购物车税额显示 2.10，支付平台明细加起来却是 2.09。订单能创建，但支付端拒绝，因为 line items 合计与总金额不一致。“只差一分钱”如果靠强行修改 grand_total，会让发票、退款和财务对账继续错下去。</p><h2>先保留未经格式化的原始金额</h2><p>页面通常只显示两位小数，数据库和计算过程中可能保留更多精度。记录 quote 与 order 的 base_subtotal、discount、shipping、tax、grand_total 及对应非 base 字段，同时保存商品 qty、税率和是否含税。用相同数据在表格中逐行重算，找出第一次舍入的位置。</p><h2>Unit Price、Row Total 与 Total 算法结果本来就可能不同</h2><p>按单价计算会先对每个单件税额舍入，再乘数量；按行计算先乘数量，再对行税额舍入；按总计计算又在更高层聚合。多商品、多数量时差一分钱并不意外，关键是购物车、订单、发票和外部支付使用同一种事实。</p><p>后台 Tax Calculation Method、Catalog Prices 是否含税、Shipping Prices 是否含税、Apply Customer Tax 与折扣先后顺序都要按 Website 作用域核对。不要只截图一个配置项。</p><h2>折扣分摊与多币种会再增加一次舍入</h2><p>购物车折扣按比例分到每个 item 时，尾差必须落到明确行。base currency 换算为 order currency 后又会舍入。支付模块如果重新用显示金额计算明细，而不是使用订单已计算字段，就可能得到另一套结果。</p><h2>外部支付明细必须可回算到订单总额</h2><p>构建 line items 后，在发送前程序化断言：商品、运费、税、折扣合计等于请求总金额。若支付服务要求每行两位小数，设计明确的尾差分配规则，通常把差额落在最后一条合适项目，而不是悄悄修改订单。</p><h2>用矩阵而不是单个订单验收</h2><p>测试单件、多数量、多个税率、优惠券、含税价、运费税、多币种、部分发票和部分退款。每一步比较 quote、order、invoice、credit memo 与支付平台。允许的显示差异要有解释，提交和结算金额必须完全对得上。税额问题真正的终点是全生命周期可对账。</p>]]></description>
      <pubDate>Wed, 03 Sep 2025 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多商店 Canonical 总指向主站，hreflang 和域名该怎么理顺？]]></title>
      <link>https://www.360magento.com/blog/multistore-canonical-points-to-main-domain/</link>
      <description><![CDATA[<p>英文站、德文站使用不同域名，但所有商品页 canonical 都指向英文主站。这样可能让搜索引擎把其他语言页面当成重复内容。修复不能简单把当前 URL 原样塞进 canonical，因为参数、分类路径和分页也需要统一策略。</p><h2>先定义每类页面的唯一地址</h2><p>商品页是否包含分类路径？同一商品在多个分类下是否统一到无分类路径？分页、排序、筛选参数是否应该 canonical 到自身、第一页或上级分类？先把规则写清楚，再看代码。没有策略时，技术修改只会从一个错误变成另一个错误。</p><h2>检查 Store View 的 Base URL 与产品分配</h2><p>分别在每个 Store Scope 读取 secure Base URL，确认域名、路径和尾斜杠。商品必须真正分配到对应 Website，并有该 Store 的启用状态和 URL Key。若德文站只是前端代理英文 Store，Magento 自然生成英文上下文。</p><p>查看最终 HTML head 中所有 canonical 和 hreflang。主题、核心功能和第三方 SEO 模块可能同时输出标签，出现两个 canonical 比没有更糟。搜索源码时不仅找 rel=canonical，也要检查 layout block 与 head additional。</p><h2>hreflang 不是 canonical 的替代品</h2><p>不同语言页面通常各自 self-canonical，再用 hreflang 相互关联。每个 hreflang 目标应返回 200，并最好形成互相引用；不存在翻译时，不要凭 URL 规则生成一个 404。x-default 是否使用，取决于站点的语言选择策略。</p><h2>缓存上下文容易造成串域</h2><p>自定义 canonical block 如果 cache key 不包含 Store ID，首次由英文站缓存后，德文站也可能拿到英文域名。Varnish/CDN host key 配置错误也会造成跨域缓存。用不同 Host 连续交叉请求，检查响应 Age 和标签是否跟随 Store。</p><p>验收选商品、分类、CMS、分页和带筛选参数页面，在每个域名检查唯一 canonical、hreflang 互链、状态码和最终跳转。再用站点爬虫生成矩阵，避免只手工检查首页。SEO 标签看似一行 HTML，背后其实是完整的多商店 URL 模型。</p>]]></description>
      <pubDate>Tue, 02 Sep 2025 07:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Sitemap 生成成功却是空的，或者全是错误域名，应该查哪些作用域？]]></title>
      <link>https://www.360magento.com/blog/sitemap-empty-wrong-domain-store-scope/</link>
      <description><![CDATA[<p>后台显示 Sitemap 生成成功，打开文件却只有 XML 头；另一个 Store View 的 sitemap 又全部指向主站域名。生成器没有报错，只说明它完成了当前作用域能看到的数据，不代表内容正确。</p><h2>先确认这条 Sitemap 属于哪个 Store View</h2><p>后台每条 sitemap 记录有明确 Store View 和文件路径。多商店环境要逐条核对，不要复用一条记录期待它自动覆盖所有域名。生成 URL 时会读取对应 Store 的 secure/unsecure Base URL，因此作用域配置错误会把整份文件指向错误站点。</p><p>用 CLI 或后台生成后，记录生成时间、文件大小和 URL 数量。文件没更新时，检查目录权限、只读 release、共享存储和多节点。后台节点写入本地磁盘，而公网请求落到另一节点，会得到旧文件或 404。</p><h2>空文件先检查实体是否具备进入条件</h2><p>商品需要在目标 Website 启用、可见，并符合 sitemap 配置；分类、CMS 页面也受启用状态和 Store View 影响。随机选择一个预期 URL，从实体分配一直查到最终 rewrite，不要先怀疑 XML writer。</p><p>若数据库有大量商品但 sitemap 只有少数，比较网站分配、可见性和索引状态。自定义插件可能在集合上添加过滤，导致某个 Store 全部被排除。</p><h2>域名正确还要检查 URL 是否可访问</h2><p>从 sitemap 抽样请求 200、301、404，确认不包含后台路径、noindex 页面、搜索结果或带 session 参数的 URL。多级 301 会浪费爬虫抓取预算；跨域跳转说明 Base URL 或 rewrite 有问题。</p><h2>定时生成与提交也要闭环</h2><p>手工生成正常、第二天又旧，检查 cron_schedule 中 sitemap 任务、计划频率、时区和错误日志。文件很大时确认拆分策略和压缩产物。robots.txt 或站长平台提交的路径要与真实文件一致。</p><p>验收按 Store View 分别统计 URL 数，抽样商品/分类/CMS，验证域名、语言、canonical 和 HTTP 状态。再模拟下一次 cron，确认时间戳和内容更新。Sitemap 的价值是稳定反映可索引页面，不是后台出现一行“成功”。</p>]]></description>
      <pubDate>Mon, 01 Sep 2025 01:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Knockout 报 Failed to load template，模板文件存在为什么仍然找不到？]]></title>
      <link>https://www.360magento.com/blog/knockout-failed-to-load-template-debug/</link>
      <description><![CDATA[<p>Checkout Console 报 <code>Failed to load the template</code>，开发者在 <code>view/frontend/web/template</code> 明明能看到文件。问题是浏览器不会直接读取源码目录，它请求的是当前主题、语言和静态版本下发布后的 HTML 模板。</p><h2>从组件配置还原模板 ID</h2><p>UI Component 里的 <code>template</code> 通常写成 <code>Vendor_Module/path/file</code>，对应 web/template/path/file.html。大小写、下划线和连字符必须一致。Linux 上大小写错误会 404，本地系统可能看不出来。</p><p>在 Network 找失败请求，检查状态码、最终 URL、Content-Type 和响应体。200 但响应是登录页、404 HTML 或 WAF 页面，Knockout 一样无法当模板解析。</p><h2>确认当前 area、主题和 locale 的发布产物</h2><p>只为 en_US 部署静态内容，zh_CN Store View 请求模板就可能缺失。主题覆盖文件如果路径不完整，也会让 fallback 结果不同。检查页面当前 locale 和 theme，而不是只在默认主题目录找。</p><pre><code>find pub/static -path '*Vendor_Module*template*' -name '*.html'
find app/design app/code -path '*web/template*' -name '*.html'</code></pre><h2>旧 HTML 与新静态版本不匹配</h2><p>发布切换后，FPC/CDN 仍返回旧 requirejs 配置或旧组件 JSON，浏览器便去请求已经清理的版本目录。静态产物应在切换前完成，HTML/FPC 清理与 release 切换顺序要固定。Service Worker 或 PWA 缓存也可能继续保存旧模板 URL。</p><h2>模板加载成功后仍报错怎么办</h2><p>HTML 中未闭合标签、错误 Knockout binding、引用不存在变量，可能让错误看起来像加载失败。用最小模板替换做对照，再逐段恢复 binding。不要在模板里执行复杂业务逻辑，把数据准备放进 view model。</p><p>修复后在目标 Store View、无痕窗口和生产静态合并模式测试，Network 返回正确 HTML，Console 无 binding 错误，结账步骤能前进。只让开发者自己的浏览器不报错不够，多语言和旧缓存路径必须一起覆盖。</p>]]></description>
      <pubDate>Fri, 29 Aug 2025 06:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 RequireJS Mixin 写了却没执行，怎么确认它真的合并进配置？]]></title>
      <link>https://www.360magento.com/blog/requirejs-mixin-not-loading-debug/</link>
      <description><![CDATA[<p>自定义 mixin 文件能直接通过 URL 打开，Console 也没有 404，但目标方法完全没进入。重复 static-content:deploy 有时让它生效，换浏览器又失效。这里要分清“文件存在”“RequireJS 配置声明成功”和“目标模块已经按 mixin 包装”三个阶段。</p><h2>路径必须匹配 AMD 模块名</h2><p><code>requirejs-config.js</code> 中的目标键应是模块 ID，不是磁盘绝对路径，也通常不带 .js。先在浏览器中确认目标组件实际通过哪个 ID 加载，主题覆盖或 bundle 可能改变你以为的路径。</p><pre><code>var config = {
    config: {
        mixins: {
            'Magento_Checkout/js/view/example': {
                'Vendor_Module/js/example-mixin': true
            }
        }
    }
};</code></pre><h2>确认合并后的配置，而不是只看源文件</h2><p>在 Network 找页面实际加载的 requirejs-config，搜索两个模块 ID。源文件正确但合并产物没有，检查文件位置是否为 <code>view/frontend/requirejs-config.js</code>、模块是否启用、area 是否正确，以及静态部署包含当前主题和语言。</p><p>多 release 或 CDN 环境还要核对 HTML 中的静态版本与 JS 文件版本。旧 HTML 引用旧配置时，你在服务器看到新文件也没用。</p><h2>Mixin 自身必须返回正确包装</h2><p>目标是 UI Component、jQuery widget 或普通对象时，写法不同。Mixin factory 必须返回扩展后的 target；遗漏 return、依赖顺序写错、方法名大小写不一致，都可能静默失败。给模块加载阶段加临时日志，再给目标方法入口加日志，能判断停在哪一层。</p><p>如果目标模块在 mixin 配置加载前已经被 require 并实例化，后补配置也不会自动改造现有实例。不要在运行中动态注入，确保配置在首次加载前合并。</p><h2>用行为测试结束排查</h2><p>清理最小必要静态缓存后开新会话，确认配置只加载一次、mixin factory 执行、目标方法参数和返回值符合预期。再测试生产合并/压缩开启的模式，因为开发模式正常不代表 bundle 后仍正常。最后移除调试日志，避免在客户浏览器输出订单或地址信息。</p>]]></description>
      <pubDate>Thu, 28 Aug 2025 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Layout XML 写了 remove，页面上的 Block 为什么还在？]]></title>
      <link>https://www.360magento.com/blog/layout-xml-remove-block-not-working/</link>
      <description><![CDATA[<p>在 <code>catalog_product_view.xml</code> 里写了 <code>&lt;referenceBlock name="..." remove="true"/&gt;</code>，清缓存、重新部署静态文件，页面上的内容仍在。多数时候不是 remove 语法失效，而是你操作的 handle 或 name 根本不是最终页面里的那个元素。</p><h2>先确认 full action name 与实际 layout handle</h2><p>商品页除了 catalog_product_view，还可能加载商品类型、布局更新、主题和 CMS 相关 handle。自定义控制器的路由名与文件名也经常写错。开启开发环境的 layout 调试或在受控日志中记录 handles，确认你的 XML 确实被加载。</p><h2>remove 使用的是 layout name，不是 CSS class</h2><p>浏览器里的 id、class 和模板文件名不能直接当 referenceBlock name。找到定义该 block 的原始 layout XML，确认 <code>name</code>。若目标是 container，应使用 referenceContainer。页面看起来相同的内容也可能由另一个 block、view model 或 JS 组件再次渲染。</p><pre><code>&lt;referenceBlock name="product.info.review" remove="true"/&gt;
&lt;referenceContainer name="sidebar.main" remove="true"/&gt;</code></pre><h2>加载顺序可能把它重新加回来</h2><p>模块 A 删除 block，模块 B 在后续 handle 又以相同或不同 name 添加。检查模块 sequence、主题继承和所有同名声明。不要只在 app/design 搜索，vendor 模块和后台 CMS Layout Update 也可能参与。</p><p>如果 block 由 PHP 在运行时创建，layout XML 的静态 remove 找不到它，需要定位创建点，从扩展机制或配置解决，而不是添加更多 remove。</p><h2>哪些缓存需要清</h2><p>Layout 合并主要受 layout/config/FPC 影响，静态内容部署通常与“block 是否存在”无关。开发时清最小必要缓存，避免每次全 flush 让其他问题被掩盖。生产修改应随完整发布流程，不要直接编辑 vendor。</p><p>验收不仅看元素消失，还要检查页面没有留下空容器、关联 JS 不报错、结构化数据与移动端布局正常。若删除的是扩展提供的业务入口，还要确认没有影响结账或可访问性。</p>]]></description>
      <pubDate>Wed, 27 Aug 2025 07:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 报 circuit_breaking_exception，商品搜索为什么会把内存打满？]]></title>
      <link>https://www.360magento.com/blog/opensearch-circuit-breaking-exception-search/</link>
      <description><![CDATA[<p>搜索页偶尔 500，OpenSearch 返回 <code>circuit_breaking_exception</code>。重启集群后暂时恢复，高峰期又出现。熔断器是在保护节点避免真正 OOM，第一步不是把限制无限调大，而是找出哪类请求占用了异常内存。</p><h2>把失败请求和集群内存放在同一时间线上</h2><p>记录 Magento request ID、搜索词、筛选项、Store View、结果页码和发生时间。OpenSearch 侧查看 heap、GC、breaker、线程池拒绝和慢日志。只有某个复杂筛选失败，可能是聚合问题；所有查询都失败，可能是集群已长期高压。</p><pre><code>curl -sS 'http://search-host:9200/_cluster/health?pretty'
curl -sS 'http://search-host:9200/_nodes/stats/jvm,breaker,indices?pretty'
curl -sS 'http://search-host:9200/_cat/indices?v'</code></pre><p>接口可能暴露内部信息，只应在受控网络使用，不要把完整输出公开。</p><h2>高基数字段和大聚合是常见元凶</h2><p>分层导航会对可筛选属性做 aggregation。把几乎每个商品都不同的文本属性设为可筛选，bucket 数量会巨大。检查新近启用的 layered navigation 属性、字段类型和 doc_values。业务不需要的筛选应关闭，而不是让集群为它预留更多内存。</p><p>深分页、超大的 pageSize、通配符前缀和同时请求大量聚合也会放大内存。前端应设置合理分页上限，避免为了总数一次取回大量文档。</p><h2>索引与分片布局也影响单节点压力</h2><p>太多小分片会消耗大量固定开销，太少且过大的分片又让查询集中。检查索引前缀是否残留多套旧环境索引、replica 是否适合节点数、分片是否均匀。不要在故障时直接删除看不懂的索引，先确认 Magento 当前别名和回滚需求。</p><h2>调 heap 只能在证据支持时进行</h2><p>容器限制、JVM heap 和宿主机内存必须匹配，不能让 JVM 认为有更多内存而被系统 OOMKill。调整后观察 GC 暂停、查询延迟与缓存命中，而不是只看熔断消失。</p><p>最终用真实搜索词、最复杂筛选、空关键词和高并发分别压测。熔断为零、heap 能回落、P95 延迟稳定，并且业务筛选结果没有被错误删减，才是完成。</p>]]></description>
      <pubDate>Tue, 26 Aug 2025 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Async Bulk API 一直显示 open，消息到底卡在哪一层？]]></title>
      <link>https://www.360magento.com/blog/async-bulk-api-operation-stuck-open/</link>
      <description><![CDATA[<p>异步批量接口很快返回一个 bulk_uuid，但几小时后查询状态仍是 open，商品一个也没更新。HTTP 202 只表示请求已被接收并拆成异步操作，不表示后台 consumer 已执行成功。</p><h2>从 bulk_uuid 找到每一条 operation</h2><p>先保存提交时间、调用身份、路由和返回 UUID。通过官方状态接口查看总数、成功、失败和未完成数量。若只有少数 operation 失败，先读单条错误；若全部未开始，重点查消息是否发布与对应 consumer。</p><p>数据库只读查询可用于辅助，但不同版本表结构可能变化，不要根据网上 SQL 直接改状态。状态表是结果，不是队列本身；把 open 手工改成 complete 不会执行任何业务。</p><h2>确认负责拆分和执行的 consumer 都在运行</h2><pre><code>php bin/magento queue:consumers:list
php bin/magento queue:consumers:start async.operations.all --max-messages=1000</code></pre><p>实际 consumer 名称以当前版本列表为准。检查进程管理器、cron consumers_runner、RabbitMQ 队列深度和未确认消息。队列不断增长但 consumer 无进程，是运行问题；consumer 存在却吞吐为零，查连接、权限和处理异常。</p><h2>一条毒消息可能拖住整个观察</h2><p>输入数据的 SKU、website、属性类型或必填字段错误，会让 operation 失败。错误处理若不断 requeue，同一条消息可能被快速重复。为消息设置可控重试和失败落点，保留错误原因，不能无限热循环。</p><p>批量请求也要控制大小。一次塞几万条虽然减少 HTTP 次数，却会放大序列化、队列和失败重跑成本。按可观测批次提交，每批保存 UUID，做到失败批次可单独重跑。</p><h2>重跑之前先判断操作是否幂等</h2><p>更新商品属性通常可以按最终值重试；扣库存、创建客户或触发外部同步则可能有副作用。根据 operation 的业务键检查是否已经部分成功，不能看到 bulk 仍 open 就整体再次提交。</p><p>验收时故意加入一条错误数据：正常项完成，错误项给出明确失败，bulk 最终状态可解释；consumer 重启后未完成项继续处理，不产生重复副作用。这样异步链路才真正可运维。</p>]]></description>
      <pubDate>Mon, 25 Aug 2025 06:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL 列表接口越查越慢，N+1 查询怎么确认和改成 BatchResolver？]]></title>
      <link>https://www.360magento.com/blog/graphql-n-plus-one-batch-resolver-performance/</link>
      <description><![CDATA[<p>查询 10 个商品只需 120ms，查询 50 个商品却超过 3 秒。数据库监控显示同一条 SQL 换着 product_id 执行几十次。这就是 GraphQL 常见的 N+1：列表本身查一次，每个 item 的自定义字段又各查一次。</p><h2>先证明慢的是哪个字段</h2><p>从最小 query 开始，只保留 items 的 id；然后每次加回一个字段，记录响应时间、SQL 数量和 resolver 耗时。不要一上来分析完整 PWA 请求，因为多个字段、fragment 与内联查询会把问题混在一起。</p><p>在预发布启用数据库 profiler 或 APM，把 SQL 指纹聚合。若商品数从 10 增到 50，某条 SQL 次数也从 10 墠到 50，基本可以锁定对应 resolver。生产环境采样时要限制日志，不记录客户 token 和完整变量。</p><h2>普通 Resolver 为什么容易制造 N+1</h2><p>字段 resolver 会针对父节点逐个调用。如果每次都用 Repository 加载实体，除了 SQL，还会触发插件、扩展属性和事件。Repository 适合清晰的单实体业务边界，不代表适合循环中批量读取。</p><p>先收集当前批次所有父实体 ID，再一次查询所需数据，以 ID 建 map 返回。Magento GraphQL 提供 BatchResolver 和 BatchServiceContractResolver 机制，用于把同一字段的多个请求合并。关键不是接口名字，而是保证批量服务只查一次，并能保持输入输出顺序与缺失值语义。</p><h2>批量之后还要处理重复字段与缓存</h2><p>同一个请求中不同 fragment 可能访问同一业务数据，可在请求生命周期内做小范围 memoization，但不要用跨客户的静态缓存保存个性化结果。可公开缓存的 query 需要正确 cache identity；含客户、购物车或权限数据的字段不能误放进公共缓存。</p><h2>防止查询本身无限膨胀</h2><p>即使没有 N+1，客户端一次请求数百 items、深层嵌套关联，也会消耗大量资源。为分页设置合理上限，评估查询复杂度和超时，并让前端只取当前页面真正使用的字段。返回巨大 payload 后再由浏览器丢掉大半，是另一种浪费。</p><p>改造后用 10、50、100 个 item 做曲线：SQL 数量应接近固定或按少量批次增长，响应时间不再线性爆炸，结果与旧 resolver 一致，缓存失效也正确。性能优化不能以漏字段或串客户数据为代价。</p>]]></description>
      <pubDate>Fri, 22 Aug 2025 02:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台频繁 Invalid Form Key，增大 max_input_vars 为什么没解决？]]></title>
      <link>https://www.360magento.com/blog/admin-invalid-form-key-session-size-debug/</link>
      <description><![CDATA[<p>保存产品偶尔提示 Invalid Form Key，重新登录又能工作；保存系统配置却几乎必现。团队把 <code>max_input_vars</code> 从 1000 调到 10000，问题仍然存在。原因是 Form Key 错误只是校验结果，不是单一根因。</p><h2>先比较失败请求中的两个 Form Key</h2><p>一个来自当前 session，另一个随表单提交。用浏览器 Network 查看请求中是否真的包含 form_key、字段是否被截断、提交前页面是否已停留很久。服务端日志只记录哈希或是否一致，不要打印完整 session 内容。</p><p>如果小表单也随机失败，优先查会话；只有字段很多的产品/配置页失败，才重点看 <code>max_input_vars</code>、<code>post_max_size</code>、Web 服务器请求限制和 WAF。</p><h2>会话为什么会在后台请求之间变化</h2><p>检查 Admin Cookie 的 Domain、Path、Secure、SameSite 与 Lifetime。后台通过 HTTPS，代理回源却让 Magento 认为是 HTTP，会生成不一致 Cookie。多节点如果 session 存本地文件，请求切换节点后也会拿不到原 session。</p><p>Redis session 场景查看连接错误、淘汰、TTL 与锁超时。后台保存大产品耗时很长，session 锁或连接超时可能在请求完成前就让下一请求使用新会话。</p><h2>字段截断要用最小复现证明</h2><p>逐步增加可配置商品选项或系统配置字段，观察 form_key 是否位于被截断部分。PHP 的 max_input_vars 按嵌套输入展开计数，页面看起来只有几百行，实际字段可能数千。修改参数后要确认 CLI 与 PHP-FPM 使用的不是两份 php.ini，并平滑重载正确的 FPM 池。</p><pre><code>php --ini
php -i | grep -E 'max_input_vars|post_max_size'
systemctl reload php-fpm</code></pre><p>命令行配置只能辅助，最终应通过 Web 请求暴露的受控诊断确认 FPM 值，诊断页面用完立即移除。</p><h2>代理不应缓存后台页面</h2><p>若 CDN/Varnish 错误缓存 Admin HTML，页面里的 form_key 属于旧会话，提交必然失败。后台路径应正确 bypass 公共缓存，响应也不应被共享。修复后跨节点连续保存、小表单与大表单都通过，长时间停留后的过期行为有明确提示，才能结束排查。</p>]]></description>
      <pubDate>Thu, 21 Aug 2025 07:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户导入提示邮箱重复，但明明属于不同 Website，怎么回事？]]></title>
      <link>https://www.360magento.com/blog/customer-import-duplicate-email-different-website/</link>
      <description><![CDATA[<p>迁移第二个网站的客户时，CSV 里邮箱在目标 Website 从未出现，导入仍提示重复。有人准备给邮箱末尾加后缀先导进去，这会破坏登录、通知和历史订单关联，通常不是可接受的修复。</p><h2>先确认客户账号共享范围</h2><p>Magento 可以按 Global 或 Per Website 共享客户账号。Global 模式下，同一个邮箱全站只能有一个客户；Per Website 模式下，同邮箱可以在不同 website_id 存在。先核对当前配置，再查询实际数据：</p><pre><code>SELECT entity_id, email, website_id, store_id, created_at
FROM customer_entity
WHERE email = :email
ORDER BY website_id;</code></pre><p>不要用 Store View 名称代替 website_id。store_id 决定客户创建时的商店上下文，唯一性核心通常是 email 与 website 范围。CSV 中 Website 字段映射错误，会把所有客户导进默认网站，于是产生“意外重复”。</p><h2>改变共享范围不是无成本开关</h2><p>从 Per Website 改成 Global 前，必须先扫描跨网站同邮箱客户，因为合并后会发生身份冲突。两个账号可能有不同密码、地址、客户组、订阅状态和订单历史，不能自动认定它们是同一个人。</p><p>反过来，从 Global 改成 Per Website 后，也要决定现有客户属于哪些网站，以及登录、重置密码和 SSO 的预期。配置改变应在迁移方案里明确，而不是为了让一次导入通过临时切换。</p><h2>导入文件还要处理大小写和空白</h2><p>邮箱前后空格、不可见字符、大小写规范化和字符编码会导致肉眼看似不同、系统判断冲突。导入前用脚本做规范化并生成重复报告，但保留原始文件以便审计。不要把“去重”写成简单保留最后一行，客户资料可能在其他行更完整。</p><h2>冲突客户要有业务决策</h2><p>同一自然人在两个网站有账户，可以选择账号合并、保留网站隔离，或建立明确关联。合并时需要迁移地址、订单可见性、订阅与客户组，并通知用户密码策略。无法自动判断的冲突进入人工清单。</p><p>最终用三种账号测试：只在网站 A、只在网站 B、两个网站同邮箱。验证登录、忘记密码、下单和后台查找都符合共享策略。导入“成功”只是技术结果，客户能在正确网站继续使用账号才是业务完成。</p>]]></description>
      <pubDate>Wed, 20 Aug 2025 01:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 批量导入后商品图片全是 404，文件到底应该放在哪里？]]></title>
      <link>https://www.360magento.com/blog/product-image-404-after-import-media-path/</link>
      <description><![CDATA[<p>商品 CSV 显示导入成功，后台也出现了图片文件名，但前台主图和缩略图全部 404。继续重复导入只会制造更多重复 gallery 记录。要先分清原图没有复制进 media，还是原图存在但派生缓存图无法生成。</p><h2>从一个失败 SKU 沿路径追踪</h2><p>记录 CSV 中 <code>base_image</code>、<code>small_image</code>、<code>thumbnail_image</code> 的值，以及导入界面填写的 Images File Directory。现代 Magento 导入通常以 <code>var/import/images</code> 为图片基础目录，CSV 应使用相对路径。开头斜杠、大小写和子目录拼接错误非常常见。</p><pre><code>find var/import/images -type f | head
find pub/media/catalog/product -type f -iname '*example*'
ls -ld pub/media pub/media/catalog pub/media/catalog/product</code></pre><p>Linux 区分大小写。CSV 写 <code>/A/B/Image.JPG</code>，文件实际是 <code>a/b/image.jpg</code>，开发者在不区分大小写的电脑上看不出问题，服务器会直接找不到。</p><h2>原图存在，404 可能发生在缓存尺寸</h2><p>分类页和商品页通常请求 <code>pub/media/catalog/product/cache</code> 下的派生图。清理图片缓存后，首次请求需要 PHP/GD 或 ImageMagick 重新生成。检查 Web 用户对 media 的读写权限、临时目录、图片格式和内存限制。</p><p>不要把整个 media 设置为 777。统一部署用户与 Web 用户的组权限，并确认新建文件继承正确组。损坏的 JPEG、超大 TIFF 或不支持的颜色空间也可能让缩放失败，日志里通常能看到具体异常。</p><h2>多节点与 CDN 会让问题看起来随机</h2><p>一台节点导入了原图，其他节点没有共享 media，请求经过负载均衡时就时好时坏。确认 media 是共享存储、对象存储，还是由发布任务同步。CDN 若缓存了 404，源站文件补齐后也可能继续返回旧失败，需要按 URL 精确清理。</p><p>验收时选主图、附加图和不同尺寸缩略图，各自请求原图与缓存图；连续命中不同节点；再新导入一个从未使用的文件名，确认无需人工 chmod 或清 CDN 就能显示。这样才证明导入链路修好，而不是手工补了一张图。</p>]]></description>
      <pubDate>Tue, 19 Aug 2025 05:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单号突然跳号甚至疑似重复，Sequence 表应该怎么看？]]></title>
      <link>https://www.360magento.com/blog/order-increment-id-sequence-gap-duplicate/</link>
      <description><![CDATA[<p>运营发现订单号从 1000123 跳到 1000127，第一反应是中间三张订单丢了。另一边，两个网站又出现“相同订单号”。这两种现象必须分开：跳号在并发、回滚和预取场景下可能正常；真正重复则涉及 Store 维度或定制代码。</p><h2>先用 entity_id、increment_id 和 store_id 对账</h2><pre><code>SELECT entity_id, increment_id, store_id, created_at, state, status
FROM sales_order
WHERE created_at BETWEEN :from AND :to
ORDER BY entity_id;</code></pre><p>不要只按 increment_id 搜索。Magento 的订单显示号通常与 Store 关联，不同 Store 可能使用不同 sequence，因此跨网站看到相同数字不一定违反数据库唯一约束。先确认业务要求是“全站唯一”还是“店铺内唯一”。</p><h2>为什么会跳号</h2><p>Sequence 号被取得后，后续事务可能失败或回滚，已经消耗的值不会自动回收。并发请求、支付失败、风控拒绝都可能留下空洞。空洞不等于存在被删除订单，更不能据此补造记录。</p><p>检查 <code>sales_sequence_meta</code>、<code>sales_sequence_profile</code> 与对应 <code>sequence_order_*</code> 表，核对当前 Store 使用的表、前缀、后缀与步长。只读查看 AUTO_INCREMENT 可以帮助判断下一号，但不要在营业中直接改小。</p><h2>真正危险的是自定义生成器绕过原子性</h2><p>有些模块用“查询当前最大值 + 1”生成订单号。在两个并发请求下，两边都可能读到同一个最大值。正确做法应依赖数据库原子序列或带唯一约束的幂等分配，不能靠 PHP 锁或毫秒时间戳碰运气。</p><p>迁移数据时也要注意导入的 increment_id 与本地序列。若导入历史订单后没有把序列推进到安全位置，新订单可能撞号；反过来盲目把 AUTO_INCREMENT 调得很大，只会造成更明显的跳号。</p><h2>处理原则</h2><p>如果只是合法空洞，向运营解释原因并用支付/quote 日志证明没有丢单，不需要填号。如果发现同一 Store 真正重复，立即停止相关定制生成器，确认数据库约束与受影响订单，并评估财务、发票和 ERP 引用。修复后用并发压测验证序列唯一，失败事务允许留空洞，但绝不能重复。</p>]]></description>
      <pubDate>Mon, 18 Aug 2025 02:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 保存订单报 Deadlock found，重试事务之前先查清谁锁住了谁]]></title>
      <link>https://www.360magento.com/blog/order-save-deadlock-transaction-retry-debug/</link>
      <description><![CDATA[<p>高峰期偶尔出现 <code>Deadlock found when trying to get lock</code>，客户重试后可能生成两张订单。因为死锁不是普通超时：数据库会主动回滚其中一个事务来解除循环，所以应用层既要找到锁顺序，也要正确处理失败后的重试。</p><h2>先保存数据库给出的死锁现场</h2><pre><code>SHOW ENGINE INNODB STATUSG</code></pre><p>重点看两个事务各自持有和等待的索引、SQL、表与记录范围。应用异常日志只显示“死锁”，不足以判断谁先锁了 inventory、sales_order、sequence 或自定义表。开启更持续的 deadlock 日志时要评估生产开销和日志敏感信息。</p><p>把数据库线程时间与 Magento request ID、quote_id、订单增量号、消费者消息 ID 对齐。常见组合是：前台下单事务按 A→B 更新，自定义 observer 或异步回调却按 B→A 更新；两个请求并发时就形成环。</p><h2>减少事务里不必要的工作</h2><p>不要在数据库事务中调用外部支付、ERP、邮件或慢 API。远程请求延长持锁时间，一次网络抖动就让锁冲突概率上升。事务里只保留必须原子完成的本地写入，外部副作用在提交后通过事件或队列执行。</p><p>批量更新多条记录时使用稳定顺序，例如始终按主键升序。两个事务访问同一组行但顺序相反，是最典型的死锁来源。SQL 还要能命中索引，范围扫描会锁住比预想更多的记录。</p><h2>重试必须围绕完整业务操作设计</h2><p>数据库回滚后可以有限次数重试，但要加随机退避，并保证重试入口幂等。支付已授权、订单保存失败时，不能简单重新扣款。使用稳定业务键检查订单是否已存在，区分“数据库事务失败”和“外部动作已经成功”。</p><p>不要在捕获异常后只重跑最后一个 UPDATE，因为原事务其他写入已经一起回滚。重试边界应覆盖完整的本地原子操作，同时避免重复发送外部请求。</p><h2>验证不能只靠压一次接口</h2><p>构造同一 SKU、同一客户或同一 quote 的并发请求，持续观察 deadlock 数量、订单重复率和响应时间。确认失败事务能给用户明确结果，重试不会创建重复订单，支付与库存最终一致。死锁很难承诺绝对为零，但发生频率、恢复行为和数据结果必须可控。</p>]]></description>
      <pubDate>Fri, 15 Aug 2025 07:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 RabbitMQ Consumer 内存不断上涨最后被杀，怎么判断是消息还是代码泄漏？]]></title>
      <link>https://www.360magento.com/blog/rabbitmq-consumer-memory-growth-oom-debug/</link>
      <description><![CDATA[<p>Consumer 刚启动只有 120MB，跑两个小时后接近 2GB，最终被容器 OOMKilled。Supervisor 重启后又重复。把 memory_limit 调大只会延后死亡，首先要确认内存是随“消息数量”线性增长，还是被某一条异常消息瞬间撑爆。</p><h2>给内存曲线加上消息坐标</h2><p>在不记录敏感 payload 的前提下，记录 consumer 名称、消息 ID、topic、处理耗时、payload 字节数、处理前后 memory_get_usage(true) 与峰值。这样能区分：</p><ul><li>每处理一条都增加少量且不回落：对象或静态缓存跨消息残留；</li><li>某个 SKU/订单后突然跳高：特定业务数据导致大集合；</li><li>失败消息快速重回队列：重试风暴不断创建异常和日志；</li><li>空闲时也增长：连接、监控或框架循环存在问题。</li></ul><p>同时查看容器和宿主机指标，不要把 PHP memory_limit 异常与系统 OOM 混为一谈。</p><h2>长生命周期进程和普通 Web 请求不一样</h2><p>Web 请求结束后对象整体释放，Consumer 会在同一进程处理很多消息。单例服务、Registry、静态数组、第三方 SDK 客户端缓存，如果没有每条消息重置，就会长期保留引用。批量加载 collection 后也应及时释放大数组，避免把完整实体堆进后续闭包。</p><p>用固定的消息样本在预发布循环重放，配合 PHP profiler 或周期性内存快照定位增长点。不要在生产直接打印完整对象图，它可能包含客户信息，也会额外放大日志与内存。</p><h2>先用有限生命周期止血，但别把它当根治</h2><p>Magento consumer 支持限制处理消息数，进程管理器可在正常退出后重启。合理的 <code>max_messages</code> 能降低长期碎片和不可控增长，是保护措施；如果每十条消息就需要重启，仍说明代码或数据有问题。</p><pre><code>php bin/magento queue:consumers:start consumer.name --max-messages=1000</code></pre><p>重试也要有上限和延迟。永久失败的消息应进入明确的失败处理流程，而不是立即 nack/requeue 形成热循环。记录失败次数和最后异常，确保同一消息不会无限消耗资源。</p><h2>修复后的验证方式</h2><p>用小消息、正常大订单、故意失败消息三组样本，各跑足够数量。内存可以在启动阶段上升，但随后应进入稳定区间；队列吞吐不下降；失败消息按设计停止重试；进程被重启时没有未确认消息长期悬挂。只有曲线、吞吐和业务结果都稳定，才算解决。</p>]]></description>
      <pubDate>Thu, 14 Aug 2025 03:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 一个 cacheable=false 为什么能拖慢整个商品页？]]></title>
      <link>https://www.360magento.com/blog/cacheable-false-disables-full-page-cache/</link>
      <description><![CDATA[<p>一次小功能上线后，商品页 TTFB 从 150ms 涨到 1.8s。Varnish 没报错，缓存刷新也正常，但每次请求都回源。最后只是一段 layout XML 给自定义 block 加了 <code>cacheable="false"</code>。</p><p>Magento 的规则很直接：可缓存页面中只要有一个 block 不可缓存，整页就不能进入 Full Page Cache。它不是“只有这个小块不缓存”。所以把会员名字、购物车数量或实时库存直接做成不可缓存 block，代价可能是所有商品页都动态渲染。</p><h2>先证明页面确实没有进入 FPC</h2><pre><code>curl -sS -D - -o /dev/null https://shop.example.com/product.html
curl -sS -D - -o /dev/null https://shop.example.com/product.html</code></pre><p>比较两次请求的 Age、X-Magento-Cache-Debug 或 Varnish 命中标记。确认不是 Cookie、Authorization、查询参数或 CDN 规则主动 bypass 后，再查 layout。</p><h2>不要只搜索自己模块</h2><p>最终 layout 来自主题、核心模块和所有扩展合并。搜索所有 <code>cacheable="false"</code>，再按当前 full action name 确认它是否真的落在商品页。某个 default.xml 的设置影响范围可能比开发者想象大。</p><pre><code>grep -R 'cacheable="false"' app/code app/design vendor/*/*/view/frontend/layout -n</code></pre><p>临时禁用可疑模块或 layout handle 做对照，避免仅凭文件名下结论。开发者工具中的 profiler 和响应头可以帮助确认页面恢复缓存后的变化。</p><h2>个性化内容应该怎么放</h2><p>购物车数量、欢迎语、客户专属提示适合 customer-data/private content，由浏览器在公共页面加载后补齐。真正必须实时请求的数据，可以做小型 AJAX/GraphQL 接口，并设置清楚的超时与失败降级。不要为了一个十几字的客户名字牺牲整个 FPC。</p><p>如果 block 内容其实对所有用户相同，只是更新频率较高，可以使用正确 cache key、cache lifetime 和 identity tag，而不是直接关闭缓存。实体保存时精准失效，比把页面永久设成 MISS 更可控。</p><h2>修复后不能只看首页变快</h2><p>我会连续请求商品页、分类页和 CMS 页，确认第二次命中；再测试登录用户的私有内容没有串号，购物车数量能更新，退出登录后数据被清理。最后比较 PHP-FPM 请求数和 Varnish hit rate。性能恢复与个性化正确必须同时成立。</p>]]></description>
      <pubDate>Wed, 13 Aug 2025 08:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 会员价还是旧价格：Customer Group 价格索引应该怎么定位？]]></title>
      <link>https://www.360magento.com/blog/customer-group-price-stale-index-debug/</link>
      <description><![CDATA[<p>普通访客看到 100 元，VIP 登录后仍显示 100 元，后台明明设置了 90 元。清页面缓存后偶尔恢复，换一个 VIP 账号又不对。这个问题需要先分清“原始价格写错”“价格索引没更新”和“页面缓存身份错误”三种情况。</p><h2>用同一个 SKU 列出所有可能的价格来源</h2><p>我会记录 website_id、customer_group_id、currency、商品类型和日期，然后核对基础价、Group Price、Tier Price、Catalog Price Rule、Special Price 时间窗口，以及 B2B 环境中的 Shared Catalog。不要只看商品编辑页顶部价格字段。</p><p>可配置商品还要分别看父子商品。列表页展示的最低价来自关联子商品索引，不一定等于父商品保存的数值。Bundle、Grouped 商品又有各自聚合规则。</p><h2>索引问题要比较维度，不要只看状态</h2><pre><code>php bin/magento indexer:status catalog_product_price
php bin/magento indexer:reindex catalog_product_price</code></pre><p>索引显示 Ready，只代表没有被标记 invalid，不代表某个维度的行一定正确。用只读查询比较目标 entity、website 和 customer_group 的索引记录，并与后台配置来源对照。绝对不要手工 UPDATE 价格索引表，它是派生数据，下一轮索引会覆盖。</p><p>若只有计划模式延迟，检查 mview changelog 与 cron；若每次 reindex 都生成错误值，问题在价格来源、作用域或插件。第三方动态定价模块可能通过 plugin 改写 price model，却没有正确声明 cache identity。</p><h2>价格正确但页面仍旧，要看缓存键是否包含客户身份</h2><p>登录用户的个性化价格通常通过 private content 或带客户组上下文的缓存处理。自定义 block 如果把会员价放进公共 FPC，却使用固定 cache key，VIP 与访客就可能互相看到缓存价格。GraphQL/PWA 还要检查请求头中的 Store、Currency 与客户 token。</p><p>我会用无痕窗口建立四个互不复用的会话：访客、普通会员、VIP、批发组；分别请求商品页、分类页、搜索结果和购物车。再切换币种与 Store View，确认显示价、quote item price 和订单金额一致。只有商品展示和下单两端都正确，会员价才算真正修复。</p>]]></description>
      <pubDate>Tue, 12 Aug 2025 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 URL Rewrite 越积越多还出现重定向链，怎么清理才不伤 SEO？]]></title>
      <link>https://www.360magento.com/blog/url-rewrite-redirect-chain-safe-cleanup/</link>
      <description><![CDATA[<p>一个商品改过几次 URL Key 后，旧链接先跳到中间地址，再跳到新地址，某些 Store View 甚至进入循环。后台 URL Rewrite 数量不断增长，直接执行“全部删除后重建”看起来痛快，但历史外链、广告链接和搜索引擎已经收录的地址可能一起失效。</p><p>我会先选一个具体商品，把它在所有 Store View 的 rewrite 完整拉出来：</p><pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE entity_type = 'product'
  AND entity_id = :product_id
ORDER BY store_id, url_rewrite_id;</code></pre><h2>先区分“当前主路径”和“历史跳转”</h2><p><code>redirect_type = 0</code> 通常是当前可访问路径；301/302 是历史或人工重定向。先画出 request_path 到 target_path 的图，确认有没有 A→B→C、A→B→A，或者两个实体争用同一 request_path。不要只按 request_path 去重，因为不同 Store View 可以合法拥有同名路径。</p><p>目标是让重要旧地址一步跳到最终 canonical URL，而不是经过多层。对仍有外链、流量或订单邮件引用的旧地址保留 301；从未上线、没有引用的生成错误记录才适合删除。</p><h2>为什么重新保存商品后问题又回来</h2><p>检查 Catalog URL 配置、是否在 URL 中包含分类路径、是否为旧 URL 创建永久重定向，以及第三方 SEO 模块的 observer/plugin。批量导入若每次都重写 url_key，也会持续制造历史记录。</p><p>分类层级变化会产生更多组合路径。一个商品属于几十个分类时，开启分类路径会显著扩大 rewrite 数量。先确认业务是否真的需要这套路径策略，不能一边批量删、一边让配置继续生成。</p><h2>清理时给自己留回滚和验证窗口</h2><p>先备份目标记录，只按明确的 entity_id、store_id 和路径集合修改。生产大表上避免一条 DELETE 扫全表，按主键分批并观察锁。清理后通过标准索引/保存流程重建当前路径，不要手写 target_path 猜内部路由。</p><p>验收清单包括：新地址 200；重要旧地址一次 301 到新地址；不存在循环；canonical 指向最终地址；各 Store View 留在自己的域名和语言；站点地图只包含当前 URL。最后从访问日志统计一周仍被请求的旧路径，再决定是否继续保留。SEO 安全的关键不是 rewrite 表有多干净，而是用户和爬虫能稳定到达唯一最终页面。</p>]]></description>
      <pubDate>Mon, 11 Aug 2025 06:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页不显示任何配送方式，明明已经配置了运费怎么办？]]></title>
      <link>https://www.360magento.com/blog/checkout-no-shipping-methods-available-debug/</link>
      <description><![CDATA[<p>后台已经启用 Flat Rate，商品也有库存，但结账页配送方式区域一直转圈，最后只剩一句“没有可用的配送方式”。遇到这种问题，我不会先卸载主题或清空全部缓存，因为配送方式不是一个静态配置，它是根据当前 quote、地址、网站、商品属性和承运商返回值动态算出来的。</p><h2>先保存一次真正失败的请求</h2><p>在浏览器 Network 中找到 shipping-information 或 estimate-shipping-methods 请求，保存请求体、响应体、quote_id 和时间。地址里的 country_id、region_id、postcode 只要缺一个，某些承运商就会直接返回空集合。前端表单看起来填了省份，不代表传给后端的是有效 region_id。</p><p>我会用同一个购物车分别测试：完整地址、另一个邮编、默认配送方式和访客/登录用户。只有某个地址失败，优先看区域规则；所有地址都失败，才继续查全局配置或代码。</p><h2>后台显示启用，不代表当前 Website 启用</h2><p>配送配置通常有 Website 或 Store View 作用域。切换作用域后核对 Enabled、Allowed Countries、Specific Error Message、价格和最小订单条件。配置值可能在 Default 是 Yes，但当前 Website 明确覆盖成 No。</p><p>用 CLI 读取实际作用域比凭后台截图更可靠：</p><pre><code>php bin/magento config:show carriers/flatrate/active
php bin/magento config:show carriers/flatrate/sallowspecific
php bin/magento config:show carriers/flatrate/specificcountry</code></pre><p>第三方承运商还要检查 API 凭据、沙箱/生产地址、超时和币种。外部接口失败时，模块如果吞掉异常，只会让前端看到空数组，所以需要在 carrier 的 <code>collectRates()</code> 入口和返回处加临时日志，记录条件但不要记录客户完整地址或密钥。</p><h2>免费配送、购物车规则和重量条件经常互相影响</h2><p>查看 quote item 的重量、是否虚拟商品、free_shipping 标记和折扣规则。一个商品重量为 0，可能被承运商判定不可报价；一个购物车规则把部分商品标成免费配送，也可能让自定义模块算出负数或直接跳过。</p><p>多源库存环境还要确认当前 Stock 能否为地址提供货源。商品“有货”只代表可销售，未必所有来源都支持该区域或配送组合。若自定义 Source Selection 在报价前介入，检查它是否错误过滤了来源。</p><h2>前端有旧缓存时，后端其实已经返回了方法</h2><p>响应 JSON 已包含 rates，但页面仍空，问题就在 JS 状态。比较 Knockout shipping-service、checkout-data 和 customer-data 中的地址标识，确认旧请求没有在较晚时返回并覆盖新结果。切换地址后应触发重新估价，而不是继续使用上一个 postcode 的结果。</p><p>我最后会用四组用例验收：访客与登录用户、国内与国外地址、普通商品与含虚拟商品购物车、优惠券前后。每组都要确认后端返回的方法、页面显示价格和订单最终 shipping_amount 一致。只有这样，才不是“某个测试地址碰巧好了”。</p>]]></description>
      <pubDate>Fri, 08 Aug 2025 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 在反向代理后无限 HTTPS 重定向，应该改 Base URL 还是 nginx？]]></title>
      <link>https://www.360magento.com/blog/https-redirect-loop-behind-reverse-proxy/</link>
      <description><![CDATA[<p>站点接入负载均衡后，浏览器提示重定向次数过多。外层访问明明是 HTTPS，源站却一直收到 HTTP，于是 Magento 每次都重定向到 HTTPS；代理再以 HTTP 回源，循环就形成了。</p><h2>先用响应头画出循环</h2><pre><code>curl -I https://shop.example.com/
curl -IL --max-redirs 10 https://shop.example.com/</code></pre><p>记录每次 Location、主机名和协议。如果在 www 与裸域之间来回，查 canonical host；同一 URL 不断 301/302，查协议识别与 Cookie。不要一开始就关闭所有 HTTPS 强制设置。</p><h2>外层代理要明确传递原始协议</h2><p>负载均衡或 nginx 通常通过 <code>X-Forwarded-Proto</code> 告诉应用客户端使用 HTTPS。源站与 Magento 必须信任正确的头，而且只能信任受控代理来源，避免客户端伪造。</p><p>同时检查 secure/unsecure Base URL、Use Secure URLs 与 offloader header。多层代理每层追加或覆盖头的方式要一致，否则某些节点识别 HTTPS、某些识别 HTTP，会随机循环。</p><h2>缓存可能继续保存错误重定向</h2><p>CDN 或 Varnish 缓存 301 后，即使源站修好，外部仍可能循环。先绕过缓存验证源站，再精确清理错误对象。浏览器也会长期记忆 301，测试时用 curl 更可靠。</p><p>修复后验证首页、后台、登录、静态资源和支付回跳，确认 Location 始终使用预期域名和 HTTPS。Base URL 与 nginx 不是二选一：代理传递事实，Magento 使用事实，两边必须一致。</p>]]></description>
      <pubDate>Thu, 07 Aug 2025 06:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 开启 CSP 后支付组件白屏，怎么放行才不把安全策略掏空？]]></title>
      <link>https://www.360magento.com/blog/csp-blocks-payment-iframe-script-fix/</link>
      <description><![CDATA[<p>升级后 Checkout 能打开，但信用卡区域只剩空白。Console 出现 CSP 报错。最危险的临时处理是给 <code>script-src</code> 加宽泛的星号或 unsafe 配置，这会让 CSP 失去大部分意义。</p><h2>先确定被哪个 directive 拦截</h2><p>支付 SDK 不只有脚本，还会创建 iframe、请求 API、加载字体或图片。分别记录被拦截 URL 和 <code>script-src</code>、<code>frame-src</code>、<code>connect-src</code>、<code>img-src</code>。第一个错误消失后，后续资源仍可能被拦。</p><h2>在模块中做最小范围白名单</h2><pre><code>&lt;policy id="frame-src"&gt;
    &lt;values&gt;
        &lt;value id="payment-frame" type="host"&gt;https://secure.payment.example&lt;/value&gt;
    &lt;/values&gt;
&lt;/policy&gt;</code></pre><p>通过 <code>etc/csp_whitelist.xml</code> 为确切资源类型添加可信主机。域名来自支付商官方文档和实际 Network，请勿把整个顶级域或任意 HTTPS 放开。测试与生产域名不同要分开管理。</p><h2>用 Report-Only 收集遗漏</h2><p>先在预发布或受控流量观察报告，按页面与来源整理。标签管理器可能动态引入更多域名，需要和业务确认哪些真正必需。</p><p>最终测试表单展示、3DS 跳转、失败重试、保存卡与回调。浏览器无 CSP 错误只是基础，支付链路也必须完整。白名单越小，后续供应商改域名时越容易审计。</p>]]></description>
      <pubDate>Wed, 06 Aug 2025 02:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Checkout 显示的总价和最终订单不一致，怎么找出是谁改了 Totals？]]></title>
      <link>https://www.360magento.com/blog/checkout-total-differs-from-order-debug/</link>
      <description><![CDATA[<p>结账页显示 899 元，支付页却扣了 909 元，后台订单也是 909 元。只刷新 Checkout 有时又正常。这类金额问题必须马上处理，而且不能只盯页面 JavaScript，最终扣款来自服务端订单或支付请求。</p><h2>给同一次结账建立金额时间线</h2><ol><li>购物车 collectTotals 后的 quote totals；</li><li>前端 totals API 返回值；</li><li>提交订单前发送给支付模块的金额；</li><li>sales_order 的金额字段。</li></ol><p>用 quote_id 与请求 ID 串起来，比较 subtotal、discount、shipping、tax、grand_total 和 base_* 字段，找出第一次不同。只比较 grand_total 会隐藏汇率或税额舍入问题。</p><h2>重复 collectTotals 本身不是修复</h2><p>自定义 total collector 应该幂等。每执行一次就追加费用，通常是没有先重置自身字段，或 sort_order 与税、折扣顺序冲突。记录 collector 类名与执行前后金额，检查同一请求是否多次运行。</p><p>前端旧 totals 也可能来自 customer-data 或并发请求覆盖。Network 中看返回顺序：较慢旧请求最后回来，会把新地址对应的金额覆盖到页面，但提交时服务端又按最新 quote 计算。</p><h2>支付模块使用订单金额作为最终事实</h2><p>不要从页面接收可修改金额。支付请求应基于服务端订单，并正确处理 base currency 与 order currency。回调金额不一致时明确拒绝或进入人工处理，不能默默标记已支付。</p><p>修复后测试优惠券、税、配送方式、多币种和地址切换，对比前端、订单、支付平台三方金额。第一次分叉消除后才算解决。</p>]]></description>
      <pubDate>Tue, 05 Aug 2025 07:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户登录后又跳回登录页，Cookie Domain 应该怎么排？]]></title>
      <link>https://www.360magento.com/blog/customer-login-loop-cookie-domain-samesite/</link>
      <description><![CDATA[<p>客户提交账号密码后接口返回成功，页面跳到账户中心，下一秒又被送回登录页。这个现象通常说明登录创建了会话，但浏览器没有在后续请求带回同一个 Cookie。</p><h2>把登录响应与下一次请求并排看</h2><p>在 Network 保留日志，检查登录响应的 <code>Set-Cookie</code>，再看跳转请求是否携带对应 Cookie。记录 Domain、Path、Expires、Secure 与 SameSite。只看存储面板容易漏掉被浏览器拒绝的 Cookie。</p><ul><li>Cookie 配成 www 域，实际登录发生在裸域或其他子域；</li><li>Cookie Path 不是站点根路径；</li><li>HTTPS 经代理回源 HTTP，Magento 误判协议；</li><li>支付或 SSO 回跳需要的 SameSite 行为与设置冲突。</li></ul><h2>Base URL 与代理头必须一致</h2><p>检查 secure/unsecure Base URL、强制 HTTPS 和负载均衡传递的协议头。若 Magento 认为请求是 HTTP，可能生成错误跳转或 Cookie 属性。不要通过关闭 Secure Cookie 修生产 HTTPS。</p><p>还要排除多节点 session 不共享：登录和跳转落到不同节点，而 session 存在本地文件，表现也像 Cookie 丢失。可用节点标记、Redis 监控辅助确认。</p><h2>修改后覆盖真实跳转链</h2><p>测试直接登录、结账中登录、退出再登录、支付回跳与不同子域入口。每条路径都确认 Cookie 被接受并发送。目标不是按钮不报错，而是同一会话在域名和 HTTPS 链路中保持一致。</p>]]></description>
      <pubDate>Mon, 04 Aug 2025 01:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重建索引后搜索仍然搜不到商品，别只重复 reindex]]></title>
      <link>https://www.360magento.com/blog/product-missing-search-after-reindex/</link>
      <description><![CDATA[<p>商品详情页可以直接打开，后台也显示启用，但站内搜索始终找不到。执行 <code>catalogsearch_fulltext</code> 重建没有报错，于是大家开始反复 reindex。真正原因往往在商品是否应进入当前商店的搜索文档。</p><h2>先检查商品资格</h2><p>确认商品属于当前 Website，状态启用，可见性包含 Search，目标 Store View 的名称、SKU 或搜索属性有值。配置商品还要确认子商品状态与库存。不要只在 Default Scope 看字段。</p><p>新建属性勾选 Use in Search 后需要索引更新；如果期望用字段筛选，还要检查 layered navigation 与搜索权重。</p><h2>证明文档是否进入搜索引擎</h2><pre><code>php bin/magento indexer:status catalogsearch_fulltext
php bin/magento indexer:reindex catalogsearch_fulltext
curl -sS 'http://search-host:9200/_cat/indices?v'</code></pre><p>核对 Magento 配置的引擎地址、索引前缀和别名。多环境共用集群时，前缀配错会导致你查看另一个环境。生产查询应限制返回量，不要随意对大索引执行通配搜索。</p><h2>有文档但前台没结果，再看查询上下文</h2><p>Store ID、Customer Group、库存状态和请求参数会影响最终集合。抓取 GraphQL 或搜索请求，比较关键词分词结果。中文、连字符 SKU 与特殊字符尤其容易受 analyzer 影响。</p><p>验收选完整 SKU、商品名普通词和需要分词的中文词。每个词在目标 Store View 返回正确商品，并确认新增、禁用和改名后计划索引能自动更新，才算恢复。</p>]]></description>
      <pubDate>Fri, 01 Aug 2025 06:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST 报 Request does not match any route，路由明明写了为什么找不到？]]></title>
      <link>https://www.360magento.com/blog/rest-request-does-not-match-any-route-fix/</link>
      <description><![CDATA[<p>自定义 REST 接口在开发环境能用，部署后返回 <code>Request does not match any route</code>。这个提示发生在服务方法执行前，所以在实现类加日志通常什么也看不到。</p><h2>先核对请求的四个基本量</h2><p>记录实际 HTTP 方法、完整路径、Store Code 和 Content-Type。GET 与 POST 是不同路由，<code>/rest/V1/</code>、<code>/rest/all/V1/</code> 和带店铺代码的 URL 也不能凭印象互换。注意代理是否重写路径前缀。</p><h2>检查 webapi.xml，不是 frontend routes.xml</h2><pre><code>&lt;route url="/V1/example/:id" method="GET"&gt;
    &lt;service class="Vendor\Module\Api\ExampleInterface" method="getById"/&gt;
    &lt;resources&gt;
        &lt;resource ref="Vendor_Module::example"/&gt;
    &lt;/resources&gt;
&lt;/route&gt;</code></pre><p>文件路径、大小写或 XSD 错误会让配置无法正确合并。模块启用后清配置缓存并在构建中重新编译，不要在线上只替换一个 XML。</p><h2>接口签名也会影响服务暴露</h2><p>参数名要与 URL 占位符、JSON 字段对应，复杂类型使用明确数据接口。方法只存在实现类、接口未声明，或 docblock 类型无法解析，都会在 Web API 层出问题。</p><p>先调用一个已知端点证明 REST 入口正常，再调用自定义路由。最后分别测试正确方法、错误方法和无权限身份，确认得到预期的成功、路由错误和授权错误，而不是被代理统一改写。</p>]]></description>
      <pubDate>Thu, 31 Jul 2025 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST Token 明明没过期却返回 401，应该从哪里查？]]></title>
      <link>https://www.360magento.com/blog/rest-api-token-401-not-expired/</link>
      <description><![CDATA[<p>Integration Token 在 Postman 调用正常，放到生产服务后却一直 401。重新生成 Token 能短暂解决，后来发现 Token 本身没问题，是反向代理没有稳定转发 Authorization 头。</p><h2>先在最靠近 Magento 的位置重放请求</h2><pre><code>curl -i \
  -H 'Authorization: Bearer REDACTED' \
  -H 'Content-Type: application/json' \
  https://shop.example.com/rest/V1/store/storeConfigs</code></pre><p>不要把真实 token 写进工单或日志。可以在 nginx/PHP 层只记录头是否存在及长度，绝不记录完整值。公网失败、绕过代理访问源站成功，优先查 CDN、WAF、负载均衡和 FastCGI 参数。</p><h2>401、403 与路由错误不是一类问题</h2><p>401 通常是身份没被接受；403 更偏向身份有效但 ACL 不允许；404 或 Request does not match any route 要查 URL 与 webapi 路由。客户端不要把所有非 200 都显示成 token 失效。</p><p>还要分清管理员 token、客户 token 与 Integration token。客户 token 无权访问后台资源；Integration 修改 ACL 后也要重新确认授权。服务器时间漂移、token 撤销和用户禁用同样会影响认证。</p><h2>随机 401 要核对多节点</h2><p>按响应头或日志定位节点。节点间 env.php、加密密钥、数据库或部署版本不一致，会造成部分请求正常、部分失败。修好后连续跨节点请求，并验证只读与需要 ACL 的两个端点。</p>]]></description>
      <pubDate>Wed, 30 Jul 2025 05:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Plugin 执行顺序不对，before、around、after 到底怎么排？]]></title>
      <link>https://www.360magento.com/blog/plugin-sort-order-around-before-after-debug/</link>
      <description><![CDATA[<p>两个模块都给同一方法加了 plugin，日志顺序却和 sortOrder 的直觉不一样。尤其出现 around 后，入口和返回阶段是嵌套的，只看一串日志很容易误判。</p><h2>先画调用栈，不要只背排序规则</h2><p>before 与 around 的进入顺序受配置排序影响，after 发生在返回过程。around 调用 <code>$proceed()</code> 前后的代码会包住后续链，所以日志常呈现：</p><pre><code>before A
around A enter
before B
original method
after B
around A leave
after A</code></pre><p>调试时为每个 plugin 打印类名、阶段和请求 ID，比只记录 plugin called 更容易确认链条。</p><h2>around 不调用 proceed 会截断后续</h2><p>第三方模块为了返回缓存结果，可能在条件分支直接 return。此时后面的 plugin 和原方法都不会执行。检查每条 return 路径，并确认参数、返回类型与目标方法兼容。</p><h2>最终配置来自多个 di.xml 合并</h2><p>同名 plugin 可以被其他模块禁用或覆盖，area 配置也会改变结果。检查模块加载顺序和生成的 interceptor。目标方法若是 final、static、构造函数或其他不可拦截范围，也不会按预期工作。</p><p>只需改参数时用 before，只改结果时用 after，确实需要包围调用再用 around。修复后用集成测试断言最终输入输出，不要把脆弱的完整日志顺序当成唯一业务契约。</p>]]></description>
      <pubDate>Tue, 29 Jul 2025 01:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 写了 preference 却完全不生效，问题通常不在 cache]]></title>
      <link>https://www.360magento.com/blog/dependency-injection-preference-not-taking-effect/</link>
      <description><![CDATA[<p>自定义模块写了 preference，<code>setup:di:compile</code> 也成功，但断点始终进不到新类。这个问题先问一句：调用方实际请求的类型，真的是你替换的接口或类吗？</p><h2>用最终 DI 配置验证，不要凭文件名猜</h2><pre><code>php bin/magento dev:di:info 'Magento\Vendor\Api\SomeInterface'
php bin/magento module:status Vendor_Module</code></pre><p>输出仍指向原实现，就检查 <code>etc/di.xml</code>、模块状态、sequence 和配置缓存。若只写在 <code>etc/adminhtml/di.xml</code> 或 <code>etc/graphql/di.xml</code>，全局调用不会读取该 area 配置。</p><h2>Proxy、Factory 与 virtualType 会让你看错对象</h2><p>调用方可能注入 Proxy、Factory、virtualType，或直接依赖另一个具体类。沿构造函数类型与 object manager 配置追踪实际实例，不要只在目标类构造函数打断点。已有 interceptor 时，也要看最终生成类和插件链。</p><h2>generated 必须与当前代码同批生成</h2><p>编译产物来自旧 release，源码来自新 release，会出现配置看起来对、运行时仍旧的混合状态。构建时清理旧 generated，安装依赖后编译，并随同一产物部署。线上不应边接流量边 compile。</p><p>如果只改一个方法行为，还应重新评估 preference 是否必要。Preference 会整体替换实现，冲突范围更大；能用 plugin、事件或组合完成时，升级风险通常更低。最终以 dev:di:info、实际实例类名和目标调用路径一致为准。</p>]]></description>
      <pubDate>Mon, 28 Jul 2025 07:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Composer Patch 显示 applied，代码为什么还是旧的？]]></title>
      <link>https://www.360magento.com/blog/composer-patch-applied-but-code-unchanged/</link>
      <description><![CDATA[<p>构建日志明确打印补丁 applied，线上报错堆栈却仍指向旧代码。重新清 Magento cache 没变化，因为 PHP 执行的源码与 Magento 数据缓存不是一回事。</p><h2>先在构建目录验证补丁落到了哪个文件</h2><pre><code>composer show vendor/package
grep -R "patched marker" vendor/vendor/package -n
composer install -vvv --no-interaction</code></pre><p>补丁按旧版本上下文制作时，有的工具会失败退出，也有流水线把失败当成非阻断警告。日志里不能只搜 applied，还要确认没有 skipped、cannot apply 或目标包未安装。</p><h2>构建成功，运行环境也可能没拿到同一份 vendor</h2><p>镜像若在 patch 前就复制了 vendor，后续构建目录再正确也没用。进入实际处理请求的容器，核对文件校验值、镜像标签与 release 路径。多节点逐台检查，避免新旧节点同时在负载均衡里。</p><h2>源码更新后还要考虑 OPcache</h2><p>如果部署会原地覆盖 PHP 文件，而 OPcache 时间戳验证关闭，PHP-FPM 可能继续执行旧字节码。正确做法通常是原子发布后平滑重载 FPM，不是 flush Magento cache。涉及生成类时，再按构建流程重建 generated 和 DI。</p><p>我习惯在补丁中选稳定片段计算校验值，在 CI、镜像和线上容器三个阶段比对。验收既看文件内容，也触发原始错误路径。这样能明确是补丁没打、产物没带、节点没换，还是运行时仍缓存旧字节码。</p>]]></description>
      <pubDate>Fri, 25 Jul 2025 02:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 setup:upgrade 一直不结束，先别急着 kill 进程]]></title>
      <link>https://www.360magento.com/blog/setup-upgrade-hanging-metadata-lock-debug/</link>
      <description><![CDATA[<p>部署窗口里 <code>setup:upgrade</code> 十几分钟没输出，CPU 也不高，看起来像死了。直接 kill 再重跑，可能每次卡在同一位置，还会清掉最有价值的数据库现场。</p><h2>先看进程正在做什么</h2><pre><code>ps -eo pid,etime,cmd | grep '[s]etup:upgrade'
SHOW FULL PROCESSLIST;
SELECT * FROM performance_schema.metadata_locks
WHERE LOCK_STATUS = 'PENDING';</code></pre><p>若 SQL 等 metadata lock，通常是长事务占用了即将 ALTER 的表。先找到阻塞链与业务来源，评估能否安全结束阻塞事务，不要先杀升级会话。</p><h2>没有锁，也可能在处理大表</h2><p>Declarative schema、数据补丁和第三方迁移都可能扫描大表。检查当前 SQL、磁盘 I/O、临时表空间与 binlog。测试库几秒的无索引 UPDATE，在生产几千万行会完全不同。</p><p>查看 patch_list 和模块状态，定位尚未完成的 patch 类并阅读实现。补丁应可重复或明确标记完成；超大数据迁移不宜全部塞进发布命令。</p><h2>中止前先准备恢复路径</h2><p>确认数据库有可恢复备份，记录 release、维护模式和已完成 patch。若必须终止，先理解事务边界。重跑前解决锁或 SQL 根因。</p><p>后续在生产规模副本演练，记录每个 patch 耗时，把大迁移拆成可观察、可续跑任务。命令结束后仍要核对 schema、patch_list、核心页面和消费者。</p>]]></description>
      <pubDate>Thu, 24 Jul 2025 06:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 部署后 pub/static 大量 404，为什么反复 deploy 也没用？]]></title>
      <link>https://www.360magento.com/blog/static-content-deploy-404-after-release/</link>
      <description><![CDATA[<p>发布完成后 HTML 能返回，但 CSS、JS 一片 404。连续执行几次 static-content:deploy 有时短暂恢复，下一次切 release 又坏。这里通常不是命令少跑一次，而是生成目录、Web 根目录与静态版本没对齐。</p><h2>从一个具体 404 反推文件路径</h2><p>不要先删整个目录。记录完整 URL、locale、area 和版本号，然后在当前 release 查对应文件：</p><pre><code>find pub/static -path '*frontend*' -name 'styles-m.css' -o -name 'requirejs-config.js'
ls -la pub/static pub/static/_cache</code></pre><p>文件不存在，查命令是否包含正确语言、主题与 area；文件存在但 nginx 404，查 root、符号链接、容器挂载和权限。</p><h2>静态签名会让文件存在仍然 404</h2><p>HTML 若来自旧 FPC/CDN，而静态目录已经切到新 release，就会请求不存在的旧版本。应先完成新静态产物，再原子切换 release，并在合适时点刷新页面缓存。</p><p>多节点要确认每个节点都生成，或构建产物通过共享存储分发。只在一台机器手工 deploy，一半流量仍会 404。</p><h2>生产不要边访问边生成</h2><p>构建阶段应固定模式、依赖、主题和语言；发布阶段只做原子切换。权限由部署用户与 Web 用户组策略统一，不要用 chmod 777。</p><p>用 curl 分别请求 HTML 与引用资源，连续命中不同节点并观察 CDN。所有节点在切换前后都返回同一版本 200，链路才算稳定。</p>]]></description>
      <pubDate>Wed, 23 Jul 2025 03:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台订单 Grid 新字段不显示，数据明明已经写进表了怎么办？]]></title>
      <link>https://www.360magento.com/blog/admin-order-grid-custom-column-not-showing/</link>
      <description><![CDATA[<p>给订单加了外部单号，详情页能看到，<code>sales_order</code> 也有值，但列表新列始终为空。原因通常是后台 Grid 并不直接查询订单实体表。</p><h2>先确认字段落在哪张表</h2><pre><code>SELECT entity_id, increment_id, external_number
FROM sales_order
WHERE entity_id = :order_id;

SELECT entity_id, increment_id, external_number
FROM sales_order_grid
WHERE entity_id = :order_id;</code></pre><p>字段只在 sales_order，XML 把列画出来也拿不到数据。应通过 declarative schema 增加 Grid 字段，并在订单保存或异步刷新时同步。不要为了省代码在列表 collection 对大表做无索引实时 join。</p><h2>数据有了，列仍不见，再查 UI Component</h2><p>检查 <code>view/adminhtml/ui_component/sales_order_grid.xml</code> 合并结果，列名是否与数据源键一致。看 Grid AJAX 响应：JSON 已有字段但页面没有，问题在前端列配置；响应没有，继续查数据源。</p><h2>管理员 bookmark 会保存旧列状态</h2><p>后台保存用户的列显示、排序和筛选。新列部署后，旧 bookmark 可能继续隐藏它。先在 Columns 菜单确认，再针对当前用户重置视图，不要清掉所有管理员配置。</p><p>最后测试新订单与历史订单。历史回填应分批且可重复执行。SQL、Grid AJAX 和页面三处一致，筛选与导出也能工作，才算完成。</p>]]></description>
      <pubDate>Tue, 22 Jul 2025 08:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单邮件不发送，别只盯着 SMTP 插件]]></title>
      <link>https://www.360magento.com/blog/order-email-not-sent-cron-queue-debug/</link>
      <description><![CDATA[<p>SMTP 插件测试邮件成功，但真实订单一封都没有。这不能证明订单邮件链路正常，因为测试按钮往往绕过订单入队、cron 消费和模板变量。</p><h2>先确认订单有没有进入邮件流程</h2><p>用明确测试订单记录下单时间、网站和邮箱，再只读检查发送标记。重点不是手工把 <code>email_sent</code> 改成 1，而是判断系统有没有尝试发送。</p><pre><code>php bin/magento cron:run
php bin/magento cron:run
tail -f var/log/cron.log var/log/exception.log var/log/system.log</code></pre><p>计划生成和执行可能需要连续两个周期。还要在 cron_schedule 中按邮件 job_code 查状态与 messages。</p><h2>SMTP 接受不等于收件成功</h2><p>应用日志显示服务器接受，只说明上游返回成功。仍需查投递日志、退信、抑制列表和 SPF/DKIM/DMARC。只有某个域收不到，优先查投递层；所有域都没记录，才回到应用传输。</p><h2>模板问题通常会留异常</h2><p>不存在变量、内联 CSS 失败或编码异常，会让渲染中止。用真实订单相同 Store View 与模板测试，别拿默认商店证明另一个网站正常。</p><p>修复后创建新订单，确认自动入队、cron 准时消费、邮件服务收到且最终邮箱到达。直接改数据库标记或不停点击发送，只会模糊问题位置。</p>]]></description>
      <pubDate>Mon, 21 Jul 2025 01:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 inventory reservation 不一致，补偿命令怎么用才不会越修越乱？]]></title>
      <link>https://www.360magento.com/blog/inventory-reservation-inconsistency-compensation/</link>
      <description><![CDATA[<p>库存可销售数量和订单对不上时，MSI inconsistency 命令很有用，但我不会看到输出就直接管道到 compensation。它根据订单状态推导差异并追加记录，不会修复造成差异的支付回调、取消流程或导入脚本。</p><h2>先只读生成清单</h2><pre><code>php bin/magento inventory:reservation:list-inconsistencies -r
php bin/magento inventory:reservation:list-inconsistencies -c</code></pre><p>参数会随版本变化，先看 <code>--help</code>。保存结果后抽取订单核对：是否真实发货、取消、重复下单，或第三方系统直接改状态。</p><p>同一订单短时间多次变更时，重点查 webhook 重放和人工批量操作。错误业务状态会让工具生成数学上正确、业务上错误的补偿。</p><h2>补偿是追加记录，不是修改历史</h2><p>Reservation 设计为 append-only。正确修复通常是新增相反数量，使订单链合计回到预期，而不是删除旧行。生产前应在同版本副本演练，记录目标 SKU 修复前后 salable quantity，并分批执行，防止消费者瞬间积压。</p><h2>修完必须复盘来源</h2><p>常见根因是旧订单缺初始 reservation、外部 OMS 直接写状态、取消事件未触发、消费者停机或插件重复处理。结束条件是历史差异按范围归零，新订单链闭合，消费者无 backlog，前台数量符合业务预期。</p>]]></description>
      <pubDate>Fri, 18 Jul 2025 05:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品有库存却显示缺货，Salable Quantity 应该怎么查？]]></title>
      <link>https://www.360magento.com/blog/product-in-stock-but-salable-quantity-zero/</link>
      <description><![CDATA[<p>仓库看到 Source Quantity 还有 20，商品页却显示缺货。把数量改成 21 后短暂恢复，过会又缺货。最容易犯的错，是把物理数量和可销售数量当成同一个数。</p><h2>先确定网站使用哪个 Stock</h2><p>MSI 里 Website 关联 Stock，Stock 聚合 Source。一个 Source 有数量，不代表它属于当前销售渠道。先确认网站、SKU、Stock ID 和 Source 分配。</p><pre><code>php bin/magento inventory:reservation:list-inconsistencies
php bin/magento indexer:status inventory</code></pre><p>不同版本的库存 CLI 可能不同，命令不存在就使用服务契约或只读 SQL 辅助确认，不要在生产猜表更新。</p><h2>Reservation 是差值，不是库存快照</h2><p>下单写负 reservation，发货、取消或退款写补偿记录。它是追加日志，正常完成后同一订单链合计应回到零。未完成订单会合法降低 Salable Quantity；异常中断才会留下不一致。</p><p>按订单号检查每个负数的业务原因，不能因为看到负数就删除，也不能直接改索引表，下一次重建仍会覆盖。</p><h2>数量正确后仍缺货，再看阈值与索引</h2><p>Out-of-Stock Threshold、Backorders、Manage Stock 和商品级覆盖都会改变结果。若库存消费者长期未运行，状态也会延迟更新。</p><p>验收覆盖下单、取消、发货：下单后 salable 降低，取消后恢复，发货后 source quantity 扣减且 reservation 抵消。只把页面暂时改成有货，不代表库存链路恢复。</p>]]></description>
      <pubDate>Thu, 17 Jul 2025 02:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 经过 Varnish 后页面还是旧的，HIT 并不代表缓存正常]]></title>
      <link>https://www.360magento.com/blog/varnish-hit-stale-page-cache-debug/</link>
      <description><![CDATA[<p>商品价格已经更新，Magento cache 也刷新过，但前台几小时还是旧值。响应头里能看到 HIT，于是有人直接把 TTL 调小。这样可能掩盖问题，却不能解释为什么正常 purge 没让对象失效。</p><h2>先确认请求经过了谁</h2><pre><code>curl -sS -D - -o /dev/null https://shop.example.com/product.html
curl -sS -D - -o /dev/null https://shop.example.com/product.html</code></pre><p>关注 Age、Varnish 标记、CDN 标记及 Magento cache debug。如果前面还有 CDN，Varnish 已 purge 但 CDN 仍命中，看起来就像 Varnish 没刷新。</p><h2>确认 purge 到达正确主机</h2><p>后台配置的缓存主机和线上真实地址经常不一致，尤其在容器和迁移后。刷新时同时看 Magento 日志与 Varnish access log，确认 PURGE/BAN 到达且 ACL 允许来源。</p><p>自定义实体若没返回正确 identity tag，系统不知道页面依赖它；使用过大的 tag 又会让一次小改动清掉大量页面。</p><h2>别忽略 grace 和后端健康</h2><p>后端 unhealthy 时，Varnish 可能在 grace 内继续提供陈旧内容。这是保可用性设计。应查健康检查 URL、nginx/PHP 响应与 Varnish 日志，而不是反复 cache:flush。</p><p>修复后做一次可追踪测试：修改无风险文本，记录保存时间，观察失效请求、Age 归零、下一次 MISS、随后再次 HIT。把链路跑通，比关掉缓存更能说明问题。</p>]]></description>
      <pubDate>Wed, 16 Jul 2025 07:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 登录用户随机掉线，Redis session 到底该查什么？]]></title>
      <link>https://www.360magento.com/blog/redis-session-random-logout-troubleshooting/</link>
      <description><![CDATA[<p>用户浏览十几分钟后偶尔被退出，后台管理员也会随机回到登录页。应用日志没有明确异常，清缓存还能短暂缓解。最后发现不是认证代码，而是 Redis 会话实例在内存压力下淘汰 key。</p><h2>先把掉线发生在哪一层分清</h2><p>浏览器仍携带 session cookie，只能证明会话编号还在；Redis 中对应 key 消失，Magento 一样会创建新会话。复现时记录响应头、Cookie 名和发生时间，然后检查：</p><pre><code>redis-cli INFO memory
redis-cli INFO stats
redis-cli CONFIG GET maxmemory
redis-cli CONFIG GET maxmemory-policy
redis-cli --latency</code></pre><p><code>evicted_keys</code> 持续增长是强信号。缓存和 session 不宜混在同一个小实例里，否则缓存膨胀会把登录态一起挤掉。</p><h2>TTL 与 Magento 配置要对得上</h2><p>核对 <code>env.php</code> 的 session 配置、后台 Cookie Lifetime 和 Redis 实际 TTL。爬虫、顾客与管理员会话的生命周期可能不同，min_lifetime、max_lifetime 也会参与限制。</p><p>若日志有连接超时，查 Redis 连接数、网络抖动和超时，而不是继续提高 Cookie Lifetime。超时调得过长只会让 PHP worker 堵得更久。</p><h2>锁等待也可能被误判为掉线</h2><p>同一用户并发 AJAX 时，session locking 会让请求串行。锁等待超阈值后，前端可能把失败当成重新登录。把 PHP 慢请求、Redis 延迟和浏览器 Network 对齐，确认是 key 丢失还是锁等待。</p><p>验收要看 evicted_keys 不再增长、内存有余量、TTL 合理，并做同账号多并发测试。四项都稳定，随机掉线才算修好。</p>]]></description>
      <pubDate>Tue, 15 Jul 2025 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 索引一直卡在 Processing，怎么安全恢复而不丢更新？]]></title>
      <link>https://www.360magento.com/blog/indexer-stuck-processing-safe-recovery/</link>
      <description><![CDATA[<p><code>bin/magento indexer:status</code> 长时间显示 Processing，第一反应往往是 reset。但后台如果还有索引进程在跑，强行启动第二个只会放大数据库压力。</p><h2>先证明它真的死了</h2><pre><code>php bin/magento indexer:status
ps aux | grep '[b]in/magento indexer'
SHOW FULL PROCESSLIST;</code></pre><p>仍能看到 PHP 进程，而且 SQL 扫描行数、临时表或 CPU 在变化，它可能只是慢。先看磁盘空间、临时目录及 metadata lock。进程已经不存在，状态却几小时不变，才属于残留状态。</p><pre><code>php bin/magento indexer:reset catalogsearch_fulltext
php bin/magento indexer:reindex catalogsearch_fulltext</code></pre><p>只处理对应索引器，不要为了省事全部 reset。</p><h2>Update by Schedule 还要查 mview</h2><p>计划模式下变化先写入 changelog。索引状态正常但前台数据旧，常见原因是订阅的 version_id 没推进：</p><pre><code>SELECT view_id, mode, status, version_id, updated
FROM mview_state
ORDER BY updated ASC;</code></pre><p>比较 version_id 与对应 <code>*_cl</code> 表最大版本。不要随便 TRUNCATE changelog，那可能跳过尚未消费的商品变化。先备份状态，再决定全量重建或从正确版本继续。</p><h2>恢复后还要回答为什么卡</h2><p>若总在同一商品或 SQL 停住，查异常数据、缺失索引、锁等待和插件；若只在高峰发生，考虑计划模式并为 cron 留独立资源。安全恢复只是第一步，找到导致 Processing 没正常收尾的进程或 SQL 才算闭环。</p>]]></description>
      <pubDate>Mon, 14 Jul 2025 06:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 cron_schedule 里大量 missed，定时任务为什么越积越多？]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-missed-jobs-piling-up/</link>
      <description><![CDATA[<p>有一次促销价格没有按时生效，我先看了 <code>cron_schedule</code>，发现不是某一个任务失败，而是一大片记录都变成了 <code>missed</code>。这种情况如果直接清表，页面会暂时清爽，但真正的问题一分钟后还会回来。</p><h2>先判断是 cron 根本没跑，还是来不及跑</h2><p>先把最近半小时的状态按时间排出来：</p><pre><code>SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE scheduled_at &gt; NOW() - INTERVAL 30 MINUTE
ORDER BY schedule_id DESC;</code></pre><p>如果只有 pending 和 missed，完全没有新的 running、success，先查操作系统计划任务。Web 站点能打开，不代表 CLI 使用的是同一个 PHP：</p><pre><code>crontab -l
which php
php -v
php bin/magento cron:run</code></pre><p>手工执行时要使用和系统 cron 相同的用户、工作目录及 PHP 路径。常见现场是 crontab 仍指向已下线的 PHP，或者发布后目录改名，命令从一开始就没进入 Magento。</p><h2>有 success 但 missed 仍增长，要找堵住队列的任务</h2><p>Magento 会提前生成计划。任务超过 Schedule Lifetime 仍未执行才变成 missed。此时应比较 <code>executed_at - scheduled_at</code>，再找耗时异常的 job。第三方同步、报表导出和全量商品脚本尤其容易拖死默认 cron 组。</p><p>自定义任务应按主键游标或时间窗口拆批，不能每分钟从第一行重新扫全表。需要互斥时，锁必须在异常退出后可释放，否则后续任务会全部跳过。</p><h2>恢复时别一股脑重跑所有 missed</h2><p>订单邮件、库存同步可能有外部副作用。补跑前先确认幂等：重复执行会不会发两封邮件、扣两次库存或重复调用 ERP。索引任务可以定向重置；业务任务更适合按 job_code 和业务主键补偿。</p><p>连续观察两个调度周期，新任务能准时从 pending 到 running 再到 success，积压持续下降，才算恢复。清表只能处理症状，系统 cron、任务耗时和幂等才是根。</p>]]></description>
      <pubDate>Fri, 11 Jul 2025 02:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台配置保存成功，部署后又变回去了怎么解决？]]></title>
      <link>https://www.360magento.com/blog/admin-config-reverted-after-app-config-import/</link>
      <description><![CDATA[<p>运营在后台改了一个配置，页面提示保存成功，当天也确实生效。第二天发布跑完 <code>app:config:import</code>，值又回到了旧版本。这个现象不应该归结为“Magento 缓存玄学”，它通常说明团队同时用了两套配置事实源：后台数据库是一套，代码仓库里的部署配置又是一套。</p><h2>先把同一个配置路径在四个位置对齐</h2><p>假设路径是 <code>vendor_module/general/enabled</code>，我会依次确认：</p><ol><li>后台保存的是 Default、Website 还是 Store View；</li><li><code>core_config_data</code> 对应 scope/scope_id 的值；</li><li><code>app/etc/config.php</code> 或 <code>app/etc/env.php</code> 是否声明了这个路径；</li><li>运行环境是否存在把配置路径转换后的环境变量覆盖。</li></ol><p>数据库查询只用于确认：</p><pre><code>SELECT scope, scope_id, path, value
FROM core_config_data
WHERE path = 'vendor_module/general/enabled'
ORDER BY scope, scope_id;</code></pre><p>不要只看 Default 行。后台在 Store View 保存的值，可能被 Website 继承关系影响；反过来，部署配置锁的是另一个作用域，也会造成“有的店变了，有的没变”。</p><h2>为什么 app:config:import 会把它改回去</h2><p><code>app:config:import</code> 的职责就是把共享配置导入当前环境。某个路径已经被 dump 进 <code>config.php</code>，仓库里的值便是部署声明。你只在生产后台改数据库，却没有更新声明文件，下一次 import 恢复仓库值，反而是命令按设计工作。</p><p><code>env.php</code> 更适合环境特有或敏感配置，环境变量又可以在运行时覆盖配置。要注意：如果最高优先级来自平台环境变量，改数据库、改 config.php 甚至清缓存都不会改变最终读值。</p><h2>先用 CLI 读最终值，再讨论谁覆盖谁</h2><p>对非敏感配置，可以在目标作用域读取 Magento 最终解析到的值，并与数据库和文件逐项对照。不要把支付密钥、令牌等敏感值打印进工单或 CI 日志。若同一命令在 Web 容器和 CLI 容器结果不同，还要检查两者挂载的 <code>app/etc</code>、环境变量和发布版本是否一致。</p><p>另一个常见误判是只清了应用缓存，却命中了旧容器。配置导入后应确认所有实例使用同一份 release 和环境修订；否则表面像值被改回，实际是请求在新旧节点之间切换。</p><h2>真正要修的是团队流程</h2><p>先给配置分三类：</p><ul><li><strong>所有环境共享：</strong>在受版本控制的 shared config 中变更，走代码评审和部署；</li><li><strong>环境专属或敏感：</strong>通过 env.php 管理命令、平台变量或密钥系统维护，不进普通仓库；</li><li><strong>允许运营实时调整：</strong>不要把该路径锁进部署文件，让数据库成为它的事实源，同时保留权限与审计。</li></ul><p>最糟糕的是同一路径今天由后台改，明天由部署改，紧急时又由环境变量改，团队却没有记录谁优先。把每个配置归属写进部署文档，比再加一次 cache flush 有用。</p><h2>不要为了让后台可编辑，直接删整段配置</h2><p>从 <code>config.php</code> 或 <code>env.php</code> 移除路径，会改变它的管理方式。提交前先确认其他环境是否依赖这条声明，以及下一次 <code>app:config:dump</code> 会不会又把它带回来。比较安全的做法是只调整目标路径，保留版本记录，并在流水线里检查未预期的配置 diff。</p><h2>一次安全的修复演练</h2><p>我会先在预发布复制相同作用域：记录当前有效值，运行 import，观察计划变更；再按确定的事实源修改，重新部署，确认后台是否应当只读以及前台实际读值。回滚也应该回滚配置声明版本，而不是临时 UPDATE 数据库。</p><p>上线验收时同时检查 CLI 读值、后台作用域和真实业务行为。配置页面显示某个数字不代表代码一定读到它——作用域、锁定文件和环境变量任意一层不同，最终值都可能变。把优先级画清楚后，这类“自己变回去”的问题就不神秘了。</p>]]></description>
      <pubDate>Thu, 10 Jul 2025 06:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 下单成功后购物车还在，Quote 为什么没有变成 inactive？]]></title>
      <link>https://www.360magento.com/blog/order-success-cart-not-cleared-quote-active/</link>
      <description><![CDATA[<p>用户支付完成回到站点，右上角购物车仍显示原来的商品。刷新后还能进 checkout，严重时同一批商品又下了一单。这个问题要立刻分级：如果只是 minicart 的旧缓存，影响展示；如果数据库里的 Quote 仍是 active，就有重复下单风险。</p><h2>十分钟内先确认是哪一种</h2><p>从订单找到 quote_id，然后只读查询：</p><pre><code>SELECT entity_id, increment_id, quote_id, state, status, created_at
FROM sales_order
WHERE increment_id = :order_number;
SELECT entity_id, is_active, reserved_order_id, items_count,       customer_id, updated_at
FROM quote
WHERE entity_id = :quote_id;</code></pre><p>如果 Quote 已经 <code>is_active = 0</code>，重新调用后端 cart API 通常拿不到这辆活动购物车，问题更偏向前端 customer-data、PWA store 或 localStorage 没清。若 Quote 仍为 1，则继续查订单提交链路。</p><h2>数据库已经正确：清的是前端“身份”，不是服务器缓存</h2><p>Luma/Hyvä/PWA 的处理方式不同，但共同点是下单成功后要让当前 cart 标识失效，并重新加载购物车区块。只做 <code>cache:clean</code> 解决不了某个浏览器 localStorage 里的旧 cart_id。</p><p>我会在成功页打开 Network，确认页面没有继续查询旧 cart；再开一个新标签页，看购物车状态是否从持久化存储恢复。若只有支付网关回跳路径失败，而货到付款正常，通常是回跳页面绕过了标准成功处理。</p><h2>Quote 真的仍 active：沿“创建订单”边界查</h2><p>标准提交过程中，Quote 会与订单建立关系并结束活动状态。定制支付模块常见的错误是：</p><ul><li>先创建订单，捕获后续异常时又把 Quote 设回 active，却没有判断订单已存在；</li><li>为了失败后恢复购物车，在支付 callback 和用户 return URL 两条路径都执行恢复；</li><li>插件包住 place order，提交成功后抛异常，补偿逻辑把状态回滚了一半；</li><li>异步下单时，前端把“已接收”当“失败”，继续沿旧 cart 操作。</li></ul><p>把订单号、quote_id、payment transaction ID 和请求 ID 串成时间线，通常能看到是哪一个回调最后修改 Quote。不要只搜用户看到成功页的那次请求，支付平台的服务器 callback 可能更早或更晚到达。</p><h2>为什么不能直接批量把这些 Quote 改成 0</h2><p>对“已经有唯一有效订单”的单条 Quote，停用看起来合理，但批量脚本若没有处理并发、重复订单和失败支付，会把仍需恢复的购物车也关掉。先找出每个 active Quote 对应的订单数量和状态；存在两张订单时，重点已不是清购物车，而是支付、库存和取消哪张订单。</p><p>修复后我会测试四条路径：普通支付成功、用户关闭回跳页、支付成功但 return 超时、支付失败后重试。每条都要求一辆 Quote 最多对应一个预期订单，成功后旧 cart 不再可写，失败时则能明确创建新 cart 或受控恢复。购物车图标变成 0 只是表面，幂等性才是最后的验收标准。</p>]]></description>
      <pubDate>Wed, 09 Jul 2025 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 新增 GraphQL 字段后仍提示 Cannot query field，究竟缓存在哪？]]></title>
      <link>https://www.360magento.com/blog/graphql-cannot-query-field-after-schema-change/</link>
      <description><![CDATA[<p>我在 <code>etc/schema.graphqls</code> 里新增了字段，文件也已经上传，GraphQL Playground 还是回答 <code>Cannot query field</code>。这时最容易进入“清缓存抽奖”：cache:clean、cache:flush、重启 Redis 全来一遍，偶尔好了，却不知道为什么。</p><p>我现在按两个问题拆：<strong>运行中的 Magento 有没有读到这份 schema？客户端拿到的是不是当前 schema？</strong></p><h2>第一步：确认文件确实属于已启用模块</h2><pre><code>php bin/magento module:status Vendor_Module
php bin/magento setup:db:status
grep -R "my_new_field" app/code/Vendor/Module/etc vendor/vendor-name/module-name/etc</code></pre><p>路径必须是模块的 <code>etc/schema.graphqls</code>，文件名、大小写和部署包都要一致。新模块若没有完成注册、启用或 setup upgrade，schema 内容再正确也不会参与合并。</p><p>多节点环境再加一项：在每台实际接流量的节点计算该文件校验值。只发布到一台时，请求会一会儿认识字段、一会儿不认识，表现得很像缓存。</p><h2>第二步：先只加一个最小字段</h2><p>复杂 schema 有时是类型扩展位置写错，或者 resolver 配置让加载失败。先缩成一个不会依赖业务数据的字段，确认它能出现在 introspection 中，再逐步加参数、返回类型和 resolver。这样比同时调 schema、DI 和业务 SQL 快得多。</p><p>同时查看 <code>var/log/exception.log</code>、<code>system.log</code> 和 PHP 日志。schema 合并错误有时在构建或首次请求就已经记录，前端只显示一句泛化错误。</p><h2>清哪类缓存才有意义</h2><p>schema 定义属于服务配置的一部分，开发环境可以先定向清理 Magento 的 config cache，再请求 introspection 验证：</p><pre><code>php bin/magento cache:clean config
php bin/magento cache:status</code></pre><p>如果项目启用了生产编译，新增 resolver 类、构造参数或 DI 配置后，还要按项目标准重新编译和部署。<code>cache:flush</code> 不会替你生成缺失的 compiled code。</p><p><code>graphql_query_resolver_result</code> 缓存保存的是可缓存 resolver 的结果，不是所有 schema 变更的万能开关。字段连 introspection 都不存在时，先处理模块加载与 config schema，不要把注意力放在业务结果缓存上。</p><h2>最后排除“其实是客户端旧 schema”</h2><p>IDE 和前端代码生成工具会缓存 introspection。直接用 curl 向实际 <code>/graphql</code> 端点发一个最小查询；如果服务端已认识字段，而 IDE 仍标红，刷新 schema 或重启代码生成工具即可。还要确认请求域名、Store header 和环境没指到另一套站点。</p><p>我的验收顺序是：introspection 能找到字段；最小查询能调用 resolver；带真实参数的查询返回正确数据；关闭开发日志后在所有节点重复请求。这样每一步只验证一个层次，不需要靠“再清一次全部缓存”碰运气。</p>]]></description>
      <pubDate>Tue, 08 Jul 2025 07:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 RabbitMQ 报 PRECONDITION_FAILED inequivalent arg，队列参数不一致怎么处理？]]></title>
      <link>https://www.360magento.com/blog/rabbitmq-precondition-failed-inequivalent-arg/</link>
      <description><![CDATA[<p>消费者一启动就退出，日志里有一长串：</p><pre><code>PRECONDITION_FAILED - inequivalent arg 'x-...' for queue '...'</code></pre><p>这不是 RabbitMQ 连不上，而是已经存在一个同名队列，Magento 当前代码想用另一组属性再次声明它。RabbitMQ 会做属性等价检查，durable、exclusive、auto-delete 或 arguments 对不上时，直接关闭 channel，避免客户端悄悄改变现有队列语义。</p><h2>先把错误原文保留下来</h2><p>错误一般会同时写出“received”和“current”值，例如代码想要 <code>x-queue-type=quorum</code>，现有队列却是 classic。不要只截取第一行，因为具体哪个参数不同，决定了能否原地调整。</p><p>随后查看当前队列，而不是立刻删除：</p><pre><code>rabbitmqctl list_queues -p / name durable auto_delete arguments messages_ready messages_unacknowledged consumers</code></pre><p>同时检查 Magento 模块中的 <code>etc/queue_topology.xml</code>、<code>queue_consumer.xml</code>，以及 RabbitMQ Policy。参数可能来自应用声明，也可能由 Policy 注入。只改一边，下一次部署仍会冲突。</p><h2>我遇到最多的三个来源</h2><ul><li>升级模块后，开发者把已有 classic queue 改成 quorum，队列名字却没变；</li><li>两个 Magento 环境误用了同一个 vhost，测试环境用不同参数声明了生产队列；</li><li>旧模块已移除，但它创建的队列还在；新模块复用了同名队列。</li></ul><h2>有消息时，删除队列不是“修复”</h2><p>如果 <code>messages_ready</code> 或 <code>messages_unacknowledged</code> 不为 0，删除会造成业务消息丢失或状态不一致。先确认消息对应什么业务：库存、异步操作、邮件与第三方同步的补偿方式完全不同。</p><p>生产上我更倾向于新建一个名字明确的新队列，让新代码发布到新队列；暂停旧生产者后把旧队列消费完，再下线旧绑定。若必须迁移消息，也要考虑消息是否仍适合新的队列类型、重试和死信设置，不能只把 payload 搬过去。</p><h2>以 classic 改 quorum 为例，不能只改一个参数</h2><p>队列类型变化通常意味着可用参数也跟着变。旧 classic queue 上的镜像参数、队列 TTL、优先级或独占设置，不一定能原样搬到 quorum queue。先根据当前 RabbitMQ 版本核对支持矩阵，再在测试 vhost 用与生产相同的 topology 声明一遍。</p><p>发布时还要考虑滚动部署：旧节点仍认为队列是 classic，新节点已经声明 quorum，两代代码同时在线就会互相打架。可以先发布兼容的生产者，让消息写到一个稳定 exchange，再切 binding 和 consumer；确认旧版本全部下线后，才移除旧队列。这样迁移边界在 RabbitMQ 拓扑，而不是寄希望于所有应用进程同一毫秒重启。</p><h2>参数明明一样，为什么还报错</h2><p>管理界面显示的名称相同，不代表来源相同。例如 <code>x-dead-letter-exchange</code> 可能由客户端 arguments 声明，也可能来自 policy；一个值是字符串，另一个被序列化成不同 AMQP 类型，也会不等价。把错误中的参数名、类型、received/current 原样对照 definitions，比肉眼看两份 XML 更可靠。</p><h2>什么时候可以删除再重建</h2><p>只有在确认队列没有待处理和未确认消息、没有旧版本节点仍在发布/消费，并且它可以从 Magento 配置安全重建时，我才会删除。操作前导出 definitions 或至少记录 exchange、binding、arguments，方便回滚和复盘。</p><p>修好后不要只看 consumer 进程“还活着”。发布一条可识别的测试消息，确认它只被处理一次，失败时进入预期的重试或死信路径；然后重启消费者，验证同名队列再次声明不会报错。能经得住重启，才说明参数来源已经统一。</p>]]></description>
      <pubDate>Mon, 07 Jul 2025 02:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 已执行 maintenance:disable，网站为什么还是维护页面？]]></title>
      <link>https://www.360magento.com/blog/maintenance-disabled-still-showing-page/</link>
      <description><![CDATA[<p>发布结束后执行了：</p><pre><code>php bin/magento maintenance:disable
php bin/magento maintenance:status</code></pre><p>命令明确显示 maintenance mode is not active，浏览器却仍是一张维护页。这里最重要的不是再删一次 flag，而是先问：<strong>这张页面到底是谁返回的？</strong></p><h2>用响应特征确定层级</h2><pre><code>curl -I https://shop.example.com/
curl -sS -D /tmp/headers.txt -o /tmp/body.html https://shop.example.com/
head -40 /tmp/headers.txt</code></pre><p>看状态码、<code>Age</code>、<code>Via</code>、CDN 命中标记、Server 以及响应里的自定义 request ID。再从允许的内网路径直连 origin 测一次。如果 origin 已正常而公网仍维护，问题在 CDN、WAF 或负载均衡，不在 Magento。</p><p>反过来，如果某些请求正常、某些仍维护，优先怀疑多节点。发布脚本可能只在一台共享代码目录外的节点执行了 disable；另一个节点的 <code>var/.maintenance.flag</code> 还在，负载均衡便会交替返回两种页面。</p><h2>别把三个“维护开关”当成一个</h2><ol><li><strong>Magento 自己的维护模式：</strong>由 CLI 管理，可用 <code>maintenance:status</code> 检查；</li><li><strong>Web 服务器或部署脚本的静态维护页：</strong>Nginx/Apache 可能根据另一个文件或环境变量直接返回；</li><li><strong>边缘层维护：</strong>CDN、Fastly、负载均衡或托管平台可能有独立开关和缓存。</li></ol><p>很多事故就是发布脚本同时打开了第 1 和第 2 个开关，收尾只关闭一个。</p><h2>如果确实是 Magento 仍在返回 503</h2><p>确认命令是在正确项目根目录、由正确发布版本执行，并检查 PHP/Web 进程看到的代码路径是否相同。蓝绿发布时，SSH 当前目录可能已经指向新 release，但 Web 流量仍在旧 release。</p><p>还要看维护模式是否配置了允许 IP。测试人员的 IP 被放行时，自己看到正常页面，并不能证明公众已经恢复。用外部探测点测试比在办公室浏览器刷新可靠。</p><h2>缓存能不能让维护页一直存在</h2><p>正常配置下 503 不应被长期缓存，但自定义 VCL、反向代理规则或错误页缓存可能做错。此时先检查响应头与缓存键，再定向 purge。不要一看到旧页面就把 Magento、Redis、CDN 全部清空；既破坏命中率，也无法知道真正是哪层。</p><p>我的恢复标准是：公网与 origin 都返回预期状态，匿名和登录请求正常，至少连续命中所有应用节点，并且负载均衡健康检查恢复。只在一个浏览器里看到首页打开，还不能宣布发布结束。</p>]]></description>
      <pubDate>Fri, 04 Jul 2025 05:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台导出订单就内存溢出，怎么拆而不是一味加 memory_limit？]]></title>
      <link>https://www.360magento.com/blog/admin-order-export-memory-exhausted/</link>
      <description><![CDATA[<p>后台订单网格点 Export，转一会儿就报 <code>Allowed memory size exhausted</code>。把 PHP 内存从 768M 加到 2G 后暂时能导，订单再多一点又失败。这种处理只是把故障日期往后推，而且导出期间单个 PHP-FPM 进程会吃掉大量内存，容易连后台其他请求一起拖慢。</p><p>我会先做一个很朴素的对照：导出 100 条、1 万条和相同数量但更窄日期范围的数据，记录峰值内存。如果内存近似按行数线性增长，代码大概率把结果或 CSV 全攒在数组里；如果加某一列后突然暴涨，就去查这列的 renderer 或插件。</p><h2>网格里“看不见”的 JOIN 也会付出代价</h2><p>不少项目给订单网格加了商品 SKU、优惠明细、支付附加信息。页面只显示 20 行时问题不明显，导出会移除分页，把 JOIN 扩展后的所有行送进 PHP。先打印导出 collection 的 SQL，并检查：</p><ul><li>一张订单是否因为 item、shipment 或 transaction JOIN 变成多行；</li><li>renderer 是否对每一行再次加载完整订单，形成 N+1 查询；</li><li>扩展字段是否反序列化了很大的 payment additional_information；</li><li>导出插件是否先 <code>getItems()</code>，再构造一个完整二维数组。</li></ul><h2>临时拿数据：先缩小范围</h2><p>如果运营当天就要文件，我会先按创建日期或 increment_id 分成几段，从后台分别导出。这是止血，不是最终方案。切分时要保存过滤条件和导出时间，避免几段之间漏单或重复。</p><h2>长期方案：稳定游标 + 流式写文件</h2><p>真正的大批量导出不适合绑在一个浏览器请求里。可以做 CLI 命令或队列任务，每批只取固定数量，以单调递增主键作为游标：</p><pre><code>SELECT entity_id, increment_id, created_at, status, grand_total
FROM sales_order
WHERE entity_id &gt; :last_id  AND created_at &gt;= :from  AND created_at &lt; :to
ORDER BY entity_id ASC
LIMIT 1000;</code></pre><p>每批读取后立即写入已打开的 CSV 流，释放集合，再保存 <code>last_id</code>。不要用越来越大的 OFFSET；数据量大时它会越翻越慢。时间条件最好用半开区间，例如 <code>[2025-07-01 00:00:00, 2025-07-02 00:00:00)</code>，边界更不容易重复。</p><p>如果导出过程中订单还会变化，要先定义一致性：是“任务开始时的快照”，还是“读取到这一刻的最新状态”。普通运营报表通常可以记录任务开始时间，并限制最大 entity_id；财务用途则可能需要从报表库或事务一致的快照生成。</p><h2>CSV 本身也有几个容易忽略的坑</h2><ul><li>用标准 CSV writer 处理逗号、引号和换行，不要手工字符串拼接；</li><li>防止以 <code>=</code>、<code>+</code>、<code>-</code>、<code>@</code> 开头的用户输入被表格软件当公式执行；</li><li>明确金额导出的是 base currency 还是 order currency；</li><li>客户邮箱、地址等数据应按权限生成，并设置下载文件的保留期。</li></ul><p>验收时我不只看“文件能下载”。还会核对数据库条件下的订单数、CSV 行数、首尾订单、金额合计，并监控峰值内存是否在批次之间回落。这样才能证明导出已经从“碰运气的大请求”变成可控任务。</p>]]></description>
      <pubDate>Thu, 03 Jul 2025 03:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发票 PDF 中文全是方框，换字体为什么不能只改 CSS？]]></title>
      <link>https://www.360magento.com/blog/invoice-pdf-chinese-square-font-fix/</link>
      <description><![CDATA[<p>有次中文站上线后，网页订单、邮件都正常，只有后台下载的发票 PDF 里，商品名和地址变成一排方框。最初有人在主题 CSS 里加了 <code>font-family: Microsoft YaHei</code>，当然没有任何变化——Magento 的原生销售 PDF 不是把 HTML 交给浏览器打印，而是代码一行一行把文字画到 PDF 页面上。</p><h2>先分清“缺字形”还是“编码坏了”</h2><p>用 PDF 阅读器复制那串方框，粘贴到纯文本里：</p><ul><li>粘贴后能看到正确中文，多半是字体不包含中文字形；</li><li>粘贴后也是乱码，要继续检查进入 PDF 前的字符串编码和自定义模块处理；</li><li>只有某些生僻字是方框，说明字体覆盖范围不完整，不是整个流程都坏了。</li></ul><p>再做一个最小样本：客户名、地址、商品名分别放常用中文、数字和英文。这样能看出是所有绘制位置都用了错误字体，还是只有商品表格的 renderer 没换。</p><h2>修复位置在 PDF 绘制代码，不在前台主题</h2><p>我会做一个小模块扩展发票 PDF 的字体选择，让正文、粗体和必要的标题都使用服务器上可读取、允许嵌入并包含 CJK 字形的字体文件。不要直接改 <code>vendor</code>，升级后一定会丢；也不建议用一个 preference 粗暴复制整个核心 PDF 类，后续版本改分页或金额布局时很难跟。</p><p>更稳妥的做法是把“创建字体”集中成一个服务，再在实际调用 <code>drawText</code> 前切换字体。伪代码大致是：</p><pre><code>$font = $fontFactory-&gt;fromPath(
    $moduleDir . '/view/base/web/fonts/YourCjkFont.ttf');
$page-&gt;setFont($font, 9);
$page-&gt;drawText($text, $x, $y, 'UTF-8');</code></pre><p>具体 API 会随项目使用的 PDF 库和 Magento 版本不同，不能照抄一行就上线。重点是：传入的字体对象必须真的嵌入 PDF，并且每个绘制中文的 renderer 都走到它。</p><h2>字体选好了，布局还可能坏</h2><p>CJK 字体通常比内置西文字体大得多，字宽也不同。换字体后我会专门看三件事：</p><ol><li>长中文商品名是否越过数量和金额列；</li><li>两行地址换页时有没有压住页脚；</li><li>粗体标题是否因为没有对应字重，又退回缺字的字体。</li></ol><p>如果项目只是为了十几个固定中文标签，盲目嵌入完整大字库会让每张发票膨胀很多。可以选择允许子集嵌入的字体和实现，但要确认所用 PDF 库是否真的做子集化。不要随便从本机复制商业字体到服务器，字体授权也属于上线检查项。</p><h2>缓存清理不是核心，但部署路径要一致</h2><p>字体文件随模块发布后，要确认生产节点都包含同一文件、PHP 进程有读取权限，编译后的类确实是新版本。只在一台节点放字体会造成“有时正常、有时方框”的诡异现象。</p><p>最后用发票、发货单、贷项通知单各导出一份，因为它们可能共享部分抽象类，却有不同 item renderer。再用至少两种 PDF 阅读器打开并实际复制文字。能显示只是第一关，能搜索、复制，打印时也不丢字，才算这次字体修复完成。</p>]]></description>
      <pubDate>Wed, 02 Jul 2025 08:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品 URL Key 总被加上 -1，怎么找出真正的冲突记录？]]></title>
      <link>https://www.360magento.com/blog/product-url-key-auto-suffix-conflict/</link>
      <description><![CDATA[<p>商品 URL Key 保存后变成 <code>blue-shirt-1</code>，很多人的第一反应是“肯定还有一个 blue-shirt 商品”。但我处理过的几次，商品名和 URL Key 都没有重复，真正占坑的是 <code>url_rewrite</code> 里的历史记录。</p><p>Magento 最终要求唯一的是某个 Store 下的 <code>request_path</code>，而不是后台表单里那一格 URL Key。分类路径、URL 后缀、旧商品的永久重定向，都会参与生成结果。</p><h2>先按最终路径搜，不要只搜商品属性</h2><p>假设目标路径是 <code>blue-shirt.html</code>，先查对应 Store：</p><pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,       target_path, redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE store_id = :store_id  AND request_path IN ('blue-shirt', 'blue-shirt.html');</code></pre><p>如果商品开启了“Use Categories Path for Product URLs”，还要搜索带分类前缀的路径。反过来也一样：你在后台看到的 key 没有分类，但生成 request_path 时可能已经加了分类层级。</p><h2>看到冲突记录后，先判断它为什么存在</h2><p>我一般把结果分成三类：</p><ul><li><strong>仍指向有效商品或分类：</strong>这是正常占用，应改新商品 URL，不能删除别人的入口；</li><li><strong>301 历史重定向：</strong>说明这个地址过去用过。删除会让旧链接失去 SEO 价值，要先确认业务是否允许复用；</li><li><strong>孤儿或重复生成记录：</strong>entity 已不存在，或者一次失败导入留下异常数据。这才是需要进一步修复的对象。</li></ul><p>查孤儿时也不要只写一个大 DELETE。先把目标范围导出来，至少保留 <code>url_rewrite_id</code>、路径、Store 和目标实体。多商店尤其容易误删：同一路径在不同 <code>store_id</code> 下可以分别存在，问题只发生在保存商品的那个 Store。</p><h2>为什么删完又回来</h2><p>如果记录的 <code>is_autogenerated = 1</code>，它通常由目录 URL 重写逻辑重新生成。你只删结果，不改产生冲突的商品、分类路径或作用域，下一次保存、导入或重建时它还会回来。</p><p>另一个隐蔽点是 Store View 回退。默认作用域里是 <code>blue-shirt</code>，某个 Store View 曾单独保存过同样的值，后来界面上又切回“Use Default Value”。排查时应该明确列出每个作用域的实际属性值，而不是只看当前后台页面。</p><h2>我的处理顺序</h2><ol><li>确定目标 Store、URL 后缀以及是否带分类路径；</li><li>在 <code>url_rewrite</code> 查最终 request_path 的占用者；</li><li>打开占用者，确认它是有效入口、历史 301 还是孤儿；</li><li>能从后台调整的，优先修改源实体并让 Magento 重建；</li><li>只有确认是异常数据时，才在备份后做定向清理，再保存单个实体验证。</li></ol><p>我不会直接清空整个 <code>url_rewrite</code> 表。那样确实可能让当前商品拿回漂亮 URL，却同时丢掉全站自定义重写和历史重定向。这个问题的关键不是“怎样去掉 -1”，而是先回答：没有 -1 的那个地址，现在究竟属于谁。</p>]]></description>
      <pubDate>Tue, 01 Jul 2025 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL 报 The cart isn't active，旧 cart_id 到底从哪来的？]]></title>
      <link>https://www.360magento.com/blog/graphql-cart-isnt-active-troubleshooting/</link>
      <description><![CDATA[<p><code>The cart isn't active</code> 不是一个模糊的系统异常，它其实说得很具体：这个 cart 对应的 Quote 找到了，但 <code>is_active</code> 已经不是 1。Magento 在购物车成功转成订单后会把原 Quote 置为非活动，这是正常生命周期，不应该再拿它加商品、改地址或重复下单。</p><p>麻烦在于，前端经常把这句正常保护机制展示成“结账失败”。用户看到红色提示又点一次，实际上第一笔订单可能已经创建了。</p><h2>先回答最重要的问题：订单到底有没有生成</h2><p>不要立刻创建新购物车重试支付。先用服务端日志中的 masked cart ID 找到 Quote，再查它和订单的关系：</p><pre><code>SELECT entity_id, is_active, reserved_order_id, customer_id,       created_at, updated_at
FROM quote
WHERE entity_id = :quote_id;
SELECT entity_id, increment_id, status, state, quote_id,       created_at, grand_total
FROM sales_order
WHERE quote_id = :quote_id;</code></pre><p>如果已经有订单，前端应该进入成功页或订单查询流程，而不是继续对原 cart 执行 mutation。尤其是支付接口超时、浏览器提前断开时，客户端没收到成功响应，不代表服务端事务没有完成。</p><h2>旧 cart_id 通常藏在三个地方</h2><p><strong>第一处是 localStorage 或 IndexedDB。</strong>下单成功后前端只清了内存状态，没有删除持久化的 cart token；用户刷新页面，又把它装回来了。</p><p><strong>第二处是登录前后的购物车合并。</strong>游客 cart 被合并进客户 cart 后，组件树里仍有请求持有游客 ID。你会看到同一秒内两个 cart_id 交替出现。</p><p><strong>第三处是重复提交。</strong>按钮虽然变灰，但双击、移动端重触或网络重试已经发出了两个 <code>placeOrder</code>。第一个请求将 Quote 变为 inactive，第二个请求随后得到这句报错。</p><h2>用时间线判断是哪一种</h2><table><thead><tr><th>日志现象</th><th>更像什么问题</th><th>修复方向</th></tr></thead><tbody><tr><td>placeOrder 成功后数秒又 query 同一 cart</td><td>成功回调未清理持久化 ID</td><td>成功态原子地清 cart，并跳转订单结果</td></tr><tr><td>两个 placeOrder 几乎同时到达</td><td>按钮防重只做在视觉层</td><td>前端互斥 + 后端幂等确认</td></tr><tr><td>登录瞬间两个 cart_id 交替</td><td>合并后的引用没有统一更新</td><td>集中管理当前 cart，取消旧请求</td></tr><tr><td>没有订单，Quote 却被停用</td><td>支付扩展或异常恢复逻辑</td><td>沿 Quote 提交日志查谁修改 is_active</td></tr></tbody></table><p>GraphQL 官方错误里也把 <code>CART_NOT_ACTIVE</code> 与 <code>CART_NOT_FOUND</code> 分开了。前者意味着对象存在但生命周期已结束；后者才更像 ID 错误或无权限。因此，遇到 inactive 就无条件新建购物车，会丢掉“订单其实已经生成”的关键信号。</p><h2>不要把 is_active 手工改回 1</h2><p>这条 UPDATE 看起来很诱人，但如果订单已经存在，相当于把已结算的商品重新开放下单。库存、优惠券、礼品卡和支付授权都可能重复。正确处理是：</p><ul><li>有订单：恢复订单结果展示，不复活 Quote；</li><li>没有订单且提交明确失败：由受控的业务流程创建新 cart 或恢复结账内容；</li><li>状态来源不明：先记录修改 Quote 的调用栈或插件，再决定补偿。</li></ul><p>最后我会用人为制造超时来验收：让 placeOrder 在服务端完成、客户端超时，然后刷新页面。页面必须能识别已有订单，而不是再次提交。这个场景通过了，才说明问题真的解决。</p>]]></description>
      <pubDate>Mon, 30 Jun 2025 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账提示 The shipping address is missing，地址明明填了怎么办？]]></title>
      <link>https://www.360magento.com/blog/checkout-shipping-address-missing-fix/</link>
      <description><![CDATA[<p>这个报错最容易把人带偏，因为结账页上姓名、街道、邮编全都有，看起来不可能“缺地址”。我第一次处理时一直盯着表单校验，后来才发现：页面展示的是浏览器里保存的地址对象，提交订单时后端检查的却是当前 Quote 里的 shipping address。两边并不是同一份状态。</p><p>所以我现在遇到这句话，第一件事不是让用户重填，而是确认<strong>最后一次 place order 使用的 cart_id，是否就是保存地址时的 cart_id</strong>。PWA、移动端和做过 checkout 定制的站点，登录、合并购物车或刷新 token 后很容易换了 cart，页面却还留着旧地址。</p><h2>先看请求顺序，不要先猜字段</h2><p>在浏览器 Network 里按 cart_id 过滤，把一次完整结账串起来。实体商品通常应该看到这样的顺序：</p><ol><li><code>setShippingAddressesOnCart</code> 成功，并返回 <code>shipping_addresses</code>；</li><li>重新读取可用配送方式；</li><li><code>setShippingMethodsOnCart</code> 成功；</li><li>设置账单地址、支付方式；</li><li><code>placeOrder</code> 使用同一个 cart_id。</li></ol><p>如果地址请求在前端显示“成功”，但响应的 <code>shipping_addresses</code> 是空数组，就不要继续看支付模块。先保存该请求的 variables 和响应，再到后端日志里用时间与请求 ID 对齐。常见情况是前端吞掉了 GraphQL 的 <code>errors</code>，只判断 HTTP 200。</p><h2>数据库只用来确认事实，不要直接补地址</h2><p>拿到 Quote 的内部 ID 后，可以只读检查地址是否真正落库：</p><pre><code>SELECT entity_id, is_active, customer_id, store_id, items_count
FROM quote
WHERE entity_id = :quote_id;
SELECT address_id, address_type, country_id, region_id, region,       postcode, city, shipping_method, collect_shipping_rates
FROM quote_address
WHERE quote_id = :quote_id;</code></pre><p>实体商品应该至少有一条 <code>address_type = 'shipping'</code> 的记录。记录存在也不等于可用，还要看国家、region、邮编和配送方式。某些国家要求 region，前端传了文字 region 却没传正确的 <code>region_id</code>，地址能显示，后续校验仍可能失败。</p><p>不要为了赶紧恢复下单，直接往 <code>quote_address</code> 插数据。地址保存不仅是几列字段，还会触发运费收集、税费和扩展属性处理；手工补行往往把“缺地址”变成更难追的金额错误。</p><h2>我会特别检查这四个分支</h2><ul><li><strong>登录后 cart 发生合并：</strong>游客 cart_id 已失效，页面组件仍把地址写给旧 cart；</li><li><strong>自定义地址组件只改了 UI 状态：</strong>Knockout/React store 更新了，但没有真正调用保存地址的 mutation；</li><li><strong>配送方式重算清掉了地址或 method：</strong>切换国家、优惠码或门店自提后，异步响应乱序覆盖了新状态；</li><li><strong>购物车全是虚拟商品：</strong>本来就不需要 shipping address，此时若自定义 place-order 校验仍强制要求它，判断位置写错了。</li></ul><h2>修复后怎样证明不是“碰巧好了”</h2><p>我会开慢速网络复测一次，再分别测试游客、登录客户、登录时合并购物车，以及返回上一步修改国家。每次都记录 cart_id，并确认保存地址的响应先回来，配送方式才允许选择。订单创建后，再核对订单 shipping address 与用户最后一次提交一致。</p><p>如果加一条“为空就再调一次保存地址”的重试便不报错，这通常只是掩盖竞态。真正的修复是让结账状态只认当前 cart，并让地址、运费、支付按可观察的顺序推进。</p>]]></description>
      <pubDate>Fri, 27 Jun 2025 02:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Newsletter 订阅状态一直不更新]]></title>
      <link>https://www.360magento.com/blog/newsletter-subscriber-status-stuck/</link>
      <description><![CDATA[<p>用户提交邮箱后收到了“订阅成功”，后台却一直显示 Not Activated；还有一种情况是，第三方邮件平台已经把联系人标成已订阅，Magento 仍然是 Unsubscribed。两个现象看起来一样，本质可能完全相反：一个卡在 Magento 的确认流程，另一个卡在系统之间的同步。</p>

<h2>把订阅当成状态机，而不是一个数字</h2>
<table><thead><tr><th>动作</th><th>可能状态</th><th>下一步</th></tr></thead><tbody>
<tr><td>访客首次提交</td><td>Not Active / Unconfirmed</td><td>等待确认邮件</td></tr>
<tr><td>点击有效确认链接</td><td>Subscribed</td><td>允许进入营销列表</td></tr>
<tr><td>主动取消</td><td>Unsubscribed</td><td>停止营销发送</td></tr>
<tr><td>重新订阅</td><td>取决于双重确认策略</td><td>可能再次确认</td></tr>
</tbody></table>
<p>站点是否开启 double opt-in 会改变正常路径。开启确认时，提交表单后没有立即变成 Subscribed 并不是故障。</p>

<h2>从一条测试邮箱追完整链路</h2>
<p>使用专门测试邮箱，记录提交时的 Store View、是否登录、subscriber ID 和时间。数据库只做查询：</p>
<pre><code>SELECT subscriber_id, subscriber_email, subscriber_status,
       store_id, customer_id, change_status_at
FROM newsletter_subscriber
WHERE subscriber_email = :email;</code></pre>
<p>然后确认邮件是否由正确 Store 模板发送，链接域名是否属于同一网站，点击后是否仍携带有效的订阅者标识和确认码。多网站环境里，Base URL、Cookie 域和路由重写错误都可能让链接回到首页，却没有真正执行确认。</p>

<h2>邮件发出不代表确认链接可用</h2>
<p>我见过模板把确认 URL 当普通文本过滤掉参数，也见过 CDN/WAF 缓存确认页或拦截查询字符串。查看服务器访问日志时只记录请求路径、状态码和请求 ID，不要把完整确认码写入日志或工单。</p>
<p>如果点击后状态没有变化，检查请求是否进入 Newsletter confirm controller、订阅者是否属于当前 Store，以及自定义插件有没有在保存后把状态改回。一次请求内先订阅再取消的情况，最终页面仍可能显示“成功”。</p>

<h2>第三方邮件平台谁是事实源</h2>
<p>集成 Mailchimp、Klaviyo 或自建 CRM 后，要明确 Magento 与外部平台谁负责同意状态。双向同步若没有事件版本或时间戳，很容易发生：</p>
<ul>
  <li>Magento 刚确认订阅，旧的外部取消事件又把它覆盖；</li>
  <li>Webhook 重试多次，重复发送确认邮件；</li>
  <li>一个 Store 取消订阅，错误地影响另一个品牌列表；</li>
  <li>批量导入联系人时绕过了同意来源和确认记录。</li>
</ul>
<p>同步消息至少要有幂等键、事件时间、列表/Store 映射和来源。遇到冲突时，通常应优先尊重更严格的取消状态，而不是为了列表数量把用户重新订阅。</p>

<h2>为什么不建议直接 UPDATE subscriber_status</h2>
<p>直接改状态会跳过确认、事件、邮件和第三方同步，也无法证明用户何时、通过什么入口同意。技术上数字变成了 Subscribed，合规和业务链路却仍是断的。修复应让正常服务完成状态迁移；历史数据需要补偿时，也要留下来源、批次和回滚记录。</p>

<h2>最后用四条路径验收</h2>
<p>分别测试访客首次订阅、登录客户订阅、取消后重新订阅、外部平台回调。每条路径都核对页面提示、Magento 状态、邮件、第三方列表和重复回调结果。再用两个 Store View 各跑一次，确认语言、域名和列表不会串站。只有这些状态转换都能解释，才算真正解决了“状态不更新”。</p>]]></description>
      <pubDate>Thu, 26 Jun 2025 07:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户导入提示重复邮箱但属于不同网站]]></title>
      <link>https://www.360magento.com/blog/customer-import-duplicate-email-website/</link>
      <description><![CDATA[<p>CSV 里有两个相同邮箱，一个属于中国站，一个属于欧洲站。业务认为它们是两个独立账号，但导入到一半出现“重复邮箱”。这不是简单的数据清洗问题，因为 Magento 是否允许相同邮箱跨网站存在，由客户账号共享范围决定。</p>

<h2>先确定你们的账号模型</h2>
<pre><code>php bin/magento config:show customer/account_share/scope

SELECT website_id, email, COUNT(*) AS cnt
FROM customer_entity
GROUP BY website_id, email
HAVING COUNT(*) &gt; 1;</code></pre>
<p>共享范围为 Global 时，一个邮箱在整个 Magento 实例只能对应一个客户；范围为 Per Website 时，相同邮箱可以分别存在于不同 Website。这里的边界是 Website，不是 Store View。</p>
<p>不要为了让导入通过就临时切换范围。已有客户、登录行为、地址、订单归属和第三方 SSO 都可能依赖当前模型。范围变更应当作为独立迁移项目评估。</p>

<h2>“两个网站”可能只是两列写法不一致</h2>
<p>客户导入文件需要把记录映射到真实 Website。不同 Magento 版本或导入模式使用的列名可能不同，后台示例文件是最可靠的起点。常见错误包括：</p>
<ul>
  <li>填写了 Store View code，却以为是 Website code；</li>
  <li>一个 code 带了不可见空格或大小写不一致；</li>
  <li>目标环境的 Website code 与测试环境不同；</li>
  <li>更新模式下没有提供客户现有 website，系统尝试在默认网站创建；</li>
  <li>CSV 中同一邮箱在同一 Website 本来就重复，只是行距很远。</li>
</ul>

<h2>导入前做一次规范化预检</h2>
<p>我会把邮箱转为统一大小写、去掉首尾空格，再按“规范化邮箱 + 目标 website code”统计重复。与此同时，从目标环境导出现有客户的 <code>entity_id</code>、email 和 website_id 做冲突比对。这样能把三种情况分开：</p>
<ol>
  <li>CSV 自己重复；</li>
  <li>CSV 与现有客户冲突；</li>
  <li>网站映射失败后全部落到了默认 Website。</li>
</ol>
<p>预检文件里不要散布真实客户邮箱。可以在受控环境处理，并在报告中使用哈希或遮罩。</p>

<h2>看到重复记录时，别直接合并 customer_entity</h2>
<p>两个客户可能各自拥有订单、地址、订阅、积分和外部系统 ID。即使邮箱相同，也不能仅凭这一字段判断是同一个人。先让业务确认账号共享策略和客户身份，再决定保留、迁移还是合并。</p>
<p>数据库唯一约束报错只说明当前键不允许插入，并不告诉你哪种业务处理正确。删除唯一索引会让脏数据进入系统，之后登录查询可能返回不确定的客户。</p>

<h2>一个安全的重跑方法</h2>
<p>先用 5 条小样本覆盖：新邮箱、目标网站已有邮箱、另一个网站同邮箱、未知 website code、带空格邮箱。选择与正式任务相同的 Add/Update 行为，核对导入报告后再扩大批次。正式重跑必须保证可幂等：已经成功的客户应被识别为更新或跳过，不能再创建一份。</p>
<p>最终不仅要看“导入成功多少条”，还要在两个 Website 分别测试登录、忘记密码、客户地址和历史订单可见性。账号范围问题最容易在导入时被绕过去，然后在客户登录时爆出来。</p>]]></description>
      <pubDate>Wed, 25 Jun 2025 02:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多节点静态资源签名不一致]]></title>
      <link>https://www.360magento.com/blog/static-signature-mismatch/</link>
      <description><![CDATA[<p>同一个页面刷新两次，第一次加载 <code>/static/version1720000000/</code>，第二次却变成另一个版本；或者 HTML 引用了新签名，CDN 回源却落到还没有新文件的节点。结果就是一部分用户正常，一部分用户 CSS/JS 404。</p>
<p>这种问题不能靠“每台机器都跑一遍 static-content:deploy”解决。恰恰相反，各节点独立生成产物和版本号，往往就是不一致的来源。</p>

<h2>用响应把请求落点标出来</h2>
<p>先让负载均衡或 Web Server 临时返回不含敏感信息的节点标识，例如 <code>X-App-Node</code> 和发布版本 <code>X-Release</code>。连续请求页面，记录：</p>
<ul>
  <li>HTML 来自哪个节点；</li>
  <li>HTML 中的 static version；</li>
  <li>失败静态文件回源到哪个节点；</li>
  <li>CDN 是 HIT、MISS 还是回源错误。</li>
</ul>
<p>如果 HTML 节点和静态文件节点属于不同 release，问题已经很清楚：发布过程没有做到版本一致性。</p>

<h2>比较的不只是 deployed_version.txt</h2>
<pre><code>cat pub/static/deployed_version.txt
sha256sum pub/static/frontend/Vendor/theme/zh_Hans/js/*.js | sort
sha256sum app/etc/config.php composer.lock
readlink -f pub/static
readlink -f current</code></pre>
<p>每台节点上的 <code>deployed_version.txt</code>、主题关键文件哈希、代码 release 和 <code>pub/static</code> 实际指向都应一致。若使用共享存储，还要确认所有节点看到的是同一挂载点，而不是路径同名的本地目录。</p>

<h2>三种发布方式，只有一种适合你的架构</h2>
<h3>构建一次，分发同一产物</h3>
<p>在 CI 构建 Magento 代码和静态内容，生成一个不可变 artifact，再分发到所有节点。版本文件与静态资源天然一致，这是最容易审计的方式。</p>
<h3>共享 pub/static</h3>
<p>所有节点读取同一份静态目录，但写入必须由单一构建流程完成。滚动发布时要避免旧代码读取到只适用于新代码的静态产物。</p>
<h3>各节点本地静态目录</h3>
<p>可以使用，但节点必须从同一个构建产物解压，不能各自运行生成命令。还要确保流量只在解压完成后切入。</p>

<h2>原子切换比清缓存重要</h2>
<p>可靠做法是把新版本部署到独立 release 目录，完成代码、依赖和静态资源校验后，再一次性切换 <code>current</code> 软链接或负载均衡目标。不要在正在服务的 <code>pub/static</code> 上边删边生成。</p>
<p>CDN 清理也应在源站全部可用之后执行。过早 purge 会让全球节点同时回源，恰好击中尚未完成部署的应用节点；过晚则继续提供旧 HTML 或旧静态内容。具体顺序取决于 CDN 缓存的是 HTML 还是只有静态文件。</p>

<h2>验证时故意绕过“幸运命中”</h2>
<p>对每个应用节点分别请求同一个 HTML 和两个关键 JS/CSS，再通过真实域名请求一遍 CDN。连续至少覆盖一个负载均衡轮次，并检查 404、MIME type、缓存头和文件哈希。只在浏览器里刷新一次，很可能只是幸运地落到了已经完成发布的节点。</p>]]></description>
      <pubDate>Tue, 24 Jun 2025 06:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis 报 MISCONF Redis is configured to save RDB snapshots]]></title>
      <link>https://www.360magento.com/blog/redis-misconf-stop-writes/</link>
      <description><![CDATA[<p>凌晨发布后，Magento 前台突然出现 500，日志里是：</p>
<pre><code>MISCONF Redis is configured to save RDB snapshots,
but it is currently not able to persist on disk</code></pre>
<p>网上最常见的“修复”是一条 <code>CONFIG SET stop-writes-on-bgsave-error no</code>。它确实可能让网站马上恢复写入，但这相当于把烟雾报警器拆掉，并没有处理 RDB 为什么失败。</p>

<h2>先判断受影响的是缓存，还是会话</h2>
<p>Magento 经常把 default cache、page cache 和 session 放在不同 Redis DB，甚至不同实例。缓存暂时不可写会造成性能下降和页面错误；Session 不可写则可能导致登录、购物车和后台会话丢失。先从 <code>app/etc/env.php</code> 确认实际连接，不要看到 Redis 就执行 <code>FLUSHALL</code>。</p>
<p>记录主机、端口、DB、key 前缀和用途即可，不要在工单里暴露密码。</p>

<h2>十分钟内应该收集的证据</h2>
<pre><code>redis-cli INFO persistence
redis-cli INFO memory
redis-cli CONFIG GET dir
redis-cli CONFIG GET dbfilename
df -h
df -i
free -m
journalctl -u redis --since "30 minutes ago"</code></pre>
<p><code>INFO persistence</code> 里重点看 <code>rdb_last_bgsave_status</code>、<code>rdb_last_bgsave_time_sec</code> 和 <code>rdb_bgsave_in_progress</code>。磁盘空间充足并不代表能写：inode 用尽、目录所有者错误、只读文件系统、容器挂载变化和安全策略都可能让 Redis 无法创建临时 RDB 文件。</p>

<h2>磁盘没满时，为什么 BGSAVE 仍会失败</h2>
<p>Redis 通过 fork 创建后台保存进程。数据集很大、内存紧张或 overcommit 策略不合适时，fork 本身可能失败。日志通常会出现 <code>Cannot allocate memory</code>。这时清几百 MB 日志不一定有用，需要评估实例内存、峰值写入、容器限制和持久化策略。</p>
<p>另一个常见现场是运维迁移了 <code>dir</code>，新目录存在但 Redis 用户无权写入。用服务实际运行用户验证目录权限，不能用 root 手工创建一个文件就宣布正常。</p>

<h2>恢复顺序</h2>
<ol>
  <li>控制应用写入压力，确认是否需要临时切维护模式；</li>
  <li>修复磁盘、inode、权限、只读挂载或内存问题；</li>
  <li>手工触发一次 <code>BGSAVE</code> 或等待计划保存，并确认状态成功；</li>
  <li>验证 Magento Cache、Session、购物车和后台登录；</li>
  <li>观察下一轮自动持久化，而不是看到第一条 PONG 就结束。</li>
</ol>

<h2>什么时候可以临时关闭 stop-writes</h2>
<p>只有当 Redis 的业务角色、数据可重建性、主从/备份和数据丢失窗口都经过明确评估，并且团队接受风险时，才可能把它作为短时应急措施。对 Session、队列或其他不可轻易重建的数据，贸然继续写尤其危险。即使临时关闭，也必须有恢复原配置的时间点和负责人。</p>
<p>本次故障关闭前，我会检查一次新的 RDB 文件时间与大小、Redis 日志无新错误、Magento 错误率恢复、Session 不再丢失，并确认磁盘告警阈值已经调整。MISCONF 不是 Magento 缓存故障的同义词，它首先是持久化失败。</p>]]></description>
      <pubDate>Mon, 23 Jun 2025 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 支付方式因币种不支持而消失]]></title>
      <link>https://www.360magento.com/blog/payment-currency-not-supported/</link>
      <description><![CDATA[<p>切换到 USD 时支付方式正常，换成 EUR 后整个选项消失，而且页面没有报错。这通常不是 Checkout 前端坏了，而是支付方式的 <code>isAvailable()</code> 在后端返回了 false。Magento 会把不可用的方法从接口结果中移除，所以浏览器只能看到“什么都没有”。</p>

<h2>先确认系统正在判断哪一种币种</h2>
<p>一张 Quote 至少涉及基础币种和展示/交易币种，支付模块还可能单独定义清算币种。记录问题 Quote 的以下字段：</p>
<pre><code>SELECT entity_id, store_id, base_currency_code,
       quote_currency_code, global_currency_code,
       base_grand_total, grand_total
FROM quote
WHERE entity_id = :quote_id;</code></pre>
<p>不要只看页面右上角显示的货币。某些网关按 <code>quote_currency_code</code> 判断，另一些旧模块误用了 base currency；也有模块允许前台显示多币种，但下单前强制转换成指定结算币种。</p>

<h2>支付方式可用性是一串条件，不只有币种</h2>
<p>当币种改变时，订单金额也会改变，进而触发最低/最高金额限制。Store View 变化还可能连带改变账单国家、客户组或配置作用域。为了不把相关条件误判成币种问题，我会做一个小矩阵：</p>
<table><thead><tr><th>测试</th><th>币种</th><th>国家</th><th>金额</th><th>结果</th></tr></thead><tbody>
<tr><td>A</td><td>USD</td><td>CN</td><td>固定商品</td><td>记录</td></tr>
<tr><td>B</td><td>EUR</td><td>CN</td><td>同一商品</td><td>记录</td></tr>
<tr><td>C</td><td>EUR</td><td>DE</td><td>同一商品</td><td>记录</td></tr>
<tr><td>D</td><td>EUR</td><td>DE</td><td>调整到限制内</td><td>记录</td></tr>
</tbody></table>
<p>只有币种变化会稳定改变结果，才继续追 supported currencies。</p>

<h2>配置页面显示“全部币种”也不一定是真的</h2>
<p>第三方网关常把支持列表写在代码、远端 Merchant 配置或 API 响应里，而不是 Magento 后台。还要检查 Default、Website 和 Store View 是否有覆盖值：</p>
<pre><code>php bin/magento config:show payment/your_method/active --scope=stores --scope-code=de_de
php bin/magento config:show payment/your_method/min_order_total --scope=stores --scope-code=de_de
php bin/magento config:show payment/your_method/max_order_total --scope=stores --scope-code=de_de
grep -RniE "canUseForCurrency|isAvailable|supported.*currenc" app/code vendor/YourVendor</code></pre>
<p>如果模块实现了 <code>canUseForCurrency()</code>，直接看它比较的是哪一个币种，以及配置空值代表“全部”还是“一个都不支持”。这类细节比清缓存更有价值。</p>

<h2>用接口响应区分后端过滤与前端显示</h2>
<p>检查获取支付方式的 REST/GraphQL 请求。响应里本来就没有该方法，问题在后端可用性判断；响应有方法但 UI 不显示，才去看 Knockout 组件、错误的 region、前端条件和 customer-data 缓存。这个分界可以省掉大量无效的浏览器调试。</p>

<p>修复后至少用两种浏览器会话、访客和登录客户各测一次，并完成到网关创建支付单的步骤。支付方式“重新出现”不等于修复完成；如果网关最终拒绝该币种，只是把错误从结账页推迟到了付款页。</p>]]></description>
      <pubDate>Fri, 20 Jun 2025 07:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发货时报 Source Deduction 失败]]></title>
      <link>https://www.360magento.com/blog/source-deduction-failed/</link>
      <description><![CDATA[<p>一张订单已经付款，创建 Shipment 时却报 Source Deduction 失败。很多人第一反应是直接改库存数量，让发货先通过。这样做可能暂时消掉错误，却把 MSI 的两本账弄得更乱。</p>
<p>先记住这个关系：下单主要影响 <strong>Reservation</strong>，它改变可售数量；发货主要影响 <strong>Source Item</strong>，它从实际来源扣减。订单取消、退款或补偿又会追加相反方向的 Reservation。报错发生在发货阶段，并不代表下单时那笔 Reservation 没有成功。</p>

<h2>用一张订单还原库存轨迹</h2>
<table><thead><tr><th>时点</th><th>Reservation</th><th>Source quantity</th></tr></thead><tbody>
<tr><td>下单</td><td>写入负数，降低 salable qty</td><td>通常不变</td></tr>
<tr><td>发货</td><td>写入补偿记录</td><td>从选中的 Source 扣减</td></tr>
<tr><td>取消未发货订单</td><td>写入补偿记录</td><td>不应扣减</td></tr>
</tbody></table>
<p>因此要同时查订单 SKU 的 Reservation 链和 Shipment 选择的 Source。只看后台商品总库存，会把两个层次混在一起。</p>

<h2>Source 为什么会扣不下去</h2>
<p>我会按下面几类证据判断，而不是反复点“发货”：</p>
<ul>
  <li><strong>来源不匹配：</strong>订单属于某个 Stock，但 Shipment 选择了不在该 Stock 销售渠道中的 Source；</li>
  <li><strong>数量已经变化：</strong>下单后仓库同步把 Source quantity 降低，发货时不再允许扣减；</li>
  <li><strong>重复处理：</strong>ERP 已创建 Shipment 或发送过扣减消息，重试又走了一遍；</li>
  <li><strong>SKU 映射错误：</strong>外部系统传的是旧 SKU、父 SKU，或大小写/空格不同；</li>
  <li><strong>自定义插件破坏扩展属性：</strong>Shipment source code 没被正确带到扣减请求。</li>
</ul>

<h2>先做只读检查</h2>
<pre><code>SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku = :sku
ORDER BY reservation_id;

SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku = :sku;

php bin/magento inventory:reservation:list-inconsistencies</code></pre>
<p><code>metadata</code> 能帮助确认 Reservation 来自哪张订单和哪类事件。不要把查到的负数当作错误；下单 Reservation 本来就是负的。真正要看的是同一订单的事件是否完整、总和是否符合它当前的业务状态。</p>

<h2>三种修法，不能混用</h2>
<h3>仓库实际有货，只是 Source 选错</h3>
<p>回到 Source Selection，选择实际履约的来源，再创建 Shipment。若由 ERP 指定来源，修复映射和幂等键，避免下一单继续选错。</p>
<h3>库存同步晚到，实际已经无货</h3>
<p>不要伪造 quantity。应拆单、换来源、等待补货或取消未能履约的数量，并让取消流程产生正确的补偿 Reservation。</p>
<h3>历史 Reservation 不一致</h3>
<p>先使用 Magento 提供的不一致检查和补偿命令在测试环境验证输出，明确会影响哪些订单，再按受控变更执行。直接删除 <code>inventory_reservation</code> 行会破坏审计链，后续很难判断某个补偿到底对应哪次业务事件。</p>

<p>最终验收不能只看 Shipment 创建成功。我会同时核对 Source quantity、目标 Stock 的 salable quantity、Reservation 总和、订单已发数量和 ERP 状态，并再做一次相同回调重放，确认幂等逻辑不会二次扣减。</p>]]></description>
      <pubDate>Thu, 19 Jun 2025 02:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 收藏夹商品无法加入购物车]]></title>
      <link>https://www.360magento.com/blog/wishlist-add-cart-failed/</link>
      <description><![CDATA[<p>收藏夹是“保存购买意图”，不是把商品完整复制一份。用户几个月前收藏的商品，后来可能换了可配置选项、删除了自定义选项、移动到别的网站，或者简单商品已经下架。于是商品详情页还能打开，点击“加入购物车”却只得到一句笼统的错误。</p>

<h2>先看失败的是一件，还是整个收藏夹</h2>
<p>单个商品失败，优先比较这条 wishlist item 保存的购买参数；所有商品都失败，才去查 Quote、Session、表单校验或自定义插件。可以从后台复现同一客户，也可以在脱敏副本中读取 wishlist item 的 <code>buy_request</code>，但不要随意修改生产数据。</p>

<h2>旧购买参数与现在的商品定义对不上</h2>
<p>可配置商品依赖 <code>super_attribute</code>；Bundle、Grouped 和带必选 Custom Option 的商品还有各自参数。最常见的真实变化是：</p>
<ul>
  <li>管理员删除了原来的颜色或尺寸选项；</li>
  <li>子商品仍存在，但已禁用、不可见或不属于当前 Website；</li>
  <li>某个原本非必填的 Custom Option 被改成必填；</li>
  <li>商品类型或选项 ID 在导入后重建，旧 ID 失去意义。</li>
</ul>
<p>这时不应该偷偷替客户选择另一个尺寸。更合理的体验是把用户带回商品页，保留仍有效的选择，并明确提示需要重新选择已经失效的选项。</p>

<h2>商品“有货”不等于当前请求可加入购物车</h2>
<p>在 MSI 环境中，要以当前 Website 对应 Stock 的 salable quantity 为准。检查父商品状态没有意义，还要确认具体子 SKU 在目标 Stock 是否可售。与此同时，最小购买数量、增量数量、客户组限制和缺货预售配置也会影响 Quote 校验。</p>
<pre><code>php bin/magento inventory:reservation:list-inconsistencies
php bin/magento indexer:status inventory

SELECT product_id, website_id
FROM catalog_product_website
WHERE product_id IN (:parent_id, :child_id);</code></pre>
<p>上面的 SQL 只用于确认网站归属。库存问题应通过 Inventory API 或 CLI 判断，不要自己把 source_item 的 quantity 当成可售数量。</p>

<h2>一个实用的判断顺序</h2>
<ol>
  <li>用目标 Store View 打开商品页，看它是否真的允许购买；</li>
  <li>确认失败的是父商品选择还是具体子商品；</li>
  <li>对比 wishlist 的 buy request 与商品当前必选参数；</li>
  <li>再检查 Website、客户组、最小数量和 MSI 可售性；</li>
  <li>最后才审查 addProduct 插件和 Quote 校验扩展。</li>
</ol>
<p>如果异常信息被前端统一改成“无法加入购物车”，临时记录异常类和商品 ID，不要只记录翻译后的消息。<code>LocalizedException</code>、无效选项和库存异常的处理方向完全不同。</p>

<h2>修复后的体验比“按钮不报错”更重要</h2>
<p>测试一条当天新收藏的商品、一条选项已删除的旧收藏、一条子商品缺货的收藏，以及跨 Website 登录的收藏。有效商品应直接进入购物车；失效选项应要求重选；不可售商品要给出准确原因。不要为了让批量“全部加入购物车”返回成功而吞掉失败项，否则客户会以为所有商品都已加入，结账时才发现数量不对。</p>]]></description>
      <pubDate>Wed, 18 Jun 2025 06:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 异步邮件仍发送旧模板内容]]></title>
      <link>https://www.360magento.com/blog/email-queue-old-template/</link>
      <description><![CDATA[<p>“模板明明改了，客户收到的还是旧版”听起来像缓存问题，但直接清全站缓存往往只是碰运气。异步邮件多了一段时间差：下单发生在 T1，邮件真正渲染和发送可能在 T2。要解决它，必须先确认系统在 T1 保存了什么、在 T2 又读取了什么。</p>

<h2>先做一个不会误导你的测试</h2>
<p>选一个只在新模板中出现的短语，例如“售后编号”，不要用颜色或页脚年份这种可能被邮件客户端缓存的元素。然后完成三次发送：</p>
<ol>
  <li>直接从后台发送模板预览；</li>
  <li>创建一张新订单并立即处理队列；</li>
  <li>处理一张修改模板之前就已进入队列的旧订单。</li>
</ol>
<p>如果预览都是新的，但新订单邮件仍旧，问题在 Store 配置或发送进程；如果只有旧队列任务使用旧内容，要检查队列是否保存了已经渲染好的正文。不要把三种结果混在一起。</p>

<h2>Magento 内置销售邮件与自定义队列的行为可能不同</h2>
<p>Magento 的销售邮件异步发送主要以订单/发票等实体的发送状态驱动，发送时再根据 Store 配置选择模板。很多第三方模块为了重试方便，会提前渲染主题和 HTML，把整封邮件作为队列消息保存。前者改模板后通常影响尚未发送的邮件，后者不会，因为旧 HTML 已经成为历史快照。</p>
<p>所以第一件事是查清实际发送类。搜索自定义模块是否把 <code>TransportInterface</code>、模板正文或序列化后的消息写入表或消息队列：</p>
<pre><code>grep -RniE "setTemplateIdentifier|TransportBuilder|message_queue|email_body" app/code vendor/YourVendor
php bin/magento config:show sales_email/general/async_sending
php bin/magento config:show sales_email/order/template
php bin/magento config:show sales_email/order/guest_template</code></pre>

<h2>最容易看漏的是配置作用域</h2>
<p>后台编辑的是一个模板，实际发送配置可能仍指向另一个模板 ID；登录客户与访客订单还可能使用不同配置。更常见的是：你在 Default Config 改了值，但目标 Website 或 Store View 早就保存了覆盖值。</p>
<p>检查时带上作用域参数，并从问题订单读取真实 <code>store_id</code>。不要以当前后台右上角选中的 Store 代替订单所属 Store。</p>
<pre><code>php bin/magento config:show sales_email/order/template --scope=stores --scope-code=cn_zh
php bin/magento config:show sales_email/order/guest_template --scope=stores --scope-code=cn_zh</code></pre>

<h2>为什么重启消费者有时真的有效</h2>
<p>如果发送由常驻 PHP 进程完成，发布新代码、修改依赖注入或更换模板解析逻辑后，旧进程可能一直使用启动时加载的类和配置对象。此时 Web 请求已经是新版本，消费者仍在旧版本。先确认进程由 Supervisor、systemd 还是容器编排管理，再做有序重启；不要在高峰期直接杀掉所有 worker，让处理中消息处于未知状态。</p>
<p>纯数据库模板文本通常不要求重启 PHP，但模板选择逻辑、插件和自定义变量提供器变更需要。这个区别能避免每次改文案都把队列服务重启一遍。</p>

<h2>把一次发送追到具体模板</h2>
<p>临时增加脱敏日志，记录订单号、Store ID、客户是否访客、最终模板标识、区域和队列消息 ID。不要记录收件人完整邮箱、邮件正文或重置链接。拿到“最终模板标识”后，问题就从模糊的旧缓存，缩小成了明确的配置选择或内容快照。</p>
<p>修复完成后，我会故意保留一条修改前任务，再创建一条修改后任务，分别观察系统是否符合设计。如果产品要求“所有未发送邮件立刻采用新模板”，而当前队列保存的是 HTML 快照，那就不是清缓存能解决的，需要调整队列的数据模型或提供受控的重建任务。</p>]]></description>
      <pubDate>Tue, 17 Jun 2025 01:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发票编号使用了错误店铺序列]]></title>
      <link>https://www.360magento.com/blog/invoice-sequence-wrong-store/</link>
      <description><![CDATA[<p>一次批量开票后，财务发现中国站的发票号里混进了欧洲站前缀。订单归属没有错，税率也没有错，只有发票 increment ID 选错了序列。这个现象最危险的地方在于：单独重试一张订单往往正常，只有管理员连续处理不同网站订单时才出现。</p>

<h2>发票号不是从订单号截出来的</h2>
<p>Magento 的订单、发票、发货和退款单各有自己的 sales sequence。创建发票时，系统会根据实体类型和 Store 选择对应 sequence profile，然后生成下一个编号。先查映射，不要先改已经生成的号码：</p>
<pre><code>SELECT meta_id, entity_type, store_id, sequence_table
FROM sales_sequence_meta
WHERE entity_type = 'invoice'
ORDER BY store_id;

SELECT profile_id, meta_id, prefix, suffix, start_value, step
FROM sales_sequence_profile
WHERE is_active = 1
ORDER BY meta_id;</code></pre>
<p>这里要回答两个问题：每个 <code>store_id</code> 是否指向预期的 sequence table；活动 profile 的前缀是否真的属于该店铺。配置本身若已经串了，任何代码都会稳定地产生错误号码；配置正确而问题偶发，才应该继续追运行时上下文。</p>

<h2>问题通常发生在“订单店铺”和“当前店铺”分开的时候</h2>
<p>前台下单时上下文比较单纯，订单属于哪个 Store，创建后续单据时通常仍沿用它。后台批量操作、Cron 或第三方 ERP 回调就不同：代码可能拿到管理员当前 Store、默认 Store，甚至上一个循环遗留的模拟环境。</p>
<p>重点审查自定义开票代码里有没有这些味道：</p>
<ul>
  <li>用 <code>StoreManagerInterface::getStore()</code> 代替 <code>$order-&gt;getStoreId()</code>；</li>
  <li>循环中调用 store emulation，却没有在 <code>finally</code> 中结束；</li>
  <li>把 Invoice Factory 或 Sequence Manager 做成带状态的长生命周期对象；</li>
  <li>ERP 只传订单号，代码随后按当前网站重新加载订单相关对象。</li>
</ul>

<h2>用一条审计日志抓住偶发串号</h2>
<p>不要把整个订单对象写进日志。创建发票之前记录订单实体 ID、订单 increment ID、订单 <code>store_id</code>、当前 Store ID、将要使用的 sequence meta/profile，以及本次任务的批次 ID。出现下一张错号时，就能判断上下文是在什么时候改变的。</p>
<pre><code>$orderStoreId = (int) $order-&gt;getStoreId();
$currentStoreId = (int) $storeManager-&gt;getStore()-&gt;getId();

$logger-&gt;info('invoice_sequence_context', [
    'order_id' =&gt; (int) $order-&gt;getEntityId(),
    'order_increment_id' =&gt; $order-&gt;getIncrementId(),
    'order_store_id' =&gt; $orderStoreId,
    'current_store_id' =&gt; $currentStoreId,
    'batch_id' =&gt; $batchId,
]);</code></pre>
<p>如果两个 Store ID 不同，并不自动代表有错；后台本来就可能处于 Admin Store。关键是后续 sequence 选择是否明确使用订单所属 Store，而不是依赖隐式的全局当前值。</p>

<h2>已经生成的错号不能直接 UPDATE</h2>
<p>发票号可能已经进入邮件、支付平台、ERP、会计凭证和客户下载文件。直接改 <code>sales_invoice.increment_id</code> 只会让各系统记录互相矛盾。先确认当地财税规则和外部系统是否允许作废重开；如果必须修复，要把 Magento、ERP、邮件/文档和审计记录作为一次受控变更处理。</p>
<p>同时检查错误序列的当前值，避免“修好了选择逻辑，却在下次生成时撞号”。不要手动把计数器调回一个看似顺眼的数字，除非已经查清所有已占用编号并准备好唯一性校验。</p>

<h2>我会怎样复测这个问题</h2>
<p>准备两个前缀不同的 Store，各下两张订单。先交替手工开票，再用批量任务按 A1、B1、A2、B2 的顺序处理，最后让消费者或 ERP 回调再跑一轮。每张发票都核对订单 <code>store_id</code>、序列表、前缀和连续性。只有跨 Store 交替执行仍稳定，才说明那个“偶尔串号”的上下文泄漏真正消失了。</p>]]></description>
      <pubDate>Mon, 16 Jun 2025 07:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品集合 getSize 数量不准确]]></title>
      <link>https://www.360magento.com/blog/product-collection-count-incorrect/</link>
      <description><![CDATA[<p>我遇到过一个很迷惑的列表问题：页面实际渲染 18 个商品，工具栏却显示“共 42 条”。更怪的是，直接打印集合的 <code>count()</code> 是 18，而 <code>getSize()</code> 一直是 42。清缓存、重建索引都没有变化。</p>
<p>这类问题先别碰分页器。<code>count()</code> 和 <code>getSize()</code> 本来就不是一回事：前者统计当前已经加载到内存里的对象数量，后者会基于集合的 Select 另外生成一条计数 SQL。只要扩展代码对原查询做过 JOIN、GROUP BY 或 HAVING，两条数字就可能分开。</p>

<h2>先把“列表 SQL”和“计数 SQL”并排打印</h2>
<p>不要只看最终数字。临时在可控环境记录下面两条 SQL，通常一眼就能看出分叉发生在哪里：</p>
<pre><code>$collection = $this->productCollectionFactory->create();
// 应用与页面相同的过滤条件

echo (string) $collection->getSelect();
echo "
--- COUNT SQL ---
";
echo (string) $collection->getSelectCountSql();</code></pre>
<p>如果商品表 JOIN 了库存来源、分类关系或自定义一对多表，一个商品可能展开成多行。页面加载时 Magento 最终仍会按实体生成对象，但计数 SQL 可能在算展开后的行数。典型特征是：</p>
<ul>
  <li>去掉某个 JOIN 后数字恢复；</li>
  <li><code>COUNT(*)</code> 明显大于 <code>COUNT(DISTINCT e.entity_id)</code>；</li>
  <li>同一个商品在原始 SQL 结果中出现多次。</li>
</ul>

<h2>最常见的三个“制造重复行”现场</h2>
<h3>一对多表只用于过滤，却直接 join</h3>
<p>例如一个商品有多个来源库存记录。需求只是“至少一个来源满足条件”，却把完整来源表连接进集合。更合适的写法往往是 <code>EXISTS</code> 子查询，或者先在子查询里聚合为每个 SKU 一行，再 JOIN 回主集合。</p>
<h3>分类关系和自定义属性同时连接</h3>
<p>商品属于多个分类时，<code>catalog_category_product</code> 会天然扩行。若页面不需要分类 position，尽量使用 Magento 已有的分类过滤能力；确实要手写 JOIN 时，必须确认每个实体最终只保留一行。</p>
<h3>GROUP BY 修好了列表，却破坏了 size</h3>
<p>有人发现重复后直接加 <code>GROUP BY e.entity_id</code>。列表看起来正常了，但集合生成计数 SQL 时可能保留或改写这个 GROUP，结果变成多个 count 行。此时不是再套一层 <code>COUNT(*)</code> 就万事大吉，而是要决定“业务上到底在数商品、组合还是分组”。</p>

<h2>别忽略 getSize() 自己的缓存</h2>
<p><code>getSize()</code> 首次执行后会把结果保存在集合实例中。下面这种调用顺序很容易留下旧数字：</p>
<pre><code>$size = $collection->getSize();
$collection->addFieldToFilter('status', 1);
// 此时再次 getSize() 可能仍返回前一次结果</code></pre>
<p>正确做法不是到处调用内部方法清缓存，而是把所有过滤、JOIN 和作用域条件都组装完成后再读取 size。需要尝试不同条件时，重新创建集合比复用一个已计算过 size 的实例更清楚。</p>

<h2>怎样修，取决于你真正要数什么</h2>
<p>如果业务对象就是商品，优先从查询结构上消除一对多扩行；仅在确定语义正确时使用 <code>COUNT(DISTINCT e.entity_id)</code>。如果列表展示的是“商品 × 来源”这样的组合，就不应该强行按商品去重，工具栏也要明确显示组合数量。</p>
<p>我会用三组数据验收：一个没有关联记录的商品、一个只有一条关联记录的商品、一个有三条关联记录的商品。然后同时核对第一页、最后一页、空结果页以及应用筛选后的总数。只测第一页很容易把分页边界的漏项藏起来。</p>
<p>因此，遇到 <code>getSize()</code> 不准时，最有效的起点不是缓存和索引，而是把两条 SQL 放在一起看。它们从哪一段开始不同，根因通常就在那里。</p>]]></description>
      <pubDate>Fri, 13 Jun 2025 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 reCAPTCHA 阻止客户提交订单]]></title>
      <link>https://www.360magento.com/blog/recaptcha-checkout-blocks-order/</link>
      <description><![CDATA[<p>客户填写完结账信息，点击 Place Order 后提示 reCAPTCHA validation failed 或无响应。关闭验证码会降低防护，应先区分前端未生成 Token、Token 已过期、action 不一致和后端验证请求失败。</p>
<h2>固定复现条件</h2>
<p>在测试订单中记录浏览器 Console、提交请求、非敏感错误码、页面域名和 reCAPTCHA action。不要记录 Token、客户地址或密钥。比较默认 Checkout 与第三方一步结账。</p>
<pre><code>php bin/magento module:status | grep -i captcha
php bin/magento config:show recaptcha_frontend/type_for/place_order
grep -R --line-number 'place_order|reCaptcha' app/code app/design 2&gt;/dev/null
grep -RniE 'captcha|recaptcha|validation' var/log | tail -n 100
curl -sS -o /dev/null -w '%{http_code} %{time_total}
' https://www.google.com/recaptcha/api/siteverify</code></pre>
<h2>根据证据定位</h2>
<p>请求没有 Token，查 JS 组件和 CSP；后端返回 hostname/action 不符，查域名与配置；偶发过期说明 Token 生成过早；仅代理后失败，检查源站出网、客户端 IP 与可信代理。第三方结账可能绕过标准 provider。</p>
<h2>修复与回滚</h2>
<p>使用目标 Magento 版本支持的 reCAPTCHA 类型，在真正提交前获取对应 action 的短期 Token，并按扩展提供的集成点挂载。修复 CSP 与出网，不在日志写 Secret；需要应急降级时应限时、受监控并保留其他风控。</p>
<h2>验收</h2>
<p>成功下单、失败后重试、页面停留超时、多个支付方式和移动端都测试；无 Token 与伪造 Token 必须被拒绝，正常客户不能产生重复订单。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 reCAPTCHA 阻止客户提交订单&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 12 Jun 2025 06:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单自定义属性没有出现在 REST API]]></title>
      <link>https://www.360magento.com/blog/order-custom-attribute-api-missing/</link>
      <description><![CDATA[<p>sales_order 表已经新增字段，后台也能显示，但 /V1/orders 接口没有该值。Magento Web API 基于 Service Contract 序列化，不会自动把任意数据库列暴露；需要 Extension Attribute 或正式数据接口。</p>
<h2>固定复现条件</h2>
<p>确认字段存在哪张表、何时保存、单订单接口与列表接口是否都缺失。检查生成的 OrderExtension 接口和 Repository get/getList 加载路径。</p>
<pre><code>grep -R --line-number 'extension_attributes.*OrderInterface|attribute code=' app/code/Vendor/Module/etc 2&gt;/dev/null
grep -R --line-number 'OrderRepositoryInterface' app/code/Vendor/Module 2&gt;/dev/null
mysql -e "SHOW COLUMNS FROM sales_order LIKE 'custom_field'"
php bin/magento setup:di:compile
curl -sS -H 'Authorization: Bearer REDACTED' https://shop.example.com/rest/V1/orders/123</code></pre>
<h2>根据证据定位</h2>
<p>只加数据库列不会进入 API；声明 Extension Attribute 但没有 hydrator/plugin 时值仍为空；get 生效而 getList 为空，通常是批量加载路径未覆盖。保存接口也需要把输入显式写入实体。</p>
<h2>修复与回滚</h2>
<p>在 extension_attributes.xml 声明合适类型，通过 Repository 插件或 extension join 加载，并使用资源模型保存。字段若含敏感数据，应先确认 ACL 与是否真的需要暴露。</p>
<h2>验收</h2>
<p>创建、读取、列表、更新订单均验证字段；无权限 Token 不得看到敏感值，批量接口避免 N+1 查询。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 订单自定义属性没有出现在 REST API&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 11 Jun 2025 01:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL Currency Header 被忽略]]></title>
      <link>https://www.360magento.com/blog/graphql-currency-header-ignored/</link>
      <description><![CDATA[<p>PWA 请求带 Content-Currency: EUR，GraphQL 仍返回 USD，或 currency 字段变了但金额未换算。币种必须在目标 Store 允许范围内并有汇率；代理/CDN 若不按相关 Header 隔离缓存，还会把一种币种响应复用给另一种。</p>
<h2>固定复现条件</h2>
<p>保存 query、Store Header、Content-Currency、响应 currency 与金额，不记录客户 Token。分别绕过 CDN 请求源站，并测试公开价格与登录客户价格。</p>
<pre><code>curl -sS -H 'Content-Type: application/json' -H 'Store: default' -H 'Content-Currency: EUR'  --data '{"query":"{storeConfig{base_currency_code default_display_currency_code} products(search:"SKU"){items{sku price_range{minimum_price{final_price{value currency}}}}}}"}'  https://shop.example.com/graphql
php bin/magento config:show currency/options/allow --scope=stores --scope-code=default
SELECT * FROM directory_currency_rate WHERE currency_from='USD' AND currency_to='EUR';</code></pre>
<h2>根据证据定位</h2>
<p>币种未允许或汇率缺失时 Magento 会回退；Store Header 错误会读取另一站点配置；源站正确而 CDN 错误，检查缓存键是否包含 Store 与 Currency。自定义 Resolver 若直接返回 base price 也会忽略上下文。</p>
<h2>修复与回滚</h2>
<p>在正确 scope 配置允许币种与可信汇率更新，Resolver 使用 Magento 定价服务而非手工字段。公共 GraphQL 缓存必须按 Store、币种及身份正确隔离；客户专属响应不得共享。</p>
<h2>验收</h2>
<p>两个 Store、三种币种、访客和客户组交叉请求，currency 与金额一致；交替请求不能串币种，购物车与订单最终币种也要匹配。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 GraphQL Currency Header 被忽略&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 10 Jun 2025 07:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 队列毒消息反复失败重试]]></title>
      <link>https://www.360magento.com/blog/queue-poison-message-retry-loop/</link>
      <description><![CDATA[<p>Consumer 日志每隔几秒出现完全相同异常，队列深度不降。某条无法成功处理的毒消息如果无限 requeue，会占用 Worker、淹没日志并阻塞后续业务；直接删除又可能丢失订单或库存事件。</p>
<h2>固定复现条件</h2>
<p>记录 topic、脱敏消息 ID、redelivered 标志、首次与最后失败时间及异常指纹。区分暂时依赖故障、业务数据永久无效和代码缺陷。</p>
<pre><code>php bin/magento queue:consumers:list
php bin/magento queue:consumers:start target.consumer --max-messages=5 -vvv
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
rabbitmqctl list_bindings source_name destination_name routing_key
grep -RniE 'consumer|redeliver|reject|requeue' var/log | tail -n 100</code></pre>
<h2>根据证据定位</h2>
<p>网络超时适合有限退避重试；实体不存在或 schema 不兼容通常是永久失败；处理已完成但 ACK 前崩溃要求消费者幂等。所有错误都 requeue=true 会制造无限循环。</p>
<h2>修复与回滚</h2>
<p>为消息建立业务幂等键和明确重试预算，可恢复错误指数退避，永久错误进入死信或人工队列并保留脱敏证据。修复代码后按原消息语义安全重放，不要直接在 RabbitMQ 管理页批量 Purge。</p>
<h2>验收</h2>
<p>构造成功、暂时失败和永久失败消息；成功只产生一次副作用，暂时失败最终恢复，永久失败不再阻塞主队列且可追踪。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 队列毒消息反复失败重试&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 09 Jun 2025 02:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 因磁盘水位变成只读]]></title>
      <link>https://www.360magento.com/blog/opensearch-disk-watermark-read-only/</link>
      <description><![CDATA[<p>商品重建索引报 cluster_block_exception，提示 index read-only / allow delete。OpenSearch 在磁盘达到 flood-stage 时自动保护节点；只解除只读标记而不解决磁盘空间，block 会很快再次出现。</p>
<h2>固定复现条件</h2>
<p>检查每个节点的磁盘、分片分布、集群健康和索引设置，确认实际 Magento 别名指向哪个版本化索引。</p>
<pre><code>df -h
curl -s 'http://127.0.0.1:9200/_cluster/health?pretty'
curl -s 'http://127.0.0.1:9200/_cat/allocation?v'
curl -s 'http://127.0.0.1:9200/_cluster/settings?include_defaults=true&amp;pretty'
curl -s 'http://127.0.0.1:9200/_all/_settings?filter_path=**.blocks.read_only_allow_delete&amp;pretty'
php bin/magento indexer:status catalogsearch_fulltext</code></pre>
<h2>根据证据定位</h2>
<p>单节点磁盘满可能让相关分片全部只读；删除文档不一定立即释放段文件空间。大量旧 Magento 索引、快照失败或日志与数据共享卷都可能占用空间。</p>
<h2>修复与回滚</h2>
<p>先扩容或安全删除确认不再使用的旧索引/日志，使磁盘低于恢复水位，再精确解除受影响索引的 read_only_allow_delete，并重建搜索索引。不要全局关闭磁盘阈值。</p>
<h2>验收</h2>
<p>集群恢复 green/yellow 的预期状态，Magento 全量与增量索引成功；观察下一个高峰和合并周期，磁盘水位与旧索引保留策略稳定。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 OpenSearch 因磁盘水位变成只读&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 06 Jun 2025 06:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 修改管理员角色后仍提示 Access Denied]]></title>
      <link>https://www.360magento.com/blog/admin-role-acl-still-denied/</link>
      <description><![CDATA[<p>管理员角色中已经勾选菜单权限，打开页面仍返回 Access Denied。菜单可见和控制器授权是两次检查，自定义模块的 menu.xml、acl.xml 和控制器 ADMIN_RESOURCE 只要资源 ID 不一致就会失败。</p>
<h2>固定复现条件</h2>
<p>记录管理员、角色、菜单资源 ID、控制器类与失败 URL。使用全权限管理员和受限管理员对照，确认是否仅自定义页面失败。</p>
<pre><code>grep -R --line-number 'ADMIN_RESOURCE|&lt;resource id=' app/code/Vendor/Module 2&gt;/dev/null
grep -R --line-number '&lt;add.*resource=' app/code/Vendor/Module/etc/adminhtml/menu.xml
php bin/magento cache:clean config
SELECT role_id,parent_id,role_type,role_name FROM authorization_role ORDER BY role_id;
SELECT role_id,resource_id,permission FROM authorization_rule ORDER BY role_id,resource_id;</code></pre>
<h2>根据证据定位</h2>
<p>菜单 resource 与控制器 resource 不同会出现看得见却进不去；acl.xml 父节点错误会让勾选项不代表真实资源。只对旧 Session 失败时，重新登录可刷新权限，但这不能修复资源定义错误。</p>
<h2>修复与回滚</h2>
<p>统一 acl.xml、menu.xml 和 ADMIN_RESOURCE，选择合理父资源并升级模块配置。后台角色应按最小权限重新保存；不要绕过 _isAllowed 或把控制器改为全局允许。</p>
<h2>验收</h2>
<p>新建最小权限角色，允许页面可访问、未授权页面继续拒绝；保存、导出、批量操作和 AJAX 子路由也要逐一验证。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 修改管理员角色后仍提示 Access Denied&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 05 Jun 2025 03:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 登录后合并购物车出现重复商品]]></title>
      <link>https://www.360magento.com/blog/cart-merge-duplicate-items/</link>
      <description><![CDATA[<p>访客购物车已有商品，登录后同一 SKU 出现两行或数量翻倍。Magento 是否合并为同一行不只看 SKU，还比较自定义选项、可配置属性和 buy request；自定义登录流程重复调用 merge 也会把数量累加两次。</p>
<h2>固定复现条件</h2>
<p>保存登录前 guest quote、客户 active quote、登录后 quote_id 和每个 item 的 SKU、qty、parent_item_id、product_options。对个人数据脱敏，并区分真正重复与选项不同的合法两行。</p>
<pre><code>SELECT entity_id,customer_id,is_active,items_count,items_qty,updated_at FROM quote WHERE entity_id IN (101,202,303);
SELECT item_id,quote_id,parent_item_id,sku,qty,product_type,product_options
FROM quote_item WHERE quote_id IN (101,202,303) ORDER BY quote_id,item_id;
grep -R --line-number 'merge(|mergeCart|assignCustomer' app/code 2&gt;/dev/null</code></pre>
<h2>根据证据定位</h2>
<p>选项完全相同但数量双倍，查 merge 被调用两次或并发登录；SKU 相同而 super_attribute/custom_options 不同，保留两行可能正确；guest quote 被错误重复激活也会产生多次合并。</p>
<h2>修复与回滚</h2>
<p>使用标准 Quote 合并流程，并以登录事务或请求标识保证幂等。自定义比较逻辑应包含影响购买结果的全部选项；不要在数据库中按 SKU 粗暴删除行，否则会丢失合法配置。</p>
<h2>验收</h2>
<p>测试空客户购物车、双方均有相同商品、不同选项、可配置与 Bundle，并发点击登录。最终数量与业务规则一致，优惠、库存和 totals 只计算一次。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 登录后合并购物车出现重复商品&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 04 Jun 2025 07:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户确认邮件链接跳到错误域名]]></title>
      <link>https://www.360magento.com/blog/customer-confirmation-link-wrong-domain/</link>
      <description><![CDATA[<p>客户在品牌站注册，确认邮件却指向默认站或另一个语言 Store。链接通常按发送时的 Store 上下文生成；异步邮件、错误的 website_id 或自定义模板硬编码域名都会破坏它。</p>
<h2>固定复现条件</h2>
<p>用测试客户记录注册 URL、store_id、website_id、邮件模板 ID 和最终链接主机，不记录真实确认 Token。比较同步与异步发送、默认模板与自定义模板。</p>
<pre><code>SELECT entity_id,email,website_id,store_id,confirmation,created_at FROM customer_entity WHERE email='test@example.com';
SELECT store_id,code,website_id FROM store ORDER BY website_id,store_id;
php bin/magento config:show web/secure/base_url --scope=stores --scope-code=store_code
php bin/magento config:show customer/create_account/email_confirmation_template
grep -R --line-number 'getConfirmationUrl|confirmation_url' app/code app/design 2&gt;/dev/null</code></pre>
<h2>根据证据定位</h2>
<p>客户实体 Store 错误说明注册上下文已丢失；实体正确但链接主机错误，检查 Base URL 与发送模拟；只有异步错误，检查队列消费者是否恢复 Store；模板直接写域名则不会随 Store 变化。</p>
<h2>修复与回滚</h2>
<p>让注册服务保存正确 website/store，邮件发送在目标 Store 环境中生成 URL，并使用安全的模板 URL 变量。不要拼接 confirmation key 或在日志暴露 Token；修复后对旧邮件应提供重新发送流程。</p>
<h2>验收</h2>
<p>在两个 Website、两个语言 Store 分别注册，链接只到对应域名并能一次完成确认；重复点击、过期与重新发送都符合安全策略。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 客户确认邮件链接跳到错误域名&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 03 Jun 2025 01:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发布后提示数据库字段不存在]]></title>
      <link>https://www.360magento.com/blog/db-column-missing-after-deploy/</link>
      <description><![CDATA[<p>发布后日志出现 Unknown column 或 Column not found，说明代码已经开始读取新结构，而数据库升级尚未完成、DDL 被跳过或某节点仍运行不匹配版本。手工 ALTER 可能漏掉索引、约束和白名单。</p>
<h2>固定复现条件</h2>
<p>保存完整 SQL、字段名、模块与构建版本，确认所有 Web、Cron、消费者是否同时报错。比较代码中的 db_schema.xml、数据库真实表结构和 setup:db:status。</p>
<pre><code>php bin/magento setup:db:status
php bin/magento module:status Vendor_Module
grep -R --line-number 'missing_column' app/code/*/*/etc/db_schema.xml vendor/*/*/etc/db_schema.xml 2&gt;/dev/null
mysql -e "SHOW CREATE TABLE target_tableG"
grep -RniE 'DDL|schema|setup' var/log | tail -n 100</code></pre>
<h2>根据证据定位</h2>
<p>代码已切换而 setup:upgrade 未执行是最常见原因；模块被禁用、白名单不一致、DDL 权限不足或锁等待也会跳过结构变更。蓝绿发布若两版代码短时间共享数据库，还要检查变更是否向后兼容。</p>
<h2>修复与回滚</h2>
<p>恢复正确维护窗口和代码版本，备份相关表后运行受支持的 setup:upgrade 并检查输出。结构变化应由声明式 Schema 或补丁管理；不要只为消除异常临时添加一个类型不明的字段。</p>
<h2>验收</h2>
<p>setup:db:status 返回一致，SHOW CREATE TABLE 与声明匹配；新旧业务路径、Cron、消费者和回滚版本均经过兼容性验证。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 发布后提示数据库字段不存在&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 02 Jun 2025 06:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis 缓存报 Unable to unserialize value]]></title>
      <link>https://www.360magento.com/blog/redis-cache-unserialize-error/</link>
      <description><![CDATA[<p>发布或 PHP 升级后页面报 Unable to unserialize value，常见原因是新旧节点使用不同序列化器、多个环境共享 Redis DB/前缀，或缓存值写入中断。它通常发生在 cache，而不是 Session；清错 Redis 库会导致用户全部退出。</p>
<h2>固定复现条件</h2>
<p>记录报错 key 前缀、Redis DB、节点、PHP 版本和发布批次，不输出缓存正文。比较正常与异常节点的 env.php 缓存配置摘要、phpredis/igbinary 扩展和构建版本。</p>
<pre><code>php -v
php -m | grep -Ei 'redis|igbinary|msgpack'
grep -nA30 "'cache'" app/etc/env.php
redis-cli INFO keyspace
redis-cli --scan --pattern 'zc:*' | head
sha256sum composer.lock app/etc/config.php</code></pre>
<h2>根据证据定位</h2>
<p>仅一台节点失败说明运行时或代码不一致；所有节点在同一 key 失败，可能是遗留或损坏值；测试与生产 key 前缀相同则属于环境串用。Session、Cache、FPC 常使用不同 DB，必须先确认连接。</p>
<h2>修复与回滚</h2>
<p>统一 PHP 扩展和序列化配置，为每个环境设置独立前缀或 Redis DB。确认是可再生 cache 后，只清目标缓存池并观察回填；不要执行无范围 FLUSHALL，也不要直接删除未知 Session key。</p>
<h2>验收</h2>
<p>连续命中所有节点，页面、后台、Cron 和消费者均无反序列化异常；缓存重新生成后命中率恢复，客户登录状态不受影响。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 Redis 缓存报 Unable to unserialize value&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近发布。所有 SQL 默认先执行 <code>SELECT</code>；写操作、目录清理、服务重启和配置切换必须确认范围、保留备份并准备回滚。多节点环境还要核对构建版本、<code>app/etc/env.php</code> 配置摘要和实际流量节点。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费、库存或订单的变更，应先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。至少准备一个正常对象和一个异常对象；旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由与协议一致</td>
</tr>
<tr>
<td>应用</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据</td>
<td>主键、时间、关联行数</td>
<td>关系完整无重复副作用</td>
</tr>
<tr>
<td>业务</td>
<td>正常、失败与重试路径</td>
<td>最终状态一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器与目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 30 May 2025 02:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 禁用模块时提示依赖关系错误]]></title>
      <link>https://www.360magento.com/blog/module-disable-dependency-error/</link>
      <description><![CDATA[<p>准备下线扩展时执行 module:disable，Magento 提示其他模块依赖它；更糟的是代码已经从 vendor 删除，CLI 直接因缺类无法启动。禁用、Composer 移除和数据卸载是三个不同阶段，顺序错误会让站点停在不可运行状态。</p>
<h2>先固定复现条件和影响范围</h2>
<p>保存当前 app/etc/config.php、composer.json、composer.lock 与 module:status，列出直接和间接依赖。确认目标是临时禁用、永久移除代码，还是连业务数据一起卸载。</p>
<pre><code>php bin/magento module:status
php bin/magento module:disable Vendor_Module --dry-run
grep -R --line-number 'Vendor_Module' app/code vendor/*/*/etc/module.xml 2&gt;/dev/null
composer why vendor/package
composer depends vendor/package
git diff -- app/etc/config.php composer.json composer.lock</code></pre>
<h2>根据证据分支定位</h2>
<p>Magento 模块 sequence 依赖阻止禁用，需先处理上层模块；Composer 包被其他包 require，必须调整包依赖；代码已删除而 config.php 仍启用，应恢复同版本代码让 CLI 可启动，再按顺序操作。sequence 表示加载顺序，服务接口和 DI 依赖还需代码审计。</p>
<h2>修复时保留回滚路径</h2>
<p>先在维护分支和生产副本验证：停用依赖模块、禁用目标模块、运行 setup:upgrade/compile、完成测试，最后再由 Composer 移除代码。数据表和配置默认保留以便回滚；只有明确审核过 uninstall 行为后才执行数据删除。</p>
<h2>上线验收</h2>
<p>干净执行 composer install、setup:upgrade、di:compile 和静态部署，前后台、Cron、消费者均无缺类错误。重新启用回滚路径也要测试，确认历史订单或配置没有因卸载丢失。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 禁用模块时提示依赖关系错误&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 29 May 2025 06:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 同义词更新后搜索无变化]]></title>
      <link>https://www.360magento.com/blog/opensearch-synonym-not-updated/</link>
      <description><![CDATA[<p>把&ldquo;手机,移动电话&rdquo;加入同义词文件后，前台搜索结果完全不变。OpenSearch 分析器在索引创建时固化部分配置，Magento 又通过版本化索引和别名切换；修改了节点文件并不代表当前商品索引已引用该 filter。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录搜索词、Store、当前商品索引别名、实际索引名和 analyzer 输出。使用 _analyze 比较修改前后 token，不只观察前台结果数量。</p>
<pre><code>curl -s 'http://127.0.0.1:9200/_cat/aliases?v'
curl -s 'http://127.0.0.1:9200/_cat/indices?v'
curl -s -X POST 'http://127.0.0.1:9200/magento2_product_1_v1/_analyze'  -H 'Content-Type: application/json'  -d '{"analyzer":"standard","text":"移动电话"}'
curl -s 'http://127.0.0.1:9200/magento2_product_1_v1/_settings?pretty'
php bin/magento indexer:reindex catalogsearch_fulltext</code></pre>
<h2>根据证据分支定位</h2>
<p>_analyze 没展开同义词，说明 filter 或 analyzer 未引用；分析正确但文档匹配不变，检查同义词用于 index 还是 search 阶段及字段 mapping；重建后新索引正确、别名仍指旧索引，查索引切换失败。集群每个数据节点还必须能读取一致配置。</p>
<h2>修复时保留回滚路径</h2>
<p>通过受版本控制的搜索配置部署同义词，在新索引上验证 analyzer 后执行 Magento 搜索索引重建和别名切换。区分需要重新索引的 index-time synonym 与可 reload 的 search-time 方案；不要直接修改生产索引 mapping 期待自动生效。</p>
<h2>上线验收</h2>
<p>准备应互相召回和不应扩展的词组，检查 token、命中 SKU、排序和多语言 Store。滚动重启或索引版本切换后结果保持一致，旧索引只在回滚窗口后删除。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 OpenSearch 同义词更新后搜索无变化&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 28 May 2025 01:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页不显示条款复选框]]></title>
      <link>https://www.360magento.com/blog/checkout-agreement-missing/</link>
      <description><![CDATA[<p>后台已创建并启用 Terms and Conditions，但结账 Place Order 前没有复选框。条款有 Store View 关联、应用模式和显示位置，前端还依赖 checkout config 与 Knockout 组件；一步结账扩展可能完全替换原组件。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录 agreement ID、是否 Active、Mode、关联 Store View 和结账主题。比较 Luma/默认结账与当前主题，检查页面配置数据和 Console 首条错误。</p>
<pre><code>SELECT agreement_id,name,is_active,is_html,mode,checkbox_text,content_height
FROM checkout_agreement ORDER BY agreement_id;
SELECT agreement_id,store_id FROM checkout_agreement_store ORDER BY agreement_id,store_id;
php bin/magento config:show checkout/options/enable_agreements
grep -R --line-number 'checkout-agreements|agreements' app/design app/code 2&gt;/dev/null
php bin/magento cache:clean config layout block_html full_page</code></pre>
<h2>根据证据分支定位</h2>
<p>agreement 接口或 checkout config 没数据，查 Store 关联与作用域；数据存在但组件没渲染，查布局、模板和 JS 错误；默认主题正常而一步结账失败，按扩展提供的集成点处理。Mode 为自动时本来就可能不要求用户勾选。</p>
<h2>修复时保留回滚路径</h2>
<p>在正确 Store View 启用需要的协议并使用标准 agreements 组件或扩展的兼容实现。不要只在前端加一个没有服务端校验的复选框；需要强制同意时，提交订单接口必须验证对应 agreement ID。</p>
<h2>上线验收</h2>
<p>访客与登录客户、每个支付方式和 Store View 都测试。未勾选时订单提交被明确阻止，勾选后可下单，非目标 Store 不应出现错误协议。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 结账页不显示条款复选框&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 27 May 2025 07:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CDN 字体被 CORS 拒绝]]></title>
      <link>https://www.360magento.com/blog/cdn-font-cors-error/</link>
      <description><![CDATA[<p>CSS 能加载，但图标或自定义字体不显示，控制台提示 font has been blocked by CORS policy。浏览器把字体视为跨源资源，CDN 必须返回与页面 Origin 匹配的允许头；错误 MIME 或缓存了不带 CORS 头的旧响应也会失败。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录页面 Origin、字体最终 URL、重定向链、Content-Type、Access-Control-Allow-Origin、Vary 和 CDN HIT/MISS。直接访问文件成功不代表字体上下文允许使用。</p>
<pre><code>curl -skI -H 'Origin: https://shop.example.com' https://cdn.example.com/static/font.woff2
curl -skIL https://cdn.example.com/static/font.woff2
php bin/magento config:show web/secure/base_static_url
find pub/static -iname '*.woff*' -o -iname '*.ttf' | head
file pub/static/frontend/Vendor/theme/en_US/fonts/font.woff2</code></pre>
<h2>根据证据分支定位</h2>
<p>CDN 无 Allow-Origin 而源站有，修 CDN 响应头策略；两者都无，配置静态资源服务器；返回 text/html 常是 404 或安全页，不是字体；只有首次 MISS 失败而 HIT 持续失败，检查 CDN 是否按 Origin 正确缓存及 Vary。</p>
<h2>修复时保留回滚路径</h2>
<p>对白名单店铺域名返回准确的 Access-Control-Allow-Origin，公共非凭据静态字体也可按安全策略使用通配符。确保 WOFF2 MIME 正确、URL 不重定向到另一未授权域名，并清除精确 CDN 对象；不要给所有动态接口无条件开放 CORS。</p>
<h2>上线验收</h2>
<p>在两个允许 Store 域名和一个不允许域名测试，字体、图标和 Network 请求符合策略。桌面与移动浏览器、生产和静态版本切换后都不再出现 CORS 错误。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 CDN 字体被 CORS 拒绝&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 26 May 2025 02:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cache Tags 响应头过大导致 502]]></title>
      <link>https://www.360magento.com/blog/cache-tags-header-too-large/</link>
      <description><![CDATA[<p>只有商品很多的分类页或复杂 CMS 页面返回 502，源站日志出现 upstream sent too big header，响应中的 X-Magento-Tags 可能包含成千上万个实体标签。单纯增大代理 buffer 会提高内存消耗，却不会解决自定义 Block 标签爆炸。</p>
<h2>先固定复现条件和影响范围</h2>
<p>分别请求源站与 Varnish/CDN，保存状态码、响应头大小、X-Magento-Tags 数量和页面包含的自定义 Block。不要把 Cookie 或认证头写入共享日志。</p>
<pre><code>curl -skD /tmp/headers.txt -o /dev/null https://shop.example.com/category.html
wc -c /tmp/headers.txt
grep -i '^X-Magento-Tags:' /tmp/headers.txt | tr ',' '
' | sort | uniq -c | sort -nr | head
grep -R --line-number 'IdentityInterface|getIdentities' app/code 2&gt;/dev/null
nginx -T 2&gt;/dev/null | grep -nE 'proxy_buffer|fastcgi_buffer|large_client_header'</code></pre>
<h2>根据证据分支定位</h2>
<p>源站已经 502，查 PHP/Web Server 头限制；源站 200、代理 502，查对应上游 buffer；标签主要来自一个自定义前缀，审计其 getIdentities。核心分类标签随商品数增长与自定义 Block 把集合每个实体都加入标签，修复策略不同。</p>
<h2>修复时保留回滚路径</h2>
<p>让自定义 Block 返回足以精确失效的聚合标签，避免无边界地追加集合中所有对象。确认应用层修复后再依据最大合理头部调整代理 buffer，并评估并发内存；不要删除所有标签，否则内容更新后可能长期不失效。</p>
<h2>上线验收</h2>
<p>测试小分类和最大分类，源站、Varnish 与 CDN 都返回 200，Header 大小受控。修改一个相关商品后页面能正确失效，无关商品更新不应清空全部站点缓存。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 Cache Tags 响应头过大导致 502&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 23 May 2025 06:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Catalog Price Rule 午夜后没有生效]]></title>
      <link>https://www.360magento.com/blog/catalog-rule-midnight-not-applied/</link>
      <description><![CDATA[<p>规则设置从今天开始，零点后前台仍是原价，手工 Apply Rules 后才恢复。Catalog Price Rule 的日期按商店时区判断，最终价格依赖规则数据准备、Cron 和价格索引；服务器 UTC 时间与后台显示时间不同会造成误判。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录规则 ID、from_date、to_date、is_active、Website、客户组、Store 时区和一个目标 SKU。比较服务器、PHP、数据库和 Magento 商店时间。</p>
<pre><code>date -u
php -r 'echo date("c"), PHP_EOL;'
mysql -e 'SELECT NOW(),UTC_TIMESTAMP(),@@session.time_zone'
php bin/magento config:show general/locale/timezone
SELECT rule_id,name,from_date,to_date,is_active FROM catalogrule WHERE rule_id=10;
SELECT rule_id,product_id,customer_group_id,from_time,to_time,rule_price
FROM catalogrule_product_price WHERE rule_id=10 LIMIT 20;
php bin/magento indexer:status catalogrule_rule catalogrule_product catalog_product_price</code></pre>
<h2>根据证据分支定位</h2>
<p>规则表未产生目标商品，检查条件、Website 与客户组；已有规则价格但前台不变，查价格索引和缓存；只在日期边界失败，核对时区转换和 Cron 执行窗口。多规则同时命中时还要检查优先级与停止后续规则。</p>
<h2>修复时保留回滚路径</h2>
<p>统一 NTP 和 PHP/数据库基础时间，Magento Store 使用正确业务时区；修复 Cron 后重新应用规则并让相关索引正常消费。不要每天用手工 Apply 代替故障的调度链，也不要直接修改 rule_product_price。</p>
<h2>上线验收</h2>
<p>在测试环境使用临近生效与失效边界的规则，覆盖两个客户组和 Website。规则应自动开始与结束，列表、详情、购物车和订单价格一致，跨午夜无需人工操作。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 Catalog Price Rule 午夜后没有生效&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 22 May 2025 01:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 部分发货数量与订单不一致]]></title>
      <link>https://www.360magento.com/blog/partial-shipment-qty-mismatch/</link>
      <description><![CDATA[<p>订单只发了部分商品，后台却显示全部已发，或剩余数量无法继续创建 Shipment。可配置、Bundle 与 Downloadable 的父子行计数不同，自定义 ERP 回写若同时更新父行和子行，容易重复累计。</p>
<h2>先固定复现条件和影响范围</h2>
<p>锁定订单和 Shipment，导出 sales_order_item 的 parent_item_id、product_type、qty_ordered、qty_shipped、qty_canceled、qty_refunded，再与 sales_shipment_item 对照。</p>
<pre><code>SELECT item_id,parent_item_id,sku,product_type,qty_ordered,qty_shipped,qty_canceled,qty_refunded
FROM sales_order_item WHERE order_id=123 ORDER BY item_id;
SELECT s.entity_id,s.increment_id,si.order_item_id,si.sku,si.qty
FROM sales_shipment s JOIN sales_shipment_item si ON si.parent_id=s.entity_id
WHERE s.order_id=123 ORDER BY s.entity_id,si.entity_id;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku IN ('SKU-A','SKU-B');</code></pre>
<h2>根据证据分支定位</h2>
<p>shipment_item 数量正确而 order_item 累计错误，查自定义保存流程；父子行同时累计，检查商品类型处理；后台正确但 ERP 显示错误，查接口映射。MSI 环境还要区分 Reservation 补偿与实际 Source deduction，不要把两个动作都当物理扣减。</p>
<h2>修复时保留回滚路径</h2>
<p>通过 Shipment Repository 或标准订单服务创建发货，按可发的叶子订单项传数量，并用外部 shipment ID 做幂等。不要直接更新 qty_shipped；修历史订单前先重建每张 Shipment 的事实明细并评估库存和邮件副作用。</p>
<h2>上线验收</h2>
<p>测试可配置、Bundle、简单商品的部分与全部发货，重复提交同一 ERP 事件只能产生一次 Shipment。剩余可发数量、订单状态、库存 Source 和客户邮件应一致。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 部分发货数量与订单不一致&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 21 May 2025 07:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 免税客户仍被收取税费]]></title>
      <link>https://www.360magento.com/blog/tax-exempt-customer-still-taxed/</link>
      <description><![CDATA[<p>客户已被标记为免税或加入免税客户组，结账仍显示税费。Magento 并不会根据一个自定义布尔属性自动免税；税率由客户税类、产品税类、计算地址、规则优先级和商品价格含税设置共同决定。</p>
<h2>先固定复现条件和影响范围</h2>
<p>选择一位异常客户和一位正常免税客户，对比 customer_group_id、tax_class_id、商品 tax_class_id、配送与账单地址、Store 和 Quote totals。不要在日志输出完整客户地址。</p>
<pre><code>SELECT customer_group_id,customer_group_code,tax_class_id FROM customer_group ORDER BY customer_group_id;
SELECT class_id,class_name,class_type FROM tax_class ORDER BY class_type,class_id;
SELECT r.code,r.priority,r.position,r.calculate_subtotal
FROM tax_calculation_rule r ORDER BY r.priority,r.position;
SELECT address_type,country_id,region_id,postcode,tax_amount,base_tax_amount
FROM quote_address WHERE quote_id=12345;
php bin/magento config:show tax/calculation/based_on</code></pre>
<h2>根据证据分支定位</h2>
<p>客户组指向普通税类，属于映射问题；税类正确但规则仍命中，检查 Tax Rule 组合；地址尚未保存时可能使用 Default Tax Destination；登录后旧 Quote 没重算，则检查客户组变更后的 totals invalidation。含税价格配置会让显示口径与 tax_amount 直觉不同。</p>
<h2>修复时保留回滚路径</h2>
<p>把免税客户组映射到明确的 Customer Tax Class，并在规则层定义不会命中税率的组合。自定义免税证书逻辑应在受控服务中决定税类或税计算上下文，保留审核记录；不要结账后直接把订单 tax_amount 改为零。</p>
<h2>上线验收</h2>
<p>测试访客、普通客户、免税客户，两种地址和含税/未税显示。购物车、结账、订单、发票与退款的税额必须一致，客户免税状态变化后已有 Quote 应重新计算。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 免税客户仍被收取税费&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 20 May 2025 02:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL 翻页出现重复或漏商品]]></title>
      <link>https://www.360magento.com/blog/graphql-pagination-duplicate-products/</link>
      <description><![CDATA[<p>前端按 currentPage 加载商品，第二页重复第一页商品或少了部分 SKU。Offset 分页要求排序在整个请求期间稳定；大量商品具有相同价格、位置或时间时，如果没有稳定的次级排序，数据库或搜索引擎可能改变同值记录顺序。</p>
<h2>先固定复现条件和影响范围</h2>
<p>保存每页请求变量、返回 SKU 顺序、total_count、索引别名和请求时间。固定分类与筛选条件，连续请求相同页两次，并在无商品更新的窗口复现。</p>
<pre><code>curl -sS -H 'Content-Type: application/json'  --data '{"query":"query($p:Int!){products(search:"",pageSize:20,currentPage:$p,sort:{price:ASC}){total_count items{sku name}}}","variables":{"p":1}}'  https://shop.example.com/graphql
grep -R --line-number 'setOrder|addOrder|sort' app/code/*/*/Model/Resolver 2&gt;/dev/null
php bin/magento indexer:status catalogsearch_fulltext catalog_product_price</code></pre>
<h2>根据证据分支定位</h2>
<p>相同请求自己就顺序变化，优先查非稳定排序和搜索集群；固定不变但页间重复，检查 offset、pageSize 和自定义结果拼接；只有索引更新时变化，则评估无限滚动期间商品变更的产品体验。自定义 Resolver 若先分页后再过滤，会必然漏项。</p>
<h2>修复时保留回滚路径</h2>
<p>使用业务排序字段加稳定且唯一的次级键，过滤应在分页之前完成。客户端对短时数据变更可按 SKU 去重，但不能用它掩盖服务端 total_count 和排序错误；导出等强一致任务改用主键游标分批。</p>
<h2>上线验收</h2>
<p>准备多个相同价格与位置的商品，遍历全部页后 SKU 集合应无重复且数量等于 total_count。索引更新、商品上下架和不同 Store View 下也要有可解释的一致行为。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 GraphQL 翻页出现重复或漏商品&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 19 May 2025 05:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 切换商店后购物车变空]]></title>
      <link>https://www.360magento.com/blog/store-switch-cart-empty/</link>
      <description><![CDATA[<p>客户从一个 Store View 切换语言或站点后购物车突然为空。若跨 Website，购物车隔离可能是设计行为；同一 Website 内切换仍清空，则要检查 Session、Quote 激活状态、商品网站分配与自定义 Store Switcher。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录切换前后 store_id、website_id、Session 是否保持、active quote_id、SKU 网站分配和货币。分别测试同 Website 的两个 Store View 与跨 Website 切换。</p>
<pre><code>SELECT store_id,code,website_id,group_id FROM store ORDER BY website_id,store_id;
SELECT entity_id,store_id,is_active,customer_id,items_count,quote_currency_code,updated_at
FROM quote WHERE entity_id IN (12345,12346);
SELECT product_id,website_id FROM catalog_product_website
WHERE product_id IN (SELECT product_id FROM quote_item WHERE quote_id=12345);
php bin/magento config:show checkout/options/enable_agreements</code></pre>
<h2>根据证据分支定位</h2>
<p>Session ID 改变，查 Cookie Domain、Path 和 Base URL；Session 相同但创建新 Quote，查 website 隔离和切换代码；Quote 保留而商品被移除，查目标网站分配、可售量、价格和必选选项。仅显示空但接口有 items，则属于 customer-data 前端刷新问题。</p>
<h2>修复时保留回滚路径</h2>
<p>先明确业务是否允许跨 Website 共享购物车。同 Website 切换应复用或安全转换 Quote；跨 Website 若需要迁移，应逐项重新验证商品、库存、价格、税和币种，不能只改 quote.store_id。</p>
<h2>上线验收</h2>
<p>覆盖访客与登录客户、同 Website、跨 Website、可售与不可售商品、优惠码和不同币种。切换结果应符合明确规则，不能静默丢失商品；被移除项目需给出可理解提示。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 切换商店后购物车变空&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 16 May 2025 03:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 邮件附件导致内存耗尽]]></title>
      <link>https://www.360magento.com/blog/email-attachment-memory-exhausted/</link>
      <description><![CDATA[<p>发送带发票 PDF 或自定义报表的邮件时出现 Allowed memory size exhausted。附件的二进制数据、Base64 编码、MIME 消息和 PDF 渲染可能同时驻留内存，实际峰值远高于文件大小；简单提高 memory_limit 可能把问题推向并发高峰。</p>
<h2>先固定复现条件和影响范围</h2>
<p>用测试订单记录 PDF 原始大小、生成耗时、发送进程 memory_get_peak_usage、附件数量和是否异步。比较无附件、单个小附件与问题附件，不在日志保存文档内容或客户信息。</p>
<pre><code>php -i | grep memory_limit
du -h var/tmp/*.pdf 2&gt;/dev/null | sort -h | tail
grep -R --line-number 'addAttachment|createAttachment|TransportBuilder' app/code 2&gt;/dev/null
grep -RniE 'Allowed memory size|out of memory|email' var/log | tail -n 80
php bin/magento config:show sales_email/general/async_sending</code></pre>
<h2>根据证据分支定位</h2>
<p>生成 PDF 前就耗尽，查商品图片和模板循环；PDF 已生成、构建 MIME 时耗尽，检查整文件多次复制和 Base64；只在队列失败，检查消息是否携带完整二进制而非可重建引用。重复附件还可能来自 Plugin 多次调用。</p>
<h2>修复时保留回滚路径</h2>
<p>限制附件数量和尺寸，减少高分辨率图片，避免在多个字符串变量中复制同一二进制。队列消息保存受控文件引用或业务 ID，并在消费时验证权限和生命周期；临时文件应在发送完成后安全清理。调整 memory_limit 只能基于峰值和并发容量评估。</p>
<h2>上线验收</h2>
<p>测试最小、平均和允许的最大附件，邮件可打开且 PDF 内容完整。并发发送时 Worker 内存应回落，失败重试不得重复生成无限临时文件或重复发送。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 邮件附件导致内存耗尽&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 15 May 2025 08:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cron 报 Area code is already set]]></title>
      <link>https://www.360magento.com/blog/area-code-already-set/</link>
      <description><![CDATA[<p>自定义 Cron 或 CLI 第一次运行正常，后续任务报 Area code is already set。Area 是进程级应用状态，同一 PHP 进程可能连续执行多个任务；在业务服务内部无条件 setAreaCode 会与入口或其他任务冲突。</p>
<h2>先固定复现条件和影响范围</h2>
<p>保存完整堆栈，找到第一个自定义类调用 State::setAreaCode 的位置。确认错误发生在 Cron 组、队列消费者还是 CLI，并检查一个进程内是否循环处理多个实体或消息。</p>
<pre><code>grep -R --line-number 'setAreaCode' app/code 2&gt;/dev/null
grep -R --line-number 'emulateAreaCode|startEnvironmentEmulation' app/code 2&gt;/dev/null
php bin/magento cron:run --group default -vvv
php bin/magento queue:consumers:start your.consumer --max-messages=2 -vvv</code></pre>
<h2>根据证据分支定位</h2>
<p>入口 Command 中设置一次而服务不再设置通常可接受；深层 Service、Observer 或 Repository 中设置 Area 会污染所有调用方。只有特定模板或配置读取需要前台上下文时，应使用受控环境模拟并保证 finally 中停止。</p>
<h2>修复时保留回滚路径</h2>
<p>把 Area 责任放在应用入口，业务服务显式接收所需 Store 或配置，不依赖全局 Area。必须兼容不同入口时先读取当前 Area，不要捕获异常后继续猜测；环境模拟需成对开始和停止，防止影响下一条消息。</p>
<h2>上线验收</h2>
<p>同一进程连续执行任务两次、处理两个 Store，并覆盖 Cron 与手工 CLI。第二次执行不报错，Store 配置和模板也不能沿用上一任务的上下文。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 Cron 报 Area code is already set&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 14 May 2025 01:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 MView changelog 表持续增长]]></title>
      <link>https://www.360magento.com/blog/mview-changelog-table-growing/</link>
      <description><![CDATA[<p>数据库中 catalog_product_price_cl、catalogsearch_fulltext_cl 等表持续膨胀，说明变更事件写入速度超过 MView 消费，或订阅状态已经停滞。直接 truncate 会让索引跳过尚未处理的实体。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录每张 *_cl 表的行数、最小与最大 version_id、对应 mview_state 的 version_id 和索引状态，间隔十分钟再次采样，判断生产与消费速度。</p>
<pre><code>SELECT view_id,mode,status,version_id,updated FROM mview_state ORDER BY view_id;
SELECT COUNT(*) cnt,MIN(version_id),MAX(version_id) FROM catalog_product_price_cl;
SELECT COUNT(*) cnt,MIN(version_id),MAX(version_id) FROM catalogsearch_fulltext_cl;
php bin/magento indexer:show-mode
php bin/magento indexer:status
php bin/magento cron:run --group index -vvv</code></pre>
<h2>根据证据分支定位</h2>
<p>最大 version_id 增长而 state 不动，查 index Cron 与索引错误；state 前进但旧行不清理，检查清理过程与长事务；表没有新行但业务有变更，核对触发器是否存在。Realtime 与 Schedule 模式混用时要确认真实预期。</p>
<h2>修复时保留回滚路径</h2>
<p>先修复失败索引器或 Cron，观察 state 恢复推进，再让系统正常清理已消费范围。确需人工归档时，只处理严格小于已确认消费 version_id 的记录，并先备份；不能把 state 强行跳到最大值。</p>
<h2>上线验收</h2>
<p>修改一个商品价格和分类关系，changelog 增加后应在预期周期被消费，前台索引同步。连续观察高峰期，表行数应在可控区间波动而不是单向增长。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 MView changelog 表持续增长&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 13 May 2025 06:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 异步批量 API 一直停在 open]]></title>
      <link>https://www.360magento.com/blog/async-bulk-operations-stuck/</link>
      <description><![CDATA[<p>异步接口很快返回 bulk_uuid，但查询状态时所有 operation 长期为 open。请求已被接收不等于已经执行；消息可能没有入队、对应 Consumer 未运行、持续失败重试，或状态写回事务被阻塞。</p>
<h2>先固定复现条件和影响范围</h2>
<p>保存 bulk_uuid、路由、提交条数、创建时间与一个 operation_key。统计 open、complete_recoverable、complete 和 rejected 数量，不记录请求中的客户或认证敏感数据。</p>
<pre><code>SELECT uuid,description,operation_count,start_time FROM magento_bulk ORDER BY start_time DESC LIMIT 10;
SELECT bulk_uuid,status,topic_name,operation_key,error_code,result_message
FROM magento_operation WHERE bulk_uuid='BULK-UUID' ORDER BY id;
php bin/magento queue:consumers:list
php bin/magento queue:consumers:start async.operations.all --max-messages=50 -vvv
php bin/magento queue:consumers:start product_action_attribute.update --max-messages=50 -vvv</code></pre>
<h2>根据证据分支定位</h2>
<p>没有 magento_operation 行，检查请求路由和提交事务；有 open 且队列深度增长，检查 Consumer；转为 recoverable 或 rejected，则读取脱敏错误信息并修业务数据。DB 队列与 RabbitMQ 环境使用的检查方式不同，先确认 env.php 的实际连接。</p>
<h2>修复时保留回滚路径</h2>
<p>恢复正确 Consumer 和 Supervisor 配置，并对失败操作按业务幂等性决定重试。不要直接把状态 UPDATE 为 complete，也不要删除 open 行掩盖积压；大批量按可承受条数拆分，并给 API 调用方提供状态与失败明细。</p>
<h2>上线验收</h2>
<p>提交包含成功、可恢复失败和永久失败的小批次，状态应最终收敛且成功实体已保存。重启 Consumer 后消息不能丢失或重复产生业务副作用，积压曲线应持续下降。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 异步批量 API 一直停在 open&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 12 May 2025 02:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发布后 PHP 仍执行旧代码]]></title>
      <link>https://www.360magento.com/blog/php-opcache-old-code/</link>
      <description><![CDATA[<p>代码文件已经更新，页面和异常堆栈却仍指向旧行号，甚至刷新后时新时旧。这通常不是 Magento Cache，而是 PHP OPcache、长生命周期进程、符号链接发布方式或多节点版本不一致。</p>
<h2>先固定复现条件和影响范围</h2>
<p>给本次构建记录不可变版本号，在响应头或健康页输出不敏感的 build ID 和节点名。对比 Web PHP 与 CLI PHP 的版本、php.ini 和实际 release 路径。</p>
<pre><code>readlink -f /var/www/current
php -i | grep -E 'opcache.validate_timestamps|opcache.revalidate_freq|opcache.enable_cli'
php-fpm -i 2&gt;/dev/null | grep -E 'opcache.validate_timestamps|opcache.revalidate_freq'
ps -eo pid,lstart,cmd | grep '[p]hp-fpm'
sha256sum app/etc/config.php composer.lock</code></pre>
<h2>根据证据分支定位</h2>
<p>只有 Web 请求旧而 CLI 新，检查 FPM OPcache 和进程；只有队列消费者旧，说明长进程未重启；刷新随机切换版本，说明负载均衡后节点或 release symlink 不一致。validate_timestamps 关闭时，仅替换文件不会使缓存自动失效。</p>
<h2>修复时保留回滚路径</h2>
<p>使用原子 release 切换，发布完成后按运维策略平滑 reload PHP-FPM 并重启 Magento 长进程；所有节点部署同一构建。不要从 Web 请求暴露 opcache reset 端点，也不要在高峰粗暴 kill 全部进程。</p>
<h2>上线验收</h2>
<p>连续请求覆盖所有节点，build ID、堆栈行号和行为必须一致；运行 Cron、消费者与后台任务验证新代码。下一次回滚也应按同样流程切换并刷新进程缓存。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 发布后 PHP 仍执行旧代码&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 09 May 2025 05:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 URL Rewrite 出现循环重定向]]></title>
      <link>https://www.360magento.com/blog/url-rewrite-redirect-loop/</link>
      <description><![CDATA[<p>浏览器提示重定向次数过多，常见链路是旧 URL 301 到新 URL，新 URL 又被 Store、后缀或 Web 规则改回旧地址。删除全部 url_rewrite 可能让大量既有链接失效，应先画出每一跳是谁返回的。</p>
<h2>先固定复现条件和影响范围</h2>
<p>用 curl 保存 Location 链、状态码、Host、协议和 Set-Cookie，分别绕过 CDN 请求源站。确认循环只发生在某个 Store View、登录状态或特定商品分类。</p>
<pre><code>curl -skIL --max-redirs 12 https://shop.example.com/old-path.html
SELECT url_rewrite_id,entity_type,entity_id,request_path,target_path,redirect_type,store_id,is_autogenerated
FROM url_rewrite
WHERE request_path IN ('old-path.html','new-path.html')
   OR target_path IN ('old-path.html','new-path.html')
ORDER BY store_id,url_rewrite_id;
php bin/magento config:show web/url/use_store
php bin/magento config:show catalog/seo/product_url_suffix</code></pre>
<h2>根据证据分支定位</h2>
<p>数据库两条 301 互相指向，属于重写链冲突；Magento 只返回一次，后续由 Nginx/CDN 改回，则检查尾斜杠、HTTP 到 HTTPS 和 www 规范化；不同 Store Code 互跳时，检查 Base URL、Cookie 与 Store Resolver。</p>
<h2>修复时保留回滚路径</h2>
<p>保留唯一规范 URL和最多一条从旧地址到规范地址的 301，通过后台实体保存或受控数据补丁修复。修改 Web 规则时一次只统一一个维度，并在 CDN 清除精确 URL；不要把所有 404 广泛重定向到首页。</p>
<h2>上线验收</h2>
<p>检查旧地址一次 301 后到达 200，新地址直接 200；HTTP、HTTPS、www、非 www、带 Store Code 和无 Store Code 都不能形成第二条反向跳转。同步验证 canonical、Sitemap 和内部链接。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 URL Rewrite 出现循环重定向&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Thu, 08 May 2025 03:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST SearchCriteria 的 AND 与 OR 条件写反]]></title>
      <link>https://www.360magento.com/blog/rest-searchcriteria-and-or/</link>
      <description><![CDATA[<p>API 明明传了多个过滤条件，结果却像只应用了其中一个，或者一条数据都没有。SearchCriteria 的布尔结构容易写反：不同 filter group 组合为 AND，同一 group 内多个 filter 通常组合为 OR，自定义 Repository 还可能错误实现处理器。</p>
<h2>先固定复现条件和影响范围</h2>
<p>先把请求缩减到单个字段单个值，再逐个增加条件。保存解码后的查询参数、返回总数和一条应命中、一条不应命中的实体，避免只看第一页。</p>
<pre><code>curl -G 'https://shop.example.com/rest/V1/products'  --data-urlencode 'searchCriteria[filter_groups][0][filters][0][field]=status'  --data-urlencode 'searchCriteria[filter_groups][0][filters][0][value]=1'  --data-urlencode 'searchCriteria[filter_groups][1][filters][0][field]=sku'  --data-urlencode 'searchCriteria[filter_groups][1][filters][0][value]=ABC%'  --data-urlencode 'searchCriteria[filter_groups][1][filters][0][condition_type]=like'
grep -R --line-number 'FilterProcessor|CollectionProcessor' app/code 2&gt;/dev/null</code></pre>
<h2>根据证据分支定位</h2>
<p>单条件正确、加入第二组后为空，检查期望是否真的是 AND；两个 filter 放同组后数据变多，说明 OR 生效；服务端日志看到括号或百分号被破坏，检查客户端 URL 编码。自定义接口若完全忽略条件，检查 Repository 是否调用 collection processor。</p>
<h2>修复时保留回滚路径</h2>
<p>先用标准 SearchCriteriaBuilder 在集成测试中表达目标逻辑，再让 REST 客户端生成等价参数。复杂的嵌套布尔条件不要硬塞进不支持的结构，可设计明确的服务接口；禁止把客户端字段直接拼接成 SQL。</p>
<h2>上线验收</h2>
<p>用真值表准备四条数据，覆盖仅满足 A、仅满足 B、同时满足和都不满足。校验 total_count、分页、排序以及特殊字符值，API 与 Repository 集成测试结果必须一致。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 REST SearchCriteria 的 AND 与 OR 条件写反&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Wed, 07 May 2025 07:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 登录后 customer-data 仍显示访客信息]]></title>
      <link>https://www.360magento.com/blog/customer-data-section-stale/</link>
      <description><![CDATA[<p>用户已经登录，账户菜单仍显示访客名称，迷你购物车也可能停留在登录前状态。整页 HTML 往往来自 FPC，客户信息由 customer-data 在浏览器端加载；问题通常是 section 未失效、版本 Cookie 未更新或自定义代码缓存了错误数据。</p>
<h2>先固定复现条件和影响范围</h2>
<p>在无痕窗口记录登录请求、customer/section/load 响应、private_content_version Cookie 和 Local Storage 中 mage-cache-storage、mage-cache-storage-section-invalidation。比较完整页面登录与 AJAX 登录两条路径。</p>
<pre><code>grep -R --line-number 'sections.xml' app/code vendor 2&gt;/dev/null
grep -R --line-number 'SectionSourceInterface' app/code 2&gt;/dev/null
php bin/magento cache:clean config full_page
curl -sS -D - 'https://shop.example.com/customer/section/load/?sections=customer,cart' -o /tmp/sections.json</code></pre>
<h2>根据证据分支定位</h2>
<p>section/load 已返回正确客户而页面仍旧，检查 Knockout 绑定和 JS 错误；响应本身还是访客，检查请求 Cookie、Session 与 SectionSource；登录后根本未请求 section/load，则检查 sections.xml 的 action 配置与自定义 AJAX 登录是否触发 invalidate/reload。</p>
<h2>修复时保留回滚路径</h2>
<p>为改变客户状态的 action 精确配置需要失效的 section，并在自定义前端流程成功后调用官方 customer-data invalidate/reload。不要把 customer、cart 等私有 section 放进公共 CDN 缓存，也不要靠每次清空所有 Local Storage 掩盖缺失的失效规则。</p>
<h2>上线验收</h2>
<p>访客、客户 A、客户 B 依次登录和注销，页头、购物车和收藏夹不得串号；测试 FPC HIT、浏览器后退和两个标签页，同一账户状态应在合理时间内同步。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 登录后 customer-data 仍显示访客信息&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Tue, 06 May 2025 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Table Rate 导入成功却没有运费]]></title>
      <link>https://www.360magento.com/blog/table-rate-import-no-rates/</link>
      <description><![CDATA[<p>后台显示 Table Rate CSV 导入完成，结账页却没有任何报价。导入成功只说明文件能被解析，是否命中还取决于 Website Scope、Condition、地址、重量或订单金额以及 CSV 中的国家地区代码。</p>
<h2>先固定复现条件和影响范围</h2>
<p>固定一个 Quote，记录 website、目的国家、region_id、邮编、包裹重量、含税和未税金额。导出同一网站当前配置作为模板，不要凭记忆自行拼表头。</p>
<pre><code>php bin/magento config:show carriers/tablerate/active --scope=websites --scope-code=base
php bin/magento config:show carriers/tablerate/condition_name --scope=websites --scope-code=base
SELECT dest_country_id,dest_region_id,dest_zip,condition_name,condition_value,price,cost
FROM shipping_tablerate ORDER BY pk DESC LIMIT 30;
SELECT country_id,region_id,postcode,weight,subtotal,base_subtotal
FROM quote_address WHERE quote_id=12345 AND address_type='shipping';</code></pre>
<h2>根据证据分支定位</h2>
<p>表中没有目标 website 的记录，说明导入时作用域错误；有记录但国家或地区不符，检查 ISO 国家代码与 region_id；地址匹配而 condition_value 不匹配，则核对 Package Weight、Order Subtotal 等条件口径和虚拟商品。邮编通配规则应按实际实现测试，不能假设星号支持任意位置。</p>
<h2>修复时保留回滚路径</h2>
<p>在正确 Website Scope 重新导入由系统导出的模板，只保留一条可验证规则作为小样本。确认命中后再分批加入区间和地区；不要直接复制 shipping_tablerate 行到另一网站，因为 website_id、地区与条件可能不同。</p>
<h2>上线验收</h2>
<p>测试同城邮编、边界重量、边界金额、不允许国家和虚拟购物车。购物车估算、结账重新计算与最终订单运费必须一致，切换地址后旧 rate 不得残留。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 Table Rate 导入成功却没有运费&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Mon, 05 May 2025 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台双重验证 Provider 不可用]]></title>
      <link>https://www.360magento.com/blog/two-factor-provider-unavailable/</link>
      <description><![CDATA[<p>后台密码验证通过后停在双重验证页面，可能提示没有可用 Provider、验证码无效或反复返回登录页。不要直接关闭 2FA 作为长期方案；先区分模块未启用、配置无法解密、时间漂移和单个管理员绑定异常。</p>
<h2>先固定复现条件和影响范围</h2>
<p>记录受影响管理员、Provider 类型、错误时间和所有管理员是否同时失败。用另一个已授权管理员对照，确认问题是账号级还是全站级；日志中不得记录一次性验证码、恢复码或共享密钥。</p>
<pre><code>php bin/magento module:status Magento_TwoFactorAuth
php bin/magento config:show admin/security
date -u
timedatectl status
grep -RniE 'two.?factor|2fa|otp|provider' var/log | tail -n 80</code></pre>
<h2>根据证据分支定位</h2>
<p>所有管理员同时失败，优先检查发布后模块状态、依赖和系统时间；只有一个用户失败，检查其 Provider 绑定与设备时间。多节点偶发失败时，比较各节点 crypt key、PHP 时区和 Session 存储，但不要把密钥内容输出到日志。</p>
<h2>修复时保留回滚路径</h2>
<p>先恢复 NTP 与一致的部署配置，再使用 Magento 当前版本支持的管理员恢复流程重置特定用户的 2FA 绑定。若必须短时应急停用模块，应限定维护窗口、限制后台网络入口并在完成后立即恢复和重新注册，不要删除数据库记录来猜测状态。</p>
<h2>上线验收</h2>
<p>分别使用两个管理员完成登录、注销、重新登录和 Session 过期测试；校验错误验证码被拒绝、正确验证码只能使用一次，多节点切换后也不能绕过二次验证。</p>
<h2>生产环境操作前的检查</h2>
<p>处理&ldquo;Magento 2 后台双重验证 Provider 不可用&rdquo;前，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 <code>SELECT</code>；任何写操作、目录清理或配置切换都应确认影响范围、保留备份并准备回滚。多节点环境要核对各节点代码版本、<code>app/etc/env.php</code> 配置摘要与流量分布。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。不要在生产高峰同时运行全量索引、静态部署和数据修复；涉及客户、支付、税费或订单的改动，先在脱敏数据副本验证。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，记录操作前值、命令、开始与结束时间、结果和回滚方式。准备一个正常对象与一个异常对象对照；若旧对象恢复而新对象仍能复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查层</th><th>需要保存的证据</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>入口层</td>
<td>URL、状态码、请求 ID、节点</td>
<td>路由和协议一致</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、作用域</td>
<td>无新异常且可重复</td>
</tr>
<tr>
<td>数据层</td>
<td>主键、时间、关联行数</td>
<td>关系完整且无重复副作用</td>
</tr>
<tr>
<td>业务层</td>
<td>正常、失败、重试路径</td>
<td>最终结果一致</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后至少观察一轮 Cron、队列和索引周期，并在两台节点、无痕浏览器和目标 Store View 重复验证。临时调试日志必须脱敏，确认错误率、响应时间和数据量稳定后及时关闭。</p>]]></description>
      <pubDate>Fri, 02 May 2025 02:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台批量更新属性后前台价格未变化]]></title>
      <link>https://www.360magento.com/blog/mass-attribute-update-price-not-changed/</link>
      <description><![CDATA[<p>后台提示批量更新成功，只代表属性保存请求完成。价格是否出现在目标网站，还受 Global/Website Scope、客户组价格、Catalog Rule、计划索引与全页缓存影响。</p>
<h2>先固定复现条件</h2>
<p>选择一个正常 SKU 和一个异常 SKU，记录编辑 Scope、website_id、客户组、币种与更新时间。直接商品页和分类页都测试，避免只看到 CDN 旧页面。</p>
<pre><code>SELECT entity_id,sku,updated_at FROM catalog_product_entity WHERE sku IN ('GOOD-SKU','MISS-SKU');
SELECT attribute_id,attribute_code,is_global FROM catalog_eav_attribute WHERE attribute_id=(SELECT attribute_id FROM eav_attribute WHERE attribute_code='price' LIMIT 1);
php bin/magento indexer:status catalog_product_price
SELECT * FROM mview_state WHERE view_id='catalog_product_price';</code></pre>
<h2>根据结果定位根因</h2>
<p>Website Scope 下可能只更新了另一个网站；Update by Schedule 模式依赖 Cron 消费 changelog。客户组价、特殊价日期或目录规则也可能覆盖基础 price。</p>
<h2>修复时保留回滚路径</h2>
<p>在正确 Scope 重做一条样本，确认 EAV decimal 值后只重建 catalog_product_price，并检查 Cron 根因。不要把每日全量 reindex 当作增量失败的替代方案。</p>
<h2>上线后的验收</h2>
<p>测试两个网站、访客与客户组、列表页和详情页，并核对购物车最终单价。再次批量更新一个小值，前台应在预期索引周期内自动变化。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 后台批量更新属性后前台价格未变化&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Thu, 01 May 2025 06:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重新索引报 The table is full]]></title>
      <link>https://www.360magento.com/blog/reindex-table-is-full/</link>
      <description><![CDATA[<p>报错不一定表示目标索引表达到行数上限。排序和重建会创建磁盘临时表，磁盘、inode、tmpdir 或 InnoDB 临时表空间耗尽都可能返回相同信息。不要先 truncate 业务表。</p>
<h2>先固定复现条件</h2>
<p>保存完整异常堆栈和失败索引器，检查数据库主机而非仅 Web 节点的文件系统、inode、tmpdir 与 MySQL 错误日志。</p>
<pre><code>df -h
df -i
mysql -e "SHOW VARIABLES LIKE 'tmpdir'; SHOW VARIABLES LIKE 'innodb_temp_data_file_path';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Created_tmp%';"
php bin/magento indexer:reindex catalog_product_price -vvv</code></pre>
<h2>根据结果定位根因</h2>
<p>磁盘利用率满、容器临时盘配额、过多临时文件或异常宽的自定义索引查询是常见根因。MEMORY 表还受 max_heap_table_size 限制，但不要不加区分地调大。</p>
<h2>修复时保留回滚路径</h2>
<p>先释放已确认可删除的日志/临时文件或扩容正确卷，再处理遗留临时表。优化自定义索引 SQL 与批次大小；变更 MySQL 临时表空间前做好备份和重启计划。</p>
<h2>上线后的验收</h2>
<p>单独重建失败索引器并确认 Ready，再运行完整索引。观察磁盘峰值、临时表数量与查询时间，下一轮定时增量不得再次耗尽空间。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 重新索引报 The table is full&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Wed, 30 Apr 2025 03:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis Session Lock 导致结账变慢]]></title>
      <link>https://www.360magento.com/blog/redis-session-lock-slow-checkout/</link>
      <description><![CDATA[<p>同一客户的多个 AJAX 请求共享 PHP Session。一个慢请求持有 Redis 锁时，其余请求会等待，看起来像 totals、运费或支付接口随机变慢。直接关闭锁可能造成购物车会话并发覆盖。</p>
<h2>先固定复现条件</h2>
<p>在浏览器瀑布图中找同一时间开始却依次结束的请求，关联 PHP-FPM slowlog、Nginx request_time 和 Redis 客户端。用测试会话复现，不记录真实 session ID。</p>
<pre><code>grep -n "session" app/etc/env.php
redis-cli INFO clients
redis-cli INFO commandstats
ps -eo pid,etime,%cpu,%mem,cmd | grep '[p]hp-fpm'
grep -R "request_slowlog_timeout" /etc/php* 2&gt;/dev/null</code></pre>
<h2>根据结果定位根因</h2>
<p>外部支付调用、同步邮件、远程库存查询或自定义 Observer 在 session 打开期间执行，会长时间持锁。锁重试次数与等待时间不当只会放大症状。</p>
<h2>修复时保留回滚路径</h2>
<p>先缩短持锁请求，把外部工作移到队列并尽早关闭不再需要的 session。谨慎调整 max_concurrency、break_after_frontend 等参数，保留并发一致性与回滚配置。</p>
<h2>上线后的验收</h2>
<p>模拟结账页面的并发 totals、shipping 与 payment 请求，P95 延迟明显下降且购物车不丢商品。Redis 锁超时日志、PHP slowlog 和错误率连续观察一轮高峰。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 Redis Session Lock 导致结账变慢&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Tue, 29 Apr 2025 07:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CSP 阻止结账第三方脚本]]></title>
      <link>https://www.360magento.com/blog/csp-blocks-checkout-script/</link>
      <description><![CDATA[<p>控制台出现 Content Security Policy 拒绝并不意味着应关闭 CSP。结账包含支付、分析和反欺诈脚本，过宽的 script-src * 会扩大 XSS 风险。先识别被哪个 directive 拒绝。</p>
<h2>先固定复现条件</h2>
<p>在无痕窗口保存完整控制台消息、blocked URI、effective directive 与页面 URL。确认脚本是业务必需、由谁加载、是否还有 iframe、connect 或 image 子资源。</p>
<pre><code>grep -R --line-number "csp_whitelist.xml" app/code vendor 2&gt;/dev/null
find app/code -path '*/etc/csp_whitelist.xml' -print
php bin/magento module:status Magento_Csp
php bin/magento cache:clean config full_page</code></pre>
<h2>根据结果定位根因</h2>
<p>只放行脚本主域名仍可能被 connect-src、frame-src 或 img-src 阻止；内联脚本需要 nonce/hash，不能靠 unsafe-inline 一次放开。支付域名也可能区分测试与生产。</p>
<h2>修复时保留回滚路径</h2>
<p>在自定义模块的 csp_whitelist.xml 中按 directive 添加精确 HTTPS host；内联代码优先使用 nonce 兼容接口。先在 report-only 环境收集遗漏，再切 enforcing。</p>
<h2>上线后的验收</h2>
<p>测试全部支付方式、3DS、地址验证与失败重试，控制台没有新的违反项。恶意内联脚本仍应被拦截，其他 Store View 和 CDN 页面头保持一致。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 CSP 阻止结账第三方脚本&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Mon, 28 Apr 2025 01:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Composer 更新后官方补丁失效]]></title>
      <link>https://www.360magento.com/blog/composer-update-patch-lost/</link>
      <description><![CDATA[<p>直接修改 vendor 的修复会在 Composer 更新后消失；使用补丁插件时，目标包版本或文件上下文变化也会让补丁无法应用。发布前必须把补丁状态作为构建验证的一部分。</p>
<h2>先固定复现条件</h2>
<p>在干净构建目录用锁文件安装一次，保存 Composer 输出，确认失败的是补丁下载、SHA 校验、目标包缺失还是 hunk 上下文不匹配。</p>
<pre><code>composer show magento/framework
composer validate
composer install -vvv 2&gt;&amp;1 | tee /tmp/composer-install.log
grep -n -Ei 'patch|failed|skipped' /tmp/composer-install.log
git diff -- composer.json composer.lock patches</code></pre>
<h2>根据结果定位根因</h2>
<p>composer.json 与 lock 不同步、补丁只配置在根项目外、目标版本已包含修复、补丁 URL 变化或插件被 allow-plugins 阻止，都会导致状态异常。</p>
<h2>修复时保留回滚路径</h2>
<p>把补丁文件纳入项目并记录来源、适用版本与校验和；在新包版本上重新生成最小补丁。不要用忽略失败继续发布，也不要重新手改 vendor。</p>
<h2>上线后的验收</h2>
<p>删除 vendor 后执行干净 install，补丁必须成功应用；运行相关单元/集成测试并检查目标代码。CI 应在补丁跳过或失败时阻断构建。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 Composer 更新后官方补丁失效&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Fri, 25 Apr 2025 06:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多来源库存可售数量变成负数]]></title>
      <link>https://www.360magento.com/blog/msi-salable-quantity-negative/</link>
      <description><![CDATA[<p>Source quantity 是物理数量，salable quantity 还会减去预留量与缺货阈值。启用 Backorders 时负数可能是配置允许的结果；未启用却持续为负，则要检查 reservation 或销售渠道。</p>
<h2>先固定复现条件</h2>
<p>记录 SKU、website、stock_id、各 Source 数量、是否可售和缺货阈值。不要只看 Default Source，也不要假设 inventory_stock_1 代表所有网站。</p>
<pre><code>SELECT stock_id,website_id FROM inventory_stock_sales_channel;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku='SKU-1';
SELECT sku,SUM(quantity) reserved FROM inventory_reservation WHERE sku='SKU-1' GROUP BY sku;
php bin/magento inventory:reservation:list-inconsistencies -r</code></pre>
<h2>根据结果定位根因</h2>
<p>常见原因包括 ERP 只更新一个 Source、网站绑定错误 Stock、取消订单缺少补偿、阈值为负或 Backorders 配置被 Store 覆盖。索引过期会让数据库源数据正确而前台仍旧。</p>
<h2>修复时保留回滚路径</h2>
<p>先修 Source 同步和 Stock 绑定，再处理经核实的 reservation 差异并重建 inventory 索引。不要直接把索引 quantity 改成零，它会在下次重建时被覆盖。</p>
<h2>上线后的验收</h2>
<p>在每个网站测试下单、取消、发货与补货，确认 Source quantity、reservation 和 salable quantity 按预期变化。库存到零时前台行为必须符合 Backorders 配置。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 多来源库存可售数量变成负数&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Thu, 24 Apr 2025 02:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 支付回调重复导致订单重复开票]]></title>
      <link>https://www.360magento.com/blog/duplicate-payment-webhook-invoice/</link>
      <description><![CDATA[<p>支付平台在超时或未收到 2xx 时会重试回调，同一事件也可能并发到达两个 Web 节点。如果代码每次都 create invoice，就会重复邮件、重复 capture 或产生金额异常。</p>
<h2>先固定复现条件</h2>
<p>按订单号汇总 webhook 访问日志、payment transaction、invoice 和订单历史，确认重复请求的事件 ID、到达间隔与响应码。日志不能保存完整签名密钥或卡数据。</p>
<pre><code>SELECT transaction_id,parent_txn_id,txn_type,is_closed,created_at FROM sales_payment_transaction WHERE order_id=123;
SELECT entity_id,increment_id,state,grand_total,created_at FROM sales_invoice WHERE order_id=123;
SELECT parent_id,status,comment,created_at FROM sales_order_status_history WHERE parent_id=123;</code></pre>
<h2>根据结果定位根因</h2>
<p>只检查订单 status 不足以防并发，因为两个请求可能同时读到 processing。缺少唯一事件表、未锁订单行、网关交易 ID 未设唯一约束或异常后返回 500，都会触发重复。</p>
<h2>修复时保留回滚路径</h2>
<p>先验签，再以 provider+event_id 建唯一记录；事务内锁定订单并检查 payment transaction 与 canInvoice。已处理事件立即返回 2xx，永久错误进入人工队列，可重试错误保留明确状态。</p>
<h2>上线后的验收</h2>
<p>在测试环境并发发送同一回调五次，只能产生一张发票、一次邮件和一个 capture。乱序、延迟与退款回调也不能破坏最终订单状态。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 支付回调重复导致订单重复开票&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Wed, 23 Apr 2025 08:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 导入商品提示 Value for Attribute Contains Incorrect Value]]></title>
      <link>https://www.360magento.com/blog/import-attribute-incorrect-value/</link>
      <description><![CDATA[<p>导入器会按属性的 frontend_input、backend_type 和 Store View 验证值。下拉属性通常要求选项标签而非 option_id，多选值还受分隔符影响。错误只出现在某几行时，应先做最小 CSV。</p>
<h2>先固定复现条件</h2>
<p>保留表头和一条失败 SKU，确认导入行为、Store View、字段原始字节及错误列。用同属性的正常商品从后台导出，比较实际格式。</p>
<pre><code>SELECT a.attribute_id,a.attribute_code,a.frontend_input,a.backend_type,a.is_required
FROM eav_attribute a WHERE a.attribute_code='color';
SELECT o.option_id,v.store_id,v.value FROM eav_attribute_option o
JOIN eav_attribute_option_value v ON v.option_id=o.option_id WHERE o.attribute_id=93;
file -bi import.csv</code></pre>
<h2>根据结果定位根因</h2>
<p>标签大小写或空格不一致、选项只存在于特定 Store、日期格式与 locale 不符、布尔值使用 Yes/No 之外的文本，都会触发错误。CSV 的 BOM 和不可见字符也要排查。</p>
<h2>修复时保留回滚路径</h2>
<p>在后台或数据补丁中创建缺失选项，再按导出格式修正 CSV。不要为通过导入而关闭验证；生产先用 Add/Update 小批验证，不使用 Replace 处理未知错误。</p>
<h2>上线后的验收</h2>
<p>导入十行样本后检查默认与 Store View 属性值、筛选器、搜索索引和前台展示。再次导出应得到稳定值，错误报告中不得出现被静默跳过的行。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 导入商品提示 Value for Attribute Contains Incorrect Value&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Tue, 22 Apr 2025 01:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 inventory reservation 出现库存差异]]></title>
      <link>https://www.360magento.com/blog/inventory-reservation-mismatch/</link>
      <description><![CDATA[<p>MSI 通过正负 reservation 记录下单、取消、发货和退款对可售量的影响。缺少补偿会让 Source 数量正确但 salable quantity 长期偏高或偏低。不要手工汇总后删除 inventory_reservation。</p>
<h2>先固定复现条件</h2>
<p>先锁定 SKU、Stock 与异常订单，比较 Source quantity、Stock 索引和 reservation 累计值，并确认订单是否经过导入、取消或部分发货。</p>
<pre><code>php bin/magento inventory:reservation:list-inconsistencies -r
SELECT sku,SUM(quantity) reservation_total FROM inventory_reservation WHERE sku='SKU-1' GROUP BY sku;
SELECT source_code,sku,quantity,status FROM inventory_source_item WHERE sku='SKU-1';
SELECT sku,quantity,is_salable FROM inventory_stock_1 WHERE sku='SKU-1';</code></pre>
<h2>根据结果定位根因</h2>
<p>常见根因是旧订单迁移后缺少 initial reservation、扩展直接改订单状态、消息队列未消费，或退款/取消事件被执行两次。先查订单历史和队列日志，不能只看当前数量。</p>
<h2>修复时保留回滚路径</h2>
<p>把官方不一致命令输出保存并逐单复核，再通过 create-compensations 处理确认的差异。修复触发源，确保业务事件幂等；不要把补偿命令当每日清理任务。</p>
<h2>上线后的验收</h2>
<p>完成下单、取消、部分发货、全额退款四条链路，每一步记录 salable quantity。下一次索引与消费者运行后差异命令应为空，多个 Source 的物理数量也应正确。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 inventory reservation 出现库存差异&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Mon, 21 Apr 2025 06:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单状态无法从 Processing 改为 Complete]]></title>
      <link>https://www.360magento.com/blog/order-state-processing-complete/</link>
      <description><![CDATA[<p>Magento 的 state 是业务流程，status 是展示标签。后台选择一个标记为 Complete 的状态，并不会跳过未完成的发票或发货。直接更新 sales_order.state 会让订单、网关和库存记录失去一致性。</p>
<h2>先固定复现条件</h2>
<p>选一张可复现订单，记录商品类型、总额、已开票金额、已发货数量和当前 state/status，再比较一张正常完成的同类型订单。</p>
<pre><code>SELECT entity_id,increment_id,state,status,total_qty_ordered,total_invoiced,total_paid,total_refunded
FROM sales_order WHERE increment_id='000000123'\G
SELECT order_id,total_qty,qty FROM sales_shipment WHERE order_id=123;
SELECT order_id,state,grand_total FROM sales_invoice WHERE order_id=123;</code></pre>
<h2>根据结果定位根因</h2>
<p>实物商品通常要完成发票和发货；虚拟商品不需要发货。部分支付模块要求 capture 成功后才能完成，自定义 Observer/Plugin 也可能把状态强制改回 processing。</p>
<h2>修复时保留回滚路径</h2>
<p>通过标准 invoice、shipment、credit memo 服务推进订单，不直接写数据库。检查自定义状态是否正确分配给 Complete state，并审计 sales_order_save_after 等扩展。</p>
<h2>上线后的验收</h2>
<p>分别测试在线 capture、离线付款、虚拟商品、部分发货和部分退款。订单历史、邮件、库存扣减与网关状态必须同步，重复回调不能再次改变已完成订单。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 订单状态无法从 Processing 改为 Complete&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Fri, 18 Apr 2025 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 修改翻译 CSV 后前台不更新]]></title>
      <link>https://www.360magento.com/blog/translation-csv-not-updated/</link>
      <description><![CDATA[<p>翻译可能来自模块、主题、语言包、数据库内联翻译和 JavaScript 字典。先判断旧文本由服务器渲染还是 Knockout/JS 组件生成。</p>
<h2>先固定复现条件</h2>
<p>确认问题 Store View 的 locale，搜索完全一致的源短语。CSV 左侧必须匹配大小写、空格和占位符，主题翻译可能覆盖模块文件。</p>
<pre><code>php bin/magento config:show general/locale/code
find app/code app/design vendor -path '*/i18n/*.csv' -print | grep zh_CN
grep -R --line-number 'Original phrase' app/code app/design vendor 2&gt;/dev/null
php bin/magento cache:clean translate block_html full_page</code></pre>
<h2>根据结果定位根因</h2>
<p>PHP 文本只需正确翻译和缓存；JS 文本还依赖静态目录中的 js-translation.json。多节点静态版本不一致也会让部分请求继续返回旧字典。</p>
<h2>修复时保留回滚路径</h2>
<p>在维护窗口只删除准确主题与语言目录，再执行 static-content:deploy。多节点发布同一构建产物，不让每台机器独立生成版本。</p>
<h2>上线后的验收</h2>
<p>用无痕窗口测试 HTML、结账文本和表单验证，并检查第二语言未被覆盖。连续命中不同 Web 节点时翻译应保持一致。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 修改翻译 CSV 后前台不更新&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Thu, 17 Apr 2025 07:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 报 Result window is too large]]></title>
      <link>https://www.360magento.com/blog/opensearch-result-window-too-large/</link>
      <description><![CDATA[<p>报错表示 from 加 size 超过索引 max_result_window。把 10000 调成几十万会让每个分片保留大量排序结果，容易造成堆内存压力。</p>
<h2>先固定复现条件</h2>
<p>记录分类、搜索词、页码、API 参数和调用方。判断是正常用户深翻页，还是导出、爬虫或扩展一次请求超大 pageSize。</p>
<pre><code>curl -s 'http://127.0.0.1:9200/_cat/indices?v'
curl -s 'http://127.0.0.1:9200/magento2_product_1_v*/_settings?pretty'
grep -R --line-number "setPageSize\|setCurPage" app/code 2&gt;/dev/null</code></pre>
<h2>根据结果定位根因</h2>
<p>普通列表应限制最大页码；批处理不该依赖深 offset。自定义搜索若缺少稳定排序，即使改成游标也可能重复或漏数据。</p>
<h2>修复时保留回滚路径</h2>
<p>前台对超界页返回可理解结果；批处理按主键分段，自定义 OpenSearch 请求使用 search_after 与稳定排序。只有评估分片数和 heap 后才临时调整窗口。</p>
<h2>上线后的验收</h2>
<p>回归首页、边界页、超界页和导出任务，并监控查询耗时、拒绝请求和 JVM heap。分页过程中新增商品也不能造成明显重复。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 OpenSearch 报 Result window is too large&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Wed, 16 Apr 2025 01:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 新增分类提示 URL key for specified store already exists]]></title>
      <link>https://www.360magento.com/blog/category-url-key-already-exists/</link>
      <description><![CDATA[<p>冲突可能来自另一分类、CMS 页面、自定义重写或旧 301。URL 唯一性按 store_id 判断，Default Scope 无冲突不代表目标 Store View 无冲突。</p>
<h2>先固定复现条件</h2>
<p>先根据父分类路径计算完整 request_path，再在每个相关 store_id 中查询，记录冲突行的 entity_type、entity_id、redirect_type 与是否自动生成。</p>
<pre><code>SELECT url_rewrite_id,entity_type,entity_id,request_path,target_path,redirect_type,store_id,is_autogenerated
FROM url_rewrite WHERE request_path IN ('new-category','new-category.html') ORDER BY store_id;
SELECT attribute_id FROM eav_attribute WHERE attribute_code='url_key';</code></pre>
<h2>根据结果定位根因</h2>
<p>有效实体占用路径时应修改新分类 URL；已删除实体残留自动重写时，才考虑清理。父分类变化、Store View 覆盖值和历史重定向都可能制造看似相同的冲突。</p>
<h2>修复时保留回滚路径</h2>
<p>备份命中行并在后台确认目标实体。优先通过分类保存流程重新生成，不批量清空 url_rewrite；需要保留旧流量时创建明确的 301，避免重定向环。</p>
<h2>上线后的验收</h2>
<p>逐个 Store View 测试新 URL、旧 URL 301、canonical、Sitemap 与面包屑。清缓存后源站和 CDN 都应返回一致路径。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 新增分类提示 URL key for specified store already exists&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Tue, 15 Apr 2025 05:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 邮件模板变量显示为空]]></title>
      <link>https://www.360magento.com/blog/email-template-variable-empty/</link>
      <description><![CDATA[<p>新版邮件模板使用严格变量解析，能否显示取决于发送代码显式传入的 template_vars。旧模板直接调用对象方法可能被过滤为空，清缓存不会补齐变量。</p>
<h2>先固定复现条件</h2>
<p>保存失败邮件的订单号、Store View、模板 ID 与发送时间，先切回默认模板对照。默认正常说明自定义模板或变量名错误。</p>
<pre><code>grep -R --line-number "setTemplateVars\|template_vars" app/code vendor 2&gt;/dev/null
php bin/magento config:show sales_email/general/async_sending
SELECT entity_id,increment_id,customer_email,store_id FROM sales_order WHERE increment_id='000000123';</code></pre>
<h2>根据结果定位根因</h2>
<p>模板中的 {{var custom_value}} 必须与数组键完全一致。异步队列执行时还要恢复正确 store、area 和环境模拟；否则同步测试正常、队列邮件却为空。</p>
<h2>修复时保留回滚路径</h2>
<p>在发送服务中显式构造最小变量数组，并对可能为空的业务值给出安全默认值。不要放宽过滤器以允许任意方法调用，也不要把完整订单对象序列化到日志。</p>
<h2>上线后的验收</h2>
<p>测试访客与登录客户、两种语言、同步与异步发送。主题、正文、附件和后台重发都应得到同一变量值，且邮件日志不含敏感对象。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 邮件模板变量显示为空&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Mon, 14 Apr 2025 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 setup:upgrade 卡在 Module data setup]]></title>
      <link>https://www.360magento.com/blog/setup-upgrade-module-data-stuck/</link>
      <description><![CDATA[<p>停在模块名称不一定是死锁，数据补丁可能更新大表，也可能被线上连接阻塞。不要直接终止后反复运行，不可重入补丁可能重复写数据。</p>
<h2>先固定复现条件</h2>
<p>记录开始时间、模块名和最后一行输出，同时观察 PHP 进程 CPU、MySQL 当前语句及日志是否继续变化。</p>
<pre><code>ps -eo pid,etime,%cpu,%mem,cmd | grep '[s]etup:upgrade'
tail -n 100 var/log/system.log var/log/exception.log
mysql -e 'SHOW FULL PROCESSLIST'
mysql -e "SELECT patch_name FROM patch_list ORDER BY patch_id DESC LIMIT 30"</code></pre>
<h2>根据结果定位根因</h2>
<p>SQL 正在扫描且行数增长，可评估维护窗口后等待；Waiting for metadata lock 则定位占锁连接。日志中准备执行但 patch_list 未记录的补丁，是首要检查对象。</p>
<h2>修复时保留回滚路径</h2>
<p>先确认旧进程退出并备份相关表，在生产数据副本复现。补丁应分批处理、以唯一条件保证幂等，不能把整表装入 PHP 内存。修复后以 -vvv 重跑，不要手工把未完成补丁写进 patch_list。</p>
<h2>上线后的验收</h2>
<p>检查模块状态、schema、数据行数与索引；第二次运行 setup:upgrade 应快速完成且不重复插入。随后退出维护模式并观察 Cron 与前台。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 setup:upgrade 卡在 Module data setup&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Fri, 11 Apr 2025 08:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL 登录后仍返回访客缓存]]></title>
      <link>https://www.360magento.com/blog/graphql-customer-guest-cache/</link>
      <description><![CDATA[<p>客户登录后 GraphQL 仍返回访客价格、空购物车或错误客户组，属于高风险缓存串号。第一步不是清缓存，而是立即确认是否可能把一个客户的数据返回给另一个客户；若响应含个人数据，应先绕过相关 CDN 规则。</p>
<h2>建立访客与登录请求对照</h2>
<pre><code>curl -sS -D /tmp/guest.h -H 'Content-Type: application/json'   --data '{"query":"{ customerCart { id total_quantity } }"}'   https://shop.example.com/graphql

curl -sS -D /tmp/customer.h -H 'Content-Type: application/json'   -H 'Authorization: Bearer REDACTED'   --data '{"query":"{ customerCart { id total_quantity } }"}'   https://shop.example.com/graphql</code></pre>
<p>Token 不要写入 shell history或工单。比较 <code>Age</code>、<code>Cache-Control</code>、Varnish/CDN 命中头和响应内容。登录请求出现公共缓存 HIT 就要优先修缓存策略。</p>
<h2>确认 Authorization 到达 PHP</h2>
<pre><code>grep -R "fastcgi_param HTTP_AUTHORIZATION" /etc/nginx 2&gt;/dev/null
grep -R "SetEnvIf Authorization" /etc/apache2 2&gt;/dev/null</code></pre>
<p>只能记录头是否存在，不能记录值。若源站看不到 Authorization，检查反向代理、WAF 和 FastCGI 参数。</p>
<h2>审计缓存键与自定义 Resolver</h2>
<pre><code>grep -R --line-number "IdentityInterface|CacheableQueryInterface|getIdentities" app/code 2&gt;/dev/null
grep -R --line-number "graphql" /etc/varnish /etc/nginx 2&gt;/dev/null</code></pre>
<p>公共商品查询可以缓存，但客户购物车、客户资料和个性化价格必须按身份正确隔离或禁止共享缓存。自定义 Resolver 若返回客户相关数据，不应只用 URL 和 query body 作为缓存键。</p>
<h2>验收矩阵</h2>
<p>准备访客、客户 A、客户 B 三个会话，以相同 query 连续交叉请求。购物车 ID、客户组价格和地址不得串用；注销后应恢复访客结果。测试还要覆盖 CDN HIT/MISS、Varnish 绕过和两台 Web 节点。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 GraphQL 登录后仍返回访客缓存&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Thu, 10 Apr 2025 03:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API 提示 Invalid signature]]></title>
      <link>https://www.360magento.com/blog/rest-api-invalid-signature/</link>
      <description><![CDATA[<p>OAuth 1.0 请求返回 <code>Invalid signature</code>，通常不是 Token 权限不足，而是客户端和服务器计算出的 signature base string 不同。密钥不要打印到日志；只记录 HTTP 方法、规范化 URL、参数名、时间戳和签名算法即可定位。</p>
<h2>先区分认证类型</h2>
<p>Bearer integration token 不使用 OAuth 签名。如果 Authorization 头以 <code>OAuth</code> 开头，才检查 consumer key、token、nonce、timestamp 和 signature。先用同一凭据请求简单只读接口，排除资源 ACL。</p>
<pre><code>date -u +%s
timedatectl status
curl -I https://shop.example.com/rest/V1/store/storeConfigs</code></pre>
<h2>打印脱敏后的签名基串</h2>
<p>签名基串由大写 HTTP 方法、百分号编码后的基础 URL 和排序后的参数串组成。查询参数与 OAuth 参数都要参与排序，<code>%20</code> 不能替换成 <code>+</code>，重复编码也会失败。</p>
<pre><code>METHOD=GET
BASE_URL='https://shop.example.com/rest/V1/products'
# 日志仅输出参数名和编码结果，不输出 consumer_secret/token_secret</code></pre>
<p>Postman、SDK 与自研客户端任选两种发送同一请求。SDK 成功而自研失败，就逐字符比较 base string；两者都失败，检查服务器凭据、时间和代理。</p>
<h2>代理后的协议与 Host</h2>
<pre><code>php bin/magento config:show web/secure/base_url
php bin/magento config:show web/unsecure/base_url
grep -R "X-Forwarded-Proto|fastcgi_param HTTPS" /etc/nginx 2&gt;/dev/null</code></pre>
<p>客户端签的是 HTTPS 域名，而 Magento 在代理后识别成 HTTP 或另一个 Host，也会计算出不同 URL。修复可信代理头配置，不要让应用无条件信任来自公网的伪造头。</p>
<h2>时间戳与 nonce</h2>
<p>时间戳必须接近服务器 UTC，nonce 每次请求唯一。重放完全相同的 Authorization 头可能被拒绝。修复后连续发送三次不同 nonce 的只读请求，再测试带查询参数和 POST body 的接口，确认编码规则一致。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 REST API 提示 Invalid signature&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Wed, 09 Apr 2025 06:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 可配置商品有库存却显示缺货]]></title>
      <link>https://www.360magento.com/blog/configurable-product-in-stock-shows-out-of-stock/</link>
      <description><![CDATA[<p>后台看到子商品 Quantity 大于 0，并不等于当前网站可售。启用 MSI 后，前台判断的是网站绑定 Stock 的 salable quantity；它由 Source 数量、Source 状态、预留量和阈值共同计算。父商品还要求至少一个启用、可见关系正确的子商品可售。</p>
<h2>用具体子 SKU 查询可售量</h2>
<pre><code>php bin/magento inventory:reservation:list-inconsistencies -r

SELECT source_code, sku, quantity, status
FROM inventory_source_item WHERE sku IN ('CONF-A-RED','CONF-A-BLUE');
SELECT stock_id, website_id FROM inventory_stock_sales_channel;</code></pre>
<p>确认当前网站对应 stock_id 后，再查该 stock 的索引表：</p>
<pre><code>SELECT sku, quantity, is_salable
FROM inventory_stock_2
WHERE sku IN ('CONF-A-RED','CONF-A-BLUE');
SELECT sku, SUM(quantity) reservation_qty
FROM inventory_reservation
WHERE sku IN ('CONF-A-RED','CONF-A-BLUE') GROUP BY sku;</code></pre>
<p>表名中的数字必须使用实际 stock_id。Source 有货但索引 <code>is_salable=0</code>，重点查 Source 是否分配到该 Stock、预留量和阈值。</p>
<h2>核对父子关系和子商品资格</h2>
<pre><code>SELECT parent_id, product_id
FROM catalog_product_super_link
WHERE parent_id=(SELECT entity_id FROM catalog_product_entity WHERE sku='CONF-A');
SELECT entity_id, sku FROM catalog_product_entity WHERE sku LIKE 'CONF-A%';</code></pre>
<p>后台逐个检查子商品 Enabled、网站分配和必选属性值。某个子商品缺少 super attribute 值时，即使有库存也不会成为可选组合。</p>
<h2>索引与补偿</h2>
<pre><code>php bin/magento indexer:status inventory catalog_product_attribute
php bin/magento indexer:reindex inventory catalog_product_attribute
php bin/magento inventory:reservation:list-inconsistencies -r</code></pre>
<p>若不一致命令给出补偿建议，先核对订单生命周期，再把输出通过官方 compensations 命令处理；不要手工删除 reservation。修复后分别测试访客、两个网站、最后一件库存下单与取消订单，确认父商品状态随子商品变化正确更新。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 可配置商品有库存却显示缺货&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Tue, 08 Apr 2025 01:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 cron_schedule 表越来越大]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-table-growing/</link>
      <description><![CDATA[<p><code>cron_schedule</code> 达到数百万行时，常见现象是 Cron 扫描变慢、锁等待增加、后台任务延迟。直接 truncate 会丢失正在排队和失败任务的证据，应先看增长来自哪种状态与哪个 job_code。</p>
<h2>统计规模与最老记录</h2>
<pre><code>SELECT COUNT(*) rows_count, MIN(created_at), MAX(created_at) FROM cron_schedule;
SELECT status, COUNT(*) cnt, MIN(scheduled_at) oldest
FROM cron_schedule GROUP BY status ORDER BY cnt DESC;
SELECT job_code, status, COUNT(*) cnt
FROM cron_schedule GROUP BY job_code,status ORDER BY cnt DESC LIMIT 30;</code></pre>
<p>pending 持续堆积表示消费者没有按时运行；success 占绝大多数但多年未清理，才是历史生命周期问题。大量 running 旧记录要先确认对应 PID 是否存在。</p>
<h2>检查 Cron 与清理配置</h2>
<pre><code>php bin/magento cron:run --group default -vvv
ps -ef | grep '[b]in/magento cron:run'
php bin/magento config:show system/cron/default/history_success_lifetime
php bin/magento config:show system/cron/default/history_failure_lifetime</code></pre>
<p>不同 cron group 可有独立配置。系统 crontab 应每分钟触发，且文件所有者、PHP 版本和 Magento CLI 一致。检查日志中是否有 <code>history_cleanup</code> 或数据库死锁异常。</p>
<h2>清理要分批并保留失败证据</h2>
<p>先备份失败任务摘要，再在维护窗口按主键小批删除过期 success/missed/error 记录。不要一次删除数百万行，否则会产生长事务与大量 undo。</p>
<pre><code>SELECT schedule_id, job_code, status, messages, scheduled_at, executed_at
FROM cron_schedule WHERE status IN ('error','missed')
ORDER BY schedule_id DESC LIMIT 200;

DELETE FROM cron_schedule
WHERE status='success' AND finished_at &lt; UTC_TIMESTAMP() - INTERVAL 7 DAY
ORDER BY schedule_id LIMIT 5000;</code></pre>
<p>重复执行前观察复制延迟和锁等待。删除后根据表空间策略决定是否 OPTIMIZE；生产高峰期不要盲目重建大表。</p>
<h2>防止再次增长</h2>
<p>连续三天记录总行数、每日新增量、最老 pending 与清理耗时。清理 Job 每轮能覆盖新增量、pending 不跨越预期周期、Cron 运行时间稳定，才算治理完成。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 cron_schedule 表越来越大&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Mon, 07 Apr 2025 07:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 购物车金额与支付页面不一致]]></title>
      <link>https://www.360magento.com/blog/cart-payment-total-mismatch/</link>
      <description><![CDATA[<p>购物车显示 99.00，进入支付页却变成 98.99 或 109.00，不能只在前端格式化金额。Magento 的总额会经过 subtotal、discount、shipping、tax、gift card 和 grand_total 等 collector，多币种站点还会同时保存 base 金额与显示币种金额。先确定偏差首次出现在哪一层。</p>
<h2>固定一个可重复的测试购物车</h2>
<p>只保留一个简单商品，记录 SKU、数量、客户组、配送国家、优惠码和币种。浏览器 Network 中保存 totals-information、shipping-information 和 payment-information 三个请求的响应，比较 <code>grand_total</code> 与 <code>base_grand_total</code>。</p>
<pre><code>SELECT entity_id, store_id, is_active, items_count, subtotal, base_subtotal,
       grand_total, base_grand_total, quote_currency_code, base_currency_code
FROM quote WHERE entity_id=12345G

SELECT address_type, subtotal, discount_amount, shipping_amount,
       tax_amount, grand_total, base_grand_total
FROM quote_address WHERE quote_id=12345;</code></pre>
<p>quote 已错误，检查 collector；quote 正确而支付请求错误，则检查支付模块转换和取值。不要直接改 grand_total，下一次 collectTotals 会覆盖它。</p>
<h2>检查自定义 totals collector</h2>
<pre><code>grep -R --line-number "sales.xml|sort_order|collect(" app/code/*/*/etc app/code/*/*/Model 2&gt;/dev/null
grep -R --line-number "setGrandTotal|setBaseGrandTotal" app/code 2&gt;/dev/null</code></pre>
<p>自定义费用必须同时维护 base 与非 base 金额，并使用加法而不是覆盖已有总额。collector 的 sort_order 若在 tax 或 discount 前后放错，会让含税口径发生变化。临时禁用模块只能在预发布环境做 A/B 对照。</p>
<h2>排除四舍五入和币种换算</h2>
<pre><code>php bin/magento config:show tax/calculation/algorithm
php bin/magento config:show currency/options/base
php bin/magento config:show currency/options/default
SELECT * FROM directory_currency_rate WHERE currency_from='USD';</code></pre>
<p>一分钱差异常由逐项四舍五入与总额四舍五入混用造成。支付请求应使用订单币种最小单位，并由精确 decimal 金额转换，不能先经过浮点运算。</p>
<h2>验收</h2>
<p>依次测试无优惠、百分比优惠、固定额优惠、含运费税和切换币种。购物车、结账 totals、订单、发票与网关后台金额必须一致；失败支付重新下单也不能复用旧 quote 总额。</p>
<h2>生产环境操作前的检查</h2>
<p>针对&ldquo;Magento 2 购物车金额与支付页面不一致&rdquo;进行处理时，先记录 Magento 版本、部署模式、问题 Store View、复现时间和最近一次发布。所有 SQL 默认先执行 SELECT；需要 UPDATE、DELETE、补偿命令或目录删除时，必须先确认命中范围并保留可恢复备份。多 Web 节点环境还要比较代码版本、<code>app/etc/env.php</code> 摘要和当前流量节点，避免只修复其中一台。</p>
<pre><code>php bin/magento --version
php bin/magento deploy:mode:show
php bin/magento maintenance:status
php bin/magento indexer:status
php bin/magento cache:status</code></pre>
<p>命令应由 Magento 文件所有者在项目根目录执行。生产站不要同时运行多个全量索引或静态部署任务；若涉及数据库结构、库存、支付或订单，先在脱敏的生产数据副本验证，再安排维护窗口。</p>
<h2>建立可比较的排查记录</h2>
<p>每次实验只改变一个变量，并保存&ldquo;操作前值、执行命令、开始时间、结束时间、结果、回滚方式&rdquo;。至少准备一个正常对象和一个异常对象作对照，例如两个 SKU、两张订单或访客与登录客户。若修复后仅当前对象恢复，而新建对象仍会复现，说明根因尚未消除。</p>
<table>
<thead>
<tr><th>检查点</th><th>需要记录</th><th>通过标准</th></tr>
</thead>
<tbody>
<tr>
<td>数据层</td>
<td>主键、Store/Website、更新时间、关联行数</td>
<td>关系完整且无孤儿记录</td>
</tr>
<tr>
<td>应用层</td>
<td>异常堆栈、模块、Cron/消费者状态</td>
<td>无新异常并可重复执行</td>
</tr>
<tr>
<td>缓存与索引</td>
<td>索引模式、版本、源站和公网响应</td>
<td>按预期周期自动更新</td>
</tr>
<tr>
<td>业务回归</td>
<td>正常路径、失败路径、重复请求</td>
<td>结果一致且没有重复副作用</td>
</tr>
</tbody>
</table>
<h2>修复后的观察窗口</h2>
<p>上线后不要只刷新一次页面就结束。至少观察一轮 Cron、队列消费和索引周期，并在两台节点、无痕浏览器及目标 Store View 重复验证。对日志、数据库行数、错误率和响应时间设置临时观察项；确认它们稳定后再移除调试日志。调试日志可能包含客户、订单或令牌信息，采集时要脱敏，问题结束后及时关闭。</p>]]></description>
      <pubDate>Fri, 04 Apr 2025 02:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 catalog_product_entity_varchar 表数据过多]]></title>
      <link>https://www.360magento.com/blog/catalog-product-varchar-table-large/</link>
      <description><![CDATA[<p><code>catalog_product_entity_varchar</code> 保存商品的文本型 EAV 属性值。商品多、Store View 多时表大很正常；真正需要处理的是异常增长、重复 Store View 覆盖、已删除实体残留或集成每次都写入无意义值。直接按行数删除会损坏商品名称、URL key、图片路径等核心数据。</p>
<h2>先量化：大在哪里</h2>
<pre><code>SELECT table_rows, data_length, index_length,
       ROUND((data_length+index_length)/1024/1024,1) AS total_mb
FROM information_schema.tables
WHERE table_schema=DATABASE()
  AND table_name='catalog_product_entity_varchar';

SELECT attribute_id, store_id, COUNT(*) AS rows_count
FROM catalog_product_entity_varchar
GROUP BY attribute_id, store_id
ORDER BY rows_count DESC
LIMIT 30;</code></pre>
<p>再把 attribute_id 映射成属性代码：</p>
<pre><code>SELECT v.attribute_id, a.attribute_code, v.store_id, COUNT(*) AS rows_count
FROM catalog_product_entity_varchar v
JOIN eav_attribute a ON a.attribute_id=v.attribute_id
GROUP BY v.attribute_id, a.attribute_code, v.store_id
ORDER BY rows_count DESC
LIMIT 50;</code></pre>
<p>如果某个自定义属性占比异常，就从它的导入或保存逻辑入手；如果每个 Store View 都接近完整商品数，可能是导入把 Default 值复制到了所有范围。</p>
<h2>检查无效 Store 和无主实体</h2>
<pre><code>SELECT v.store_id, COUNT(*)
FROM catalog_product_entity_varchar v
LEFT JOIN store s ON s.store_id=v.store_id
WHERE v.store_id&lt;&gt;0 AND s.store_id IS NULL
GROUP BY v.store_id;

SELECT COUNT(*) AS orphan_rows
FROM catalog_product_entity_varchar v
LEFT JOIN catalog_product_entity p ON p.entity_id=v.entity_id
WHERE p.entity_id IS NULL;</code></pre>
<p>Commerce 某些版本使用 <code>row_id</code> 关联，必须先 <code>DESCRIBE</code> 表并按当前架构改查询。暂存内容也可能让看似无主的 row_id 实际有效，不能照抄删除。</p>
<h2>识别与 Default 完全相同的 Store View 覆盖</h2>
<pre><code>SELECT s.value_id, s.entity_id, s.attribute_id, s.store_id, s.value
FROM catalog_product_entity_varchar s
JOIN catalog_product_entity_varchar d
  ON d.entity_id=s.entity_id
 AND d.attribute_id=s.attribute_id
 AND d.store_id=0
WHERE s.store_id&lt;&gt;0 AND s.value=d.value
LIMIT 100;</code></pre>
<p>相同值不一定冗余：业务可能故意固定 Store View 值，防止 Default 后续变化。先与内容团队确认继承语义，并按属性、商店和来源系统生成候选清单。</p>
<h2>用时间和批次判断增长来源</h2>
<p>EAV value 表通常没有 created_at。若需要定位最近增长，可从 binlog、数据库审计、导入报告和商品 updated_at 建立时间关联。先统计一段时间内被大量修改的商品，再对这些 entity_id 的 varchar 属性分布进行抽样：</p>
<pre><code>SELECT DATE(updated_at) AS day, COUNT(*) AS products_changed
FROM catalog_product_entity
WHERE updated_at &gt;= CURRENT_DATE - INTERVAL 14 DAY
GROUP BY DATE(updated_at)
ORDER BY day;

SELECT v.attribute_id, v.store_id, COUNT(*) AS rows_count
FROM catalog_product_entity_varchar v
JOIN catalog_product_entity p ON p.entity_id=v.entity_id
WHERE p.updated_at &gt;= CURRENT_DATE - INTERVAL 1 DAY
GROUP BY v.attribute_id, v.store_id
ORDER BY rows_count DESC;</code></pre>
<p>某次 ERP 全量同步后所有 Store View 同时增长，通常比单个商品编辑更可疑。把增长曲线与任务开始、结束时间对齐，能找到真正写入者。</p>
<h2>删除前评估索引和锁的成本</h2>
<p>大批删除会产生 undo、redo 和复制流量。先在副本上用相同 WHERE 条件执行 <code>SELECT COUNT(*)</code>，查看执行计划是否使用 entity_id/attribute_id/store_id 索引。生产清理应按主键小批次提交，并监控副本延迟：</p>
<pre><code>EXPLAIN SELECT value_id
FROM catalog_product_entity_varchar
WHERE attribute_id=999 AND store_id=3;

SHOW INDEX FROM catalog_product_entity_varchar;
SHOW ENGINE INNODB STATUS\G</code></pre>
<p>如果删除目标是&ldquo;Store View 值与 Default 相同&rdquo;，需要在临时表固化 value_id 清单，避免清理过程中 Default 值又发生变化。清理脚本必须可重复执行且不会扩大匹配范围。</p>
<h2>找到制造数据的流程</h2>
<p>对比表增长时间与商品导入、ERP 同步、批量属性更新日志。检查集成是否每次为所有 Store View 写空字符串或重复值。正确做法是：没有本地覆盖时不写 Store View 行；需要恢复继承时删除特定范围值，而不是写一份 Default 副本。</p>
<h2>清理必须可回滚</h2>
<ol>
<li>在副本数据库执行统计和候选查询。</li>
<li>把待删除行复制到带日期的备份表，并记录 SQL 与行数。</li>
<li>抽查名称、URL key、图片、元数据等高风险属性。</li>
<li>小批量事务删除，检查复制延迟和锁等待。</li>
<li>重建相关索引并做前台回归。</li>
</ol>
<p>删除行后表文件未立即变小很正常。<code>OPTIMIZE TABLE</code> 可能重建大表并占用大量磁盘与锁时间，只能在评估空间、复制和维护窗口后执行。目标应是停止异常增长和改善查询，而不是追求立刻缩小文件。</p>]]></description>
      <pubDate>Thu, 03 Apr 2025 07:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 静态内容部署卡在 frontend/Magento/blank]]></title>
      <link>https://www.360magento.com/blog/static-content-deploy-stuck/</link>
      <description><![CDATA[<p><code>setup:static-content:deploy</code> 长时间停在 <code>frontend/Magento/blank</code>，终端没有新输出不一定代表死锁。它可能在压缩大量文件、等待子进程、发生内存换页，或某个主题继承/语言包文件让编译器反复处理。不要在生产发布窗口盲目 Ctrl+C，先看进程是否仍有进展。</p>
<h2>一分钟内判断进程状态</h2>
<pre><code>ps -eo pid,ppid,etime,%cpu,%mem,stat,cmd | grep '[s]etup:static-content:deploy'
pgrep -P 12345 -a
pidstat -p 12345 5 6
df -h
df -i
free -m</code></pre>
<p>CPU 持续有占用、输出目录文件数在增长，通常只是慢；进程状态 D 且磁盘 I/O 等待高，查存储；进程 S、无子进程、日志和文件长时间不变，才更像等待或锁。</p>
<h2>观察输出是否推进</h2>
<pre><code>watch -n 5 'find pub/static/frontend/Magento/blank -type f 2&gt;/dev/null | wc -l'
du -sh pub/static var/view_preprocessed 2&gt;/dev/null
tail -f /tmp/static-deploy.log</code></pre>
<p>下次执行把 stdout 和 stderr 同时保存：</p>
<pre><code>php -d memory_limit=-1 bin/magento setup:static-content:deploy -f -vvv \
  2&gt;&amp;1 | tee /tmp/static-deploy.log</code></pre>
<p><code>memory_limit=-1</code> 只适合有容器/系统内存限制和监控的维护环境，不是长期默认。若主机开始大量 swap，取消无限内存并减少并行度。</p>
<h2>按 area、theme、locale 隔离失败组合</h2>
<pre><code>php bin/magento setup:static-content:deploy -f en_US \
  --area frontend --theme Magento/blank -vvv

php bin/magento setup:static-content:deploy -f zh_CN \
  --area frontend --theme Vendor/theme -vvv</code></pre>
<p>Blank 成功、自定义主题失败，检查主题继承、LESS 变量与 requirejs 配置；en_US 成功、zh_CN 失败，检查语言包文件编码和翻译 CSV。一次只测一个组合比全量部署更容易定位。</p>
<h2>搜索编译器异常和循环引用</h2>
<pre><code>grep -n -Ei 'error|exception|fatal|memory|permission' /tmp/static-deploy.log
find app/design app/code -name '*.less' -o -name 'requirejs-config.js'
grep -R --line-number '@import' app/design/frontend/Vendor/theme/web/css/source 2&gt;/dev/null</code></pre>
<p>自定义 LESS 的循环 import、巨大 source map、不可读文件或损坏软链接都可能表现为某主题长时间不动。使用 <code>namei -l</code> 检查路径权限，不要全局 chmod 777。</p>
<h2>安全中止与重新开始</h2>
<p>确认进程无 I/O、无子任务且已超出基线时间后，先发送 TERM 并等待清理，不直接 kill -9。重新部署前只删除已确认属于目标 area/theme/locale 的输出与预处理目录；构建型发布最好在独立构建机生成产物，再原子切换到 Web 节点。</p>
<h2>并行部署卡住时检查子进程和文件描述符</h2>
<p>使用并行策略后，父进程可能在等待一个失败但未正常回收的子进程。记录父子 PID、打开文件数量和系统限制：</p>
<pre><code>PARENT=12345
pstree -ap "$PARENT"
for p in "$PARENT" $(pgrep -P "$PARENT"); do
  printf '%s ' "$p"; ls /proc/$p/fd 2&gt;/dev/null | wc -l
done
ulimit -n
cat /proc/$PARENT/limits | grep -i 'open files'</code></pre>
<p>若日志出现 Too many open files，先确认是主题文件数量、进程泄漏还是系统限制过低，再调整构建环境。只提高 ulimit 而不查泄漏，下一次更大的部署仍会卡住。</p>
<h2>确认构建目录没有被其他发布同时修改</h2>
<pre><code>lsof +D pub/static/frontend/Magento/blank 2&gt;/dev/null | head -n 50
ps -ef | grep -E '[s]etup:static-content:deploy|[d]eploy' 
find pub/static -maxdepth 2 -name deployed_version.txt -print -exec cat {} \;</code></pre>
<p>两套流水线同时删除和生成 <code>pub/static</code> 会出现&ldquo;本进程一直有输出但目标文件反复消失&rdquo;的假卡死。发布系统应使用互斥锁或构建版本目录，完成后一次性切换软链接。</p>
<p>验收时比较部署命令退出码、目标文件数量、首页和结账关键 JS/CSS 的 HTTP 200，并从所有 Web 节点各取一次静态版本。部署&ldquo;跑完&rdquo;但节点版本不一致仍会产生随机 404。</p>]]></description>
      <pubDate>Wed, 02 Apr 2025 02:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 退款后库存没有自动回补]]></title>
      <link>https://www.360magento.com/blog/refund-stock-not-restored/</link>
      <description><![CDATA[<p>退款成功并不必然等于库存回补。Magento 2 创建 Credit Memo 时，财务退款与库存退货是两个决定；启用 MSI 后还要区分 Source Quantity 和 Salable Quantity。排查前先记录订单号、Credit Memo、SKU、退款数量、发货来源和操作人。</p>
<h2>先确认 Credit Memo 是否要求 Return to Stock</h2>
<p>打开退款记录，检查每个商品的 Return to Stock 是否勾选、Qty to Refund 是否正确。线上退款网关返回成功，只证明资金处理完成；如果 API 创建贷项通知单时没有传回库参数，库存不会自动增加。</p>
<h2>把订单生命周期查完整</h2>
<pre><code>SELECT entity_id, increment_id, state, status, total_qty_ordered
FROM sales_order WHERE increment_id='000001500';

SELECT entity_id, increment_id, order_id, created_at
FROM sales_creditmemo
WHERE order_id=(SELECT entity_id FROM sales_order WHERE increment_id='000001500');

SELECT sku, qty, back_to_stock
FROM sales_creditmemo_item
WHERE parent_id=321;</code></pre>
<p>不同版本字段可能略有差异，执行前用 <code>DESCRIBE sales_creditmemo_item</code> 核对。查询用于取证，不直接 UPDATE 销售表。</p>
<h2>MSI 中 Source Quantity 与 Reservation 分开看</h2>
<pre><code>SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku='REFUND-SKU';

SELECT stock_id, sku, quantity, is_salable
FROM inventory_stock_1
WHERE sku='REFUND-SKU';

SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku='REFUND-SKU'
ORDER BY reservation_id DESC
LIMIT 20;</code></pre>
<p><code>inventory_stock_1</code> 可能是视图或索引表，Stock ID 也不一定是 1，应按销售渠道实际绑定查询。发货时 Source Deduction 减少来源库存；取消或退款相关操作则可能通过补偿预留影响可售量，两者变化时间不同。</p>
<h2>检查不一致而不是手工加数量</h2>
<pre><code>php bin/magento inventory:reservation:list-inconsistencies -r
php bin/magento inventory:reservation:list-inconsistencies -c</code></pre>
<p>先只列出结果并核对订单。只有确认属于缺失补偿且理解命令输出时，才在维护流程中生成补偿。直接 UPDATE <code>inventory_reservation</code> 或 source quantity 容易造成重复回补。</p>
<h2>第三方退款接口是否只做了在线退款</h2>
<p>搜索支付模块和 ERP 集成中创建 Credit Memo 的代码，检查是否设置退款商品数量与 return-to-stock 标志：</p>
<pre><code>grep -R --line-number --include='*.php' \
  -E 'Creditmemo|refund\(|back_to_stock|ReturnToStock' app/code vendor/vendorname 2&gt;/dev/null</code></pre>
<p>修复时要实现幂等：支付回调重试不能创建第二张 Credit Memo，也不能再次加库存。</p>
<p>回归至少覆盖未发货取消、已发货全额退款、部分数量退款、Bundle/可配置商品和多来源发货。每种情况同时记录 Source Quantity、Salable Quantity、Reservation 与销售单据，四者符合业务含义才算通过。</p>]]></description>
      <pubDate>Tue, 01 Apr 2025 06:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 下单提示 Please enter a valid phone number]]></title>
      <link>https://www.360magento.com/blog/checkout-valid-phone-number/</link>
      <description><![CDATA[<p>结账时提示 <code>Please enter a valid phone number</code>，不要先把 telephone 改成非必填。这个提示可能来自浏览器端自定义正则、第三方地址模块，或后端地址验证。第一步是确认错误发生在输入时、点击 Next 时，还是 place order 接口返回后。</p>
<h2>识别报错来源</h2>
<ol>
<li>打开 Console 和 Network，输入一个纯数字测试号码。</li>
<li>如果离开输入框立即报错，查看元素的 class、data-validate 和 Knockout 配置。</li>
<li>如果点击 Next 后报错，查看 shipping-information 请求响应。</li>
<li>如果最后下单才失败，保存 payment-information 请求的响应体和服务端日志时间。</li>
</ol>
<p>不要在日志或工单中记录真实客户电话，使用测试号码复现。</p>
<h2>检查 telephone 客户属性配置</h2>
<p>后台 Stores &rarr; Configuration &rarr; Customers &rarr; Customer Configuration &rarr; Name and Address Options 中核对 Show Telephone。再检查 EAV 属性：</p>
<pre><code>SELECT attribute_id, attribute_code, is_required, frontend_class
FROM eav_attribute
WHERE attribute_code='telephone';</code></pre>
<p><code>frontend_class</code> 或扩展属性可能添加了 <code>validate-phoneStrict</code> 等规则。前端组件又可能在 layout processor 中覆盖它。</p>
<h2>找到是谁注册了验证规则</h2>
<pre><code>grep -R --line-number --include='*.js' --include='*.php' --include='*.xml' \
  -E 'valid phone number|validate-phone|telephone.*validation|phoneStrict' \
  app/code app/design vendor/vendorname 2&gt;/dev/null</code></pre>
<p>如果多个模块使用同一规则名，后加载的定义会覆盖前一个。检查 requirejs mixin 和 checkout layout processor 的执行顺序。</p>
<h2>用国家维度测试，而不是只换一个号码</h2>
<table>
<thead>
<tr><th>国家</th><th>输入样例</th><th>目的</th></tr>
</thead>
<tbody>
<tr>
<td>中国</td>
<td>本地格式与 +86 格式</td>
<td>检查空格、加号和位数</td>
</tr>
<tr>
<td>美国</td>
<td>10 位与 +1 格式</td>
<td>检查括号/连字符</td>
</tr>
<tr>
<td>无固定格式国家</td>
<td>短号与国际格式</td>
<td>防止正则过度限制</td>
</tr>
</tbody>
</table>
<p>业务若需要严格验证，正则应随 country_id 变化；一个全球通用的固定 11 位规则一定会误伤。</p>
<h2>后端仍需独立校验和标准化</h2>
<p>不能只删除前端规则。REST/GraphQL 或恶意请求可绕过 JavaScript。建议后端允许业务接受的字符，去除展示空格后做长度和国家校验，并返回明确字段错误。不要擅自把客户输入改成另一个号码。</p>
<pre><code>tail -f var/log/exception.log var/log/system.log
grep -R --line-number 'telephone' app/code/*/*/Plugin app/code/*/*/Observer 2&gt;/dev/null</code></pre>
<p>完成修改后测试访客结账、登录客户旧地址、新建地址、后台创建订单和 API 下单。电话号码保存到 quote_address 与 order_address 后应一致，且历史地址仍可正常选择。</p>]]></description>
      <pubDate>Mon, 31 Mar 2025 01:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多网站切换币种后价格不更新]]></title>
      <link>https://www.360magento.com/blog/currency-switch-price-not-updated/</link>
      <description><![CDATA[<p>Magento 2 货币切换器改变了 URL 或选择框，但商品价格仍是原币种时，先区分&ldquo;币种符号没变&rdquo;和&ldquo;符号变了但金额没换算&rdquo;。前者多半是会话、Cookie 或全页缓存问题，后者更接近汇率或自定义价格渲染问题。</p>
<h2>建立四格测试</h2>
<table>
<thead>
<tr><th>场景</th><th>要记录的结果</th></tr>
</thead>
<tbody>
<tr>
<td>访客、网站 A、默认币种</td>
<td>Cookie、符号、金额</td>
</tr>
<tr>
<td>访客、网站 A、第二币种</td>
<td>切换响应与页面缓存头</td>
</tr>
<tr>
<td>登录客户、网站 A</td>
<td>是否跟随客户 Session</td>
</tr>
<tr>
<td>同浏览器、网站 B</td>
<td>Cookie Path/Domain 是否串站</td>
</tr>
</tbody>
</table>
<p>在无痕窗口执行，避免旧 <code>currency</code> Cookie 干扰。Network 中找到切换请求，确认响应是否 Set-Cookie，以及后续商品页请求是否带上新值。</p>
<h2>检查网站允许币种与基础币种</h2>
<pre><code>php bin/magento config:show currency/options/base
php bin/magento config:show currency/options/default
php bin/magento config:show currency/options/allow
php bin/magento config:show catalog/price/scope</code></pre>
<p>CLI 默认读取范围可能不是问题网站，后台切换 Website Scope 再核对。网站基础币种与允许展示币种是两件事；Catalog Price Scope 为 Website 时，不同网站可以有独立基础价格。</p>
<h2>验证汇率不是 0 或过期值</h2>
<pre><code>SELECT currency_from, currency_to, rate
FROM directory_currency_rate
ORDER BY currency_from, currency_to;</code></pre>
<p>用一个固定价格商品手算期望金额，避免被税费或特殊价格干扰。若后台 Import Rates 报错，检查 Cron、汇率服务凭据和日志；不要把汇率默认为 1 作为长期修复。</p>
<h2>全页缓存必须按币种区分</h2>
<p>连续请求默认币种和第二币种页面并保存响应头：</p>
<pre><code>curl -sSI -b 'currency=USD' https://shop.example.com/test-product.html
curl -sSI -b 'currency=EUR' https://shop.example.com/test-product.html</code></pre>
<p>检查 <code>X-Magento-Vary</code>、Age 和缓存命中。若 CDN 忽略必要 Cookie，可能把第一位访客的币种页面缓存给所有人。CDN 规则应与 Magento/Varnish 设计一致，不要简单把所有 Cookie 加进缓存键导致命中率归零。</p>
<h2>自定义前端是否绕过价格组件</h2>
<pre><code>grep -R --line-number --include='*.phtml' --include='*.js' \
  -E 'getPrice\(|price-box|formatPrice|baseCurrency' app/design app/code 2&gt;/dev/null</code></pre>
<p>直接输出数据库 price 或在 JavaScript 写死货币符号，会绕过当前货币换算。可配置商品切换选项时还要确认 price-box 收到的是当前货币 JSON。</p>
<p>修复后用同一商品验证列表页、详情页、迷你购物车、购物车和结账；再切回原币种，确保金额不会二次换算。订单中保存的 order_currency_code 和 base_currency_code 也必须符合预期。</p>]]></description>
      <pubDate>Fri, 28 Mar 2025 08:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 连接提示 Connection refused]]></title>
      <link>https://www.360magento.com/blog/opensearch-connection-refused/</link>
      <description><![CDATA[<p><code>Connection refused</code> 与&ldquo;认证失败&rdquo;不是一类问题。它表示 TCP 连接到目标主机和端口时，没有服务接受连接，或网络设备主动拒绝。先确认 Magento 实际连接的 host/port，再从运行 PHP 的同一网络环境测试，不能只在 OpenSearch 服务器本机 curl。</p>
<h2>读取 Magento 当前有效配置</h2>
<pre><code>php bin/magento config:show catalog/search/engine
php bin/magento config:show catalog/search/opensearch_server_hostname
php bin/magento config:show catalog/search/opensearch_server_port
php bin/magento config:show catalog/search/opensearch_enable_auth</code></pre>
<p>配置可能被 <code>app/etc/env.php</code> 或环境变量锁定。后台显示值与 CLI 不一致时，以当前运行实例读取到的值为准。</p>
<h2>在 PHP 容器或 Web 节点内测试网络</h2>
<pre><code>getent hosts opensearch
nc -vz opensearch 9200
curl -v --connect-timeout 3 http://opensearch:9200/</code></pre>
<p><code>getent</code> 失败是 DNS/容器服务名问题；DNS 正常但 nc refused，查目标监听；连接建立后返回 401/403，网络已经通了，转去查认证。不要把 401 当作端口问题。</p>
<h2>OpenSearch 服务器实际监听在哪里</h2>
<pre><code>systemctl status opensearch --no-pager
journalctl -u opensearch -n 120 --no-pager
ss -lntp | grep 9200
curl -sS http://127.0.0.1:9200/</code></pre>
<p>只监听 127.0.0.1 时，远程 Magento 无法连接。修改 <code>network.host</code> 前先确认防火墙、TLS 和访问控制，不能为了连接成功直接暴露 0.0.0.0:9200 到公网。</p>
<h2>容器与主机名的常见误区</h2>
<p>在 Docker/Kubernetes 中，<code>localhost</code> 指当前 PHP 容器，不是 OpenSearch 容器。Magento 应使用 service name 和容器端口；宿主机映射端口只供宿主机或外部访问。检查：</p>
<pre><code>docker ps --format 'table {{.Names}}\t{{.Ports}}'
docker network inspect app-network
kubectl get svc,endpoints -n commerce</code></pre>
<h2>TLS 和协议不匹配</h2>
<p>若服务只接受 HTTPS，而 Magento 配成 HTTP，常见表现可能是连接重置或协议错误。分别测试：</p>
<pre><code>curl -vk https://opensearch:9200/
openssl s_client -connect opensearch:9200 -servername opensearch &lt;/dev/null</code></pre>
<p>证书验证失败应安装正确 CA 或修证书 SAN，不要长期使用跳过验证。账号密码也不要出现在命令历史中。</p>
<h2>连接恢复后的应用验证</h2>
<pre><code>php bin/magento indexer:reindex catalogsearch_fulltext
php bin/magento indexer:status catalogsearch_fulltext
curl -s 'http://opensearch:9200/_cluster/health?pretty'</code></pre>
<p>集群至少要能正常分配目标索引，前台搜索常用词能返回商品。然后重启一台 PHP 节点或消费者确认配置仍有效，避免只修好了当前 shell 所在容器。</p>]]></description>
      <pubDate>Thu, 27 Mar 2025 01:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台打开订单页面特别慢]]></title>
      <link>https://www.360magento.com/blog/admin-order-page-slow/</link>
      <description><![CDATA[<p>订单列表打开很快，点击某个订单详情却等待十几秒，通常说明详情页面的额外 Block、Plugin 或外部接口在阻塞。优化前先回答两个问题：所有订单都慢，还是只有特定订单慢；服务器耗时，还是浏览器加载资源耗时。</p>
<h2>把一次请求拆成四段时间</h2>
<pre><code>curl -k -o /dev/null -s -w \
'dns=%{time_namelookup} connect=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
'https://admin.example.com/admin/sales/order/view/order_id/123/'</code></pre>
<p>后台 URL 需要有效会话，curl 仅用于你已有安全测试方式；不要把管理员 Cookie 写入共享脚本。浏览器 Network 里若主文档 TTFB 很高，查 PHP/MySQL；主文档快而某个 XHR 慢，直接定位该接口。</p>
<h2>对比快订单与慢订单</h2>
<p>选择同一天、相近商品数的一快一慢订单，比较订单项数量、评论历史、发票/发货数、地址、自定义字段和支付方式。只有含某支付方式的订单慢，通常是模块在页面加载时实时调用网关。</p>
<h2>在受控时间窗捕获慢查询</h2>
<pre><code>SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G</code></pre>
<p>不要在高峰期随意把 long_query_time 调成 0。使用现有慢日志按订单请求时段过滤，再对具体 SQL 执行 <code>EXPLAIN</code>。常见问题是自定义表按 order_id 查询却没有索引，或每个订单项执行一次查询形成 N+1。</p>
<pre><code>EXPLAIN SELECT * FROM vendor_order_extra WHERE order_id=123;
SHOW INDEX FROM vendor_order_extra;</code></pre>
<h2>按布局和插件二分</h2>
<pre><code>grep -R --line-number 'sales_order_view' app/code app/design vendor/vendorname 2&gt;/dev/null
grep -R --line-number --include='di.xml' \
  'Magento\\Sales\\Block\\Adminhtml\\Order\\View' app/code vendor/vendorname 2&gt;/dev/null</code></pre>
<p>在预发布环境禁用最近增加的订单 Block 或模块，重新编译后比较同一订单 TTFB。不要在生产直接改 XML 注释。若模块从 ERP、物流或支付平台读取状态，页面渲染应使用本地缓存数据，实时刷新改成显式按钮或异步请求，并设置连接与读取超时。</p>
<h2>PHP-FPM 侧确认是否等待外部资源</h2>
<p>开启受限的 slowlog，设置合理的 request_slowlog_timeout，复现一次后立即读取堆栈。若堆栈停在 curl/HTTP client，处理外部超时；停在 collection load，检查查询字段与索引；停在模板循环，避免在循环里加载 repository。</p>
<p>修复验收要取至少 10 个订单，记录 P50/P95 的主文档 TTFB，而不是只打开一个页面感觉变快。还要确认订单操作按钮、评论、发票和退款功能没有因为删除 Block 而丢失。</p>]]></description>
      <pubDate>Wed, 26 Mar 2025 06:55:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单邮件或发票邮件重复发送]]></title>
      <link>https://www.360magento.com/blog/duplicate-sales-email/</link>
      <description><![CDATA[<p>客户收到两封订单或发票邮件，不能仅凭收件时间判断 Magento 发了两次。邮件服务商重投、队列重复消费、后台手动发送和扩展监听同一事件，都可能产生相同现象。先从两封邮件的原始头开始。</p>
<h2>两封邮件是否拥有相同 Message-ID</h2>
<p>下载两封邮件原始内容，比较 <code>Message-ID</code>、<code>Date</code>、<code>Received</code> 链和 SMTP provider id：</p>
<ul>
<li>Message-ID 相同：更像邮件网关重投或收件端复制。</li>
<li>Message-ID 不同、内容时间相近：应用层执行了两次发送。</li>
<li>一封标记为管理员副本：检查 Send Order Email Copy To 配置。</li>
</ul>
<p>邮件原文包含客户信息，保存在受限工单，不要粘贴到公开日志。</p>
<h2>按订单时间核对发送标志</h2>
<pre><code>SELECT entity_id, increment_id, state, status, email_sent, created_at, updated_at
FROM sales_order
WHERE increment_id='000001234';

SELECT entity_id, increment_id, order_id, email_sent, created_at
FROM sales_invoice
WHERE order_id=(SELECT entity_id FROM sales_order WHERE increment_id='000001234');</code></pre>
<p><code>email_sent=1</code> 只能说明最终状态，不能证明调用次数。继续检索应用日志、SMTP 日志和第三方邮件平台事件。</p>
<h2>画出订单的发送时间线</h2>
<pre><code>grep -R '000001234' var/log | tail -n 100
journalctl -u crond --since '2025-03-25 09:50' --until '2025-03-25 10:10'
ps -ef | grep '[c]ron:run'
ps -ef | grep '[q]ueue:consumers:start'</code></pre>
<p>如果两个 Cron 入口同时配置（系统 crontab 与托管平台任务），同一分钟可能并发处理邮件。执行 <code>crontab -l</code> 并检查 systemd timer、容器计划任务和平台计划任务，确保只有一套入口。</p>
<h2>寻找自定义重复发送代码</h2>
<pre><code>grep -R --line-number --include='*.php' \
  -E 'OrderSender|InvoiceSender|send\(' app/code 2&gt;/dev/null
grep -R --line-number --include='events.xml' \
  -E 'sales_order_place_after|checkout_onepage_controller_success_action|sales_order_invoice' app/code 2&gt;/dev/null</code></pre>
<p>核心结账流程已经负责订单邮件，自定义 Observer 再调用 <code>OrderSender-&gt;send()</code> 就会重复。支付回调也可能被网关重试，处理器必须以 transaction id 或订单状态做幂等判断。</p>
<h2>SMTP 超时不代表发送失败</h2>
<p>应用把邮件交给服务商后若响应超时，扩展可能重试并产生第二封。检查 provider 的接受事件：如果第一次已经 accepted，重试策略应识别相同业务消息。不要简单关闭重试，否则真实网络失败会丢邮件。</p>
<p>修复后用测试订单验证五个动作：首次下单、重复支付回调、后台 Resend、创建发票、Cron 重启。每个业务动作应产生预期数量的唯一 Message-ID，订单历史只记录一次自动发送；同时确认管理员副本仍按配置工作。</p>]]></description>
      <pubDate>Tue, 25 Mar 2025 02:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 批量导入商品后价格变成 0]]></title>
      <link>https://www.360magento.com/blog/product-import-price-zero/</link>
      <description><![CDATA[<p>批量导入后价格变成 0，第一件事不是再导入一次，而是冻结原 CSV、导入行为和后台报告。重复导入可能把更多 Store View 或子商品覆盖成 0。先列出受影响 SKU，并保留导入前备份用于比较。</p>
<h2>CSV 中的空值并不总等于&ldquo;不修改&rdquo;</h2>
<p>用不会自动改格式的文本工具检查原始文件：</p>
<pre><code>file products.csv
head -n 3 products.csv
python3 -c "import csv; f=open('products.csv',newline='',encoding='utf-8-sig'); r=csv.DictReader(f); print([k for k in r.fieldnames if 'price' in k])"</code></pre>
<p>重点列包括 <code>price</code>、<code>special_price</code>、<code>special_price_from_date</code>、<code>special_price_to_date</code>、<code>store_view_code</code>、<code>product_websites</code>。某些表格软件会把空字符串、0、科学计数法或日期自动改写。</p>
<h2>取一个受影响 SKU 与一个正常 SKU 对照</h2>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity
WHERE sku IN ('PRICE-ZERO','PRICE-OK');

SELECT attribute_id, attribute_code, backend_type
FROM eav_attribute
WHERE entity_type_id=(SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code='catalog_product')
AND attribute_code IN ('price','special_price');</code></pre>
<p>按查询到的属性 ID 和当前版本的实体键读取 decimal 表，比较 store_id。不要把示例 attribute_id 写死：</p>
<pre><code>SELECT store_id, entity_id, attribute_id, value
FROM catalog_product_entity_decimal
WHERE entity_id IN (101,102)
  AND attribute_id IN (75,76)
ORDER BY entity_id, attribute_id, store_id;</code></pre>
<p>Default Scope 有正常价格而网站前台显示 0，继续查 Website 级价格范围和索引；数据库值就是 0，则回到导入映射。</p>
<h2>可配置商品的价格看子商品</h2>
<p>新版 Magento 2 的可配置商品展示价格通常来自可售子商品。导入若只给父商品价格、子商品 price 为空或为 0，前台最低价就可能变成 0。查询关系：</p>
<pre><code>SELECT parent_id, child_id
FROM catalog_product_super_link
WHERE parent_id = 101;

SELECT sku, entity_id FROM catalog_product_entity
WHERE entity_id IN (SELECT child_id FROM catalog_product_super_link WHERE parent_id=101);</code></pre>
<h2>恢复时使用小批量、明确列</h2>
<p>从备份或业务系统生成只包含 5 个测试 SKU 的修复 CSV，明确设置 <code>sku</code>、<code>price</code>、<code>store_view_code</code> 和需要的特殊价格列。先在后台 Check Data，保存错误报告，再导入。不要用&ldquo;Replace&rdquo;行为修价格，除非你明确接受删除重建商品的后果。</p>
<pre><code>php bin/magento indexer:reindex catalog_product_price
php bin/magento cache:clean full_page block_html</code></pre>
<p>导入后从数据库、商品页、分类页、购物车各核对一次。对可配置商品切换两个子项，对两个客户组和网站分别验证。确认小批量无误后再扩大到完整清单，并把修复前后的 SKU/价格差异存档，而不是只看后台&ldquo;Import successfully&rdquo;。</p>]]></description>
      <pubDate>Mon, 24 Mar 2025 07:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 加入购物车提示 We can't add this item to your shopping cart right now]]></title>
      <link>https://www.360magento.com/blog/cant-add-item-to-cart/</link>
      <description><![CDATA[<p><code>We can't add this item to your shopping cart right now</code> 是 Magento 2 把底层异常转换后的通用提示。真正原因可能是必选项缺失、Quote 不可用、库存校验失败或扩展在 addProduct 流程中抛错。继续点击只会制造更多噪声，先保留一次请求的完整上下文。</p>
<h2>从浏览器请求取证</h2>
<p>打开开发者工具 Network，清空记录后只点击一次加入购物车。记录 POST URL、HTTP 状态、form_key、product、qty、selected_configurable_option、super_attribute 和 custom options。响应若是 302，继续看跳转后的消息；若 500，按请求时间查服务端日志。</p>
<pre><code>tail -n 150 var/log/exception.log
tail -n 150 var/log/system.log
grep -n -B15 -A50 'shopping cart right now' var/log/*.log</code></pre>
<p>使用生产模式时前台消息通常被隐藏，异常日志中的第一条业务异常比最后一条通用 LocalizedException 更有价值。</p>
<h2>做四个对照，快速缩小范围</h2>
<ol>
<li>同一客户加入一个普通简单商品。</li>
<li>访客加入问题商品。</li>
<li>问题商品数量改为 1。</li>
<li>在新无痕会话中重新选择全部必选项。</li>
</ol>
<p>只有登录客户失败，查 customer group、shared catalog 或旧 quote；只有问题商品失败，查商品类型、选项和库存；数量 1 成功则查最小/最大销售数量与增量。</p>
<h2>核对 Quote 是否仍然活动</h2>
<pre><code>SELECT entity_id, is_active, customer_id, store_id, items_count,
       reserved_order_id, updated_at
FROM quote
WHERE entity_id = 12345;

SELECT item_id, sku, qty, parent_item_id, product_type
FROM quote_item
WHERE quote_id = 12345;</code></pre>
<p>不要把已下单 quote 的 <code>is_active</code> 直接改回 1。若 Session 指向旧 quote，应修会话恢复或自定义 checkout 逻辑，让 Magento 创建新购物车。</p>
<h2>库存必须按当前 Stock 判断</h2>
<pre><code>php bin/magento inventory:reservation:list-inconsistencies -r
php bin/magento indexer:status inventory
SELECT stock_id, sales_channel_type, code
FROM inventory_stock_sales_channel;</code></pre>
<p>可配置商品要检查实际选中的子 SKU；Bundle、Grouped 商品还要检查每个必选子项。后台显示 Source Quantity 大于 0，不等于目标网站的 Salable Quantity 大于 0。</p>
<h2>定位拦截 addProduct 的自定义代码</h2>
<pre><code>grep -R --line-number --include='di.xml' \
  'Magento\\Checkout\\Model\\Cart\|Magento\\Quote\\Model\\Quote' app/code vendor 2&gt;/dev/null
grep -R --line-number --include='events.xml' \
  'checkout_cart_product_add\|sales_quote_product_add' app/code vendor 2&gt;/dev/null</code></pre>
<p>在预发布环境按模块做二分禁用，重新编译后复现。若某插件捕获异常后只返回 false，应改为保留原异常上下文；若插件再次调用 cart save，检查是否造成递归或事务冲突。</p>
<p>修复后测试简单、可配置、Bundle 商品，各执行访客与登录客户两组；再确认迷你购物车、购物车页数量和库存预留一致。加入成功但 Quote 数据不完整，同样不能上线。</p>]]></description>
      <pubDate>Fri, 21 Mar 2025 03:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页面 mixins.js 返回 404]]></title>
      <link>https://www.360magento.com/blog/checkout-mixins-js-404/</link>
      <description><![CDATA[<p>结账页面白屏或一直转圈，控制台出现 <code>mixins.js 404</code>，说明 RequireJS 启动链在加载混入配置前就中断。此时业务接口可能完全正常，反复清浏览器缓存不会生成缺失文件。先把 404 URL 精确抄下来，因为其中的 area、theme、locale 和静态版本号决定了部署命令。</p>
<h2>拆解 404 URL</h2>
<p>示例路径：</p>
<pre><code>/static/version1742400000/frontend/Vendor/theme/zh_CN/mage/requirejs/mixins.js</code></pre>
<p>依次得到：静态版本、frontend、主题、zh_CN 和目标文件。到服务器检查去掉 <code>version...</code> 后的物理路径：</p>
<pre><code>ls -l pub/static/frontend/Vendor/theme/zh_CN/mage/requirejs/mixins.js
cat pub/static/deployed_version.txt 2&gt;/dev/null
php bin/magento deploy:mode:show</code></pre>
<h2>文件存在但 HTTP 仍 404</h2>
<p>这通常是 Nginx/Apache 重写、软链接权限或多节点不同步。绕过 CDN 请求具体节点：</p>
<pre><code>curl -sSI -H 'Host: shop.example.com' \
  http://10.0.2.15/static/version1742400000/frontend/Vendor/theme/zh_CN/mage/requirejs/mixins.js
namei -l pub/static/frontend/Vendor/theme/zh_CN/mage/requirejs/mixins.js</code></pre>
<p>若一台节点 200、另一台 404，修发布同步和负载均衡摘挂流程。若磁盘文件存在但所有节点 404，检查静态文件 location 是否正确去掉 version 前缀，以及 Web 用户能否穿过每一级目录。</p>
<h2>文件确实不存在：按实际主题与语言部署</h2>
<p>生产模式在维护窗口执行精确部署：</p>
<pre><code>php bin/magento maintenance:enable
rm -rf pub/static/frontend/Vendor/theme/zh_CN \
       var/view_preprocessed/pub/static/frontend/Vendor/theme/zh_CN
php bin/magento setup:static-content:deploy -f zh_CN en_US \
  --theme Vendor/theme --area frontend
php bin/magento cache:clean config full_page
php bin/magento maintenance:disable</code></pre>
<p>删除范围必须是已核对的具体主题/语言目录，不能在路径变量为空时运行。多节点应由同一构建产物发布，不要在每台机器独立生成可能不同的静态版本。</p>
<h2>部署命令成功却没有 mixins.js</h2>
<p>检查生成日志中是否有主题继承、语言包或文件权限错误：</p>
<pre><code>php bin/magento setup:static-content:deploy -f zh_CN \
  --theme Vendor/theme -vvv 2&gt;&amp;1 | tee /tmp/static-deploy.log
grep -n -Ei 'error|exception|permission|mixins' /tmp/static-deploy.log</code></pre>
<p>再搜索自定义 <code>requirejs-config.js</code> 是否语法错误或声明了不存在的 mixin：</p>
<pre><code>find app/code app/design -name requirejs-config.js -print
grep -R --line-number "mixins" app/code app/design</code></pre>
<p>打开结账页后，Network 中 <code>mixins.js</code>、<code>requirejs-config.js</code> 和关键 checkout bundle 都应返回 200，Console 无 RequireJS 模块错误。还要从第二台 Web 节点和无痕窗口各测一次，避免只验证了本机缓存。</p>]]></description>
      <pubDate>Thu, 20 Mar 2025 06:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品图片上传成功但前台显示占位图]]></title>
      <link>https://www.360magento.com/blog/product-image-placeholder/</link>
      <description><![CDATA[<p>后台上传图片成功，但前台显示 Magento 占位图，最容易误判为&ldquo;缓存没清&rdquo;。实际要同时满足三件事：商品媒体属性引用正确、原图文件可读、前台能生成或读取对应尺寸的缓存图。下面按文件路径走一遍，哪一步断开就修哪一步。</p>
<h2>从商品角色图片值开始</h2>
<p>在后台商品 Images and Videos 中确认 Base、Small、Thumbnail 至少分配了需要的图片，并切换到问题 Store View 检查是否被覆盖为 <code>no_selection</code>。使用 CLI 查询属性值时，先查商品 ID 与属性 ID，再读取对应 EAV 表；不要假设属性 ID 在所有环境相同。</p>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity WHERE sku='MISS-IMAGE-SKU';
SELECT attribute_id, attribute_code, backend_type
FROM eav_attribute
WHERE attribute_code IN ('image','small_image','thumbnail');</code></pre>
<p>确认具体 backend_type 后，再在对应表按 entity_id、store_id 查询。若 Default 有值而 Store View 是 <code>no_selection</code>，前台会使用占位图。</p>
<h2>把数据库路径映射到真实文件</h2>
<p>图片值通常类似 <code>/a/b/abc.jpg</code>，对应文件应位于 <code>pub/media/catalog/product/a/b/abc.jpg</code>：</p>
<pre><code>IMG='pub/media/catalog/product/a/b/abc.jpg'
stat "$IMG"
file "$IMG"
php -r '$i=getimagesize($argv[1]); var_export($i);' "$IMG"</code></pre>
<p>文件不存在时检查导入路径、大小写和远程媒体同步；文件存在但 <code>getimagesize</code> 失败，可能是损坏或扩展名与真实格式不一致。</p>
<h2>用 Web 用户测试读取和写入</h2>
<pre><code>sudo -u www-data test -r "$IMG" &amp;&amp; echo readable
sudo -u www-data test -w pub/media/catalog/product/cache &amp;&amp; echo cache-writable
find pub/media/catalog/product -maxdepth 3 -type d ! -perm -u+x | head</code></pre>
<p>Web 用户名需按服务器实际修改。不要把整个 <code>pub/media</code> 设为 777；修正所有者和组权限，并确认父目录具有执行权限。</p>
<h2>确认图片处理库与缓存生成</h2>
<pre><code>php -m | grep -Ei 'gd|imagick'
php -i | grep -Ei 'GD Support|JPEG Support|PNG Support|WebP Support'
tail -n 100 var/log/exception.log
find pub/media/catalog/product/cache -type f -name '*abc*' | head</code></pre>
<p>如果只对 WebP、CMYK JPEG 或超大图片失败，先用一张普通 RGB JPEG 做对照。缓存目录为空且日志出现内存错误，需要调整图片尺寸或 PHP-FPM 内存，而不是无限提高 CLI 的 memory_limit。</p>
<h2>远程媒体或 CDN 场景</h2>
<p>对页面中的实际图片 URL 执行 HEAD 请求：</p>
<pre><code>curl -sSI 'https://cdn.example.com/media/catalog/product/cache/.../abc.jpg'</code></pre>
<p>源站 200、CDN 404 表示同步或缓存键问题；源站也 404 就回到文件和重写规则。检查 Nginx/Apache 是否把 <code>/media/</code> 错误转给 PHP，或安全规则拒绝某些扩展名。</p>
<p>修复后只清理该商品相关缓存图或按维护计划执行图片缓存清理，再访问商品页触发生成。最后确认列表图、详情大图、缩略图、两个 Store View 和 CDN URL 都返回正确 MIME 类型；仅后台预览正常不算完成。</p>]]></description>
      <pubDate>Wed, 19 Mar 2025 01:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 分类页商品排序保存后不生效]]></title>
      <link>https://www.360magento.com/blog/category-product-sort-not-working/</link>
      <description><![CDATA[<p>后台分类中的 Position 保存成功，只代表 <code>catalog_category_product.position</code> 已写入；前台是否使用它排序，还取决于分类的 Available Product Listing Sort By、Default Product Listing Sort By、主题参数以及搜索引擎查询。先不要反复拖动商品，取三个 SKU 做可核对的排序样本。</p>
<h2>确认数据库中的 position 真正改变</h2>
<pre><code>SELECT c.entity_id AS category_id, p.sku, cp.position
FROM catalog_category_product cp
JOIN catalog_product_entity p ON p.entity_id = cp.product_id
JOIN catalog_category_entity c ON c.entity_id = cp.category_id
WHERE cp.category_id = 37
  AND p.sku IN ('SKU-A','SKU-B','SKU-C')
ORDER BY cp.position, p.entity_id;</code></pre>
<p>若 position 没变，检查后台保存请求是否返回 200、管理员权限以及扩展是否覆盖分类保存。若数据已变，问题在前台排序链路。</p>
<h2>看页面实际发送的排序参数</h2>
<p>在分类页清除 URL 参数，观察地址栏和 Network 请求中是否出现 <code>product_list_order</code>。浏览器 Local Storage、Session 或主题脚本可能记住用户上次选择的 price/name 排序。使用无痕窗口访问同一 URL，能快速排除这一层。</p>
<p>后台分类的 Display Settings 中，把默认排序显式设置为 Position，并确认 Store View 左上角 Scope。若&ldquo;Use Config Settings&rdquo;勾选，真正值来自商店配置；不同 Store View 可能不同。</p>
<h2>锚点分类和搜索引擎排序的区别</h2>
<p>非锚点分类通常直接读取分类商品关系；锚点分类还会合并子分类商品，并可能通过搜索引擎构造集合。此时同一商品可能来自多条分类关系，position 不一定按你编辑的分类解释。可临时在预发布环境关闭锚点做对照，确认是否属于聚合结果。</p>
<h2>检查主题或扩展是否强制 order</h2>
<pre><code>grep -R --line-number --include='*.php' --include='*.xml' \
  -E 'setOrder\(|addAttributeToSort|product_list_order|setDefaultOrder' \
  app/code app/design 2&gt;/dev/null</code></pre>
<p>常见扩展会按销量、库存或自定义属性重排，并在插件中忽略 position。找到代码后先在预发布禁用模块或布局块对照，不要直接改 vendor。</p>
<h2>只清理需要的索引和缓存</h2>
<pre><code>php bin/magento indexer:status catalog_category_product catalog_product_category
php bin/magento indexer:reindex catalog_category_product catalog_product_category
php bin/magento cache:clean full_page block_html</code></pre>
<p>如果使用 Varnish/CDN，再确认分类 URL 对象已失效。用 <code>curl -s</code> 抓取页面中三个 SKU 的出现顺序，比肉眼看图片稳定：</p>
<pre><code>curl -s 'https://shop.example.com/category.html?sort_test=1' \
 | grep -n -E 'SKU-A|SKU-B|SKU-C'</code></pre>
<p>验收时分别测试默认访问、显式 <code>?product_list_order=position</code>、选择价格排序后再返回，以及另一个 Store View。只有默认访问使用后台位置、用户主动选择其他排序仍能生效，才是正确结果。</p>]]></description>
      <pubDate>Tue, 18 Mar 2025 05:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 搜索结果缺少部分商品]]></title>
      <link>https://www.360magento.com/blog/search-missing-products/</link>
      <description><![CDATA[<p>当一部分商品可直接打开、分类页也可能显示，但站内搜索找不到时，先选择一个&ldquo;正常 SKU&rdquo;和一个&ldquo;缺失 SKU&rdquo;做对照。不要一开始就全量重建搜索索引；对照能快速判断是商品资格、索引写入还是查询分析问题。</p>
<h2>第一关：商品是否具备进入搜索索引的资格</h2>
<p>在后台逐项比较两个 SKU：Enabled 状态、Visibility、分配网站、所属分类、库存状态、Store View 是否覆盖名称。可见性必须包含 Search；仅 Catalog 的商品不会出现在普通搜索结果。</p>
<pre><code>php bin/magento indexer:status catalogsearch_fulltext
php bin/magento store:list

SELECT entity_id, sku FROM catalog_product_entity
WHERE sku IN ('GOOD-SKU','MISS-SKU');</code></pre>
<p>多来源库存环境还要比较目标销售渠道绑定的 Stock，而不是只看 Source Quantity。可售量小于等于 0 且配置为不显示缺货商品时，索引或查询会过滤该商品。</p>
<h2>第二关：缺失 SKU 是否进入搜索引擎文档</h2>
<p>先从配置确认搜索引擎地址和索引前缀，不要猜索引名：</p>
<pre><code>php bin/magento config:show catalog/search/engine
php bin/magento config:show catalog/search/opensearch_server_hostname
php bin/magento config:show catalog/search/opensearch_index_prefix
curl -s 'http://127.0.0.1:9200/_cat/indices?v'</code></pre>
<p>在非公网监听的管理节点查询对应索引，按 SKU 或 entity_id 查文档。若正常 SKU 有文档而缺失 SKU 没有，重点回到增量索引和商品资格；两者都有文档，则检查查询字段与 analyzer。</p>
<h2>第三关：增量索引是否漏掉变更</h2>
<pre><code>php bin/magento indexer:show-mode catalogsearch_fulltext
php bin/magento indexer:status catalogsearch_fulltext
SELECT * FROM mview_state WHERE view_id='catalogsearch_fulltext';</code></pre>
<p>若模式为 Update by Schedule，检查 Cron 是否在推进版本。只有在确认没有正在运行的索引进程后，再执行：</p>
<pre><code>php bin/magento indexer:reindex catalogsearch_fulltext
php bin/magento cache:clean full_page block_html</code></pre>
<p>重建后立刻出现、下一次商品修改又消失，说明增量链路有问题，不应把定时全量 reindex 当永久方案。</p>
<h2>用索引器维度表记录每次实验</h2>
<p>同一个商品可能同时受 catalogsearch_fulltext、catalog_category_product、inventory 和 price 索引影响。建议在排查单中为&ldquo;正常 SKU&rdquo;和&ldquo;缺失 SKU&rdquo;各记录：商品更新时间、索引器 mode、mview version、OpenSearch 文档时间、前台首次恢复时间。这样可以判断是变更根本没有进入 changelog，还是 changelog 已消费但文档写入失败。</p>
<pre><code>SELECT view_id, version_id, status, updated
FROM mview_state
WHERE view_id IN ('catalogsearch_fulltext','inventory');

SHOW TABLES LIKE '%_cl';</code></pre>
<p>不要随意清空 changelog 表。version_id 与 changelog 最大版本之间的差距能说明积压量，手工删除会让尚未消费的变更永久丢失。</p>
<h2>搜索词本身也可能被分析器改变</h2>
<p>分别搜索完整 SKU、商品名称中的独特词、名称前半段和带连字符的原词。完整 SKU 能找到但中文名称找不到，检查搜索属性权重、分词与同义词；名称能找到但 SKU 找不到，确认 SKU 属性是否参与搜索以及自定义 analyzer 是否拆分特殊字符。</p>
<p>记录前台请求的 Store Code 和搜索词，再查看 OpenSearch 慢日志或临时抓取查询。不要在生产长期开启完整请求日志，因为搜索词可能包含客户输入。</p>
<h2>修复后的验收方式</h2>
<ul>
<li>目标 Store View 的关键词能找到缺失 SKU；</li>
<li>换到未分配的网站时仍不会错误出现；</li>
<li>修改名称后，按当前索引模式在合理时间内更新；</li>
<li>禁用商品或移除网站分配后，搜索结果会消失；</li>
<li>分类页、搜索页和 GraphQL/REST 的可见性结果一致。</li>
</ul>
<p>这一组正反测试能防止&ldquo;为找回一个商品而把不可售商品全部放进搜索&rdquo;的副作用。</p>]]></description>
      <pubDate>Mon, 17 Mar 2025 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 优惠券满足条件却提示不可用]]></title>
      <link>https://www.360magento.com/blog/coupon-code-not-valid/</link>
      <description><![CDATA[<p>Magento 2 的购物车价格规则不是只比较&ldquo;优惠码正确&rdquo;和&ldquo;金额达到&rdquo;。同一规则还会受网站、客户组、生效时间、用量、商品条件、购物车地址以及是否允许与其他规则叠加影响。排查时最好复制当前购物车，逐项缩小条件，而不是不断新建规则。</p>
<h2>先确认代码命中了哪条规则</h2>
<pre><code>SELECT c.coupon_id, c.code, c.rule_id, c.usage_limit, c.usage_per_customer,
       r.name, r.is_active, r.from_date, r.to_date, r.sort_order, r.stop_rules_processing
FROM salesrule_coupon c
JOIN salesrule r ON r.rule_id = c.rule_id
WHERE c.code = 'TEST2025';</code></pre>
<p>如果返回多行，说明存在重复或历史规则，前端看到的提示未必来自你正在编辑的那条。先记录 rule_id，再在后台直接打开对应规则核对。</p>
<h2>建立一个最小可用购物车</h2>
<p>使用无痕窗口和专用客户，购物车只保留一个明确符合条件的简单商品。记录 SKU、网站、客户组、数量、折扣前小计、币种、配送国家。此时清除已应用代码后重新输入，避免 quote 中残留旧规则结果。</p>
<table>
<thead>
<tr><th>字段</th><th>实际参与判断的值</th></tr>
</thead>
<tbody>
<tr>
<td>网站</td>
<td>当前 store 所属 website_id</td>
</tr>
<tr>
<td>客户组</td>
<td>登录客户组或 NOT LOGGED IN</td>
</tr>
<tr>
<td>小计</td>
<td>规则选择的含税/未税口径</td>
</tr>
<tr>
<td>地址</td>
<td>购物车的 shipping/billing address</td>
</tr>
<tr>
<td>商品属性</td>
<td>用于促销条件的索引值和 Store View 值</td>
</tr>
</tbody>
</table>
<h2>检查网站和客户组映射</h2>
<pre><code>SELECT * FROM salesrule_website WHERE rule_id = 42;
SELECT * FROM salesrule_customer_group WHERE rule_id = 42;
SELECT website_id, code, name FROM store_website;
SELECT customer_group_id, customer_group_code FROM customer_group;</code></pre>
<p>访客结账必须包含 NOT LOGGED IN 客户组。多网站环境中，Store View 相同并不代表 website_id 相同。</p>
<h2>用量限制要同时看总量和客户量</h2>
<pre><code>SELECT coupon_id, times_used FROM salesrule_coupon WHERE code='TEST2025';
SELECT customer_id, rule_id, times_used
FROM salesrule_customer
WHERE rule_id=42 AND customer_id=123;</code></pre>
<p>不要直接把 times_used 改成 0。先检查是否有取消、失败或重复订单导致计数与业务期望不同，并在测试环境复现订单生命周期。生产修正需要留下审计记录。</p>
<h2>条件树从外到内拆开</h2>
<p>复杂规则可复制为测试规则：先保留网站、客户组和优惠码，删除所有商品/购物车条件；确认能应用后，每次只加回一层。特别注意&ldquo;满足全部&rdquo;与&ldquo;满足任一&rdquo;、SKU 是否带空格、分类条件是否针对子商品、配送国家是否在用户填写地址后才可用。</p>
<p>如果代码在购物车可用，进入结账选择地址后消失，问题就在地址或配送条件；若输入即失败，则优先查基础规则、客户组和用量。打开浏览器 Network，检查 coupon POST 的响应消息，同时查看：</p>
<pre><code>tail -f var/log/system.log var/log/exception.log
php bin/magento indexer:status
php bin/magento cache:clean config full_page</code></pre>
<p>最后至少回归访客、登录客户、两个网站、一次成功订单和一次取消订单。促销规则修复的标准不仅是&ldquo;代码能用&rdquo;，还要确保不符合条件的购物车仍然不能获得折扣。</p>]]></description>
      <pubDate>Fri, 14 Mar 2025 08:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重置密码链接打开后提示已过期]]></title>
      <link>https://www.360magento.com/blog/password-reset-link-expired/</link>
      <description><![CDATA[<p>客户刚收到重置密码邮件，点击却提示链接无效或已过期，先不要反复延长 Token 有效期。这个问题经常由多网站范围、邮件链接域名、服务器时间或模板变量错误造成；有效期只是最后才检查的一项。</p>
<h2>用一个专用测试客户记录完整请求</h2>
<ol>
<li>在对应网站创建测试客户，记录 website_id 和邮箱。</li>
<li>只点击一次&ldquo;忘记密码&rdquo;，保存邮件原始链接。</li>
<li>不要转发公开链接，Token 等同临时凭据。</li>
<li>在无痕窗口打开，并记录最终跳转 URL 与提示时间。</li>
</ol>
<p>若邮件中的域名属于另一个网站，先修 Base URL 和邮件发送范围，不要修改数据库 Token。</p>
<h2>核对客户记录与服务器时间</h2>
<pre><code>date -u
timedatectl status
php -r 'echo date(DATE_ATOM), PHP_EOL;'

SELECT entity_id, website_id, email, rp_token_created_at,
       CASE WHEN rp_token IS NULL THEN 'empty' ELSE 'present' END AS token_state
FROM customer_entity
WHERE email='test@example.com';</code></pre>
<p>数据库只确认 Token 是否生成以及生成时间，不要把 <code>rp_token</code> 输出到聊天、工单或监控日志。Web 节点、Cron 节点和数据库时间应一致；容器时区不同并不必然有问题，但 UTC 时间必须对齐。若 NTP 漂移数分钟，刚生成的 Token 也可能被判断为未来或过期。</p>
<h2>检查配置范围而不是只看 Default Config</h2>
<pre><code>php bin/magento config:show customer/password/password_reset_protection_type
php bin/magento config:show customer/password/reset_link_expiration_period
php bin/magento store:list</code></pre>
<p>后台切换到发生问题的网站 Scope，再核对 Customers 配置。多网站共享邮箱时，客户实体可能属于网站 A，而用户从网站 B 请求重置；请求看似成功，实际找到的客户范围不一致。此时要确认客户账号共享设置和前台表单运行的 website_id。</p>
<h2>检查邮件模板生成的链接</h2>
<p>恢复到默认模板做一次对照测试。自定义模板常见错误包括：把 customer id 当作 token、漏掉 id 参数、对 URL 再次 HTML 编码，或硬编码成错误域名。查看邮件源代码，确认查询参数没有被邮件系统安全重写截断。</p>
<pre><code>curl -sSI 'https://shop.example.com/customer/account/createPassword/?id=123&amp;token=REDACTED'</code></pre>
<p>实际测试时使用真实链接，但不要把它写进 shell history；可以临时放入受限变量，测试后立即清除。若代理把 HTTPS 改回 HTTP，检查 <code>X-Forwarded-Proto</code> 与 secure Base URL。</p>
<h2>Token 是否被第二次请求提前消耗</h2>
<p>部分邮件安全网关会在客户点击前扫描链接。对访问日志按测试客户的 createPassword 路径和时间检索，判断是否已有机器人请求：</p>
<pre><code>grep 'customer/account/createPassword' /var/log/nginx/access.log | tail -n 30</code></pre>
<p>如果安全扫描器首先访问并导致业务逻辑改变，应修扩展代码：GET 只展示表单，真正修改密码必须由带 form key 的 POST 完成。不能通过关闭邮件安全扫描来掩盖不安全实现。</p>
<p>修复后重新发起一次全新的重置请求，因为旧 Token 可能已被覆盖。回归时测试同网站、跨网站、链接临近有效期、链接重复使用四种情况；密码修改成功后旧链接必须失效，这一点不能为了&ldquo;好用&rdquo;而取消。</p>]]></description>
      <pubDate>Thu, 13 Mar 2025 03:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台保存商品提示 Asymmetric transaction rollback]]></title>
      <link>https://www.360magento.com/blog/asymmetric-transaction-rollback/</link>
      <description><![CDATA[<p><code>Asymmetric transaction rollback</code> 表示 Magento 认为当前资源连接的事务嵌套层级已经失衡。常见情况是核心保存流程开启事务后，自定义插件、Observer 或第三方扩展又直接调用了 <code>commit()</code> 或 <code>rollBack()</code>，导致外层结束时找不到对应事务。它不是&ldquo;数据库偶尔抽风&rdquo;，重复点击保存可能扩大部分写入的问题。</p>
<h2>保留一次完整失败现场</h2>
<p>先复制商品 SKU、管理员、发生时间和本次修改字段。随后查看同一秒内的异常链：</p>
<pre><code>grep -n -B20 -A80 'Asymmetric transaction' var/log/exception.log
grep -n -B20 -A80 'Asymmetric transaction' var/log/system.log
tail -n 200 var/log/debug.log</code></pre>
<p>如果生产模式没有足够堆栈，在预发布环境用相同商品数据复现。不要为了取堆栈长时间打开前台 display_errors。</p>
<h2>先判断是否只有特定商品或特定操作触发</h2>
<table>
<thead>
<tr><th>测试</th><th>结果指向</th></tr>
</thead>
<tbody>
<tr>
<td>只改商品名称</td>
<td>基础保存、URL rewrite 或索引插件</td>
</tr>
<tr>
<td>只改库存</td>
<td>MSI、ERP 同步或库存 Observer</td>
</tr>
<tr>
<td>只改图片</td>
<td>媒体库、图片处理扩展</td>
</tr>
<tr>
<td>新建最小商品</td>
<td>全局插件或数据库触发器</td>
</tr>
</tbody>
</table>
<p>每次只改变一个变量，并使用新测试 SKU，避免前一次半保存状态影响判断。</p>
<h2>扫描可疑的事务控制代码</h2>
<pre><code>grep -R --line-number --include='*.php' -E '\-&gt;(beginTransaction|commit|rollBack)\(' app/code vendor/vendorname 2&gt;/dev/null
grep -R --line-number --include='di.xml' 'ProductRepository\|Product\\Save' app/code vendor/vendorname 2&gt;/dev/null
grep -R --line-number --include='events.xml' 'catalog_product_save' app/code vendor/vendorname 2&gt;/dev/null</code></pre>
<p>优先检查最近上线模块与堆栈中出现的命名空间。不要修改 <code>vendor</code> 里的文件验证；可以通过 <code>bin/magento module:disable Vendor_Module</code> 在预发布环境做 A/B 测试，然后重新编译和清缓存。</p>
<h2>错误写法与正确边界</h2>
<pre><code>// 风险：插件进入时外层可能已经在事务中
$connection-&gt;beginTransaction();
try {
    $subject-&gt;save($entity);
    $connection-&gt;commit();
} catch (\Throwable $e) {
    $connection-&gt;rollBack();
    throw $e;
}</code></pre>
<p>插件不应再次调用同一个 repository 的 save，也不应擅自结束由核心流程开启的事务。若业务确实需要同时写自定义表，优先把写入放在明确的服务层，让同一 ResourceConnection 管理完整边界；或者在提交后事件中执行可补偿的异步任务。</p>
<h2>检查数据库是否已有部分写入</h2>
<p>保存失败后，用 SKU 查主实体的更新时间，再核对自定义表、库存和 URL rewrite。只读查询示例：</p>
<pre><code>SELECT entity_id, sku, updated_at
FROM catalog_product_entity WHERE sku='TEST-SKU';

SELECT request_path, target_path, store_id
FROM url_rewrite
WHERE entity_type='product' AND entity_id=123;</code></pre>
<p>若核心商品已更新、自定义表未更新，说明存在部分提交，修复代码后还要补数据。正式发布前执行：新商品保存、已有商品保存、批量属性更新、导入、库存同步五组回归；同时观察异常日志与索引状态。仅仅让当前商品能保存，不足以证明事务边界已经正确。</p>]]></description>
      <pubDate>Wed, 12 Mar 2025 06:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 消息队列任务一直停在 in progress]]></title>
      <link>https://www.360magento.com/blog/queue-message-in-progress/</link>
      <description><![CDATA[<p>队列后台或数据库里看到大量 <code>in progress</code>，不能直接把状态改回 new。某些消息可能正在处理大文件或调用外部接口；强制重置会让第二个消费者同时执行，造成重复扣库存、重复发邮件或重复推送 ERP。</p>
<h2>用时间线判断&ldquo;慢&rdquo;还是&ldquo;死&rdquo;</h2>
<p>记录一条消息 ID，在一分钟内连续取两次状态，同时确认消费者 PID 是否还存在：</p>
<pre><code>ps -eo pid,lstart,etime,cmd | grep '[q]ueue:consumers:start'
php bin/magento queue:consumers:list

SELECT message_id, queue_id, status, updated_at
FROM queue_message_status
WHERE status = 3
ORDER BY updated_at ASC
LIMIT 30;</code></pre>
<p>不同版本或队列适配器的状态值可能不同，先在当前库抽样 new、complete、retry 的记录核对含义。不要把网上看到的数字直接用于 UPDATE。</p>
<h2>消费者还活着：找到它正在等待什么</h2>
<pre><code>PID=12345
ps -p "$PID" -o pid,etime,%cpu,%mem,stat,cmd
sudo lsof -p "$PID" | tail -n 30
sudo strace -p "$PID" -tt -f -o /tmp/consumer.strace</code></pre>
<p>短时间采样后停止 strace。若反复停在网络 connect/read，检查外部 API 超时；若等待 MySQL 锁，运行 <code>SHOW PROCESSLIST</code> 和 <code>SHOW ENGINE INNODB STATUSG</code>；若 CPU 持续很高，则从消费者日志和 profiler 找循环。不要在未取证前 kill -9。</p>
<h2>进程已消失：核对 Supervisor 与消费者退出策略</h2>
<pre><code>supervisorctl status
journalctl -u supervisor --since '30 minutes ago'
grep -R "queue:consumers:start" -n /etc/supervisor* /etc/systemd/system 2&gt;/dev/null</code></pre>
<p>消费者使用 <code>--max-messages</code> 正常退出后应由 Supervisor 重新拉起。若配置了 <code>autorestart=false</code>，队列会停在无人处理的状态。推荐显式配置进程数、最大消息数与停止等待时间，并让进程以 Magento 文件所有者运行。</p>
<h2>业务代码必须让失败可重试</h2>
<p>自定义消费者中捕获所有异常然后只写日志，会让框架误以为消息处理成功；相反，无限抛出同一异常又会形成重试风暴。外部写操作应使用业务唯一键实现幂等，例如以 <code>order_increment_id + event_type</code> 建唯一索引。超时要抛出可重试异常，数据永久不合法则进入失败队列或告警。</p>
<pre><code>SELECT message_id, topic_name, body
FROM queue_message
WHERE message_id = 123456G</code></pre>
<p>消息 body 可能含客户信息或令牌，排查输出不要发到公共工单。先在隔离环境用同一 payload 调用消费者，确认异常是否稳定复现。</p>
<h2>什么时候可以恢复卡住的消息</h2>
<p>只有同时满足以下条件才处理状态：原消费者 PID 已不存在；外部系统确认没有成功执行；业务动作具备幂等保护；已备份对应消息与状态行。优先使用队列适配器提供的重试机制，不直接改数据库。恢复后只启动一个消费者观察首批消息，确认 complete 数增加、in progress 最老时间向前移动，再恢复正常并发。</p>
<pre><code>watch -n 5 "ps -ef | grep '[q]ueue:consumers:start'"
tail -f var/log/system.log var/log/exception.log</code></pre>
<p>最终验证不只是&ldquo;积压数量下降&rdquo;，还要抽查订单、邮件或 ERP 是否出现重复副作用，这才算真正恢复。</p>]]></description>
      <pubDate>Tue, 11 Mar 2025 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重新索引报 No such entity with id]]></title>
      <link>https://www.360magento.com/blog/reindex-no-such-entity/</link>
      <description><![CDATA[<p><code>bin/magento indexer:reindex</code> 抛出 <code>No such entity with id = ...</code> 时，真正损坏的往往不是索引表，而是某条关联记录指向了已经不存在的商品、分类、网站或库存实体。若一上来就 truncate 索引表，重建过程仍会读到同一条坏数据，报错不会消失。</p>
<h2>先确定是哪一个索引器、哪一种实体</h2>
<pre><code>php bin/magento indexer:status
php bin/magento indexer:reindex catalog_product_price -vvv 2&gt;&amp;1 | tee /tmp/price-index.log
tail -n 120 var/log/exception.log
grep -n -B8 -A20 'No such entity' var/log/*.log</code></pre>
<p>不要只记录报错 ID。堆栈里出现 <code>ProductRepository</code>、<code>CategoryRepository</code>、<code>WebsiteRepository</code> 或库存相关类，决定了后面要查哪组表。若全量 reindex 才报错，就逐个执行索引器，直到得到最小失败范围。</p>
<h2>示例：价格索引读取到不存在的商品</h2>
<p>假设日志明确给出商品 entity_id 2451，先做只读查询：</p>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity WHERE entity_id = 2451;
SELECT * FROM catalog_product_website WHERE product_id = 2451;
SELECT * FROM catalog_category_product WHERE product_id = 2451;
SELECT * FROM catalog_product_relation WHERE child_id = 2451 OR parent_id = 2451;</code></pre>
<p>第一条无结果，而后几条仍有结果，就存在孤儿关联。先完整备份命中记录，不要凭一个 ID 直接删除：</p>
<pre><code>CREATE TABLE repair_20250310_catalog_product_website AS
SELECT * FROM catalog_product_website WHERE product_id = 2451;

CREATE TABLE repair_20250310_catalog_category_product AS
SELECT * FROM catalog_category_product WHERE product_id = 2451;</code></pre>
<p>确认备份表行数与原查询一致后，才在维护窗口删除已经确认无主的关联。若主商品其实存在但 repository 仍找不到，还要检查 store scope、row_id/entity_id 结构以及暂存版本，不能照搬上述删除。</p>
<h2>批量找孤儿记录，比逐次追报错更可靠</h2>
<pre><code>SELECT cp.product_id, COUNT(*) AS rows_count
FROM catalog_category_product cp
LEFT JOIN catalog_product_entity p ON p.entity_id = cp.product_id
WHERE p.entity_id IS NULL
GROUP BY cp.product_id;

SELECT pw.product_id, pw.website_id
FROM catalog_product_website pw
LEFT JOIN catalog_product_entity p ON p.entity_id = pw.product_id
LEFT JOIN store_website w ON w.website_id = pw.website_id
WHERE p.entity_id IS NULL OR w.website_id IS NULL;</code></pre>
<p>查询结果不应立即等同于可删除数据。先确认是否处于导入、暂存更新或部署中；生产站建议将结果导出并与最近一次商品删除、ERP 同步日志对齐。</p>
<h2>修复后按顺序验证</h2>
<ol>
<li>只重建刚才失败的索引器，避免全量任务掩盖新的错误。</li>
<li>检查状态是否从 Reindex required 变成 Ready。</li>
<li>按报错 SKU 访问商品页、分类页并模拟加入购物车。</li>
<li>观察下一轮 Cron 增量索引是否再次产生异常。</li>
</ol>
<pre><code>php bin/magento indexer:reset catalog_product_price
php bin/magento indexer:reindex catalog_product_price
php bin/magento indexer:status catalog_product_price</code></pre>
<h2>如果报错实体来自分类或网站</h2>
<p>堆栈指向 CategoryRepository 时，除了 <code>catalog_category_product</code>，还要检查分类本身是否仍在当前根分类树中；指向 WebsiteRepository 时，检查已经删除的网站是否仍被商品、价格或库存销售渠道引用。下面的查询只用于发现异常关系：</p>
<pre><code>SELECT cp.category_id, COUNT(*) AS rows_count
FROM catalog_category_product cp
LEFT JOIN catalog_category_entity c ON c.entity_id=cp.category_id
WHERE c.entity_id IS NULL
GROUP BY cp.category_id;

SELECT pw.website_id, COUNT(*) AS rows_count
FROM catalog_product_website pw
LEFT JOIN store_website w ON w.website_id=pw.website_id
WHERE w.website_id IS NULL
GROUP BY pw.website_id;</code></pre>
<p>若网站曾被业务迁移工具删除，还要检查 price scope、shared catalog 和 inventory sales channel。删除一张关联表的孤儿行可能只是把异常推迟到下一个索引器。</p>
<h2>检查是否由并发导入制造瞬时缺口</h2>
<p>如果重试后偶尔成功，比较 reindex 与 ERP/CSV 导入的时间。某些自定义导入先删主实体再重建，索引器恰好在中间读取就会得到 No such entity。修复方向是让导入使用事务或官方保存接口，并将全量重建安排在导入完成后，而不是给索引命令加无限重试。</p>
<pre><code>grep -R 'import|reindex' /var/log/cron* /var/log/syslog 2&gt;/dev/null | tail -n 100
SELECT job_code, status, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE job_code LIKE '%index%' OR job_code LIKE '%import%'
ORDER BY schedule_id DESC LIMIT 50;</code></pre>
<p><code>indexer:reset</code> 只重置状态，不会修复脏数据。若没有找到孤儿关系，却每次在不同 ID 失败，应检查索引期间是否有并发导入或删除任务，并在测试环境复现同一批数据。修复的目标是恢复实体关系的一致性，而不是让命令暂时不报错。</p>]]></description>
      <pubDate>Mon, 10 Mar 2025 07:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 清除缓存后前台仍显示旧内容]]></title>
      <link>https://www.360magento.com/blog/cache-cleared-old-content/</link>
      <description><![CDATA[<p>在 Magento 2 中执行 <code>bin/magento cache:clean</code> 后页面仍然是旧内容，并不代表命令没有生效。一次前台请求可能依次经过 CDN、Varnish、Magento Full Page Cache、Block HTML、Redis 和浏览器缓存。只清理其中一层，旧响应仍可能从上一层返回。最有效的办法不是反复执行 flush，而是先确认旧内容由哪一层提供。</p>
<h2>先做一个不会破坏生产缓存的对照请求</h2>
<p>选择一个仍显示旧内容的页面，用查询参数绕过已有的 URL 缓存键，并同时查看响应头：</p>
<pre><code>curl -sSI 'https://shop.example.com/category.html?cache_test=20250307'
curl -sS  'https://shop.example.com/category.html?cache_test=20250307' | grep -n '旧文案'</code></pre>
<p>重点看 <code>Age</code>、<code>X-Magento-Cache-Debug</code>、<code>X-Cache</code>、<code>CF-Cache-Status</code> 等字段。如果普通 URL 是旧内容，而带随机参数的新请求已经更新，问题通常在 Varnish 或 CDN；两个请求都旧，再查 Magento 与数据源。</p>
<h2>确认清理的是正确实例和正确缓存类型</h2>
<pre><code>php bin/magento cache:status
php bin/magento cache:clean full_page block_html layout config
php bin/magento cache:status</code></pre>
<p><code>cache:clean</code> 只删除 Magento 标记为相关的缓存条目；<code>cache:flush</code> 会清空当前缓存存储，若同一个 Redis DB 被其他应用共用，flush 可能误伤，所以生产环境不要把它当作常规第一步。多台 Web 节点还要确认命令运行目录与线上节点使用的是同一份 <code>app/etc/env.php</code>。</p>
<p>可对比每台节点的部署版本和配置摘要：</p>
<pre><code>pwd
sha256sum app/etc/env.php
php bin/magento --version
grep -R "cache" -n app/etc/env.php</code></pre>
<h2>Redis 中是否存在旧前缀</h2>
<p>先从 <code>env.php</code> 读取 Redis 的 host、port、database 与 id_prefix，再对对应 DB 做只读检查。不要在大库上执行 <code>KEYS *</code>：</p>
<pre><code>redis-cli -h 127.0.0.1 -p 6379 -n 1 INFO keyspace
redis-cli -h 127.0.0.1 -p 6379 -n 1 --scan --pattern 'zc:*' | head</code></pre>
<p>如果新旧节点使用不同的 database 或 <code>id_prefix</code>，你在 A 节点清理的缓存不会影响 B 节点。修正配置后先维护模式切流，再清理相关缓存，避免不同节点继续写入两套键空间。</p>
<h2>Varnish 与 CDN 分开验证</h2>
<p>绕过 CDN，直接请求源站或负载均衡的内网地址，同时保留 Host：</p>
<pre><code>curl -sSI -H 'Host: shop.example.com' http://10.0.2.15/category.html
curl -sS  -H 'Host: shop.example.com' http://10.0.2.15/category.html | grep '新文案'</code></pre>
<p>源站已新、公网仍旧，就不应继续清 Magento。Varnish 可检查 BAN/PURGE 是否到达以及对象命中情况；CDN 则按具体 URL 或标签刷新。若响应头的 <code>Age</code> 不断增长，说明旧对象确实还在代理层。</p>
<h2>只有某个浏览器旧时检查静态资源和 Service Worker</h2>
<p>打开无痕窗口测试，再在开发者工具 Network 中禁用缓存。如果 HTML 已更新但 JS/CSS 仍旧，核对页面引用的静态版本号：</p>
<pre><code>php bin/magento config:show dev/static/sign
find pub/static -maxdepth 2 -name deployed_version.txt -print -exec cat {} ;</code></pre>
<p>PWA 或自定义主题注册过 Service Worker 时，还要在 Application 面板中查看 Cache Storage。仅当确认旧文件由 Service Worker 返回时再注销它，不能用&ldquo;让所有客户清浏览器缓存&rdquo;代替修复发布流程。</p>
<p>最后用三种请求回归：公网普通 URL、公网随机参数 URL、源站 Host 请求。三者都出现新内容，且连续两次访问能正常 HIT，才说明缓存链路恢复完整。</p>]]></description>
      <pubDate>Fri, 07 Mar 2025 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API 返回 Consumer is not authorized to access %resources]]></title>
      <link>https://www.360magento.com/blog/api-consumer-not-authorized/</link>
      <description><![CDATA[<p>REST API 返回 401 或 403，正文包含 <code>The consumer isn't authorized to access %resources</code>。这说明请求大多已经到达 Magento，Token 也可能被识别，但当前身份没有目标 ACL 资源。不要反复重新生成 Token，先确认&ldquo;谁的 Token、访问哪个资源&rdquo;。</p>
<pre><code>curl -sk -D /tmp/api.headers  -H 'Authorization: Bearer REDACTED'  'https://shop.example.com/rest/V1/orders/000000123'  -o /tmp/api.json
cat /tmp/api.headers
cat /tmp/api.json</code></pre>
<h3>四种身份不要混用</h3>
<ul>
<li>Admin Token：权限来自管理员角色；</li>
<li>Customer Token：只能访问客户 self 资源；</li>
<li>Integration Token：权限来自 Integration Resources；</li>
<li>匿名请求：只允许 anonymous 资源。</li>
</ul>
<p>用 Customer Token 调管理订单接口，即使 Token 有效也会被拒绝。先从 Token 创建流程确认身份类型，不要在日志中输出 Token。</p>
<h3>自定义接口的 resource 必须存在</h3>
<pre><code>&lt;route url="/V1/vendor/item/:id" method="GET"&gt;
 &lt;service class="VendorModuleApiItemRepositoryInterface" method="getById" /&gt;
 &lt;resources&gt;
  &lt;resource ref="Vendor_Module::item_read" /&gt;
 &lt;/resources&gt;
&lt;/route&gt;</code></pre>
<p>对应 ACL 要在 <code>etc/acl.xml</code> 定义，ID 大小写完全一致。把 resource 临时改成 anonymous 虽能绕过错误，却会暴露内部数据。</p>
<pre><code>grep -Rni 'Vendor_Module::item_read' app/code/Vendor/Module/etc
bin/magento cache:clean config
bin/magento setup:di:compile</code></pre>
<h3>Integration 修改权限后重新激活</h3>
<p>后台检查 Resources 是 All 还是 Custom，并确认目标资源节点已勾选。某些变更需要重新激活才能得到与权限一致的 Token。先在测试 Integration 验证，不要直接替换生产系统凭据。</p>
<p>最后用一个允许接口和一个明确禁止的接口做正反测试：前者应返回数据，后者仍被拒绝。若两者都成功，说明 ACL 放得过宽；若两者都失败，继续检查 Token 身份或配置缓存。</p>
<h3>Store Code 路径错误也会造成误判</h3>
<p><code>/rest/V1/...</code> 使用默认 Store；多店铺接口需要确认是否应使用 <code>/rest/zh_cn/V1/...</code>。Store Code 不会替代 ACL，但会改变网站范围、商品可见性和配置结果。权限恢复后，再用目标 Store Code 验证业务数据是否正确。</p>
<h3>保留可审计的最小权限</h3>
<p>Integration 不应因为排障临时选择 All 后一直保留。记录接口与 ACL resource 的对应表，只勾选所需读取或写入资源，并在回归测试中确认写接口仍受限制。</p>]]></description>
      <pubDate>Thu, 06 Mar 2025 07:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多店铺 robots.txt 修改后内容不一致]]></title>
      <link>https://www.360magento.com/blog/multistore-robots-txt/</link>
      <description><![CDATA[<p>后台修改了 robots.txt，主域名已经更新，其他语言域名仍返回旧内容；或者后台预览正确，公网请求却完全不同。多店铺 robots 的最终响应取决于请求落到哪个 Store、Web Server 是否直接返回静态文件，以及 CDN 是否缓存旧版本。</p>
<h3>先建立域名对照表</h3>
<table>
<thead>
<tr><th>域名</th><th>期望 Store Code</th><th>状态</th><th>内容哈希</th></tr>
</thead>
<tbody>
<tr>
<td>example.com</td>
<td>default</td>
<td>200</td>
<td>待测</td>
</tr>
<tr>
<td>cn.example.com</td>
<td>zh_cn</td>
<td>200</td>
<td>待测</td>
</tr>
<tr>
<td>de.example.com</td>
<td>de_de</td>
<td>200</td>
<td>待测</td>
</tr>
</tbody>
</table>
<pre><code>for host in example.com cn.example.com de.example.com; do
  curl -sk "https://$host/robots.txt" -o "/tmp/robots-$host.txt"
  sha256sum "/tmp/robots-$host.txt"
done
diff -u /tmp/robots-example.com.txt /tmp/robots-cn.example.com.txt</code></pre>
<p>先明确这些站点是否本来就应该相同。生产与测试环境尤其不能共用允许抓取的 robots。</p>
<h3>请求 Host 是否映射到正确 Store</h3>
<pre><code>bin/magento store:list
bin/magento config:show web/secure/base_url
nginx -T 2&gt;/dev/null | grep -nE 'server_name|MAGE_RUN_CODE|MAGE_RUN_TYPE' | head -n 100</code></pre>
<p>同一代码库通过 MAGE_RUN_CODE 切换网站时，server block 写错会让 cn 域名一直读取 default scope。后台在中文 Store View 保存，不能修复 Nginx 映射。</p>
<h3>静态 robots.txt 是否抢先响应</h3>
<pre><code>find . -maxdepth 3 -name robots.txt -ls
curl -skI https://cn.example.com/robots.txt | egrep -i 'age|x-cache|last-modified|etag'
curl -sk --resolve cn.example.com:443:10.0.0.12 https://cn.example.com/robots.txt</code></pre>
<p>Web Server 若在 pub 目录找到实体 robots.txt，可能不会进入 Magento 动态路由。源站新、CDN 旧则刷新这一条 URL，并检查缓存键是否包含 Host。</p>
<h3>更新后检查语义</h3>
<pre><code>grep -nE '^(User-agent|Allow|Disallow|Sitemap):' /tmp/robots-cn.example.com.txt
curl -skI https://cn.example.com/sitemap.xml</code></pre>
<p>检查 Sitemap 是否使用当前域名，Disallow 是否误封 static、media 或商品路径。robots.txt 不是访问控制，敏感后台路径仍需认证。最后从外部网络请求所有域名并保存响应头与正文，后台预览只能证明数据库值存在。</p>]]></description>
      <pubDate>Wed, 05 Mar 2025 02:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台导出 CSV 中文乱码或内存溢出]]></title>
      <link>https://www.360magento.com/blog/admin-csv-export-error/</link>
      <description><![CDATA[<p>后台 Grid 能正常显示，但导出的 CSV 在 Excel 打开后中文乱码；记录稍多又报 <code>Allowed memory size exhausted</code>。这是两个问题：乱码属于文件解释方式，内存溢出属于导出实现一次加载过多数据。</p>
<h3>先判断文件是不是 UTF-8</h3>
<pre><code>file -bi export.csv
xxd -l 16 export.csv
iconv -f UTF-8 -t UTF-8 export.csv -o /dev/null</code></pre>
<p>UTF-8 CSV 被 Excel 按本地编码打开时可能乱码。需要兼容 Excel 的场景可在输出开头加入 UTF-8 BOM，但 API 或数据交换文件未必应该带 BOM。</p>
<pre><code>$stream-&gt;write("&iuml;&raquo;&iquest;");
$stream-&gt;writeCsv($headers);
foreach ($rows as $row) {
    $stream-&gt;writeCsv($row);
}</code></pre>
<h3>不要用 getData() 装入整个集合</h3>
<p>导出十万行时，集合、扩展属性和二维数组会同时驻留内存。使用分页分批读取，并直接写临时文件流。</p>
<pre><code>$pageSize = 1000;
for ($page = 1; ; $page++) {
    $collection-&gt;setPageSize($pageSize)-&gt;setCurPage($page);
    $collection-&gt;load();
    if (!count($collection)) { break; }
    foreach ($collection as $item) {
        $stream-&gt;writeCsv($this-&gt;rowBuilder-&gt;build($item));
    }
    $collection-&gt;clear();
}</code></pre>
<p>不要在每一行调用 Repository 加载完整实体，这会产生 N+1 查询。Grid 需要哪些列，就在集合 SQL 中选择哪些列；复杂展示字段与导出字段可以使用不同数据提供器。</p>
<h3>区分 PHP 限制与代理超时</h3>
<pre><code>php -i | grep -E 'memory_limit|max_execution_time'
grep -RniE 'Allowed memory size|Maximum execution time' var/log | tail -n 30
tail -n 50 /var/log/nginx/error.log</code></pre>
<p>浏览器得到 504 而 PHP 仍在运行，说明同步大导出不适合一次后台请求。将任务放入消息队列，完成后生成受权限保护的下载文件，比无限增加 Nginx timeout 更可靠。</p>
<p>用包含逗号、双引号、换行和中文的测试行检查转义，再用接近生产规模的数据测峰值内存。文件能下载但列错位，同样不能算成功。</p>
<h3>导出文件也要防止公式注入</h3>
<p>客户名称、备注等字段如果以 <code>=</code>、<code>+</code>、<code>-</code> 或 <code>@</code> 开头，Excel 可能把它解释成公式。面向人工下载的 CSV 应在输出层按业务规则转义不可信文本，同时保留原始数据导出渠道用于系统交换。</p>
<p>异步导出文件应设置过期时间、下载权限和清理任务，不能永久留在公开 media 路径。</p>]]></description>
      <pubDate>Tue, 04 Mar 2025 06:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据库出现 Deadlock found when trying to get lock]]></title>
      <link>https://www.360magento.com/blog/mysql-deadlock-magento/</link>
      <description><![CDATA[<p>高峰期下单、库存扣减或批量更新时，日志出现 <code>SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock</code>。死锁不是简单的&ldquo;数据库太慢&rdquo;，而是两个事务以不同顺序等待彼此持有的锁。MySQL 会回滚其中一个事务解除循环。</p>
<h3>事故发生时先保存现场</h3>
<pre><code>mysql -e "SHOW ENGINE INNODB STATUS\G" &gt; /tmp/innodb-status.txt
mysql -e "SELECT * FROM information_schema.innodb_trx\G" &gt; /tmp/innodb-trx.txt
mysql -e "SHOW FULL PROCESSLIST" &gt; /tmp/processlist.txt
grep -Rni 'Deadlock found|SQLSTATE[40001]' var/log | tail -n 100</code></pre>
<p><code>SHOW ENGINE INNODB STATUS</code> 只保留最近一次死锁，等故障过去再查往往已被覆盖。生产环境可开启适当的 deadlock 日志并配置轮转。</p>
<h3>阅读 LATEST DETECTED DEADLOCK</h3>
<ul>
<li>记录两个事务正在执行的 SQL；</li>
<li>记录已持有和正在等待的 lock mode；</li>
<li>记录涉及的索引、记录和修改行数；</li>
<li>确认最终被回滚的是哪个事务；</li>
<li>追到发起 SQL 的 Cron、Consumer、API 或后台操作。</li>
</ul>
<p>仅凭表名停掉所有消费者会扩大影响。要从时间、线程和业务唯一键把数据库现场与 Magento 日志对应起来。</p>
<h3>事务范围过大会放大冲突</h3>
<pre><code>$connection-&gt;beginTransaction();
try {
    $this-&gt;resourceA-&gt;save($a);
    // 数据库事务中不要调用外部 API 或处理大文件
    $this-&gt;resourceB-&gt;save($b);
    $connection-&gt;commit();
} catch (Throwable $e) {
    $connection-&gt;rollBack();
    throw $e;
}</code></pre>
<p>把外部接口、邮件与大文件处理移出事务。多个业务路径更新同一组实体时统一顺序，例如总是先订单、再库存，避免另一条路径反向加锁。</p>
<h3>缺少索引会锁住更多记录</h3>
<pre><code>EXPLAIN UPDATE custom_table SET status=1
WHERE external_id='abc' AND store_id=2;
SHOW INDEX FROM custom_table;</code></pre>
<p>增加索引前先在预发布验证执行计划和写入成本，不要在高峰期直接 ALTER 大表。</p>
<h3>有限重试必须以幂等为前提</h3>
<pre><code>for ($attempt = 1; $attempt &lt;= 3; $attempt++) {
    try {
        $this-&gt;operation-&gt;execute($idempotencyKey);
        break;
    } catch (MagentoFrameworkDBAdapterDeadlockException $e) {
        if ($attempt === 3) { throw $e; }
        usleep(random_int(50000, 200000) * $attempt);
    }
}</code></pre>
<p>纯内部状态更新可有限重试；已经调用支付、发券、发货或 ERP 的流程，必须先用唯一键确认外部动作是否发生。上线后同时观察死锁次数、事务耗时、队列重试和订单完整性，不能把异常吞掉或无限重试。</p>
<h3>用业务键核对被回滚事务</h3>
<p>数据库选择的 victim 可能是客户下单，也可能是后台批量任务。根据订单号、SKU、外部请求 ID 检查事务是否已经部分产生消息、历史记录或外部调用。若数据库回滚但消息已投递，就必须依赖消费者幂等性阻止重复处理。</p>
<p>对于周期性批量任务，可按主键排序并分小批提交，减少一次事务持有的锁数量，同时避免多个 worker 处理重叠范围。</p>
<h3>把死锁频率与流量放在一起看</h3>
<p>单次死锁可能是正常并发竞争，持续增长则需要工程修复。按分钟汇总错误次数，并与下单量、消费者并发数、批量任务开始时间和数据库 CPU/IO 对齐。若每次索引任务启动就出现同一组表冲突，可以调整任务窗口或拆分批次，但仍要统一代码的锁顺序。</p>
<pre><code>grep 'Deadlock found' var/log/*.log | cut -c1-16 | sort | uniq -c | tail -n 30
mysql -e "SHOW GLOBAL STATUS LIKE 'Innodb_deadlocks';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Threads_running';"</code></pre>
<p>修改后保留一段时间的基线数据，确认死锁下降不是因为吞吐也下降。性能优化必须同时观察成功订单数与处理延迟。</p>]]></description>
      <pubDate>Mon, 03 Mar 2025 01:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 setup:di:compile 报 Cannot instantiate interface]]></title>
      <link>https://www.360magento.com/blog/cannot-instantiate-interface/</link>
      <description><![CDATA[<p>执行 <code>bin/magento setup:di:compile</code> 时出现 <code>Cannot instantiate interface Vendor\Module\Api\Data\RuleInterface</code>。直观含义是 Object Manager 需要创建接口，却没有可实例化实现；真正原因可能是 preference 缺失、配置放错 area，或构造参数把数据接口当服务对象注入。</p>
<h3>从谁要求实例化接口开始</h3>
<pre><code>bin/magento setup:di:compile -vvv 2&gt;&amp;1 | tee /tmp/di-compile.log
grep -Rni 'RuleInterface' app/code vendor/*/*/etc | head -n 100
grep -Rni 'function __construct' app/code/Vendor/Module | head -n 50</code></pre>
<p>异常最后一行只是接口名。向上找第一个自定义类，确认它为何直接依赖该接口。Data Interface 通常由 Factory 或 Repository 返回，不应直接注入单个数据实例。</p>
<pre><code>// 容易触发实例化接口
public function __construct(VendorModuleApiDataRuleInterface $rule) {}

// 需要新对象时注入工厂
public function __construct(
    VendorModuleApiDataRuleInterfaceFactory $ruleFactory
) {
    $this-&gt;ruleFactory = $ruleFactory;
}</code></pre>
<h3>服务接口需要全局 preference</h3>
<pre><code>&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"&gt;
 &lt;preference for="VendorModuleApiRuleManagementInterface"
             type="VendorModuleModelRuleManagement" /&gt;
&lt;/config&gt;</code></pre>
<p>全局服务放在 <code>etc/di.xml</code>。若 preference 只在 <code>etc/frontend/di.xml</code>，CLI 编译或 Cron 看不到。只有确实需要不同 area 实现时才拆分。</p>
<h3>实现类是否真的可实例化</h3>
<ul>
<li>文件与类名大小写一致；</li>
<li>没有漏写接口方法；</li>
<li>构造函数的新依赖也能解析；</li>
<li>所属模块已启用；</li>
<li>Composer autoload 能找到命名空间。</li>
</ul>
<pre><code>composer dump-autoload -o
bin/magento module:status Vendor_Module
php -r "require 'app/bootstrap.php'; var_dump(class_exists('Vendor\Module\Model\RuleManagement'));"</code></pre>
<h3>清生成代码不是第一步</h3>
<p>旧生成代码可能干扰，但清 generated 只应发生在代码和 DI 配置正确之后。在维护窗口保存错误日志，再清理目标目录：</p>
<pre><code>rm -rf generated/code/Vendor generated/metadata/*
bin/magento setup:di:compile</code></pre>
<p>最后运行真正使用该服务的 CLI、后台页面或 API。编译成功只证明依赖图能生成，不证明业务实现与 area 行为正确。</p>
<h3>检查编译环境是否加载了完整模块集合</h3>
<p>构建机若缺少仅在生产安装的私有包，config.php 却启用了对应模块，也会表现为接口实现消失。比较 composer.lock、vendor/composer/installed.php 与 app/etc/config.php，确保编译发生在与运行环境一致的依赖集合中。</p>
<pre><code>composer show vendor/module-name
grep -n "Vendor_Module" app/etc/config.php
sha256sum composer.lock</code></pre>
<p>如果只有 production mode 编译失败，而 developer mode 页面暂时能打开，仍不能跳过编译上线。Developer mode 可能延迟到运行时才解析依赖，把故障推迟到某个低频接口。</p>]]></description>
      <pubDate>Fri, 28 Feb 2025 08:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品已启用但前台访问显示 404]]></title>
      <link>https://www.360magento.com/blog/enabled-product-404/</link>
      <description><![CDATA[<p>后台能搜索到商品，Status 也是 Enabled，但从前台地址访问却得到 404。商品是否可访问由多项条件共同决定，启用状态只是其中之一。</p>
<h3>五项数据快速排除</h3>
<ol>
<li>商品是否分配到当前 Store 所属 Website；</li>
<li>目标 Store View 是否覆盖为 Disabled；</li>
<li>Visibility 是否允许独立访问；</li>
<li>request_path 是否存在且属于正确 store_id；</li>
<li>页面请求是否被自定义路由或旧 301 改写。</li>
</ol>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity WHERE sku='ABC-001';
SELECT product_id, website_id FROM catalog_product_website WHERE product_id=123;
SELECT store_id, code, website_id FROM store ORDER BY store_id;

SELECT url_rewrite_id, request_path, target_path,
       redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE entity_type='product' AND entity_id=123
ORDER BY store_id, redirect_type;</code></pre>
<p>URL Rewrite 只存在 store_id=1，而请求进入 store_id=3，Magento 找不到对应路由。不要复制一条数据库记录伪造重写，应修正网站分配和 URL key 后让系统生成。</p>
<h3>直接请求目标路径并保存跳转链</h3>
<pre><code>curl -skIL https://shop.example.com/red-shirt.html
curl -sk -o /tmp/product404.html -w '%{http_code} %{url_effective}
'  https://shop.example.com/red-shirt.html
grep -iE 'no-route|404|product' /tmp/product404.html | head</code></pre>
<p>如果先 301 到错误 Store 再 404，检查 Base URL、Store Code 与历史重写；直接 404 则继续看产品初始化日志和重写表。</p>
<p>修复后同时验证商品原 URL、分类中的商品链接和 sitemap 中的 URL。旧地址如果已经被搜索引擎收录，应保留一次 301 到新地址，而不是把所有旧重写删除。</p>
<h3>状态和可见性要读取目标 Store 的最终值</h3>
<p>商品属性存在默认值和 Store View 覆盖。后台默认范围显示 Enabled，不代表当前 Store 也启用。使用产品 Repository 指定 store_id 读取最终状态、visibility 与 url_key，或查询对应 EAV store_id 记录。若切换 Store View 后发现 Use Default 未勾选，先确认这条覆盖是否业务需要，再决定删除或修改。</p>
<h3>索引与缓存是最后一层</h3>
<pre><code>bin/magento indexer:status catalog_product_attribute catalogsearch_fulltext
bin/magento indexer:reindex catalog_product_attribute catalogsearch_fulltext
bin/magento cache:clean full_page block_html</code></pre>
<p>重建后有结果说明更新链路存在积压，还要回查 Cron/MView；不能把每天 reindex 当成长期方案。</p>]]></description>
      <pubDate>Thu, 27 Feb 2025 02:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 支付成功但订单一直是 Pending Payment]]></title>
      <link>https://www.360magento.com/blog/payment-success-pending/</link>
      <description><![CDATA[<p>客户在支付平台看到付款成功，Magento 后台订单却一直停在 Pending Payment。不要先手工改为 Processing；必须确认 Magento 是否收到并验证了服务端通知，否则可能造成重复发货、重复扣款或后续退款无法关联。</p>
<h3>把一次支付拆成四个时间点</h3>
<table>
<thead>
<tr><th>时间点</th><th>证据</th></tr>
</thead>
<tbody>
<tr>
<td>创建支付</td>
<td>订单号、网关支付 ID、请求时间</td>
</tr>
<tr>
<td>客户跳转</td>
<td>return URL 的 HTTP 状态和参数</td>
</tr>
<tr>
<td>服务端通知</td>
<td>Webhook 请求 ID、签名验证结果</td>
</tr>
<tr>
<td>订单更新</td>
<td>状态历史、invoice、transaction</td>
</tr>
</tbody>
</table>
<pre><code>SELECT entity_id, increment_id, state, status,
       grand_total, total_paid, base_total_paid, created_at, updated_at
FROM sales_order
WHERE increment_id='000000123';

SELECT transaction_id, txn_id, txn_type, is_closed, created_at
FROM sales_payment_transaction
WHERE order_id=789
ORDER BY transaction_id;</code></pre>
<p>有 capture transaction 但 total_paid 为 0，检查模块写交易与更新订单是否处在同一事务；完全没有 transaction，则通知可能没进入 Magento。</p>
<h3>Webhook 是否真正到达应用</h3>
<pre><code>grep -Rni 'gateway_payment_id_123|000000123' var/log | tail -n 100
grep -E 'POST .*webhook|POST .*callback' /var/log/nginx/access.log | tail -n 50
curl -skI https://shop.example.com/payment/webhook</code></pre>
<p>Webhook 通常要求 POST，curl -I 返回 405 不一定是故障；这里主要确认 DNS、TLS 与路由是否到达站点。WAF、Basic Auth、维护模式或强制地区跳转都可能阻止支付平台调用。</p>
<h3>签名失败不能直接跳过验证</h3>
<p>对照支付平台控制台的通知时间、事件 ID 和签名版本。检查 raw body 是否在验证前被 JSON 重新编码，代理是否解压或修改了请求体，以及生产/测试密钥是否混用。不要通过&ldquo;暂时关闭签名&rdquo;来恢复订单。</p>
<h3>幂等处理决定能否安全重放</h3>
<pre><code>SELECT parent_id, status, comment, created_at
FROM sales_order_status_history
WHERE parent_id=789
ORDER BY entity_id;</code></pre>
<p>同一 Webhook 可能被发送多次。处理器应以事件 ID 或交易 ID 去重：已完成的 capture 再次到达时返回成功，但不能再次开票。修复后优先从支付平台重放原事件，在测试订单上验证订单状态、invoice、total_paid 和 transaction 四处一致，再处理真实订单。</p>]]></description>
      <pubDate>Wed, 26 Feb 2025 06:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页面显示 No shipping methods available]]></title>
      <link>https://www.360magento.com/blog/no-shipping-methods/</link>
      <description><![CDATA[<p>结账地址填写完整后，配送区域只显示 <code>No shipping methods available</code>。这句话只代表当前 Quote 没收集到可用 rate，并没有说明是地址、承运商配置、商品数据还是第三方接口失败。</p>
<h3>先固定一个可重复的测试 Quote</h3>
<pre><code>SELECT entity_id, store_id, is_active, items_count,
       items_qty, subtotal, grand_total
FROM quote
WHERE entity_id=456;

SELECT address_id, address_type, country_id, region_id,
       region, postcode, city, shipping_method
FROM quote_address
WHERE quote_id=456;</code></pre>
<p>postcode、region_id 和 country_id 缺失会让某些承运商直接返回 false。不要只看前端表单文字，检查保存进 Quote 的真实值。</p>
<h3>配置作用域对照</h3>
<table>
<thead>
<tr><th>配置</th><th>检查内容</th></tr>
</thead>
<tbody>
<tr>
<td>Enabled</td>
<td>目标 Website/Store 是否启用</td>
</tr>
<tr>
<td>Ship to Applicable Countries</td>
<td>地址国家是否允许</td>
</tr>
<tr>
<td>Minimum/Maximum Order Amount</td>
<td>是否按含税或未税金额判断</td>
</tr>
<tr>
<td>Specific Error Message</td>
<td>是否隐藏了真实原因</td>
</tr>
<tr>
<td>Handling Fee</td>
<td>格式是否导致 rate 计算异常</td>
</tr>
</tbody>
</table>
<pre><code>bin/magento config:show carriers/flatrate/active
bin/magento config:show carriers/flatrate/sallowspecific
bin/magento config:show carriers/flatrate/specificcountry
bin/magento config:show general/country/allow</code></pre>
<p>CLI 默认读取的 scope 可能不是问题店铺。多网站站点要同时核对后台 Use Default/Use Website 的继承状态。</p>
<h3>商品是否具备运费计算所需信息</h3>
<pre><code>SELECT item_id, sku, product_type, qty, weight,
       is_virtual, free_shipping
FROM quote_item
WHERE quote_id=456
ORDER BY item_id;</code></pre>
<p>全虚拟购物车本来就不需要配送；实体商品重量为 0 时，第三方实时运费可能拒绝；可配置、Bundle 商品要避免父子重量重复或全部丢失。库存不可售也可能让结账流程提前阻止收集。</p>
<h3>第三方承运商请求应记录什么</h3>
<ul>
<li>请求发生时间、目标 endpoint 和非敏感响应码；</li>
<li>目的国家、邮编、包裹总重量和币种；</li>
<li>连接超时、认证失败或无可用服务的原始响应；</li>
<li>不要在日志中记录 API 密钥和完整客户地址。</li>
</ul>
<pre><code>grep -RniE 'shipping|carrier|rate|timeout' var/log | tail -n 100
curl -sk -o /dev/null -w '%{http_code} %{time_connect} %{time_total}
'  'https://carrier-api.example.com/health'</code></pre>
<h3>用四组地址做边界测试</h3>
<p>同城正常邮编、允许国家的偏远邮编、不允许国家、缺少 Region 的地址各测试一次。若只有一个邮编失败，问题多半在服务范围或远程 API；所有地址都失败，再查配置 scope 与模块异常。</p>
<p>恢复后确认用户选择的 shipping_method 已写入 quote_address，订单创建后 shipping_description 与金额一致。仅让列表出现一个 rate，还不能证明下单时同一个 rate 能被再次验证。</p>]]></description>
      <pubDate>Tue, 25 Feb 2025 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 导入商品图片提示 Imported resource doesn’t exist]]></title>
      <link>https://www.360magento.com/blog/import-image-not-exist/</link>
      <description><![CDATA[<p>商品数据导入成功，图片列却报 <code>Imported resource (image.jpg) could not be downloaded from external resource due to timeout or access permissions</code>，或者直接提示资源不存在。先判断 CSV 写的是本地导入文件，还是 HTTP 外部图片；两条处理路径不同。</p>
<ol>
<li><strong>本地文件：</strong>后台导入时填写 Images File Directory，CSV 写相对文件名；</li>
<li><strong>远程文件：</strong>CSV 写完整 URL，服务器需要能主动访问该地址；</li>
<li><strong>已有媒体文件：</strong>不能假设 catalog/product 下的路径会自动被导入器识别。</li>
</ol>
<h3>本地导入目录的可见性</h3>
<pre><code>pwd
find var/import/images -maxdepth 3 -type f -printf '%P
' | head -n 30
stat var/import/images/red-shirt.jpg
namei -l var/import/images/red-shirt.jpg</code></pre>
<p>后台填写 <code>var/import/images</code> 时，CSV 通常使用 <code>red-shirt.jpg</code> 或子目录相对路径，而不是服务器绝对路径。Linux 文件名区分大小写，<code>Red-Shirt.JPG</code> 与 <code>red-shirt.jpg</code> 不是同一文件。</p>
<h3>先用最小 CSV 验证一张图</h3>
<pre><code>sku,base_image,small_image,thumbnail,additional_images
ABC-001,red-shirt.jpg,red-shirt.jpg,red-shirt.jpg,"back.jpg,detail.jpg"</code></pre>
<p>CSV 分隔符和 additional_images 分隔符不要混淆。文件名包含逗号时必须正确引用；图片路径前多一个空格也会变成不同文件。</p>
<h3>远程 URL 从 Magento 服务器测试</h3>
<pre><code>curl -L --max-time 20 -o /tmp/import-image.jpg  'https://cdn.example.com/import/red-shirt.jpg'
file /tmp/import-image.jpg
du -h /tmp/import-image.jpg</code></pre>
<p>返回 200 不代表拿到图片，CDN 可能返回 HTML 验证页。用 <code>file</code> 检查真实类型，并确认重定向后的域名仍可访问。不要为了下载图片关闭 SSL 验证。</p>
<p>完成小样本后再批量导入。抽查后台 Base、Small、Thumbnail 角色和前台缩略图，不只看数据库 media_gallery 有记录；如果原图已关联但前台 404，问题已经转到图片缓存生成，而不是导入器。</p>
<h3>大批量导入前生成一份文件清单</h3>
<p>先从 CSV 提取所有图片字段，去重后与导入目录清单比较，可以在进入 Magento 前发现拼写和大小写问题。不要在生产目录边导入边上传文件，否则同一批次会得到不一致结果。</p>
<pre><code>find var/import/images -type f -printf '%P
' | sort &gt; /tmp/image-files.txt
cut -d, -f2-5 products.csv | tr ',' '
' | sed 's/^ *//;s/ *$//' | sort -u &gt; /tmp/csv-images.txt
comm -23 /tmp/csv-images.txt /tmp/image-files.txt | head -n 100</code></pre>]]></description>
      <pubDate>Mon, 24 Feb 2025 07:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台登录后自动退出并返回登录页面]]></title>
      <link>https://www.360magento.com/blog/admin-session-loop/</link>
      <description><![CDATA[<p>用户名和密码没有报错，点击&ldquo;登录&rdquo;后页面短暂跳转，随后又回到后台登录页。这种现象通常不是 ACL，也不一定是密码错误，而是登录成功后新会话没有在下一次请求中被识别。</p>
<table>
<thead>
<tr><th>观察结果</th><th>优先检查</th></tr>
</thead>
<tbody>
<tr>
<td>浏览器没有生成 admin Cookie</td>
<td>Cookie Domain、Path、Secure、SameSite</td>
</tr>
<tr>
<td>Cookie 已生成但下一请求换了 Session ID</td>
<td>Session 存储、Redis、负载均衡</td>
</tr>
<tr>
<td>只有 HTTPS 代理后失败</td>
<td>Offloader Header、Base URL、代理协议</td>
</tr>
<tr>
<td>只有某一台节点失败</td>
<td>env.php、crypt key、共享 Session</td>
</tr>
</tbody>
</table>
<h3>从浏览器保存的 Cookie 开始</h3>
<p>在开发者工具 Application/Storage 中查看后台域名的 Cookie。记录名称、Domain、Path、Secure、SameSite 和过期时间，不要把 Cookie 值复制到工单或日志。</p>
<pre><code>bin/magento config:show web/cookie/cookie_domain
bin/magento config:show web/cookie/cookie_path
bin/magento config:show web/cookie/cookie_httponly
bin/magento config:show web/secure/use_in_adminhtml
bin/magento config:show web/secure/base_url</code></pre>
<p>后台地址使用 <code>admin.example.com</code>，Cookie Domain 却限制在另一个域名时，浏览器会拒绝或不回传 Cookie。HTTPS 后台若生成非 Secure Cookie，也要检查 Magento 是否正确识别代理后的原始协议。</p>
<h3>确认 Session 是否写入共享存储</h3>
<pre><code>grep -nA25 "'session'" app/etc/env.php
redis-cli -h redis.example.internal -p 6379 PING
redis-cli -h redis.example.internal -p 6379 INFO memory | head -n 20
find var/session -maxdepth 1 -type f -mmin -5 | head</code></pre>
<p>站点配置 Redis 却同时在 var/session 生成文件，说明 CLI 与 Web 可能读取了不同 env.php 或不同 release。多节点站点若使用本地文件 Session，登录请求落到 A 节点、下一请求落到 B 节点，就会立即退出。</p>
<h3>反向代理后的协议识别</h3>
<pre><code>curl -skI https://admin.example.com/backend/ | egrep -i 'location|set-cookie|x-forwarded'
nginx -T 2&gt;/dev/null | grep -nE 'X-Forwarded-Proto|fastcgi_param HTTPS|proxy_set_header Host' | head -n 60</code></pre>
<p>负载均衡终止 TLS 时，源站收到的是 HTTP。需要把原始协议安全地传给应用，并确保 Magento 的 offloader header 配置与代理一致。不要信任来自公网客户端任意伪造的 X-Forwarded-Proto，应由受控代理覆盖该 Header。</p>
<h3>多节点只失败一部分请求</h3>
<pre><code>sha256sum app/etc/env.php app/etc/config.php
grep -n "'key'" app/etc/env.php
hostname</code></pre>
<p>各节点 crypt key 和 Session 配置必须一致，但不要把 key 输出到聊天或监控。可临时在响应头增加不含敏感信息的节点名，确认登录前后落到哪台机器，定位完成后移除。</p>
<p>最终用全新无痕窗口连续登录、打开三个后台页面、等待 Session 闲置时间后再操作。只验证&ldquo;登录一次成功&rdquo;不足以排除 Session 过期或节点切换问题。</p>]]></description>
      <pubDate>Fri, 21 Feb 2025 03:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[消费者进程内存一直涨，别让 queue:consumers:start 永久运行]]></title>
      <link>https://www.360magento.com/blog/consumer-memory-growth/</link>
      <description><![CDATA[<p>消费者刚启动只占 180 MB，运行几小时后增长到 1.5 GB，最后被 OOM Killer 终止。把 PHP memory_limit 调大只会推迟故障。长进程中，静态缓存、批处理数组、未释放实体和第三方 SDK 连接会跨消息保留。</p>
<h3>判断是预热平台还是线性增长</h3>
<pre><code>pgrep -af 'queue:consumers:start'
pid=12345
while true; do
 date '+%F %T'
 ps -o pid,rss,vsz,etime,cmd -p "$pid"
 sleep 30
done</code></pre>
<p>启动后增长一段再稳定，可能是框架预热；每处理固定数量消息都增加相近 RSS，更像业务代码保留引用。把消息处理数与 RSS 放在同一时间轴上，不要只截一张 top。</p>
<h3>用 max-messages 设置生命周期</h3>
<pre><code>bin/magento queue:consumers:start async.operations.all --max-messages=500
bin/magento queue:consumers:start product_action_attribute.update --max-messages=200</code></pre>
<p>让 Supervisor 在进程正常退出后重启。max-messages 是保护边界，不是修复内存泄漏；值要根据单条消息耗时、启动成本和内存曲线测定。</p>
<pre><code>[program:magento-consumer]
command=/usr/bin/php /var/www/html/bin/magento queue:consumers:start async.operations.all --max-messages=500
autostart=true
autorestart=true
stopsignal=TERM
stopwaitsecs=60
numprocs=1
redirect_stderr=true</code></pre>
<h3>最常见的累积点</h3>
<ul>
<li>把每条消息实体追加到类属性数组；</li>
<li>循环加载完整 Product/Order 对象并长期持有；</li>
<li>失败后保留异常对象和大响应正文；</li>
<li>图片、XML 或 CSV 资源没有在 finally 中关闭；</li>
<li>第三方 SDK 静态缓存没有 reset。</li>
</ul>
<pre><code>journalctl -k --since '2 hours ago' | grep -iE 'oom|killed process'
grep -RniE 'Allowed memory size|out of memory' var/log | tail -n 50
bin/magento queue:consumers:list</code></pre>
<p>上线后同时观察队列积压、每分钟处理量、失败重试和 RSS。内存稳定但队列越来越长，说明重启间隔过于保守；内存下降而重复消费增加，则检查消息确认和幂等性。最终目标是吞吐、内存与正确性一起稳定。</p>
<h3>给退出留出确认消息的时间</h3>
<p>Supervisor 的 stopwaitsecs 要长于最慢一条消息的正常处理时间。过早发送 KILL 会让消息来不及 ack，进程重启后再次消费。发布时先发 TERM，观察当前消息完成、连接关闭和进程退出，再由进程管理器启动新实例。</p>
<p>每次重启前后记录进程退出码；正常达到 max-messages 应是可预期退出，不能和 OOM、SIGKILL 混在同一 autorestart 指标里。</p>]]></description>
      <pubDate>Thu, 20 Feb 2025 07:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[多语言站 canonical 全指向默认店铺，Magento 2 SEO 配置从这三处核对]]></title>
      <link>https://www.360magento.com/blog/wrong-canonical-store-view/</link>
      <description><![CDATA[<p>中文商品页是 <code>/zh/red-shirt.html</code>，页面 canonical 却指向英文默认店铺。搜索引擎可能把当前页信号合并到另一个 URL。处理前先抓取真实 HTML，不要只看浏览器地址栏。</p>
<pre><code>curl -sk https://shop.example.com/red-shirt.html -o /tmp/en.html
curl -sk https://shop.example.com/zh/red-shirt.html -o /tmp/zh.html
grep -ioE '&lt;link[^&gt;]+canonical[^&gt;]*&gt;' /tmp/en.html /tmp/zh.html</code></pre>
<h3>一：Base URL 和 Store Code</h3>
<pre><code>bin/magento store:list
bin/magento config:show web/url/use_store
bin/magento config:show web/secure/base_url
bin/magento config:show web/unsecure/base_url</code></pre>
<p>同域名加 Store Code 与独立域名的生成方式不同。配置要在正确 scope 下检查，默认范围正确不代表中文 Store View 正确。</p>
<h3>二：Magento 自带 canonical 开关</h3>
<pre><code>bin/magento config:show catalog/seo/product_canonical_tag
bin/magento config:show catalog/seo/category_canonical_tag
bin/magento config:show catalog/seo/product_use_categories</code></pre>
<p>这些开关决定商品和分类是否输出 canonical，但不会自动解决 hreflang 和跨店铺策略。商品是否带分类路径也会产生不同 URL。</p>
<h3>三：主题或 SEO 扩展是否覆盖 head</h3>
<pre><code>grep -RniE 'canonical|hreflang|rel=.alternate' app/design app/code | head -n 120
bin/magento module:status | grep -i seo</code></pre>
<p>若主题直接拼默认 Base URL，任何 Store View 都会指回默认站。应使用当前 Store 的 URL 服务和目标 Store 重写，不能只做字符串替换。</p>
<p>制作一个矩阵：英文商品、中文商品、英文分类、中文分类各抓一次，记录 HTTP 状态、canonical 与 hreflang。canonical 应指当前语言的首选 URL，hreflang 才负责语言对应；中文页 canonical 到英文页，同时声明中文自引用，会产生冲突信号。</p>
<h3>分页、筛选和协议也要进入抽查</h3>
<p>分类第二页、带 layered navigation 参数的 URL 和 HTTP 到 HTTPS 跳转可能由不同模块处理。首选页应输出稳定 canonical，参数页不能互相形成跳转链。用同一抓取脚本保存响应码、最终 URL 和 canonical，便于上线前后比较。</p>
<pre><code>curl -skIL 'https://shop.example.com/zh/category.html?p=2' | egrep -i 'HTTP/|location:'
curl -sk 'https://shop.example.com/zh/category.html?p=2' | grep -ioE '&lt;link[^&gt;]+canonical[^&gt;]*&gt;'</code></pre>]]></description>
      <pubDate>Wed, 19 Feb 2025 02:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台保存配置报 The configuration file has changed，先处理部署文件的所有权]]></title>
      <link>https://www.360magento.com/blog/config-file-changed-error/</link>
      <description><![CDATA[<p>管理员保存系统配置时出现 <code>The configuration file has changed</code>，或页面提示成功但 config.php、env.php 没有按预期更新。先明确：普通 Store 配置多数写数据库，只有被锁定、导出或部署管理的配置才涉及文件。不要直接给 app/etc 目录 777 权限。</p>
<h3>确认文件在部署流程中的状态</h3>
<pre><code>stat app/etc/config.php app/etc/env.php
ls -l app/etc/config.php app/etc/env.php
git status --short app/etc/config.php app/etc/env.php
bin/magento app:config:status</code></pre>
<p>如果 config.php 属于发布用户、PHP-FPM 只读，这是许多生产环境的正确设计。此时不应让后台任意改文件，而应通过配置部署流程提交变更。</p>
<h3>数据库值、锁定值和环境变量分开看</h3>
<pre><code>bin/magento config:show web/secure/base_url
bin/magento config:show payment/checkmo/active
grep -n "web|payment" app/etc/config.php app/etc/env.php
env | grep -E '^CONFIG__|^MAGENTO_'</code></pre>
<p>后台表单值可能被环境变量或文件覆盖。若某项被锁定，后台修改不是正确入口；需要在部署源中改值，再执行导入。不要为了&ldquo;让后台能保存&rdquo;删除所有锁定配置。</p>
<h3>审查后再导入</h3>
<pre><code>bin/magento maintenance:enable
bin/magento app:config:import
bin/magento cache:clean config
bin/magento maintenance:disable</code></pre>
<p>导入可能涉及模块启用状态和作用域配置。生产站不要把 <code>app:config:dump</code> 当成无害命令，它可能导出数据库配置并改变后台可编辑状态。</p>
<pre><code>namei -l app/etc/config.php
ps -eo user,group,cmd | grep '[p]hp-fpm'
getfacl app/etc app/etc/config.php app/etc/env.php</code></pre>
<p>单机可使用共同组权限；不可变发布应让文件随 release 切换，运行用户只读。修复标准是明确哪类配置由后台管理、哪类由代码与环境管理，并在下一次部署后仍保持一致。</p>
<h3>保存前后的文件时间能揭示谁在竞争写入</h3>
<p>连续记录 inode、mtime 和发布任务时间。如果后台保存期间部署脚本正好替换 release，表单基于旧配置提交就可能触发 changed 提示。把配置修改纳入发布队列，避免管理员后台写文件与 CI/CD 同时运行。</p>
<pre><code>stat -c '%n inode=%i mtime=%y owner=%U:%G' app/etc/config.php app/etc/env.php
ps -ef | grep -E '[d]eploy|[c]omposer|app:config'</code></pre>
<p>对共享 app/etc 的多节点站点，还要确认没有两套发布任务同时写同一文件。最好让每个 release 携带确定的 config.php，并只在切换版本时执行一次受控导入。</p>]]></description>
      <pubDate>Tue, 18 Feb 2025 06:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Mismatched anonymous define() module：RequireJS 映射冲突别靠刷新掩盖]]></title>
      <link>https://www.360magento.com/blog/requirejs-mismatched-define/</link>
      <description><![CDATA[<p>页面偶尔白屏，控制台报 <code>Mismatched anonymous define() module</code>，刷新后又正常。这类问题常被缓存掩盖，实际原因是匿名 AMD 模块被 RequireJS 以无法对应的方式加载，或者同一文件既被 script 标签加载，又被 RequireJS 加载。</p>
<p><strong>不要先开合并。</strong>在预发布环境关闭 merge/bundling，保留源路径复现：</p>
<pre><code>bin/magento config:set dev/js/merge_files 0
bin/magento config:set dev/js/enable_js_bundling 0
bin/magento cache:clean config full_page
rm -rf pub/static/frontend/Vendor/theme/zh_CN
bin/magento setup:static-content:deploy -f zh_CN</code></pre>
<p>删除静态目录应在维护窗口进行，并保留 <code>pub/static/.htaccess</code>。</p>
<h3>找到匿名 define 与重复 script</h3>
<pre><code>grep -RniE 'define(s*[' app/code app/design | head -n 100
grep -RniE '&lt;script[^&gt;]+src=.*js' app/code app/design | head -n 100
grep -Rni "map:|mixins:" app/code/*/*/view app/design | head -n 120</code></pre>
<p>模块文件使用匿名 <code>define</code> 本身并非错误；错误通常发生在它脱离 RequireJS loader 被直接插入页面，或 bundle 拼接顺序让 loader 无法关联当前 URL。</p>
<h3>mixin 目标使用模块 ID，不是文件路径</h3>
<pre><code>var config = {
 config: {
  mixins: {
   'Magento_Checkout/js/view/minicart': {
    'Vendor_Module/js/minicart-mixin': true
   }
  }
 }
};</code></pre>
<p>目标不要带 <code>.js</code>。两个模块同时 map 同一别名时，合并后的 requirejs-config 以后加载者为准，部署顺序变化就可能表现不稳定。</p>
<p>修复后重新启用生产配置，连续冷加载、强制刷新和无痕窗口各测试多次，并确认故障文件只请求一次。若只有 bundling 开启才失败，应检查 bundle 与第三方脚本兼容性，而不是加延时重试。</p>
<h3>部署后比较合并前后的模块名</h3>
<p>从浏览器报错堆栈记录第一个业务 JS URL，在 pub/static 与源目录分别计算哈希，并检查页面是否还引用上一个 release 的 requirejs-config。多节点环境如果只有一台保留旧静态文件，故障会随负载均衡随机出现。</p>
<pre><code>sha256sum app/code/Vendor/Module/view/frontend/web/js/*.js
find pub/static/frontend -path '*Vendor_Module/js/*.js' -exec sha256sum {} ;</code></pre>]]></description>
      <pubDate>Mon, 17 Feb 2025 01:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[取消订单后库存没有回来，用 Reservation 记录确认补偿是否生成]]></title>
      <link>https://www.360magento.com/blog/cancel-order-stock-not-restored/</link>
      <description><![CDATA[<p>订单取消后，Source Item 的实际数量可能从未减少，但 Salable Quantity 仍少了下单数量。这是 MSI 中&ldquo;物理数量&rdquo;和&ldquo;Reservation&rdquo;没有对齐的典型现象。下单通常写负 reservation，取消应写对应的正补偿记录。</p>
<h3>按订单号查询完整 Reservation 链</h3>
<pre><code>SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE metadata LIKE '%000000123%'
ORDER BY reservation_id;</code></pre>
<p>同一 SKU 正常会看到负数下单记录和正数取消记录，两者合计为零。不要修改已有 reservation 行；它是追加式记录，直接 UPDATE 会破坏审计链。</p>
<pre><code>SELECT sku, stock_id, SUM(quantity) AS reservation_total
FROM inventory_reservation
WHERE sku='ABC-001'
GROUP BY sku, stock_id;

SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku='ABC-001';</code></pre>
<p>reservation_total 为负表示仍有未补偿预留，但还要确认订单是否存在其他有效占用。Source Item quantity 正常并不能证明可售数量正常。</p>
<h3>让 Magento 找不一致，不手写补偿 SQL</h3>
<pre><code>bin/magento list inventory | grep reservation
bin/magento inventory:reservation:list-inconsistencies -r
bin/magento inventory:reservation:list-inconsistencies  | bin/magento inventory:reservation:create-compensations</code></pre>
<p>不同版本参数可能略有差异，先用 list 确认。生成补偿前保存命令输出并限定维护窗口；结果可能包含仍在处理的订单，不应看到列表就全部执行。</p>
<h3>取消为何没生成正记录</h3>
<ul>
<li>ERP 直接改了订单 state/status，没有调用 Magento 取消服务；</li>
<li>插件在取消事务中抛异常，库存消息未完成；</li>
<li>消息消费者停止，异步库存处理积压；</li>
<li>外部系统重复取消，幂等处理有缺口。</li>
</ul>
<pre><code>grep -Rni '000000123|ABC-001' var/log | tail -n 100
bin/magento queue:consumers:list | grep -i inventory
ps -ef | grep '[q]ueue:consumers:start'</code></pre>
<p>补偿后重新查询 reservation 合计，并从前台执行加入购物车和下单预检。真正修复还应让 ERP 通过订单服务取消，而不是继续直接更新数据库。</p>
<h3>先确认订单动作是真的 Cancel</h3>
<p>后台的自定义状态名称可能叫&ldquo;已取消&rdquo;，但订单 state 仍是 processing 或 closed。查询 <code>sales_order.state</code>、<code>status</code>、<code>total_canceled</code> 和商品的 <code>qty_canceled</code>，确认业务系统调用的是取消服务而不是只改显示状态。只有真实取消事务才会触发库存补偿。</p>]]></description>
      <pubDate>Fri, 14 Feb 2025 08:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[优惠券显示已应用却没有折扣，Quote 条件究竟卡在哪里]]></title>
      <link>https://www.360magento.com/blog/coupon-applied-no-discount/</link>
      <description><![CDATA[<p>前台提示&ldquo;优惠券已应用&rdquo;，输入框也保留 coupon code，但订单汇总没有折扣。这里要区分&ldquo;代码格式通过&rdquo;与&ldquo;规则真正作用于商品&rdquo;。Magento 会按网站、客户组、时间、条件和 Action 商品逐层过滤。</p>
<ol>
<li>记录 quote_id、store_id、客户组和 coupon code；</li>
<li>查看规则有效时间和 action 类型；</li>
<li>确认 Conditions 控制购物车，Actions 控制哪些商品获得折扣；</li>
<li>重新 collect totals，比较前后数据。</li>
</ol>
<pre><code>SELECT entity_id, store_id, customer_group_id, coupon_code,
 subtotal, discount_amount, grand_total
FROM quote WHERE entity_id=456;

SELECT r.rule_id, r.name, r.is_active, r.from_date, r.to_date,
 r.simple_action, r.discount_amount, r.stop_rules_processing
FROM salesrule r
JOIN salesrule_coupon c ON c.rule_id=r.rule_id
WHERE c.code='SAVE10';</code></pre>
<h3>网站和客户组要查关系表</h3>
<pre><code>SELECT * FROM salesrule_website WHERE rule_id=12;
SELECT * FROM salesrule_customer_group WHERE rule_id=12;
SELECT website_id, code FROM store_website;
SELECT customer_group_id, customer_group_code FROM customer_group;</code></pre>
<p>游客使用 NOT LOGGED IN 组；登录前后 group 改变，旧 Quote 可能需要重新收集 totals。多网站环境中，优惠券属于规则覆盖的网站，不是 Store View 名称。</p>
<h3>用商品级数据找出被 Action 排除的 SKU</h3>
<pre><code>SELECT item_id, sku, product_type, parent_item_id, qty,
 row_total, discount_amount, applied_rule_ids
FROM quote_item
WHERE quote_id=456
ORDER BY item_id;</code></pre>
<p><code>applied_rule_ids</code> 没有目标 rule_id，说明规则未命中；有 rule_id 但折扣为零，继续查 action 类型、最大折扣、step quantity 和固定金额。可配置商品要明确匹配 parent 还是 child。</p>
<pre><code>SELECT address_id, address_type, country_id, region_id, postcode,
 subtotal, discount_amount, grand_total
FROM quote_address WHERE quote_id=456;</code></pre>
<p>包含配送国家、邮编或运费方式的规则，在地址未完整前可能先显示代码已接受，随后才被排除。修复后测试游客、登录客户、临界日期和最低金额上下两组购物车。</p>]]></description>
      <pubDate>Thu, 13 Feb 2025 03:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 图片缓存目录不断出现 404，原图、权限和 WebP 各查一层]]></title>
      <link>https://www.360magento.com/blog/product-image-cache-404/</link>
      <description><![CDATA[<p>商品列表里的图片时好时坏，URL 通常落在 <code>/media/catalog/product/cache/...</code>。这个目录是派生产物，404 可能是原图不存在、PHP 无法写入、Nginx 没把缺失图片交给 Magento 生成，也可能是 WebP 扩展或 CDN 改写了后缀。</p>
<h3>拿一条失败 URL 反查原图</h3>
<pre><code>curl -skI 'https://shop.example.com/media/catalog/product/cache/abc123/r/e/red-shirt.jpg'
find pub/media/catalog/product -path '*/r/e/red-shirt.jpg' -ls
stat pub/media/catalog/product/r/e/red-shirt.jpg
file pub/media/catalog/product/r/e/red-shirt.jpg</code></pre>
<p>数据库有文件名但磁盘无原图，resize 不可能成功。共享媒体或对象存储站点要在 PHP 节点验证，不能只登录 Nginx 节点查看。</p>
<h3>在维护窗口主动生成</h3>
<pre><code>bin/magento catalog:images:resize
tail -n 100 var/log/exception.log
find pub/media/catalog/product/cache -type f -mmin -5 | head</code></pre>
<p>报 permission denied 时检查 CLI 用户与 PHP-FPM 用户是否共享组权限。不要执行 <code>chmod -R 777 pub/media</code>，应修正 owner、group 和目录继承策略。</p>
<pre><code>namei -l pub/media/catalog/product/cache
ps -eo user,group,cmd | grep '[p]hp-fpm'
getfacl pub/media/catalog/product pub/media/catalog/product/cache | head -n 80</code></pre>
<h3>文件存在，HTTP 仍 404</h3>
<p>比较 Web Server root 与 Magento pub 目录，检查 media location 是否被错误的 try_files 截断。若 URL 改成 .webp，确认转换文件实际存在。</p>
<pre><code>nginx -T 2&gt;/dev/null | grep -nE 'root |location .*/media|try_files' | head -n 80
curl -sk --resolve shop.example.com:443:10.0.0.12  'https://shop.example.com/media/catalog/product/cache/abc123/r/e/red-shirt.jpg'  -o /tmp/image.bin
file /tmp/image.bin</code></pre>
<p>CDN 404 而源站 200，就刷新具体失败路径并检查是否缓存了早期 404。最后从商品列表、详情页、购物车各验证一种尺寸，因为它们的 cache key 不同。</p>
<h3>不要把清空 cache 当作修复</h3>
<p>删除图片 cache 只会强制重新生成。如果原图缺失、目录不可写或转换器配置错误，清空后会让原本还能访问的缓存也消失。先选一张失败图片完成端到端验证，再决定是否批量重建。</p>]]></description>
      <pubDate>Wed, 12 Feb 2025 06:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Area code is not set 出现在 Cron：命令行代码少了哪一步初始化]]></title>
      <link>https://www.360magento.com/blog/area-code-not-set-cron/</link>
      <description><![CDATA[<p><code>Area code is not set</code> 常见于自定义 Cron、Console Command 或批处理脚本。它不是让你在任意位置加一行 <code>setAreaCode('frontend')</code> 就结束，而是在提醒：代码调用了依赖区域配置的服务，却没有明确运行上下文。</p>
<h3>从异常栈找到第一个自定义类</h3>
<pre><code>grep -Rni "Area code is not set" var/log generated/log 2&gt;/dev/null | tail -n 20
bin/magento cron:run --group default -vvv
bin/magento your:command -vvv</code></pre>
<p>异常栈中第一次进入 <code>VendorModule</code> 的位置比最后的 State.php 更重要。邮件模板、主题配置、Session 和 Layout 可能要求 area；Repository 的普通数据读取通常不需要。</p>
<h3>命令确实固定运行在一个 area</h3>
<pre><code>use MagentoFrameworkAppArea;
use MagentoFrameworkAppState;

try {
 $this-&gt;state-&gt;setAreaCode(Area::AREA_ADMINHTML);
} catch (MagentoFrameworkExceptionLocalizedException $e) {
 // area 已由外层设置时，不在这里覆盖
}</code></pre>
<p>一个进程内只能设置一次 area；批量命令或其他模块已设置后，再设置会得到 Area code is already set。不要用 ObjectManager 临时取 State。</p>
<h3>只为一小段逻辑模拟前台环境</h3>
<pre><code>$this-&gt;appState-&gt;emulateAreaCode(
 MagentoFrameworkAppArea::AREA_FRONTEND,
 function () use ($storeId) {
  return $this-&gt;renderer-&gt;renderForStore($storeId);
 }
);</code></pre>
<p>生成邮件或模板时通常还需要 Store Emulation：</p>
<pre><code>$this-&gt;emulation-&gt;startEnvironmentEmulation($storeId, 'frontend', true);
try {
 $this-&gt;service-&gt;execute($storeId);
} finally {
 $this-&gt;emulation-&gt;stopEnvironmentEmulation();
}</code></pre>
<p><code>finally</code> 很关键，否则异常后长进程会继续带着错误 Store 环境处理下一条任务。修复判断不只是命令不报错，还要确认输出使用正确店铺的语言、货币、主题和发件人。若只读取商品数据却必须模拟 frontend，应检查服务依赖是否过重。</p>
<h3>不要在构造函数里依赖区域</h3>
<p>依赖注入创建对象发生在 execute 之前。如果构造函数就读取主题、翻译或 Store 环境，即使 execute 开头设置 area 也太晚。把区域相关工作延迟到明确的方法中，并把纯数据读取服务与渲染服务拆开，能从根源减少 Area Code 耦合。</p>]]></description>
      <pubDate>Tue, 11 Feb 2025 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[customer/section/load 反复返回 400，购物车小图标为何一直转圈]]></title>
      <link>https://www.360magento.com/blog/section-load-400/</link>
      <description><![CDATA[<p>页面主体已经打开，但右上角购物车一直转圈，Network 中 <code>customer/section/load</code> 连续返回 400。这个请求负责加载购物车、客户信息等私有内容，问题通常不在 minicart 模板，而在请求参数、会话 Cookie 或自定义 section 的返回值。</p>
<p><strong>先保留一个失败请求。</strong>在 Network 里复制为 cURL，去掉真实会话值后记录请求路径、sections 参数、Store Cookie 和响应正文。400 的 JSON 消息比&ldquo;前端转圈&rdquo;更接近原因。</p>
<pre><code>curl -sk 'https://shop.example.com/customer/section/load/?sections=cart&amp;force_new_section_timestamp=false'  -H 'X-Requested-With: XMLHttpRequest'  -D /tmp/section.headers -o /tmp/section.json
cat /tmp/section.headers
head -c 1000 /tmp/section.json</code></pre>
<h3>只在特定页面失败：查 sections.xml</h3>
<pre><code>grep -Rni "&lt;section name=" app/code/*/*/etc/frontend/sections.xml
grep -Rni "customerData.reload|customerData.invalidate" app/code app/design | head -n 80</code></pre>
<p>自定义 action 若把所有 section 都标记为失效，每次点击都会触发大请求；section 名称写错，或 JS 请求服务端不存在的 section，也会失败。先把请求缩小到 <code>sections=cart</code>，若单独成功，再逐个加入其他 section。</p>
<h3>所有页面都失败：对齐会话与 Cookie</h3>
<ul>
<li>确认域名、HTTPS 和 Cookie Domain 没有在 www/非 www 间跳转；</li>
<li>检查 PHPSESSID、private_content_version 是否被 CDN 缓存进公共响应；</li>
<li>多节点环境确认 Session 使用共享存储；</li>
<li>清测试域名站点数据可用于验证，但不能当成最终修复。</li>
</ul>
<pre><code>bin/magento config:show web/cookie/cookie_domain
bin/magento config:show web/secure/base_url
grep -n "session" app/etc/env.php</code></pre>
<h3>自定义 section 不应让整条请求崩溃</h3>
<pre><code>public function getSectionData(): array
{
 try {
  return ['value' =&gt; $this-&gt;service-&gt;getValue()];
 } catch (MagentoFrameworkExceptionLocalizedException $e) {
  return ['value' =&gt; null, 'available' =&gt; false];
 }
}</code></pre>
<p>不要吞掉所有 Throwable；真正的代码错误应写日志并修复。完成时，首次加载只有预期的 section 请求，响应 200，重复刷新不形成循环，加入购物车后数量及时变化。</p>]]></description>
      <pubDate>Mon, 10 Feb 2025 07:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品价格改了前台不变：先判断价格索引还是页面缓存]]></title>
      <link>https://www.360magento.com/blog/product-price-not-updated/</link>
      <description><![CDATA[<p>后台把商品价格从 399 改成 359，保存提示成功，前台却仍显示 399。把所有缓存清一遍可能暂时见效，但无法说明故障是在价格索引、页面缓存、第三方搜索还是店铺作用域。先用同一 SKU 做一次&ldquo;数据&mdash;索引&mdash;输出&rdquo;对照。</p>
<h3>确认改的是前台正在使用的网站范围</h3>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity WHERE sku='ABC-001';
SELECT store_id, code, website_id FROM store ORDER BY store_id;
SELECT store_id, value
FROM catalog_product_entity_decimal
WHERE entity_id=123 AND attribute_id=(
 SELECT attribute_id FROM eav_attribute
 WHERE attribute_code='price' AND entity_type_id=(
  SELECT entity_type_id FROM eav_entity_type WHERE entity_type_code='catalog_product'
 )
);</code></pre>
<p>不要照抄 attribute_id。若后台切在另一个网站范围，继续清缓存不会改变目标站点价格。</p>
<h3>比较源价格与索引价格</h3>
<pre><code>SELECT entity_id, customer_group_id, website_id,
 price, final_price, min_price, max_price
FROM catalog_product_index_price
WHERE entity_id=123
ORDER BY website_id, customer_group_id;

bin/magento indexer:status catalog_product_price
bin/magento indexer:show-mode catalog_product_price
SELECT * FROM mview_state WHERE view_id LIKE '%product_price%';</code></pre>
<p>源属性已经是 359、索引表仍是 399，问题落在 indexer/MView。若模式为 Update by Schedule，继续看 Cron 和 changelog 积压，不要把模式永久改成 Save 来掩盖调度问题。</p>
<pre><code>bin/magento indexer:reindex catalog_product_price
bin/magento indexer:status catalog_product_price</code></pre>
<h3>索引正确时再查输出缓存</h3>
<pre><code>curl -sk https://shop.example.com/product.html -o /tmp/product.html
grep -nE '359|399|priceAmount' /tmp/product.html | head -n 20
curl -skI https://shop.example.com/product.html | egrep -i 'age|x-cache|x-magento-cache-debug'</code></pre>
<p>HTML 仍是旧价，检查 Full Page Cache、Varnish 和 CDN；HTML 已是新价而组件仍旧，检查 customer-data、价格 box 与本地存储。搜索结果页单独使用搜索索引时，也要验证它和商品详情页是否来自不同数据源。</p>
<p>修复后用匿名用户、登录用户和两个 customer group 各验证一次。启用了 catalog price rule 或 group price 的站点，&ldquo;某一个账号价格正确&rdquo;不能代表所有维度都恢复。</p>]]></description>
      <pubDate>Fri, 07 Feb 2025 02:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[GraphQL products 查得到 SKU 却返回空数组，Store Header 和可见性先对齐]]></title>
      <link>https://www.360magento.com/blog/graphql-products-empty/</link>
      <description><![CDATA[<p>数据库里能找到 SKU，后台也能打开商品，但 GraphQL <code>products</code> 返回 <code>items: []</code>。这不一定是 Resolver 出错；GraphQL 会按当前 Store、网站分配、商品状态、可见性以及搜索索引过滤结果。第一步是让 API 请求和你在后台查看的店铺范围一致。</p>
<h3>用同一查询对比不同 Store Header</h3>
<pre><code>curl -sk https://shop.example.com/graphql  -H 'Content-Type: application/json'  -H 'Store: default'  --data '{"query":"{products(filter:{sku:{eq:"ABC-001"}}){total_count items{sku name url_key}}}"}'

curl -sk https://shop.example.com/graphql  -H 'Content-Type: application/json'  -H 'Store: zh_cn'  --data '{"query":"{products(filter:{sku:{eq:"ABC-001"}}){total_count items{sku name url_key}}}"}'</code></pre>
<p>一个 Store 有结果、另一个为空，优先检查商品网站分配与店铺视图属性，不要立即改 Resolver。Header 值使用 store code，不是网站名称。</p>
<h3>数据库里确认网站关系与范围值</h3>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity WHERE sku='ABC-001';

SELECT product_id, website_id
FROM catalog_product_website
WHERE product_id=123;

SELECT store_id, code, website_id
FROM store
ORDER BY website_id, store_id;</code></pre>
<p>商品必须分配到 Store 所属 website。状态和可见性是 EAV 属性，还可能被 Store View 覆盖；后台默认范围显示&ldquo;启用&rdquo;，并不能证明目标 Store 的值相同。</p>
<h3>用命令确认索引没有积压</h3>
<pre><code>bin/magento indexer:status catalogsearch_fulltext catalog_product_attribute
bin/magento indexer:show-mode catalogsearch_fulltext
bin/magento indexer:reindex catalogsearch_fulltext catalog_product_attribute
bin/magento cache:clean graphql</code></pre>
<p>只重建全文索引后有结果，说明之前的更新链路存在问题，还要继续查 Cron 与 MView，而不是把每天手工 reindex 当成修复方案。</p>
<h3>可见性和库存要按查询场景理解</h3>
<p>简单商品如果只允许在 Catalog 中不可单独搜索，按搜索语义调用可能被过滤；可配置商品的子 SKU 也未必作为独立产品返回。启用了库存相关过滤或前端只展示可售商品时，还要对照 source、stock 和 salable quantity。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies -r | grep 'ABC-001'
bin/magento inventory:reservation:list-inconsistencies | grep 'ABC-001'</code></pre>
<p>不同版本的库存命令参数可能有差异，先用 <code>bin/magento list inventory</code> 确认可用命令。最终验证应记录请求 Header、GraphQL 原始响应、商品 website 和目标 Store 属性；不要只凭前端页面&ldquo;看不到&rdquo;判断 GraphQL 返回空。</p>]]></description>
      <pubDate>Thu, 06 Feb 2025 07:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Varnish 已经 HIT，Magento 2 页面仍然慢在什么地方]]></title>
      <link>https://www.360magento.com/blog/varnish-hit-slow-page/</link>
      <description><![CDATA[<p>看到 <code>X-Cache: HIT</code> 就认为 Magento 性能没有问题，是常见误判。Varnish 只说明主响应命中了某个缓存对象；页面可交互时间还受 private content、ESI、GraphQL/AJAX、图片、JavaScript 和第三方标签影响。</p>
<h3>先把主文档时间单独量出来</h3>
<pre><code>curl -sk -o /dev/null  -w 'code=%{http_code} dns=%{time_namelookup} connect=%{time_connect} start=%{time_starttransfer} total=%{time_total}
'  https://shop.example.com/category.html

curl -skI https://shop.example.com/category.html |  egrep -i 'age|x-cache|cache-control|x-magento-cache-debug|via'</code></pre>
<p>TTFB 很低而浏览器仍慢，问题大概率不在 PHP 生成主页面。TTFB 仍高时，要确认所谓 HIT 是否来自正确层、是否发生 ESI 回源，或边缘节点到用户的网络耗时。</p>
<h3>列出首屏之后发起的动态请求</h3>
<p>在浏览器 Network 按开始时间排序，关注 <code>customer/section/load</code>、推荐接口、搜索建议、第三方支付与统计请求。任一同步等待都可能让加载动画持续。</p>
<pre><code>curl -sk -o /dev/null -w '%{time_starttransfer} %{time_total}
'  'https://shop.example.com/customer/section/load/?sections=cart,customer'
grep -Rni "customerData.reload|section/load" app/design app/code | head -n 40</code></pre>
<p>自定义组件每次页面加载都强制 reload private section，会绕过主页面缓存优势。应检查 <code>sections.xml</code> 是否把无关 action 绑定到大量 section。</p>
<h3>确认 Varnish 对不同访问条件的表现</h3>
<pre><code>for i in 1 2 3; do
  curl -skI https://shop.example.com/category.html | egrep -i 'age|x-cache|set-cookie';
done

curl -skI -H 'Cookie: PHPSESSID=test' https://shop.example.com/category.html |  egrep -i 'age|x-cache|cache-control'</code></pre>
<p>匿名、带会话 Cookie、不同 Store 和货币的缓存键可能不同。不要只用一次无 Cookie 请求代表真实用户。</p>
<h3>用浏览器 Performance 找主线程瓶颈</h3>
<p>如果所有网络请求都快，但页面迟迟不能点击，记录 Performance trace，查长任务、重复 layout 和大型 bundle 执行。此时再调 Varnish TTL 没有帮助，应拆分前端模块、延迟非关键脚本并减少首屏 DOM。</p>
<p>最终报告应分别给出主文档 TTFB、最大动态请求耗时、静态资源体积和主线程长任务，而不是一句&ldquo;缓存已命中&rdquo;。这样才能把后端缓存、接口和前端执行分给正确负责人。</p>]]></description>
      <pubDate>Wed, 05 Feb 2025 03:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付页面被 CSP 拦截，不要把 Magento 2 的安全策略整段关闭]]></title>
      <link>https://www.360magento.com/blog/csp-blocks-payment-script/</link>
      <description><![CDATA[<p>结账页能打开，选择支付方式后却没有弹窗，控制台出现 <code>Refused to load the script</code> 或 <code>Refused to connect</code>。最危险的处理是关闭 CSP 或添加 <code>*</code>。正确做法是识别被拦截的资源类型、准确域名和实际业务阶段，只放行必需来源。</p>
<h3>先读完整的浏览器违规信息</h3>
<p><code>script-src</code>、<code>connect-src</code>、<code>frame-src</code> 和 <code>img-src</code> 不能互相替代。支付 SDK 主脚本可能来自一个域，API 请求、3DS iframe 和像素图片又来自其他域。把控制台信息按 directive 分类记录。</p>
<pre><code>grep -Rni "Content-Security-Policy" app/code app/design vendor/*/*/etc
find app/code -path '*etc/csp_whitelist.xml' -print
curl -skI https://shop.example.com/checkout/ | grep -i content-security-policy</code></pre>
<h3>为模块建立最小白名单</h3>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd"&gt;
 &lt;policies&gt;
  &lt;policy id="script-src"&gt;
   &lt;values&gt;
    &lt;value id="gateway-sdk" type="host"&gt;https://js.gateway.example&lt;/value&gt;
   &lt;/values&gt;
  &lt;/policy&gt;
  &lt;policy id="connect-src"&gt;
   &lt;values&gt;
    &lt;value id="gateway-api" type="host"&gt;https://api.gateway.example&lt;/value&gt;
   &lt;/values&gt;
  &lt;/policy&gt;
 &lt;/policies&gt;
&lt;/csp_whitelist&gt;</code></pre>
<p>示例域名必须替换为支付服务商真实生产域名。不要把 sandbox 和 production 混在一条宽泛通配符中；测试环境可单独配置。</p>
<h3>更新配置后检查响应头而不是只清缓存</h3>
<pre><code>bin/magento cache:clean config full_page
bin/magento setup:di:compile
curl -skI https://shop.example.com/checkout/ | grep -i content-security-policy</code></pre>
<p>如果 CDN 或 Nginx 也写 CSP header，浏览器会同时执行多条策略，Magento 白名单正确仍可能被外围响应头拦截。用 Network 面板查看最终响应里到底有几条 CSP。</p>
<h3>结账验证要覆盖 3DS 和失败路径</h3>
<p>普通测试卡成功并不代表规则完整。还要测试 3DS iframe、支付失败后返回、切换支付方式和订单成功页，并确认没有新增 CSP 违规。白名单变更应纳入代码审查，因为它改变的是浏览器信任边界，而不只是修一个前端报错。</p>]]></description>
      <pubDate>Tue, 04 Feb 2025 05:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 管理员能登录却看不到菜单：ACL 资源没有按角色生效]]></title>
      <link>https://www.360magento.com/blog/admin-menu-acl-missing/</link>
      <description><![CDATA[<p>超级管理员能看到自定义菜单，普通角色登录后整组菜单消失，通常不是路由问题，而是菜单绑定的 ACL resource 没有被该角色授权。若所有角色都看不到，再检查模块和 XML 是否被加载。</p>
<h3>menu.xml 与 acl.xml 的 ID 必须完全一致</h3>
<pre><code>&lt;!-- etc/adminhtml/menu.xml --&gt;
&lt;add id="Vendor_Module::report"
     title="Report"
     module="Vendor_Module"
     sortOrder="50"
     parent="Magento_Backend::content"
     action="vendor/report/index"
     resource="Vendor_Module::report" /&gt;

&lt;!-- etc/acl.xml --&gt;
&lt;resource id="Magento_Backend::admin"&gt;
    &lt;resource id="Vendor_Module::report" title="Report" sortOrder="50" /&gt;
&lt;/resource&gt;</code></pre>
<p>大小写、模块前缀或尾部单复数任一不同，都会变成两个资源。不要为了让菜单出现而临时改成 <code>Magento_Backend::admin</code>，这相当于扩大权限。</p>
<h3>确认模块和合并后的 ACL</h3>
<pre><code>bin/magento module:status Vendor_Module
bin/magento cache:clean config
bin/magento setup:di:compile
grep -R "Vendor_Module::report" app/code vendor/*/*/etc</code></pre>
<p>开发环境 XML 能加载，不代表生产编译产物一定同步。多节点部署应确认代码版本一致；只清一个节点的 config cache 可能产生时有时无的菜单。</p>
<h3>角色保存后要重新建立后台会话</h3>
<p>在&ldquo;系统 &rarr; 权限 &rarr; 角色&rdquo;中为目标角色勾选资源并保存，然后让该管理员退出重新登录。旧会话可能保留授权树。若资源树里根本没有该节点，问题仍在 acl.xml，而不是角色选择。</p>
<h3>控制器也要使用相同授权边界</h3>
<pre><code>class Index extends MagentoBackendAppAction
{
    public const ADMIN_RESOURCE = 'Vendor_Module::report';

    public function execute()
    {
        return $this-&gt;resultFactory-&gt;create(
            MagentoFrameworkControllerResultFactory::TYPE_PAGE
        );
    }
}</code></pre>
<p>菜单显示但点击 Access Denied，常见原因是 Controller 的 <code>ADMIN_RESOURCE</code> 与菜单 resource 不一致。相反，控制器放宽而菜单收紧也会留下可直接访问的路由。</p>
<p>验证时至少使用两个账号：一个拥有该资源，一个明确不拥有。前者应看到并能访问，后者菜单不可见且直接输入 URL 也应被拒绝。只有界面和服务端授权同时成立，ACL 才算正确。</p>]]></description>
      <pubDate>Mon, 03 Feb 2025 01:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 购物车金额和订单金额差一分钱，税费舍入发生在哪一层]]></title>
      <link>https://www.360magento.com/blog/one-cent-total-difference/</link>
      <description><![CDATA[<p>购物车显示 199.99，订单或支付网关收到 200.00，这类问题不能靠在最后一步强行减 0.01。Magento 的金额同时存在基础币种和订单币种，并在 item、address、quote 与 order 多层累计；自定义 Totals 在错误层级舍入，会把一分钱放大成对账差异。</p>
<h3>先锁定差异第一次出现的位置</h3>
<pre><code>SELECT entity_id, quote_currency_code, base_currency_code,
       subtotal, base_subtotal, discount_amount, base_discount_amount,
       tax_amount, base_tax_amount, grand_total, base_grand_total
FROM quote WHERE entity_id=456;

SELECT entity_id, increment_id, order_currency_code, base_currency_code,
       subtotal, base_subtotal, discount_amount, base_discount_amount,
       tax_amount, base_tax_amount, grand_total, base_grand_total
FROM sales_order WHERE quote_id=456;</code></pre>
<p>Quote 已经错，查看 collectTotals 和价格规则；Quote 正确、Order 错，检查 quote 转 order 的扩展字段与 observer；Order 正确、支付请求错，则查支付模块把 major unit 转 minor unit 的代码。</p>
<h3>逐个商品比较，而不是只看总计</h3>
<pre><code>SELECT item_id, sku, qty, row_total, base_row_total,
       tax_amount, base_tax_amount, discount_amount, base_discount_amount,
       row_total_incl_tax, base_row_total_incl_tax
FROM quote_item WHERE quote_id=456 AND parent_item_id IS NULL;

SELECT item_id, sku, qty_ordered, row_total, base_row_total,
       tax_amount, base_tax_amount, discount_amount, base_discount_amount,
       row_total_incl_tax, base_row_total_incl_tax
FROM sales_order_item WHERE order_id=789 AND parent_item_id IS NULL;</code></pre>
<p>组合商品要排除 parent/child 重复累计。差额只出现在某个商品时，检查该商品税类、目录价含税配置和折扣分摊；差额集中在运费，查看 shipping tax class 与免费配送规则。</p>
<h3>检查自定义 Total 是否过早 round</h3>
<pre><code>// 错误倾向：每个中间步骤都 round
$amount = round($unit * $qty, 2);
$discount = round($amount * $rate, 2);

// 更稳妥：沿用 Magento PriceCurrency 的舍入边界
$amount = $this-&gt;priceCurrency-&gt;round($calculatedAmount);</code></pre>
<p>不是说任何地方都不能舍入，而是同一金额只能按业务定义的边界舍入。尤其不要一会儿用 PHP round，一会儿用字符串格式化，再让网关乘以 100。</p>
<h3>构造能暴露问题的测试组合</h3>
<p>用 3 件单价 0.33、含税价、百分比优惠券和运费税组成最小测试，分别记录购物车、结账 review、订单、发票和网关请求金额。若系统支持多币种，再加入非整数汇率。测试目标是找出第一个发生差异的对象，而不是让最终页面&ldquo;看起来一样&rdquo;。</p>]]></description>
      <pubDate>Fri, 31 Jan 2025 08:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[产品 URL 保存一次多一个 -1，先查重写冲突再动 url_key]]></title>
      <link>https://www.360magento.com/blog/product-url-suffix-conflict/</link>
      <description><![CDATA[<p>商品地址原本是 <code>red-shirt.html</code>，保存后变成 <code>red-shirt-1.html</code>，再次保存又出现新的后缀。Magento 这样做通常是为了避免同一店铺下的 request_path 冲突。直接改 <code>url_key</code> 只能绕开表面冲突，还可能留下更多历史重写。</p>
<h3>从目标路径反查占用者</h3>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE request_path IN ('red-shirt.html','red-shirt-1.html')
ORDER BY store_id, request_path;</code></pre>
<p>同一个 request_path 可以存在于不同 store_id，但不能在同一店铺范围重复。重点判断冲突记录属于另一个商品、分类路径、CMS 自定义重写，还是该商品自己的旧 301。</p>
<h3>商品层面的 url_key 是否被 Store View 覆盖</h3>
<pre><code>SELECT a.attribute_id, a.attribute_code
FROM eav_attribute a
JOIN eav_entity_type t ON t.entity_type_id=a.entity_type_id
WHERE t.entity_type_code='catalog_product' AND a.attribute_code='url_key';

SELECT value_id, attribute_id, store_id, entity_id, value
FROM catalog_product_entity_varchar
WHERE entity_id=123 AND attribute_id=117;</code></pre>
<p>这里的 attribute_id 必须使用第一条查询实际返回值，不能照抄示例。store_id=0 是默认值，其他记录是店铺视图覆盖。后台切错范围时，你修改的值可能并不是前台正在使用的那个。</p>
<h3>决定保留历史跳转还是清理错误记录</h3>
<p>正常的 URL 变更会生成旧地址到新地址的 301，这对 SEO 有价值。只有确认某条记录由失败导入、错误店铺范围或已删除实体遗留造成，才备份后定向处理。</p>
<pre><code>CREATE TABLE url_rewrite_backup_20250130 AS
SELECT * FROM url_rewrite
WHERE store_id=1 AND request_path LIKE 'red-shirt%';

SELECT * FROM url_rewrite
WHERE store_id=1 AND entity_type='product' AND entity_id=123;</code></pre>
<p>不要执行无条件 <code>TRUNCATE url_rewrite</code>。它会同时清掉自定义重写和历史跳转，重建后也未必恢复人工规则。</p>
<h3>修复后的检查不止打开新 URL</h3>
<pre><code>curl -skI https://shop.example.com/red-shirt.html
curl -skI https://shop.example.com/red-shirt-old.html
bin/magento cache:clean full_page</code></pre>
<p>新地址应返回 200，确定需要保留的旧地址应只跳转一次并到达新地址，不能形成 301 链或循环。最后再保存商品一次，如果 request_path 保持稳定，才说明冲突已真正解除。</p>]]></description>
      <pubDate>Thu, 30 Jan 2025 02:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 邮件队列有记录却一直不发送，沿着 Cron 找到真正的阻塞点]]></title>
      <link>https://www.360magento.com/blog/email-queue-not-sending/</link>
      <description><![CDATA[<p>订单已经生成，后台也能看到邮箱地址，但客户收不到通知。先不要用同一订单反复测试，因为发信逻辑可能已经把它标记为 queued。应从&ldquo;是否排队、谁消费、是否交给邮件服务器&rdquo;三段拆开检查。</p>
<h3>确定当前是不是异步发送</h3>
<pre><code>bin/magento config:show sales_email/general/async_sending
bin/magento cron:run --group default
php -r 'echo date("c"), PHP_EOL;'
date -u</code></pre>
<p>异步发送开启时，结账成功只负责记录需要发送，真正发送依赖 Cron。应用时区、数据库 UTC 时间和服务器时间差异过大，会让任务看起来&ldquo;还没到执行时间&rdquo;。</p>
<h3>不要只看 cron:run 的退出码</h3>
<pre><code>SELECT job_code, status, scheduled_at, executed_at, finished_at,
       LEFT(messages, 300) AS message
FROM cron_schedule
WHERE job_code LIKE '%email%' OR job_code LIKE '%send%'
ORDER BY schedule_id DESC LIMIT 30;

SELECT status, COUNT(*)
FROM cron_schedule
WHERE scheduled_at &gt; UTC_TIMESTAMP() - INTERVAL 2 HOUR
GROUP BY status;</code></pre>
<p>大量 pending 且 executed_at 为空，优先查系统 crontab 和进程锁；大量 error，读取 messages 和 <code>var/log/cron.log</code>；success 但仍无邮件，则说明 Magento 任务跑完了，问题可能在 transport、SMTP 中继或收件方。</p>
<h3>用单独的传输测试隔离 SMTP</h3>
<pre><code>openssl s_client -starttls smtp -connect smtp.example.com:587 -crlf
nc -vz smtp.example.com 587
grep -RniE 'smtp|transport|mail|authentication failed|timed out' var/log | tail -n 80</code></pre>
<p>生产环境不要把真实密码写进命令历史。若使用 SMTP 扩展，打开它自己的 debug 日志并完成一次受控测试，然后立即关闭详细日志，避免记录收件人和服务器响应。</p>
<h3>订单状态与发送标志也要核对</h3>
<pre><code>SELECT entity_id, increment_id, customer_email,
       send_email, email_sent, created_at
FROM sales_order
WHERE increment_id='000000123';</code></pre>
<p><code>send_email=0</code> 表示该订单根本没被安排发送；<code>email_sent=1</code> 只代表应用认为发送完成，不等于对方收件箱一定收到。后者要继续查邮件服务商的投递、退信和抑制列表。</p>
<p>修复后新建一笔测试订单，记录订单号、Cron 执行时间和邮件服务商 message ID。只有这三处能串起来，才算链路恢复；&ldquo;后台点发送邮件没有报错&rdquo;不是可靠结论。</p>]]></description>
      <pubDate>Wed, 29 Jan 2025 06:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[No alive nodes found in your cluster：Magento 2 搜索连接从哪里断了]]></title>
      <link>https://www.360magento.com/blog/no-alive-search-nodes/</link>
      <description><![CDATA[<p><code>No alive nodes found in your cluster</code> 表示 Magento 的搜索客户端没有找到可用节点，但它没有说明是端口拒绝、TLS 握手、账号错误，还是搜索服务本身不可用。先在运行 PHP 的同一台主机或容器中测试，避免&ldquo;运维电脑能连&rdquo;造成误判。</p>
<pre><code>getent hosts opensearch
nc -vz opensearch 9200
curl -v http://opensearch:9200/
curl -vk https://opensearch:9200/
curl -sku 'search_user:REDACTED' https://opensearch:9200/_cluster/health?pretty</code></pre>
<p><code>Connection refused</code> 看监听地址和容器端口；超时看安全组、网络策略和防火墙；HTTP 请求收到&ldquo;plain HTTP traffic was sent to HTTPS port&rdquo;，说明 Magento 配置的协议不对；401/403 则继续检查认证和权限。</p>
<h3>对照 Magento 实际读取的配置</h3>
<pre><code>bin/magento config:show catalog/search/engine
bin/magento config:show catalog/search/elasticsearch7_server_hostname
bin/magento config:show catalog/search/elasticsearch7_server_port
bin/magento config:show catalog/search/elasticsearch7_enable_auth
grep -n "catalog/search" app/etc/env.php app/etc/config.php</code></pre>
<p>后台显示值不一定是运行时最终值，环境变量或 <code>env.php</code> 可能覆盖数据库配置。容器里不要把 <code>localhost</code> 当成搜索容器；localhost 指向当前 PHP 容器本身。</p>
<h3>集群黄色不等于客户端一定不可用</h3>
<pre><code>curl -sku 'search_user:REDACTED' https://opensearch:9200/_cluster/health?pretty
curl -sku 'search_user:REDACTED' https://opensearch:9200/_cat/nodes?v
curl -sku 'search_user:REDACTED' https://opensearch:9200/_cat/indices?v | head</code></pre>
<p>单节点集群因副本无法分配可能长期 yellow，但仍能处理请求；red、没有主分片或磁盘达到水位线才会直接影响索引。检查搜索日志中的磁盘、熔断器和 shard allocation 信息。</p>
<h3>配置修复后再验证 Magento 调用</h3>
<pre><code>bin/magento indexer:reset catalogsearch_fulltext
bin/magento indexer:reindex catalogsearch_fulltext
bin/magento indexer:status catalogsearch_fulltext
curl -sk 'https://shop.example.com/catalogsearch/result/?q=test' -o /tmp/search.html</code></pre>
<p>不要在搜索服务仍不可达时循环 reindex，这只会增加失败任务和日志。最终应同时确认：PHP 运行环境能请求集群、全文索引成功、前台搜索返回商品，并且日志不再产生新的连接异常。</p>]]></description>
      <pubDate>Tue, 28 Jan 2025 01:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台订单列表一片空白，问题可能不在订单数据]]></title>
      <link>https://www.360magento.com/blog/admin-order-grid-blank/</link>
      <description><![CDATA[<p>&ldquo;销售 &rarr; 订单&rdquo;能打开，但表头、筛选器或数据区域完全空白，不等于 <code>sales_order_grid</code> 没有数据。Magento 后台列表由 UI Component 在浏览器端渲染，任何一个 JSON 配置、XHR 或用户书签异常都可能让网格消失。</p>
<h3>先用 Network 判断前端还是后端</h3>
<p>打开开发者工具后重新进入订单页，重点看返回 JSON 的 XHR 请求。如果请求是 500，保存响应中的异常编号并到日志搜索；如果请求 200 但控制台出现 <code>Cannot read properties of undefined</code>，优先排查 UI 组件配置与第三方模块。</p>
<pre><code>grep -R "report.CRITICAL" var/log/exception.log var/log/system.log | tail -n 30
tail -n 100 var/log/debug.log
bin/magento module:status | grep -i sales</code></pre>
<h3>订单是否真的进入网格表</h3>
<pre><code>SELECT COUNT(*) FROM sales_order;
SELECT COUNT(*) FROM sales_order_grid;
SELECT entity_id, increment_id, created_at
FROM sales_order ORDER BY entity_id DESC LIMIT 5;
SELECT entity_id, increment_id, created_at
FROM sales_order_grid ORDER BY entity_id DESC LIMIT 5;</code></pre>
<p>两张表数量略有差异不一定是故障，但最新订单长期缺失才需要检查异步网格配置和消费者。只有确认网格数据缺失时，才考虑针对销售网格的同步机制；前端 JS 已报错时，重建表不会让页面恢复。</p>
<h3>只清当前管理员的异常书签</h3>
<p>列被拖拽、保存过自定义视图或升级后字段已删除，<code>ui_bookmark</code> 里可能仍保留旧配置。先找到当前管理员 ID，再备份并限定 namespace 删除，不能清整张表。</p>
<pre><code>SELECT user_id, username FROM admin_user WHERE username='alwayly';
SELECT bookmark_id, user_id, namespace, identifier
FROM ui_bookmark
WHERE user_id=7 AND namespace LIKE 'sales_order_grid%';

CREATE TABLE ui_bookmark_backup_20250127 AS
SELECT * FROM ui_bookmark WHERE user_id=7 AND namespace LIKE 'sales_order_grid%';

DELETE FROM ui_bookmark
WHERE user_id=7 AND namespace LIKE 'sales_order_grid%';</code></pre>
<p>退出后台再登录，系统会为该用户重建默认视图。若无效，可临时禁用最近修改订单列表的自定义模块，并比较其 <code>view/adminhtml/ui_component/sales_order_grid.xml</code>。重复 column name、错误 dataType 或引用不存在的 JS component 都会中断渲染。</p>
<h3>用另一管理员账号做快速分流</h3>
<p>另一账号正常，通常是 bookmark 或 ACL；所有账号都空白，则更像模块配置、静态文件或接口异常。这个对照测试比直接清缓存更快，也能避免把用户级问题扩大成全站维护。</p>]]></description>
      <pubDate>Mon, 27 Jan 2025 07:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 静态文件版本号变了，浏览器为什么还在加载旧 JS？]]></title>
      <link>https://www.360magento.com/blog/old-js-after-deploy/</link>
      <description><![CDATA[<p>代码已经更新，<code>setup:static-content:deploy</code> 也执行成功，但浏览器 Sources 里仍是旧 JavaScript。此时继续清浏览器缓存往往没有意义：需要先回答一个问题&mdash;&mdash;旧内容究竟来自 HTML、CDN，还是服务器上的静态产物。</p>
<h3>先比较 HTML 引用和真实文件</h3>
<pre><code>curl -sk https://shop.example.com/ -o /tmp/home.html
grep -oE '/static/version[0-9]+/[^"]+' /tmp/home.html | head
curl -skI 'https://shop.example.com/static/version123/frontend/Vendor/theme/zh_CN/js/app.js'
sha256sum app/code/Vendor/Module/view/frontend/web/js/app.js
sha256sum pub/static/frontend/Vendor/theme/zh_CN/Vendor_Module/js/app.js</code></pre>
<p>HTML 仍引用旧 version 路径，问题在页面缓存或部署切换；HTML 已引用新路径但响应内容旧，继续查 CDN 与源站文件。不要只看 URL 上有新的版本号，版本目录通常经过重写，真正的缓存键还取决于完整 URL 和 CDN 规则。</p>
<h3>绕过 CDN 请求源站</h3>
<pre><code>curl -sk --resolve shop.example.com:443:10.0.0.12   'https://shop.example.com/static/version123/frontend/Vendor/theme/zh_CN/js/app.js'   -o /tmp/origin-app.js
curl -sk 'https://shop.example.com/static/version123/frontend/Vendor/theme/zh_CN/js/app.js'   -o /tmp/cdn-app.js
sha256sum /tmp/origin-app.js /tmp/cdn-app.js</code></pre>
<p>两个哈希不同，先按具体静态路径刷新 CDN，而不是清空整个站点缓存。哈希相同则 CDN 无罪，回到服务器产物。</p>
<h3>重新生成前先删对目录</h3>
<pre><code>bin/magento maintenance:enable
rm -rf pub/static/frontend/Vendor/theme/zh_CN
rm -rf var/view_preprocessed/pub/static/frontend/Vendor/theme
bin/magento setup:static-content:deploy -f zh_CN en_US
bin/magento cache:clean full_page block_html
bin/magento maintenance:disable</code></pre>
<p>保留 <code>pub/static/.htaccess</code>，不要直接删除整个 pub/static。多节点环境还要确认每台 Web 节点使用同一发布产物；如果负载均衡轮到旧节点，就会出现刷新一次新、一次旧。</p>
<h3>RequireJS 合并开启时再查一层</h3>
<pre><code>bin/magento config:show dev/js/merge_files
bin/magento config:show dev/js/enable_js_bundling
find pub/static -path '*_cache/merged*' -type f -maxdepth 8 | head</code></pre>
<p>生产环境启用合并或 bundling 后，修改源模块并不代表页面直接请求该文件。用 Network 面板确认实际命中的 bundle，再比较源站内容。修复完成的标准不是&ldquo;命令没报错&rdquo;，而是 HTML 引用、新旧节点文件哈希和外部请求响应三者一致。</p>]]></description>
      <pubDate>Fri, 24 Jan 2025 03:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台保存商品很慢或超时的优化方法]]></title>
      <link>https://www.360magento.com/blog/product-save-timeout/</link>
      <description><![CDATA[<p>保存一个商品需要几十秒，批量更新更容易 504。单纯增加 Nginx/PHP 超时只会让后台 Worker 被占得更久。需要把一次保存拆成数据库写入、插件/Observer、URL Rewrite、索引、缓存失效和外部同步分别计时。</p>
<h3>先建立可重复样本</h3>
<p>选择一个普通 Simple Product，只改一个不影响库存和价格的文本属性，记录开始时间、结束时间、SKU、管理员和 request ID。再分别测试价格、分类、图片、库存字段，比较哪类修改明显变慢。</p>
<pre><code>curl -sk -w 'TTFB:%{time_starttransfer} TOTAL:%{time_total}
'   -o /dev/null https://admin.example.com/admin/</code></pre>
<p>浏览器 Network 能看到保存 POST 的 Waiting 时间，但后台请求需要真实登录，不能用 curl 伪造 Session。</p>
<h3>保存期间观察 MySQL</h3>
<pre><code>watch -n 1 "mysql -Nse 'SHOW FULL PROCESSLIST'"
mysql -e 'SHOW ENGINE INNODB STATUSG'
</code></pre>
<p>若长期等待 catalog_product、url_rewrite、inventory 或 index 表的锁，找持有事务；若大量相似 SELECT，可能是 Observer 循环加载 Repository 造成 N+1。</p>
<h3>列出所有 product save 扩展点</h3>
<pre><code>rg "catalog_product_save|ProductRepositoryInterface|afterSave|aroundSave"   app/code vendor/*/*/etc vendor/*/*/Plugin vendor/*/*/Observer
</code></pre>
<p>第三方 ERP、搜索、营销模块常在同步 Observer 中调用外部 API。网络超时会直接拖住管理员请求。应把外部同步改成可靠队列，保存事务只写本地 outbox；消费者负责重试和失败告警。</p>
<h3>用 Profiler 或 APM 看每段耗时</h3>
<p>仅在预发布或受控维护窗口启用 Magento Profiler/APM，复现一次后立即关闭。重点查看 Plugin 链、事件 Observer、SQL 数量、URL Rewrite 生成、图片处理和 cache clean。不要在生产长期输出包含管理员 URL 和商品数据的详细 trace。</p>
<h3>分类和 URL Rewrite 规模问题</h3>
<pre><code>SELECT COUNT(*) FROM catalog_category_product
WHERE product_id = 1234;

SELECT COUNT(*) FROM url_rewrite
WHERE entity_type='product' AND entity_id=1234;</code></pre>
<p>商品挂在数百分类、启用分类路径 URL 或存在异常重复 rewrite 时，保存会生成大量记录。先修分类模型和冲突数据，不能简单关闭所有 URL Rewrite。</p>
<h3>索引模式是否把重活放进请求</h3>
<pre><code>bin/magento indexer:show-mode
bin/magento indexer:status</code></pre>
<p>Update on Save 会让管理员等待相关索引；Update by Schedule 可缩短请求，但必须保证 Cron 能及时消费。切换模式前评估价格、库存和搜索更新延迟，不能为速度牺牲业务一致性。</p>
<h3>验证优化是否真的有效</h3>
<p>对同一 SKU 重复三次，记录 P50/P95 保存时间、SQL 数、外部调用数和锁等待；再测试复杂 Configurable/Bundle 商品。最后确认前台属性、价格、库存、分类 URL 和搜索均正确更新。只把 504 变成 200，不代表保存链路没有丢步骤。</p>]]></description>
      <pubDate>Thu, 23 Jan 2025 07:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Invalid Form Key. Please refresh the page 怎么解决？]]></title>
      <link>https://www.360magento.com/blog/invalid-form-key/</link>
      <description><![CDATA[<p><code>Invalid Form Key. Please refresh the page</code> 表示提交的 Form Key 与当前 Session 不匹配，或者字段根本没有到达 PHP。先判断是所有表单都失败、只有某个管理员失败，还是只有字段很多的商品/配置表单失败。</p>
<h3>浏览器中对比表单值与 Session</h3>
<p>在 Network 里打开失败 POST，确认 Form Data 中存在 <code>form_key</code>，请求同时带有后台 Session Cookie。再看响应前是否发生域名或 http/https 跳转。不要把真实 Cookie 或 Form Key 发到公开日志。</p>
<h3>只有大表单失败，先查 max_input_vars</h3>
<pre><code>php -i | grep max_input_vars
php-fpm -i | grep max_input_vars
nginx -T | grep client_max_body_size</code></pre>
<p>商品属性、Bundle 选项或系统配置字段很多时，PHP 超过 <code>max_input_vars</code> 会截断后面的字段，form_key 若位于被截断部分就会报错。以 PHP-FPM 配置为准，适度提高并重载 FPM，然后检查 PHP 日志是否还有 Input variables exceeded 提示。</p>
<h3>所有表单都失败，检查 Session</h3>
<pre><code>grep -n "session" app/etc/env.php
redis-cli -h SESSION_REDIS ping
redis-cli -h SESSION_REDIS info clients
redis-cli -h SESSION_REDIS info memory</code></pre>
<p>多 Web 节点使用本地 Session、Redis 不稳定、Cookie Domain/Path 错误，都会让 GET 页面和 POST 请求落在不同 Session。固定访问单节点后恢复，是共享 Session 问题的重要证据。</p>
<h3>后台页面绝不能被 CDN/FPC 缓存</h3>
<pre><code>curl -skI https://admin.example.com/admin/catalog/product/
</code></pre>
<p>检查 Age、X-Cache、Cache-Control 与 Set-Cookie。后台 HTML 若被共享缓存，用户会拿到过期 Form Key。CDN 和 Varnish 应绕过后台路径、带后台 Session Cookie 的请求及 POST。</p>
<h3>自定义表单要正确生成和验证 Form Key</h3>
<pre><code>&lt;input type="hidden"
       name="form_key"
       value="&lt;?= $block-&gt;escapeHtmlAttr($block-&gt;getFormKey()) ?&gt;" /&gt;</code></pre>
<p>后台控制器通常应实现相应 HTTP/CSRF 接口并使用 Magento 表单机制。不要通过全局关闭 CSRF 验证来解决报错；这会把管理操作暴露给跨站请求。</p>
<h3>Session 过期属于另一种情况</h3>
<p>编辑页面打开数小时后提交失败，可能只是管理员 Session 已过期。应用可以给出清晰提示并保留未提交内容，但不应无限延长后台 Session。修复后分别测试普通表单、大商品表单、多节点和长时间停留，确认安全校验仍然有效。</p>
<h3>检查 PHP 是否真的收到完整 POST</h3>
<p>在受控环境记录 <code>count($_POST)</code>、Content-Length 和是否存在 form_key，不记录具体字段值。浏览器表单有 form_key、PHP 却没有，说明请求大小、变量数量或代理解析阶段截断；PHP 已收到但验证失败，才回到 Session/Cookie 链路。</p>
<h3>多个后台标签页的边界</h3>
<p>管理员退出再登录后，旧标签页仍保留旧 Form Key，提交自然失败。用新标签验证并提示用户重新加载，但不能把所有 Invalid Form Key 都归咎于多标签页。若新打开页面立即失败，继续检查共享缓存和 Session。</p>
<p>修复 max_input_vars 后再次保存同一复杂商品，并确认没有字段静默丢失；只是不再报 Form Key，并不能证明所有属性都被 PHP 接收。</p>]]></description>
      <pubDate>Wed, 22 Jan 2025 02:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 搜索不到刚添加的商品怎么办？]]></title>
      <link>https://www.360magento.com/blog/new-product-not-in-search/</link>
      <description><![CDATA[<p>商品保存成功，直接 URL 能打开或后台能找到，但前台输入 SKU、名称都没有结果。搜索结果会经过 Website、Store、状态、可见性、库存和搜索索引过滤，不能只运行一次 reindex 就结束。</p>
<h3>先在后台核对五个条件</h3>
<ol>
<li>商品已分配到当前 Website；</li>
<li>目标 Store View 下 Status=Enabled；</li>
<li>Visibility 包含 Search；</li>
<li>当前 Website 对应 Stock 中可售；</li>
<li>名称、SKU 或目标属性配置为 Use in Search。</li>
</ol>
<p>多 Store 商品常在 Default Config 正常，但目标 Store 的名称为空、状态被覆盖或 Website 根本未分配。</p>
<h3>用 SQL 快速确认实体和网站</h3>
<pre><code>SELECT entity_id, sku FROM catalog_product_entity
WHERE sku = 'SKU-001';

SELECT product_id, website_id
FROM catalog_product_website
WHERE product_id = 1234;</code></pre>
<p>EAV 状态和可见性不要凭 attribute_id 硬猜，先从 eav_attribute 查 attribute_id 和 backend_type，再读取对应表。</p>
<h3>检查索引状态与积压</h3>
<pre><code>bin/magento indexer:status
bin/magento indexer:show-mode
bin/magento cron:run --group=index
bin/magento indexer:reindex catalogsearch_fulltext</code></pre>
<p>手工 reindex 只用于诊断。若商品随后出现，再修改一次名称，确认 Update by Schedule 能自动更新；否则应继续修 Cron/MView。</p>
<h3>确认 Magento 连的是哪套搜索服务</h3>
<pre><code>bin/magento config:show catalog/search/engine
bin/magento config:show catalog/search/opensearch_server_hostname
bin/magento config:show catalog/search/opensearch_server_port
curl -sS 'http://OPENSEARCH:9200/_cluster/health?pretty'
curl -sS 'http://OPENSEARCH:9200/_cat/indices?v'</code></pre>
<p>命令行检查的 endpoint 必须与应用配置一致。不要在生产输出认证密码，也不要因为一个商品缺失就删除全部索引。</p>
<h3>按 SKU 检查搜索文档</h3>
<p>先从 Magento 当前索引别名确定实际 index，再做只读查询：</p>
<pre><code>GET /magento2_product_1/_search
{
  "query": {
    "term": { "sku.keyword": "SKU-001" }
  }
}</code></pre>
<p>字段映射随版本变化，先查看 mapping。文档不存在，问题在索引输入；文档存在但搜索无结果，检查 analyzer、Store/website 字段、查询过滤和主题/搜索扩展。</p>
<h3>搜索词本身也可能被配置过滤</h3>
<p>Minimum Query Length、停用词、同义词和第三方搜索规则会影响结果。用完整 SKU 与唯一名称分别测试，并比较 GraphQL/REST 搜索和前台主题请求，确认问题在后端还是前端展示。</p>
<p>最终验证不只看一个关键词：测试 SKU、名称、目标属性、分类页和不同 Store View，确认新商品可被找到，而禁用或不可售商品仍按业务规则隐藏。</p>]]></description>
      <pubDate>Tue, 21 Jan 2025 06:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 无法创建发票，You can’t create an invoice without products 怎么修复]]></title>
      <link>https://www.360magento.com/blog/invoice-without-products/</link>
      <description><![CDATA[<p>后台点击 Invoice 后提示 <code>You can&rsquo;t create an invoice without products</code>，含义是 Magento 计算出的本次可开票数量全部为 0。先确认这张订单是否真的还有未开票商品，不能通过修改 state/status 强行显示按钮。</p>
<h3>查询订单行的数量关系</h3>
<pre><code>SELECT item_id, parent_item_id, sku, product_type,
       qty_ordered, qty_invoiced, qty_canceled,
       qty_refunded, row_total
FROM sales_order_item
WHERE order_id = 1234
ORDER BY item_id;</code></pre>
<p>通常可开票数量由 ordered、invoiced 和 canceled 等字段计算。Configurable、Bundle 和 Downloadable 存在父子行，真正开票数量可能在子行或父行，不能把每行都手工设为 1。</p>
<h3>确认是否已经有发票</h3>
<pre><code>SELECT entity_id, increment_id, state, grand_total, created_at
FROM sales_invoice
WHERE order_id = 1234;

SELECT invoice_id, order_item_id, sku, qty, row_total
FROM sales_invoice_item
WHERE order_item_id IN (
  SELECT item_id FROM sales_order_item WHERE order_id = 1234
);</code></pre>
<p>支付回调重试或 ERP 同步可能已创建发票，只是后台邮件/状态没有更新。不要创建第二张发票来修界面。</p>
<h3>支付方式决定 Online Capture 是否可用</h3>
<p>查看订单 Payment 的 method、amount_authorized、amount_paid、last_trans_id，以及 transaction 表中的 authorization/capture。在线开票可能触发 Capture；如果网关已经在外部 Capture，本地再次 Capture 会重复扣款。</p>
<pre><code>SELECT method, amount_authorized, amount_paid,
       amount_refunded, last_trans_id
FROM sales_order_payment
WHERE parent_id = 1234;

SELECT txn_id, parent_txn_id, txn_type, is_closed
FROM sales_payment_transaction
WHERE order_id = 1234;</code></pre>
<h3>自定义代码创建 Invoice 的正确边界</h3>
<pre><code>if (!$order-&gt;canInvoice()) {
    throw new MagentoFrameworkExceptionLocalizedException(
        __('Order has no invoiceable items.')
    );
}

$invoice = $invoiceService-&gt;prepareInvoice($order, $qtys);
if (!$invoice-&gt;getTotalQty()) {
    throw new RuntimeException('Prepared invoice is empty');
}</code></pre>
<p><code>$qtys</code> 的键必须是 order_item_id，不是 product_id。传错 ID 时 prepareInvoice 会得到空发票。保存 Invoice、Order 与 Transaction 应放在一致事务中，并为外部事件建立幂等键。</p>
<h3>不要直接更新 qty_invoiced</h3>
<p>这些字段与 Invoice 实体、支付交易、税、折扣和订单总额有关。直接 SQL 改数量会让 Credit Memo 与对账继续错误。应从漏掉的业务动作入手，通过支付模块/服务层补偿。</p>
<p>修复后对比订单、发票、网关 Capture 三方金额；重复执行同一回调不得生成第二张发票，部分开票订单仍能只开剩余数量。</p>]]></description>
      <pubDate>Mon, 20 Jan 2025 01:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 sitemap.xml 生成失败或访问 404 的解决方法]]></title>
      <link>https://www.360magento.com/blog/sitemap-generate-404/</link>
      <description><![CDATA[<p>后台显示 Sitemap 已提交，但访问 <code>/sitemap.xml</code> 返回 404；或者 Last Generated 一直为空。先区分&ldquo;文件没有生成&rdquo;和&ldquo;文件存在但 Web Server 不提供&rdquo;两种情况。</p>
<h3>后台路径与实际 URL 要一一对应</h3>
<p>Marketing &rarr; SEO &amp; Search &rarr; Site Map 中检查 Filename、Path 和 Store View。常见配置是 Filename=<code>sitemap.xml</code>、Path=<code>/</code>。多 Store 使用不同域名或目录时，每条 Sitemap 应绑定正确 Store。</p>
<h3>手工生成一条并立即查看错误</h3>
<pre><code>bin/magento sitemap:generate -vvv
find pub -maxdepth 3 -name 'sitemap*.xml' -ls
tail -n 100 var/log/system.log var/log/exception.log</code></pre>
<p>命令名称以当前版本 <code>bin/magento list sitemap</code> 为准。权限错误、目标目录不存在、Base URL 无效或商品集合异常都会在前台 Cron 之外更直接地暴露。</p>
<h3>检查运行用户写权限</h3>
<pre><code>namei -l pub
sudo -u www-data test -w pub &amp;&amp; echo writable
stat pub/sitemap.xml</code></pre>
<p>生成用户可能是文件系统 owner，而 Web Server 是另一个用户。通过共享 group 和合理 umask 管理权限，不要对整个 pub 目录使用 777。</p>
<h3>文件存在仍然 404</h3>
<pre><code>curl -skI https://www.example.com/sitemap.xml
curl -sk --resolve www.example.com:443:ORIGIN_IP   -I https://www.example.com/sitemap.xml
nginx -T | grep -n 'sitemap|location.*xml|try_files'</code></pre>
<p>源站 200、CDN 404，清理精确对象并缩短错误缓存 TTL；源站也 404，检查 document root 是否指向 pub、蓝绿发布中的 sitemap 是否放在共享目录，以及 location 规则是否阻止 XML。</p>
<h3>自动生成依赖 Cron</h3>
<pre><code>bin/magento cron:run
SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE job_code LIKE '%sitemap%'
ORDER BY schedule_id DESC
LIMIT 20;</code></pre>
<p>手工生成成功、自动生成失败，重点查 Cron 运行用户、计划时间和失败日志。不要用系统 Cron 额外再写一个直接覆盖文件的脚本，否则后台时间与真实文件会不一致。</p>
<h3>SEO 验证</h3>
<p>打开 XML 检查域名、协议、Store code、商品和分类 URL 是否属于当前 Store；抽样请求返回 200，不能把后台 URL 或另一个网站写进 Sitemap。最后在 robots.txt 中声明的 Sitemap 地址也必须与最终公开 URL 一致。</p>
<h3>大型目录需要检查拆分文件</h3>
<p>商品数量较多时 Sitemap 会拆成多个文件或达到搜索引擎对单文件 URL 数量、体积的限制。统计 XML 中 <code>&lt;url&gt;</code> 数量和文件大小，确保 Sitemap index 引用的每个子文件都可公开访问，并且没有混入后台、搜索结果和带 Session 参数的 URL。</p>
<pre><code>grep -c '&lt;url&gt;' pub/sitemap.xml
du -h pub/sitemap*.xml
xmllint --noout pub/sitemap.xml</code></pre>
<h3>生成期间避免半文件被抓取</h3>
<p>自定义生成器应先写临时文件、完成 XML 校验后再原子重命名。直接覆盖公开 sitemap.xml 时，搜索引擎可能抓到半截 XML。发布与共享存储也要保证 rename 发生在同一文件系统。</p>]]></description>
      <pubDate>Fri, 17 Jan 2025 08:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis Connection refused，网站打不开的恢复步骤]]></title>
      <link>https://www.360magento.com/blog/redis-connection-refused/</link>
      <description><![CDATA[<p>错误日志出现 <code>Connection refused [tcp://redis:6379]</code>，前后台同时 500。不要先删除 Redis 数据目录；拒绝连接只说明目标地址当前没有接受 TCP 连接，原因可能是服务退出、地址写错、防火墙或容器网络变化。</p>
<h3>确认 Magento 实际连接哪个 Redis</h3>
<pre><code>grep -n "redis|cache|session|page_cache" app/etc/env.php
getent hosts redis
nc -vz redis 6379
redis-cli -h redis -p 6379 ping</code></pre>
<p>输出配置时必须隐藏密码。缓存、FPC 和 Session 可能使用不同数据库或不同 Redis 主机，要分别确认。</p>
<h3>Redis 服务是否存活</h3>
<pre><code>systemctl status redis-server
journalctl -u redis-server --since '30 minutes ago'
ss -lntp | grep 6379
redis-cli info server
redis-cli info clients
redis-cli info memory</code></pre>
<p>服务反复重启时，看 OOM、配置语法、磁盘持久化和 maxclients。连接数达到上限通常返回 max number of clients，而不是简单 refused，但负载均衡器健康检查可能会摘除节点。</p>
<h3>容器或集群环境检查地址变化</h3>
<pre><code>docker ps --filter name=redis
docker logs --tail 100 REDIS_CONTAINER
docker inspect REDIS_CONTAINER --format '{{json .NetworkSettings.Networks}}'</code></pre>
<p>应用应连接稳定的服务名，而不是易变容器 IP。Kubernetes 环境检查 Service endpoints、NetworkPolicy 和 Pod readiness；不要把 Redis 端口临时暴露到公网。</p>
<h3>恢复服务后验证三类数据</h3>
<pre><code>redis-cli -h redis ping
bin/magento cache:status
bin/magento cache:clean config
curl -skI https://www.example.com/</code></pre>
<p>如果 Session 也在故障 Redis，客户登录和购物车可能失效。恢复缓存不等于 Session 数据已恢复，应测试登录、购物车和后台会话。</p>
<h3>能不能临时改用文件或数据库</h3>
<p>只有在明确业务影响、共享文件系统和多节点行为后才切换。直接把 Session 改成本地文件会让多节点用户随机掉线。更改 env.php 前备份文件，并通过受控部署同步所有节点；恢复 Redis 后也不能频繁来回切换。</p>
<h3>避免再次发生</h3>
<p>监控 Redis 存活、used_memory、evicted_keys、connected_clients、rejected_connections、延迟和主从状态。缓存实例需要合适淘汰策略；Session 实例不应因缓存淘汰策略随机丢会话。告警必须在应用 500 前触发。</p>
<h3>主从切换后仍 refused</h3>
<p>托管 Redis 发生故障切换时，DNS 可能短暂指向旧地址，长驻 PHP/Consumer 还保持失效连接。核对 endpoint TTL、客户端重连设置和消费者日志；Web 恢复后应滚动重启长期 Consumer，但不能同时停止所有交易任务。</p>
<h3>区分缓存清空与 Session 丢失</h3>
<p>缓存 Redis 可以安全重建，但 Session Redis 的数据丢失会让已登录客户和购物车会话失效。故障复盘应分别统计 cache hit、Session 登录失败和购物车丢失，不要只写&ldquo;Redis 已恢复&rdquo;。若使用持久化/副本，定期演练恢复并验证 TTL 与 key 前缀。</p>]]></description>
      <pubDate>Thu, 16 Jan 2025 03:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 执行 setup:upgrade 卡住不动怎么办？]]></title>
      <link>https://www.360magento.com/blog/setup-upgrade-stuck/</link>
      <description><![CDATA[<p><code>bin/magento setup:upgrade</code> 停在某个模块几分钟没有输出，不一定真的死锁。大表 DDL、数据补丁或搜索引擎操作可能很慢。先用另一个终端取证，不要连续按 Ctrl+C 后重复执行。</p>
<h3>确认进程是否还在工作</h3>
<pre><code>pgrep -af 'bin/magento setup:upgrade'
ps -o pid,etime,%cpu,%mem,state,cmd -p PID
cat /proc/PID/io
ls -l /proc/PID/fd | head</code></pre>
<p>CPU、I/O 或数据库查询在变化，任务可能仍推进；进程处于长时间睡眠且数据库无对应活动，再查外部连接和锁。</p>
<h3>MySQL 正在执行什么</h3>
<pre><code>mysql -e 'SHOW FULL PROCESSLIST'
mysql -e 'SHOW ENGINE INNODB STATUSG'

SELECT * FROM performance_schema.metadata_locks
WHERE LOCK_STATUS = 'PENDING';</code></pre>
<p><code>Waiting for table metadata lock</code> 常由未提交事务、后台导出或长查询阻塞 DDL。找出持有者的业务用途，确认后再终止；不能看到运行久就 kill。</p>
<h3>定位执行到哪个 Patch</h3>
<pre><code>SELECT patch_name FROM patch_list ORDER BY patch_name;
grep -R "class .* implements.*Patch" app/code/Vendor/Module/Setup/Patch
tail -f var/log/system.log var/log/exception.log</code></pre>
<p>自定义 Data Patch 若一次加载全表、每行调用 Repository 或访问外部 API，可能数小时不输出。应改为稳定游标分批、记录进度，并保证重复执行安全。Patch 中不要调用不可控的远程服务。</p>
<h3>终止前先判断 DDL 状态</h3>
<p>MySQL 正在 ALTER 大表时强制终止可能触发长时间回滚或残留临时表。记录 SQL、表大小、数据库版本和执行时间，评估在线 DDL 能力。生产环境应在维护窗口执行，并准备可验证的数据库备份。</p>
<h3>安全恢复流程</h3>
<pre><code># 确认旧进程已退出后再运行
pgrep -af 'bin/magento setup:upgrade'
bin/magento maintenance:enable
bin/magento setup:upgrade -vvv
bin/magento setup:di:compile
bin/magento cache:clean
bin/magento maintenance:disable</code></pre>
<p>不要手工向 patch_list 插入 Patch 名称来&ldquo;跳过&rdquo;。那只会告诉 Magento 已执行，却没有完成数据修改。失败 Patch 必须修成可重入，或从已验证备份恢复后重跑。</p>
<p>升级完成后核对模块版本、表结构、Patch 记录、Cron、Indexer 和核心下单流程。命令返回 0 不代表业务数据一定迁移正确。</p>
<h3>给每个自定义 Patch 增加可观察性</h3>
<p>大数据迁移应按批次输出已处理主键范围和耗时，但不能输出客户敏感字段。使用 <code>startSetup/endSetup</code> 不能自动解决长事务；批量提交策略要根据 Patch 是否允许中断恢复设计。为 Patch 建立独立测试数据，至少覆盖首次执行、中途失败后重跑、空数据和大批量四种情况。</p>
<h3>升级前先估算大表</h3>
<pre><code>SELECT table_name, table_rows,
       ROUND((data_length+index_length)/1024/1024) AS mb
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY data_length+index_length DESC
LIMIT 20;</code></pre>
<p>预发布数据量远小于生产时，DDL 时间没有参考意义。使用接近生产规模的副本演练并记录回滚时间，发布计划才知道何时应该继续等待、何时回退。</p>]]></description>
      <pubDate>Wed, 15 Jan 2025 06:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台上传产品图片失败怎么处理？]]></title>
      <link>https://www.360magento.com/blog/product-image-upload-failed/</link>
      <description><![CDATA[<p>上传商品图片后进度条停住、出现红色错误，或保存商品后图片消失。先拿一张尺寸较小、文件名只含英文数字的 JPG 做基准测试，再与失败图片比较，避免同时排查格式、大小和权限。</p>
<h3>先看上传请求的真实返回</h3>
<p>打开 Network，重新上传，找到 media/upload 请求。常见结果：</p>
<ul>
<li>413：Nginx/代理限制请求体；</li>
<li>500：PHP 或图片处理异常；</li>
<li>403：WAF、后台 Session 或 Form Key；</li>
<li>200 但 JSON 含 error：Magento 校验或文件移动失败。</li>
</ul>
<p>保存响应 body 与 request ID，再检查同一时间的日志。</p>
<h3>核对 PHP 和 Web Server 限制</h3>
<pre><code>php -i | egrep 'upload_max_filesize|post_max_size|max_file_uploads|upload_tmp_dir|memory_limit'
php-fpm -i | egrep 'upload_max_filesize|post_max_size|upload_tmp_dir'
nginx -T | grep -n client_max_body_size</code></pre>
<p>CLI PHP 与 PHP-FPM 可能读取不同 php.ini，应以处理上传请求的 FPM 为准。<code>post_max_size</code> 必须大于单文件限制和完整表单开销，修改后平滑重载 FPM/Nginx。</p>
<h3>检查临时目录和媒体目录是否可写</h3>
<pre><code>php -r 'echo sys_get_temp_dir(), PHP_EOL;'
namei -l pub/media/catalog/product
sudo -u www-data test -w pub/media/catalog/product &amp;&amp; echo writable
find pub/media/catalog/product -maxdepth 2 -type d ! -perm -g+w | head</code></pre>
<p>不要用 <code>chmod -R 777</code>。统一部署用户与 PHP-FPM 用户的 group，目录给 group 写入和 setgid，文件保持最小权限。对象存储环境还要检查远程存储凭据与同步队列。</p>
<h3>用失败文件单独测试图片处理</h3>
<pre><code>file /tmp/problem.jpg
identify /tmp/problem.jpg
php -m | egrep 'gd|imagick|exif'
identify -verbose /tmp/problem.jpg | head -n 40</code></pre>
<p>超大像素图片即使文件只有几 MB，解码后也会占用大量内存。损坏的 ICC/EXIF、CMYK JPEG 或不受支持的 WebP/AVIF 也可能失败。先用受支持格式重新编码副本验证，不要覆盖客户原图。</p>
<h3>上传成功但保存后消失</h3>
<pre><code>SELECT value_id, value, media_type, disabled
FROM catalog_product_entity_media_gallery
WHERE value LIKE '%problem%';</code></pre>
<p>临时文件上传成功、商品保存时移动失败，通常与 media 临时目录、权限或自定义 product save observer 有关。检查保存 POST 是否 500，并对比 <code>pub/media/tmp/catalog/product</code> 与正式目录。</p>
<p>最后用两张图验证：一张小 JPG，一张接近允许上限的图片。上传、设置主图、保存、重新打开后台、前台生成新缩略图均成功，才算完整修复。</p>]]></description>
      <pubDate>Tue, 14 Jan 2025 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页面一直转圈的排查方法]]></title>
      <link>https://www.360magento.com/blog/checkout-loading-forever/</link>
      <description><![CDATA[<p>结账页显示加载动画但地址、配送或支付区域不出现时，不要先关闭所有模块。先打开无痕窗口与浏览器开发者工具，找到&ldquo;第一条失败请求或第一条 JavaScript 异常&rdquo;。后面的报错往往只是连锁反应。</p>
<h3>用 Network 判断卡在哪一步</h3>
<p>过滤 Fetch/XHR，刷新 Checkout，常见请求包括 totals、shipping-information、payment-information 和 customer sections。记录 URL、状态码、响应 body 与耗时：</p>
<ul>
<li>请求一直 Pending：查 PHP、数据库、外部运费/支付 API；</li>
<li>返回 500：用响应 request ID 对应 exception.log；</li>
<li>返回 401/403：查 Session、Form Key 或 API 路由；</li>
<li>全部 200 但界面不渲染：继续查 Console 和 Knockout 组件。</li>
</ul>
<h3>检查页面是否生成了 checkoutConfig</h3>
<p>在 Console 中只读检查：</p>
<pre><code>typeof window.checkoutConfig
Object.keys(window.checkoutConfig || {})
window.checkoutConfig &amp;&amp; window.checkoutConfig.quoteData</code></pre>
<p>对象不存在或 HTML 被截断，查 checkout layout processor、自定义 Block 和 FPC；对象存在但某个字段结构异常，比较正常环境 JSON，定位扩展加入的数据。不要把完整 checkoutConfig 发到公开工单，其中可能含客户和购物车信息。</p>
<h3>RequireJS 报错怎么找模块来源</h3>
<pre><code>bin/magento deploy:mode:show
bin/magento config:show dev/js/merge_files
bin/magento config:show dev/js/enable_js_bundling
bin/magento config:show dev/js/minify_files
rg "目标组件名" app/code app/design vendor/*/*/view/frontend</code></pre>
<p>Console 出现 Script error、mismatched anonymous define 或某 mixin undefined 时，在预发布临时关闭合并/压缩并重新部署静态内容，让堆栈指向源文件。生产环境不要边请求边删除 pub/static。</p>
<h3>逐个隔离 Checkout 扩展</h3>
<p>先从页面的 RequireJS config 找到支付、地址验证、One Step Checkout 等 mixin。一次只禁用一个可疑模块或 mixin，在预发布重新执行：</p>
<pre><code>bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f zh_CN en_US
bin/magento cache:clean</code></pre>
<p>如果禁用后恢复，再用原购物车、同一地址和支付方式复现，不能只看空购物车。</p>
<h3>接口很慢时抓服务端证据</h3>
<pre><code>tail -f var/log/exception.log var/log/system.log
mysql -e 'SHOW FULL PROCESSLIST'
curl -w '
TTFB:%{time_starttransfer} TOTAL:%{time_total}
'   -o /dev/null -sS 'https://www.example.com/checkout/'</code></pre>
<p>运费接口没有连接/读取超时、支付模块在 isAvailable 阶段访问网关、地址校验同步调用第三方，都可能让 Spinner 永远不结束。为外部调用设置明确超时和降级逻辑。</p>
<p>修复后分别测试访客、登录客户、实体商品、虚拟商品、国内外地址、优惠券和支付失败返回。只让页面&ldquo;显示出来&rdquo;不够，订单金额和最终提交必须正确。</p>]]></description>
      <pubDate>Mon, 13 Jan 2025 07:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 安装模块后出现 500 错误怎么解决？]]></title>
      <link>https://www.360magento.com/blog/module-install-500-error/</link>
      <description><![CDATA[<p>安装新模块后，前台和后台同时显示 500，最重要的是先保留第一条异常，而不是连续执行清缓存、编译和重启，把原始错误覆盖掉。下面按&ldquo;先恢复访问，再修模块&rdquo;的顺序处理。</p>
<h3>先确认 500 来自 PHP 还是 Web Server</h3>
<pre><code>curl -sk -D- -o /tmp/magento500.html https://www.example.com/
tail -n 100 var/log/exception.log
tail -n 100 var/log/system.log
tail -n 100 /var/log/nginx/error.log
journalctl -u php-fpm --since '10 minutes ago'</code></pre>
<p>PHP Fatal error、类不存在和构造参数错误通常在 Magento/PHP 日志；Nginx 的 upstream timed out、Primary script unknown 则属于回源或路径问题。记录异常类、文件和部署时间。</p>
<h3>模块是否真的被启用</h3>
<pre><code>bin/magento module:status Vendor_Module
composer show vendor/module-name
grep -n "Vendor_Module" app/etc/config.php</code></pre>
<p>代码目录存在但 Composer 包未完整安装，或 config.php 已启用模块而 vendor 缺依赖，都会直接 500。不要从另一台服务器随手复制一个 vendor 子目录；应使用同一 composer.lock 重建完整产物。</p>
<h3>在维护模式下重新跑安装步骤</h3>
<pre><code>bin/magento maintenance:enable
bin/magento setup:upgrade --keep-generated
bin/magento setup:di:compile
bin/magento cache:clean</code></pre>
<p>每条命令单独执行，第一条失败就停止。<code>setup:upgrade</code> 报数据库补丁错误时，不要继续 compile；compile 报 preference、接口或构造参数错误时，回到模块的 di.xml 和 PHP 类型声明处理。</p>
<h3>快速判断是不是新模块导致</h3>
<p>如果模块没有执行不可逆数据迁移，可在维护窗口禁用它做隔离：</p>
<pre><code>bin/magento module:disable Vendor_Module
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:clean</code></pre>
<p>恢复后说明故障与该模块有关，但这不是最终修复。模块若创建了订单字段、队列表或数据补丁，禁用前应阅读卸载说明并备份数据库，不能直接删除代码。</p>
<h3>常见 Fatal error 对应处理</h3>
<ul>
<li><code>Class ... does not exist</code>：检查 Composer autoload、类名大小写和 registration.php；</li>
<li><code>Cannot instantiate interface</code>：检查 area 对应 di.xml 是否缺 preference；</li>
<li><code>Too few arguments</code>：模块版本可能不兼容当前 Magento/PHP；</li>
<li><code>Permission denied</code>：检查 var、generated、pub/static 的运行用户权限；</li>
<li><code>Allowed memory size exhausted</code>：先定位循环依赖或异常集合，不能只无限加内存。</li>
</ul>
<h3>恢复上线前的验证</h3>
<pre><code>bin/magento maintenance:disable
curl -fsS https://www.example.com/health_check.php
bin/magento cron:run
bin/magento indexer:status</code></pre>
<p>测试首页、商品页、购物车、结账、后台登录和模块自己的功能。还要确认 Cron 与 Consumer 使用的新 release，否则 Web 恢复了，后台任务仍可能加载旧模块代码。</p>]]></description>
      <pubDate>Fri, 10 Jan 2025 02:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 索引器卡在 Processing，不要先 reset：先确认进程是否真的还活着]]></title>
      <link>https://www.360magento.com/blog/indexer-stuck-processing/</link>
      <description><![CDATA[<p>后台或命令行显示某个索引器长期处于 Processing。直接运行 <code>indexer:reset</code> 有两种风险：真正的进程仍在写索引时被第二个任务并发启动；或者你抹掉了状态，却没有找到导致进程退出的根因。</p>
<h3>先记录状态，不执行任何修改</h3>
<pre><code>bin/magento indexer:status
bin/magento indexer:show-mode
bin/magento indexer:info
</code></pre>
<p>记下 indexer ID、mode、状态和 backlog 数量。若只有一个 indexer 异常，围绕它查；全部异常则优先查 Cron、数据库或部署。</p>
<h3>进程还在吗？</h3>
<pre><code>ps -eo pid,lstart,etime,cmd | grep -E '[m]agento (indexer:reindex|cron:run)'
pgrep -af 'bin/magento.*(indexer:reindex|cron:run)'
</code></pre>
<p>找到 PID 后，不要马上 kill。先确认工作目录、启动时间和打开文件：</p>
<pre><code>readlink -f /proc/PID/cwd
ls -l /proc/PID/fd | head
cat /proc/PID/status | egrep 'State|VmRSS|Threads'</code></pre>
<p>进程 CPU/I/O 在变化，且数据库查询推进，可能只是大索引；进程不存在，才更像状态残留。</p>
<h3>进程存在但不推进：到 MySQL 找它在等什么</h3>
<pre><code>mysql -e 'SHOW FULL PROCESSLIST'
mysql -e 'SHOW ENGINE INNODB STATUSG'
</code></pre>
<p>关注长时间 Sending data、Creating sort index、Waiting for table metadata lock 或行锁。metadata lock 常来自未提交的后台会话或部署 DDL；行锁则要找持有事务。确认业务影响后再终止阻塞者，不能按运行时间盲杀。</p>
<h3>状态残留的数据库证据</h3>
<pre><code>SELECT indexer_id, status, updated, hash_config
FROM indexer_state
ORDER BY updated;

SELECT view_id, mode, status, version_id, updated
FROM mview_state
ORDER BY updated;</code></pre>
<p>不同版本字段略有差异。updated 很旧、没有对应 OS/DB 进程、日志显示进程已异常退出，才满足&ldquo;状态残留&rdquo;的基本条件。</p>
<h3>Update by Schedule 还要看 changelog 是否持续增长</h3>
<p>先从 mview 配置确认订阅表，再查看对应 <code>*_cl</code> 表的最大 version_id 和行数。示例：</p>
<pre><code>SELECT COUNT(*) AS rows_waiting, MAX(version_id) AS newest
FROM catalog_product_price_cl;
</code></pre>
<p>backlog 快速增长时，即使 reset 成功，全量/增量任务也可能追不上写入速度。需要处理长事务、批量导入频率和 Cron 能力。</p>
<h3>满足条件后再 reset 指定索引器</h3>
<pre><code>bin/magento indexer:reset catalog_product_price
bin/magento indexer:reindex catalog_product_price
bin/magento indexer:status catalog_product_price
</code></pre>
<p>不要无差别 reset 全部索引器。生产全量 reindex 会增加 CPU、I/O 和锁压力，应在容量允许的窗口执行，并观察日志：</p>
<pre><code>tail -f var/log/cron.log var/log/system.log var/log/exception.log
</code></pre>
<h3>真正完成的标准</h3>
<p>状态回到 Ready 只是第一步。再修改一个测试商品价格，确认 changelog 出现新版本、Cron 消费它、索引表更新且前台价格变化。只有&ldquo;增量更新再次自动工作&rdquo;，才能说明问题解决；手工全量成功不代表调度链路已经恢复。</p>]]></description>
      <pubDate>Thu, 09 Jan 2025 08:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品还有库存却报 The requested qty is not available，结账时到底检查了哪个 Stock]]></title>
      <link>https://www.360magento.com/blog/requested-qty-not-available/</link>
      <description><![CDATA[<p>SKU 在后台显示 Quantity=50，加入购物车或提交订单时却提示 <code>The requested qty is not available</code>。在 MSI 中，后台看到的某个 Source Quantity 不一定属于当前 Website 使用的 Stock；结账检查的是可售数量和销售通道，不是任意一个 Source 的数字。</p>
<h3>从发生错误的 Website 反查 Stock</h3>
<pre><code>SELECT website_id, code, name
FROM store_website;

SELECT stock_id, type, code
FROM inventory_stock_sales_channel
WHERE type = 'website';</code></pre>
<p>确认当前域名对应的 website code，再找到 stock_id。若 Website 绑定错 Stock，默认库存再多也不会参与当前站点销售。</p>
<h3>列出这个 Stock 实际包含哪些 Source</h3>
<pre><code>SELECT l.stock_id, l.source_code, s.name, s.enabled
FROM inventory_source_stock_link l
JOIN inventory_source s ON s.source_code = l.source_code
WHERE l.stock_id = 2;</code></pre>
<p>然后只查询这些 Source 上的 SKU：</p>
<pre><code>SELECT sku, source_code, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001'
ORDER BY source_code;</code></pre>
<p>Quantity 大于零但 status=0，仍不可售；有数量的 Source 不在 Stock 里，也不会计入。</p>
<h3>把 Reservation 加进计算</h3>
<pre><code>SELECT stock_id, sku, SUM(quantity) AS reservation_total
FROM inventory_reservation
WHERE sku = 'SKU-001'
GROUP BY stock_id, sku;</code></pre>
<p>例如 Source 可用合计 10，reservation 合计 -8，再考虑 Out-of-Stock Threshold 后，可售量可能只剩 2。购物车要 3 件就会被拒绝。不要删除负 reservation；先确认对应订单仍有效。</p>
<h3>检查商品与全局库存配置</h3>
<p>后台商品 Advanced Inventory 中的 Manage Stock、Backorders、Minimum Qty、Maximum Qty、Qty Uses Decimals、Out-of-Stock Threshold 都会改变结果。商品若勾选 Use Config Settings，还要核对全局值。Bundle/Configurable 需要继续检查最终子 SKU，而不是只看父商品。</p>
<h3>用接口重现，分开&ldquo;加入购物车&rdquo;和&ldquo;下单&rdquo;</h3>
<p>保留一个测试 Cart，先加入 1 件，再逐步增加。若加入购物车成功、place order 失败，说明两次检查之间库存、reservation 或并发发生变化；若一开始就失败，重点查 Stock 映射和阈值。</p>
<pre><code># 诊断索引状态，名称以 indexer:info 输出为准
bin/magento indexer:info | grep -i inventory
bin/magento indexer:status
bin/magento cron:run --group=index</code></pre>
<p>手动 reindex 后恢复但很快再次失败，说明增量索引/Cron 链路有问题，不是商品数据本身。</p>
<h3>最后库存的并发场景</h3>
<p>两个客户同时购买最后一件商品时，两边页面都可能先显示可售，但最终只能有一个订单成功。结账阶段必须以权威库存校验为准。不能为了消除提示而跳过最终校验，否则会超卖。</p>
<p>修复后用当前 Website、当前 Stock、目标客户组完成加入购物车、下单、取消和再次下单。四个动作后的 Source、Reservation 与 Salable Quantity 应能逐笔解释。</p>]]></description>
      <pubDate>Wed, 08 Jan 2025 02:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台配置保存成功但前台没变化：查清 Scope、env.php 和 config.php 谁覆盖了谁]]></title>
      <link>https://www.360magento.com/blog/config-saved-not-effective/</link>
      <description><![CDATA[<p>后台出现绿色&ldquo;保存成功&rdquo;，前台行为却完全不变。不要从清 Redis 开始。Magento 配置有范围，也可能被部署配置或环境变量锁定；数据库写入成功不代表它是最终生效值。</p>
<h3>用具体配置路径代替后台标签</h3>
<p>先从模块配置或字段 HTML 找到 path，例如 <code>catalog/search/min_query_length</code>。然后在应用节点执行：</p>
<pre><code>bin/magento config:show catalog/search/min_query_length
bin/magento config:show catalog/search/min_query_length   --scope=stores --scope-code=zh_cn</code></pre>
<p>第二条命令的参数按当前 Magento 版本帮助信息确认。如果默认值正确、Store 值错误，就是 scope 覆盖，而不是缓存。</p>
<h3>数据库中把每层值排开</h3>
<pre><code>SELECT config_id, scope, scope_id, path, value
FROM core_config_data
WHERE path = 'catalog/search/min_query_length'
ORDER BY scope, scope_id;</code></pre>
<p>再把 scope_id 翻译成实际网站和 Store：</p>
<pre><code>SELECT website_id, code, name FROM store_website;
SELECT store_id, website_id, code, name, is_active FROM store;
</code></pre>
<p>前台请求属于哪个 Store，必须从 URL、Store header 或当前 store code 确认。不要因为后台下拉框显示 Default Config，就认为子范围没有旧值。</p>
<h3>数据库正确，检查文件与环境变量覆盖</h3>
<pre><code>grep -n "catalog/search/min_query_length" app/etc/config.php app/etc/env.php
printenv | grep '^CONFIG__'
</code></pre>
<p>敏感配置通常在 env.php，非敏感系统配置可能 dump 到 config.php。部署环境变量还可以使用编码后的配置路径覆盖运行值。不要把完整 <code>printenv</code> 输出发到日志，它可能包含密钥。</p>
<p>如果字段在后台呈锁定状态，应通过部署流程修改源配置，而不是改 DOM 强行提交。典型流程是：</p>
<pre><code># 在配置源环境调整后
bin/magento app:config:dump

# 将 app/etc/config.php 的受控变更随代码发布
bin/magento app:config:import
</code></pre>
<p>执行前先查看版本对应命令帮助，并把 config.php 纳入审查。不要把含敏感值的 env.php 提交到仓库。</p>
<h3>最后才处理缓存</h3>
<pre><code>bin/magento cache:status
bin/magento cache:clean config
</code></pre>
<p><code>cache:clean config</code> 只清 Magento 配置缓存，不等于清整个 Redis。若配置影响页面 HTML，再精确清相关 FPC/CDN；若影响长驻 Consumer，需要重启对应进程，因为它可能只在启动时读取配置。</p>
<h3>用代码打印&ldquo;运行时值&rdquo;定位自定义模块</h3>
<pre><code>$value = $scopeConfig-&gt;getValue(
    'catalog/search/min_query_length',
    MagentoStoreModelScopeInterface::SCOPE_STORE,
    $storeId
);</code></pre>
<p>在受控调试中记录 path、scope、store_id 和脱敏后的值。很多自定义模块错误地使用默认 scope，导致后台 Store View 设置永远不被读取。修正调用方后，分别在两个 Store 验证，确保没有把一个站点的值共享给另一个。</p>]]></description>
      <pubDate>Tue, 07 Jan 2025 05:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[queue:consumers:start 一直运行但消息不减少，Magento 2 消费者卡在哪里]]></title>
      <link>https://www.360magento.com/blog/consumer-running-no-progress/</link>
      <description><![CDATA[<p><code>ps</code> 能看到 Consumer，Supervisor 也显示 RUNNING，但队列里的消息越来越多。RUNNING 只说明进程没退出，不说明它正在处理正确的队列，更不说明处理成功。</p>
<h3>十分钟内先拿到四个数字</h3>
<pre><code>bin/magento queue:consumers:list
ps -ef | grep '[q]ueue:consumers:start'

# RabbitMQ 环境
rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers
</code></pre>
<p>观察十分钟内 Ready、Unacked、Consumer 数和业务成功数。Ready 上升、Unacked 为零：进程可能监听错队列或拿不到消息；Unacked 长期不降：处理函数阻塞；Ready 下降又回升：消息 reject/requeue 或消费者崩溃。</p>
<h3>确认进程参数与当前 release</h3>
<pre><code>readlink -f /proc/CONSUMER_PID/cwd
tr '�' ' ' &lt; /proc/CONSUMER_PID/cmdline
readlink -f /var/www/current</code></pre>
<p>蓝绿发布后 Supervisor 可能仍运行旧 release 的 Consumer。Web 已经使用新 schema，旧 Consumer 继续反序列化新消息，就会反复失败。部署流程应先优雅停止旧消费者，再从新 release 启动。</p>
<h3>前台运行一个有限消费者抓异常</h3>
<pre><code>bin/magento queue:consumers:start async.operations.all   --max-messages=10 -vvv
</code></pre>
<p>使用实际 consumer 名称，并在测试或维护窗口执行，避免和现有消费者争抢不可重复的消息。与此同时查看：</p>
<pre><code>tail -f var/log/system.log var/log/exception.log
journalctl -u supervisor --since '15 minutes ago'
</code></pre>
<p>一个坏消息若每次失败都重新入队，会占满日志和 CPU。捕获 message ID、topic、重试次数和异常类型；payload 可能含客户数据，不要完整打印。</p>
<h3>Unacked 不下降时查阻塞点</h3>
<p>先对 Consumer 进程抓安全的进程栈/系统调用，再查数据库：</p>
<pre><code>strace -p CONSUMER_PID -f -tt -T -e trace=network,read,write
mysql -e 'SHOW FULL PROCESSLIST'
mysql -e 'SHOW ENGINE INNODB STATUSG'
</code></pre>
<p>持续等待同一 SQL，查锁持有者和事务边界；持续等待外部 API，给连接和读取设置超时，并把可重试与永久失败分开。不要直接 kill 数据库会话，先确认它是否正在提交订单或库存事务。</p>
<h3>消费者生命周期不能只靠永不退出</h3>
<p>在 <code>env.php</code> 与 Supervisor 中统一 max-messages、内存限制、重启和 stopwaitsecs。有限消息后正常退出再由 Supervisor 拉起，可以释放长期进程中的内存和旧对象，但太小会造成频繁启动。</p>
<h3>恢复积压时控制并发</h3>
<p>先用一个消费者确认成功率，再逐步扩到安全并发。一次启动几十个进程可能把 RabbitMQ 压力转移到 MySQL 或第三方 API。监控&ldquo;最老消息年龄&rdquo;和每分钟成功处理数，直到积压归零；仅看进程数会再次误判。</p>]]></description>
      <pubDate>Mon, 06 Jan 2025 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API 返回 401，先用这组 curl 区分 Token、ACL 和网站路由]]></title>
      <link>https://www.360magento.com/blog/rest-api-401-debug/</link>
      <description><![CDATA[<p>同一个接口昨天正常，今天统一返回 401。先不要重新创建一堆 Token；401 可能发生在 Magento 之前，也可能是 Token、Integration 状态、ACL 或 Store 路由问题。</p>
<h3>建立一条可重复的最小请求</h3>
<pre><code>export API_BASE='https://www.example.com'
export API_TOKEN='在安全终端中设置，不要写进脚本仓库'

curl -sS -i   -H "Authorization: Bearer ${API_TOKEN}"   -H 'Accept: application/json'   "${API_BASE}/rest/V1/store/storeConfigs"</code></pre>
<p>保留 HTTP 状态、响应 body 和服务器 request ID。不要在工单里粘贴完整 curl，因为 shell 历史、CI 日志和截图都可能泄露 Token。</p>
<h3>先看 401 是谁返回的</h3>
<p>Magento JSON 常带 <code>message</code> 和参数；反向代理、WAF 或 Basic Auth 返回的 body/响应头不同。比较：</p>
<pre><code>curl -sS -D /tmp/no-auth.headers -o /tmp/no-auth.body   "${API_BASE}/rest/V1/store/storeConfigs"

curl -sS -D /tmp/token.headers -o /tmp/token.body   -H "Authorization: Bearer ${API_TOKEN}"   "${API_BASE}/rest/V1/store/storeConfigs"

diff -u /tmp/no-auth.headers /tmp/token.headers</code></pre>
<p>两次响应完全相同，很可能 Authorization 在 CDN/Nginx/PHP-FPM 前丢失。检查 Nginx FastCGI 参数和代理规则是否转发该头，不要把 Token 打进访问日志。</p>
<h3>用一个已知允许的端点区分 ACL</h3>
<p>某端点 401/403、另一个成功，Token 本身可用，重点查 Integration 的 API 资源。后台进入 System &rarr; Integrations，打开对应 Integration，确认状态为 Active，并只勾选需要的资源。保存资源后，按版本和集成类型确认是否需要重新授权。</p>
<p>自定义接口的 <code>webapi.xml</code> 必须声明正确 resource：</p>
<pre><code>&lt;route url="/V1/alwayly/job/:id" method="GET"&gt;
    &lt;service class="AlwaylyJobApiJobRepositoryInterface"
             method="getById"/&gt;
    &lt;resources&gt;
        &lt;resource ref="Alwayly_Job::job_read"/&gt;
    &lt;/resources&gt;
&lt;/route&gt;</code></pre>
<p>同时在 <code>acl.xml</code> 中定义相同 ID。拼写不一致时，管理员全权限可能通过，Integration 却被拒绝。</p>
<h3>检查 Store Code 路由</h3>
<pre><code>curl -sS -i -H "Authorization: Bearer ${API_TOKEN}"   "${API_BASE}/rest/all/V1/store/storeConfigs"

curl -sS -i -H "Authorization: Bearer ${API_TOKEN}"   "${API_BASE}/rest/default/V1/store/storeConfigs"</code></pre>
<p>实际 Store code 不一定叫 default。路由被 Web Server 重写成另一个站点，或 Base URL 跳转到其他主机时，Authorization 可能在跨主机跳转中被丢弃。用 <code>-i</code> 看 Location，不要先加 <code>-L</code> 隐藏跳转。</p>
<h3>OAuth 方式再查时钟和 nonce</h3>
<p>如果不是 Bearer Token，而是 OAuth 1.0a，服务器时钟偏差、重复 nonce、签名 Base String 或 URL 编码都会导致认证失败。比较应用、Magento 节点与数据库的 UTC 时间，并保留一次脱敏签名输入用于重算。</p>
<pre><code>date -u
mysql -Nse 'SELECT UTC_TIMESTAMP();'</code></pre>
<p>修复后用最小只读端点、目标业务端点和一个无权端点各测一次：前两者成功，无权端点仍被拒绝，才能证明 Token 与 ACL 同时正确。</p>]]></description>
      <pubDate>Fri, 03 Jan 2025 08:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品导入提示 URL key for specified store already exists，怎样找到真正冲突记录]]></title>
      <link>https://www.360magento.com/blog/import-url-key-conflict/</link>
      <description><![CDATA[<p>导入报告只告诉你 <code>URL key for specified store already exists</code>，但后台搜索 URL Key 又找不到重复商品。真正冲突的是某个 Store 下的最终 <code>request_path</code>，占用者可能不是另一个商品。</p>
<h3>先把失败范围缩到一行</h3>
<ol>
<li>复制原 CSV，只保留表头和一个失败 SKU；</li>
<li>在导入页面选择 Check Data，不立即 Import；</li>
<li>记录导入行为、Store View code、SKU、url_key、categories 和 product_websites。</li>
</ol>
<p>如果单行通过，冲突来自同一 CSV 内两行生成相同路径；如果单行仍失败，继续查数据库。</p>
<h3>计算它想生成的 request_path</h3>
<p>假设 url_key 为 <code>red-shirt</code>，后缀为 <code>.html</code>，最直接的候选是 <code>red-shirt.html</code>。启用&ldquo;Use Categories Path for Product URLs&rdquo;、多 Store 覆盖或扩展后，还可能生成分类路径。先读取后缀与 Store 配置：</p>
<pre><code>bin/magento config:show catalog/seo/product_url_suffix
bin/magento config:show catalog/seo/product_use_categories</code></pre>
<h3>在准确 Store 查询占用者</h3>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id,
       request_path, target_path, redirect_type,
       store_id, is_autogenerated, metadata
FROM url_rewrite
WHERE store_id = 1
  AND request_path IN ('red-shirt', 'red-shirt.html')
ORDER BY request_path, url_rewrite_id;</code></pre>
<p><code>entity_type=product</code> 时，用 entity_id 查 SKU；category 则查分类；custom 记录可能来自旧跳转或扩展。Store ID 不同通常不冲突，所以不能忽略范围。</p>
<pre><code>SELECT entity_id, sku
FROM catalog_product_entity
WHERE entity_id IN (123, 456);</code></pre>
<h3>没有精确记录，再查同一目标和大小写</h3>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id,
       request_path, target_path, store_id
FROM url_rewrite
WHERE store_id = 1
  AND (LOWER(request_path) = LOWER('red-shirt.html')
       OR target_path = 'catalog/product/view/id/123');</code></pre>
<p>数据库排序规则可能不区分大小写；Web Server 和 CDN 路径处理又可能区分。不要用只改变大小写的 URL Key 解决冲突。</p>
<h3>按占用类型决定处理方式</h3>
<ul>
<li><strong>另一个有效商品：</strong>为新商品选择不同且有意义的 URL Key；</li>
<li><strong>旧商品需要迁移：</strong>先确定新旧 canonical，再保留精确 301；</li>
<li><strong>分类占用：</strong>不要让商品和分类争同一路径，重新规划其中一个 slug；</li>
<li><strong>确认无主的残留自动记录：</strong>先导出该记录与关联实体，在预发布删除并重新保存目标商品验证。</li>
</ul>
<p>不要把整个 <code>url_rewrite</code> 表清空，也不要直接插入一条新 rewrite。核心会在保存实体时重新生成，手工记录很容易在下次更新后再次冲突。</p>
<h3>重导前做两个检查</h3>
<pre><code># CSV 中检查重复 url_key（示意，按实际列号调整）
awk -F',' 'NR&gt;1 {print $5}' products.csv | sort | uniq -d

# 备份待改的 rewrite
mysqldump DB_NAME url_rewrite   --where="store_id=1 AND request_path='red-shirt.html'"   &gt; /tmp/red-shirt-rewrite.sql</code></pre>
<p>重新导入成功后，请求新 URL 应返回 200；旧 URL 如果存在历史流量，应只跳转一次到新地址；canonical 与 Sitemap 也要使用最终路径。</p>]]></description>
      <pubDate>Thu, 02 Jan 2025 03:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 可售数量对不上实际库存，用 Reservation CLI 找出并补偿差异]]></title>
      <link>https://www.360magento.com/blog/fix-reservation-inconsistency/</link>
      <description><![CDATA[<p>后台 Source Quantity 是 20，前台可售数量却是 14；或者订单取消后库存没有回来。MSI 的 Salable Quantity 不是简单等于 Source Quantity，它还会叠加对应 Stock 的 reservation。修复时应追加补偿 reservation，不能删除表记录。</p>
<h3>先记录 SKU、Website 与 Stock</h3>
<pre><code>bin/magento inventory:reservation:list-inconsistencies</code></pre>
<p>数据量大时不要把输出直接在终端滚完，可以先限制到订单范围：</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies   -r 000001200-000001500</code></pre>
<p>不同版本命令参数可能略有差异，先运行 <code>--help</code> 确认。输出中的订单号、SKU、补偿数量和 Stock ID 是后续审核依据。</p>
<h3>拿一条结果手工核算</h3>
<pre><code>SELECT stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku = 'SKU-001'
ORDER BY reservation_id;

SELECT sku, source_code, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001';</code></pre>
<p>reservation 正数和负数代表对可售量的增减，不能只数行数。打开 metadata 中的 order increment ID 和 event type，对照订单的下单、取消、发货或退款时间。若订单仍在正常处理中，负 reservation 可能完全合法。</p>
<h3>把 CLI 输出先保存为审核文件</h3>
<pre><code>bin/magento inventory:reservation:list-inconsistencies   -r 000001200-000001500   &gt; /tmp/reservation-fix.txt

sed -n '1,40p' /tmp/reservation-fix.txt
wc -l /tmp/reservation-fix.txt</code></pre>
<p>逐条排除正在处理、外部 ERP 尚未回写或业务人员正在操作的订单。高峰期库存还在变化，诊断与执行之间的窗口越长，越容易把新状态当成旧差异。</p>
<h3>确认无误后通过管道创建补偿</h3>
<pre><code>bin/magento inventory:reservation:list-inconsistencies   -r 000001200-000001500   | bin/magento inventory:reservation:create-compensations</code></pre>
<p>先在预发布和一个很小的订单范围验证。生产执行前备份数据库，并暂停会同时修改相关订单/库存的集成任务。该命令应该新增补偿记录，而不是改写历史；历史 reservation 是审计链。</p>
<h3>补偿以后不要只看后台 Grid</h3>
<pre><code>bin/magento indexer:status
bin/magento indexer:reindex inventory
bin/magento cache:clean</code></pre>
<p>实际 indexer 名称按版本的 <code>indexer:info</code> 为准。随后重新运行 <code>list-inconsistencies</code>，原结果应消失；再用商品页、GraphQL/REST 可售查询和一次测试下单确认。</p>
<h3>差异为什么会反复出现</h3>
<p>常见根因不是索引，而是旧版本升级时缺少初始补偿、订单导入绕过标准服务、状态回滚失败、第三方模块直接改订单状态，或消费者/Cron 没有完成异步库存动作。根据 metadata 的 event type 和故障时间定位源头；否则今天补平，下一批订单还会继续产生差异。</p>]]></description>
      <pubDate>Wed, 01 Jan 2025 06:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付平台显示成功，Magento 2 订单却停在 Pending Payment：从 Webhook 补状态]]></title>
      <link>https://www.360magento.com/blog/paid-order-pending-payment/</link>
      <description><![CDATA[<p>这是一类必须先对账、再补偿的故障。最危险的处理方式，是在后台把订单状态直接改成 Processing：这样页面看起来正常，但 Magento 可能仍没有 Capture transaction、Invoice 和网关交易关联，后续退款会继续出错。</p>
<h3>先冻结自动重试，建立一张订单的时间线</h3>
<p>记录 Magento increment_id、entity_id、支付平台 transaction/payment ID、币种、金额和三个时间点：客户提交、网关成功、Webhook 到达。所有日志都应脱敏，不记录卡号、密钥或完整签名。</p>
<pre><code>SELECT o.entity_id, o.increment_id, o.state, o.status,
       o.grand_total, o.order_currency_code,
       p.method, p.last_trans_id
FROM sales_order o
JOIN sales_order_payment p ON p.parent_id = o.entity_id
WHERE o.increment_id = '000001234';

SELECT transaction_id, parent_id, txn_id, parent_txn_id,
       txn_type, is_closed, created_at
FROM sales_payment_transaction
WHERE order_id = 1234
ORDER BY transaction_id;</code></pre>
<p>网关成功但本地没有 capture/authorization 记录，说明回调或返回页没有完成业务动作；本地已有 transaction 但订单仍 Pending，查支付扩展的状态映射和异常回滚。</p>
<h3>确认 Webhook 到没到服务器</h3>
<pre><code>grep 'PAYMENT_EVENT_ID' var/log/*.log
grep '/payment/webhook' /var/log/nginx/access.log | tail -n 50</code></pre>
<p>访问日志没有请求：查网关后台的投递记录、DNS、防火墙和回调 URL。出现 301/302 时尤其要修复，很多网关不会对跨域跳转保留 POST body。出现 401/403：检查签名 secret、时间容差和 WAF；500：用 request ID 对应 exception.log。</p>
<h3>在测试环境重放，不要伪造事件</h3>
<p>优先使用支付平台提供的&ldquo;重发 Webhook&rdquo;功能，它会生成合法签名。若平台提供 CLI，使用同一 event ID 重放到预发布回调地址。不要从日志复制 JSON 后自己计算一个假签名，更不能在生产临时关闭签名校验。</p>
<p>回调处理至少需要下面的幂等边界：</p>
<pre><code>// 伪代码：以网关 event_id 建立唯一记录
if ($eventRepository-&gt;exists($eventId)) {
    return; // 已处理事件直接确认，不重复开票
}

$this-&gt;transaction-&gt;begin();
$this-&gt;verifyAmountCurrencyAndOrder($payload, $order);
$this-&gt;captureOrRegisterPayment($order, $gatewayTransactionId);
$this-&gt;eventRepository-&gt;markProcessed($eventId);
$this-&gt;transaction-&gt;commit();</code></pre>
<h3>安全补单应该调用支付模块支持的服务</h3>
<p>确认网关交易真实成功后，使用扩展提供的同步/重放命令或服务完成授权/捕获、Invoice、订单历史与邮件。若扩展没有补偿入口，应先在预发布写一次性脚本，通过 Repository 和 Payment API 处理，并以订单 ID + 网关交易 ID 做幂等。不要直接 UPDATE <code>sales_order.state</code>。</p>
<h3>补偿后做四方对账</h3>
<ul>
<li>Magento 订单金额、币种和已付金额正确；</li>
<li>Invoice 只生成一张，数量与金额正确；</li>
<li>sales_payment_transaction 中 txn_id 可追溯到网关；</li>
<li>重复投递同一个 Webhook 不再开第二张 Invoice 或发第二封邮件。</li>
</ul>
<p>最后修复导致漏回调的根因，并对故障时间范围内所有 Pending Payment 订单按网关交易批量对账。单独修一张订单不是结束。</p>]]></description>
      <pubDate>Tue, 31 Dec 2024 01:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发布后仍加载旧 JS/CSS，不清浏览器也能定位缓存在哪一层]]></title>
      <link>https://www.360magento.com/blog/old-static-after-deploy/</link>
      <description><![CDATA[<p>发布新主题后，服务器上的文件已经变化，客户页面却仍执行旧 JavaScript。让所有人&ldquo;强制刷新&rdquo;只能绕过单个浏览器，不能证明 CDN 或 Web 节点已经切到新资源。</p>
<h3>先选一个有明确改动的资源</h3>
<p>不要拿合并后的随机文件猜。选一个本次确实改过的 JS/CSS，在源码中放入可搜索的版本标记，例如模块版本号或一段不会影响功能的注释。然后从页面 HTML 复制它实际请求的完整 URL。</p>
<pre><code>curl -sS -D /tmp/static.headers   -o /tmp/static.body   'https://www.example.com/static/version123/frontend/Vendor/theme/zh_CN/js/app.js'

sha256sum /tmp/static.body
grep -n 'release-20241230' /tmp/static.body
sed -n '1,40p' /tmp/static.headers</code></pre>
<p>响应头中的 <code>Age</code>、<code>X-Cache</code>、<code>ETag</code>、<code>Last-Modified</code> 能说明对象来自哪一层。URL 里仍是旧的 <code>version...</code>，先查 HTML/FPC；URL 已是新版本但 body 旧，查 CDN、Nginx 或错误源站文件。</p>
<h3>直接对比 CDN 与源站，避免猜测</h3>
<p>知道源站 IP 时，可在受控终端用 <code>--resolve</code> 保持 Host 和 TLS 名称不变：</p>
<pre><code>curl -sk --resolve www.example.com:443:ORIGIN_IP   -o /tmp/origin.js   'https://www.example.com/static/version123/frontend/Vendor/theme/zh_CN/js/app.js'

sha256sum /tmp/origin.js /tmp/static.body</code></pre>
<p>源站新、CDN 旧：精确 purge 当前资源或版本目录；源站也旧：继续检查 release。不要先全站 purge，因为这会制造缓存击穿，还会把定位证据清掉。</p>
<h3>确认运行 release 里究竟有什么</h3>
<pre><code>readlink -f /var/www/current
find pub/static/frontend/Vendor/theme/zh_CN -type f -name 'app.js' -ls
grep -R 'release-20241230' pub/static/frontend/Vendor/theme/zh_CN/js
bin/magento config:show dev/static/sign</code></pre>
<p>常见错误是先切换 <code>current</code> 软链接，再在旧目录执行 static deploy；或者多台 Web 节点只有一台更新。逐台输出 release ID 和文件哈希，轮询访问时在响应头加入脱敏节点标识，很快就能看到是否某一台在返回旧资源。</p>
<h3>正确的构建顺序</h3>
<pre><code>composer install --no-dev --prefer-dist --no-interaction
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f zh_CN en_US
bin/magento cache:clean config layout block_html
# 健康检查通过后，再原子切换 current 到新 release</code></pre>
<p>静态内容应在独立 release 中构建完成，不能一边被请求一边覆盖。<code>pub/static/.htaccess</code>、主题 locale 和部署 mode 也要跟随发布产物。</p>
<h3>如果 URL 签名没变</h3>
<p>静态签名开启后，新部署通常应产生新的版本路径。签名仍旧，检查 <code>deployed_version.txt</code>、共享的 pub/static、只读文件系统和发布用户权限。不要手工改 HTML 里的版本号；版本必须与实际目录和回源 rewrite 一致。</p>
<p>最终用一个全新资源 URL完成三点证明：HTML 引用新签名、CDN 与源站文件哈希相同、连续访问命中缓存。这样即使不清浏览器，也能确认问题真正解决。</p>]]></description>
      <pubDate>Mon, 30 Dec 2024 07:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台登录成功又跳回登录页，Cookie 和 Base URL 这样排查]]></title>
      <link>https://www.360magento.com/blog/admin-login-loop/</link>
      <description><![CDATA[<p>账号和密码没有报错，提交登录后地址短暂跳转，随后又回到管理员登录页。这类问题通常不是&ldquo;密码不对&rdquo;，而是服务器建立了管理员 Session，浏览器却没有在下一次请求带回正确的 Session Cookie。</p>
<p>下面按一次真实登录请求来查，不先清全部缓存，也不直接改数据库。</p>
<h3>第一步：在浏览器确认 Cookie 有没有种下</h3>
<p>打开开发者工具的 Network，勾选 Preserve log，再提交一次登录。找到登录 POST，重点看两处：</p>
<ul>
<li>响应头是否包含 <code>Set-Cookie</code>；</li>
<li>紧接着的后台 GET 请求是否带上同名 Cookie。</li>
</ul>
<p>POST 没有 Set-Cookie，查 PHP Session 或 Magento 日志；有 Set-Cookie、下一跳没带，通常是 Domain、Path、Secure 或 SameSite 不匹配。浏览器 Issues 面板会直接说明 Cookie 被拒绝的原因。</p>
<h3>第二步：只读出真正生效的 URL 与 Cookie 配置</h3>
<pre><code>bin/magento config:show web/secure/base_url
bin/magento config:show web/secure/use_in_adminhtml
bin/magento config:show web/cookie/cookie_domain
bin/magento config:show web/cookie/cookie_path
bin/magento config:show web/cookie/cookie_httponly
bin/magento config:show web/cookie/cookie_lifetime</code></pre>
<p>如果后台访问地址是 <code>admin.example.com</code>，Cookie Domain 却写成另一个域名，浏览器不会回传。单站点一般可以让 Cookie Domain 留空；多子域共享时才使用类似 <code>.example.com</code>，但必须先确认不会把后台 Session 扩散给不需要的子域。</p>
<h3>遇到 HTTPS 代理，先证明 Magento 看到的协议</h3>
<p>负载均衡器对外是 HTTPS，回源却是 HTTP 时，Magento 需要从可信代理头识别原始协议。用 Web Server 日志记录 <code>X-Forwarded-Proto</code>，并比较登录 POST 的 Location：</p>
<pre><code>curl -skI https://admin.example.com/admin/
curl -sk -D- -o /dev/null https://admin.example.com/admin/</code></pre>
<p>如果跳转在 http/https 或两个主机名之间来回，先修代理与 Base URL，不能靠延长 Cookie Lifetime 解决。不要把 <code>Secure</code> Cookie 关闭来迁就错误的 HTTPS 识别。</p>
<h3>数据库配置需要按 scope 查</h3>
<pre><code>SELECT scope, scope_id, path, value
FROM core_config_data
WHERE path IN (
 'web/secure/base_url',
 'web/secure/use_in_adminhtml',
 'web/cookie/cookie_domain',
 'web/cookie/cookie_path'
)
ORDER BY path, scope, scope_id;</code></pre>
<p>发现重复 scope 后，先备份具体记录，再通过 <code>bin/magento config:set</code> 或后台修正。不要直接删除所有 web 配置。配置改完执行：</p>
<pre><code>bin/magento cache:clean config
bin/magento cache:clean full_page</code></pre>
<h3>Cookie 正常仍回登录页，再检查 Session 后端</h3>
<p>多 Web 节点若使用本地文件 Session，请求落到另一台机器就会丢登录状态。确认 <code>app/etc/env.php</code> 的 session save 配置、Redis 连通性、TTL、前缀和各节点配置一致。只在一台节点成功，是非常明确的证据。</p>
<pre><code>grep -n "session" app/etc/env.php
redis-cli -h REDIS_HOST ping
redis-cli -h REDIS_HOST info memory</code></pre>
<p>生产日志不要打印 Session ID。修复后的判断标准不是&ldquo;偶尔能登录&rdquo;，而是无痕窗口连续登录、刷新、切换后台页面和退出都稳定；同时 Cookie 的 Domain、Path、Secure、HttpOnly 符合预期。</p>]]></description>
      <pubDate>Fri, 27 Dec 2024 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[订单邮件排队几小时才发出，Magento 2 邮件队列堵在哪里？]]></title>
      <link>https://www.360magento.com/blog/sales-email-queue-backlog/</link>
      <description><![CDATA[<p>订单在下午三点创建，确认邮件晚上才收到。订单流程和邮件发送是两个系统：开启异步发送后，结账只标记待发，Cron/队列稍后生成并交给 SMTP。需要找出延迟发生在&ldquo;未入队、未消费、生成慢、SMTP 接收慢&rdquo;哪一步。</p>
<h3>以一张订单画时间线</h3>
<p>记录订单 created_at、email_sent、相关队列/邮件记录时间、Cron executed/finished、SMTP accepted 与最终投递时间。收件箱显示时间可能经过时区转换，统一用 UTC 比较。</p>
<h3>异步配置与 Cron</h3>
<p>确认 Sales Emails 的异步选项、对应 Cron job 是否按分钟成功运行。大量 missed/error、一个长任务占住 Group 或系统 crontab 间隔过长，都会造成积压。手工运行 cron 能恢复，只说明入口链路有问题，不是长期方案。</p>
<h3>失败邮件会不会阻塞整批</h3>
<p>一个无效地址、模板异常或 SMTP 超时若每次从队首重试，可能拖住后续正常邮件。消费者应记录有限重试、错误原因并将永久失败隔离；不能无限重试，也不能静默丢弃。</p>
<h3>SMTP 已接收仍延迟</h3>
<p>Magento 日志显示 250 accepted 后，延迟发生在邮件服务商、DNS、反垃圾或收件方。用 Message-ID 在服务商日志追踪。不要因为最终投递慢就重复发送，客户会收到多封订单邮件。</p>
<h3>模板生成成本</h3>
<p>邮件模板中的自定义 block 若查询大量订单项、外部 API 或加载前台页面，会让每封邮件很慢。对批量发送测单封生成时间和 SQL 数，缓存公共数据，但不能跨订单缓存客户内容。</p>
<p>修复后在正常与 SMTP 故障两种场景创建测试订单，观察积压长度、最老消息年龄、重试和恢复速度。邮件应在目标时间内发送，永久失败可见且不会阻塞整条队列。</p>
<h3>积压容量怎么估算</h3>
<p>计算到达速率、单封平均处理时间和并发消费者数。处理速率低于订单峰值，积压必然增长；只在出事后手工 cron 无法解决。模板生成与 SMTP 发送可拆分监控，决定是优化代码、提高安全并发还是升级邮件服务额度。</p>
<h3>队列数据与订单状态</h3>
<p>取消订单前尚未发送的确认邮件是否仍应发送，业务要有明确规则。消费者读取旧订单快照可能发出错误状态；发送前重新读取必要字段，同时保持金额与下单时订单快照一致，不能从当前商品价格重算。</p>
<h3>多 Store 发件身份</h3>
<p>队列处理时若缺少 store emulation，可能使用默认 Store 模板、语言和发件人。记录 store_id、template id、recipient 与 order id，处理后恢复 emulation，避免下一封邮件继承错误范围。</p>
<h3>告警与补发</h3>
<p>监控最老待发年龄比只看队列长度更有意义。补发工具应按订单/消息唯一键操作，显示原失败原因并要求权限；批量补发前抽样，防止积压恢复后又把同一批发送两次。</p>
<h3>建立可操作的积压指标</h3>
<p>建议至少记录待发数量、最老消息年龄、每分钟成功数、失败率与 SMTP 响应时间，并按 Store/模板拆分。阈值要与业务承诺对应：订单确认超过十分钟与营销邮件延迟十分钟影响不同。告警中附上最近失败原因和运行节点，值班人员才能直接行动。</p>
<h3>恢复时控制发送洪峰</h3>
<p>SMTP 恢复后一次性放开全部消费者，可能触发服务商限流并再次失败。按可接受速率逐步提高并发，优先交易邮件，观察 4xx/5xx 与重复率。积压清空后再评估自动扩缩容，而不是把临时高并发永久保留。</p>]]></description>
      <pubDate>Thu, 26 Dec 2024 08:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付页面按钮没反应，Magento 2 CSP 是否拦住了第三方 JavaScript？]]></title>
      <link>https://www.360magento.com/blog/csp-blocked-payment-js/</link>
      <description><![CDATA[<p>支付方式能选中，点击按钮没有反应，Console 出现 <code>Refused to load/execute ... because it violates Content Security Policy</code>。CSP 阻止的可能是脚本、iframe、API 连接、图片或内联代码；把整个策略改成 <code>*</code> 会失去防护。</p>
<h3>先读取完整 violation</h3>
<p>记录 directive（script-src、frame-src、connect-src 等）、blocked URI、页面与支付步骤。第三方 SDK 脚本能加载，不代表它创建的 iframe 和 API 域也被允许。测试模式与生产模式域名通常不同。</p>
<h3>白名单按资源类型最小放行</h3>
<p>在自定义模块的 CSP whitelist 中添加支付提供商官方要求的精确 host 与类型，区分 https、子域和 WebSocket。不要凭错误逐个允许未知追踪域；先核对支付商文档和实际调用用途。</p>
<h3>内联脚本与 nonce/hash</h3>
<p>自定义模板把大段初始化代码直接写在 script 标签里，严格策略会阻止。优先移到 RequireJS/静态模块并通过 data config 传参数；需要内联时使用 Magento 当前版本支持的 secure renderer/nonce/hash 机制，而不是 unsafe-inline。</p>
<h3>Report-only 与 Enforce</h3>
<p>升级时可先在报告模式收集 violation，再在测试环境启用 enforce。报告端点要限制数据和流量，violation 可能包含页面 URL。不要长期只 report 而从不收敛规则。</p>
<h3>支付回归不能只到按钮</h3>
<p>验证 SDK 加载、3DS iframe、tokenization、确认 API、成功/失败回跳和 Webhook。还要检查 CSP 放行没有让任意第三方脚本进入结账。最终 Console 无意外 violation，真实测试交易完成，敏感支付数据仍只进入合规组件。</p>
<h3>第三方域名会动态变化</h3>
<p>支付商可能按地区、3DS 提供商或风控服务加载不同子域。白名单应基于官方集成清单并定期复核，不能看到 Console 域名就直接允许。通配符范围越大，供应链脚本被攻破时影响越大。</p>
<h3>Checkout CSP 与后台不同</h3>
<p>CSP mode 可以按 area/route 有不同配置。只在开发首页测试不够，要从实际 checkout action、成功/失败页验证。多网站使用不同支付商时，白名单模块也应按启用范围加载，避免所有站点共享不必要来源。</p>
<h3>报告去重</h3>
<p>浏览器会为同一阻止产生大量 report。按 directive、blocked host、source file 和版本聚合，设置采样与告警阈值。部署新增 violation 应阻止发布；已确认的浏览器扩展噪声则单独过滤。</p>
<h3>Report-Only 不是可以长期忽略</h3>
<p>Report-Only 适合上线前收集真实资源，但如果长期只报告，策略并没有保护作用。为观察期设置结束日期，清理 nonce/hash/host 清单后再转 enforce。紧急回滚应只回滚新增规则或支付发布，不要永久改成允许所有 inline/eval。</p>
<h3>支付完成页也要验证</h3>
<p>第三方脚本可能在下单按钮阶段正常，却在 3DS 返回、vault 保存或 success 页面被拦截。覆盖 iframe、redirect、弹窗、失败重试和保存卡片场景，并在浏览器隐私模式测试。最终以网关交易与 Magento 订单状态一致为准。</p>]]></description>
      <pubDate>Wed, 25 Dec 2024 03:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[读写分离后库存忽高忽低，Magento 2 是不是读到了延迟副本？]]></title>
      <link>https://www.360magento.com/blog/replica-lag-stale-inventory/</link>
      <description><![CDATA[<p>客户下单后商品可售量下降，几秒后页面又显示旧库存，再刷新才恢复。接入数据库读写分离后，这可能是写入主库成功、随后的读取被路由到复制延迟的副本。对库存、订单和客户会话，读后写一致性比普通目录查询更敏感。</p>
<h3>先测延迟，不凭感觉</h3>
<p>使用数据库平台指标或复制状态记录 seconds/GTID lag、回放队列和 I/O。应用日志给一次请求加 correlation ID，标明读写连接与关键实体版本。只测网络 ping 不能代表事务已复制。</p>
<h3>哪些读取必须回主库</h3>
<p>提交订单后的确认、支付状态、可售性校验、刚保存的客户地址通常需要 read-after-write。路由层应在事务和短期一致性窗口内保持主库读取，不能随机把每条 SELECT 分散到副本。</p>
<h3>MSI 与缓存会叠加</h3>
<p>reservation 写入数据库，可售量又可能经过库存索引和页面缓存。即使副本同步，FPC/CDN 仍可能显示旧提示；反过来，绕过缓存仍读副本也会旧。分别记录数据库版本、索引更新时间和响应 cache status。</p>
<h3>副本不应承担不兼容查询</h3>
<p>长报表在副本运行会拖慢 SQL thread 回放，制造更大 lag。监控副本 CPU、I/O、长事务和锁；必要时把报表副本与在线读取副本分开。故障切换前确认候选副本已追平，否则提升会丢失最近交易。</p>
<h3>验证一致性边界</h3>
<p>测试下单、取消、退款、库存导入和高并发最后库存；每次立即读取与延迟读取都记录连接。允许最终一致的目录展示应有清晰窗口，但结账最终校验必须在权威数据上。修复不能只靠强制所有读走主库，应在正确性与扩展性之间明确路由。</p>
<h3>事务粘滞的实现边界</h3>
<p>&ldquo;写后若干秒读主库&rdquo;需要以请求/会话或实体版本为依据，不能全站固定等待。后台批量任务可能在一个流程中多次提交并读取，连接路由要理解事务结束和新事务。ORM 层若缓存实体，也可能返回旧对象，排查时要区分应用缓存与副本。</p>
<h3>监控复制位点</h3>
<p>比秒数更可靠的是写入位点与副本回放位点。关键流程可以等待副本追到已知 GTID/LSN 后再读，但必须有短超时和主库回退，不能让结账无限等待。具体能力取决于数据库与代理。</p>
<h3>复制过滤和 schema 差异</h3>
<p>副本缺表、列、触发器或过滤了某些数据库时，表现不只是延迟，而是永久不一致。部署 schema 后核对复制错误与表结构，再把副本加入读池。读副本必须在应用版本切换前兼容新查询。</p>
<h3>故障演练</h3>
<p>模拟副本延迟、断开和主从切换，观察应用是否自动摘除不健康节点、是否把写错误路由到只读库。库存正确只是结果之一，还要确认订单、客户与配置读取没有回退到旧版本。</p>
<h3>用版本号识别旧读</h3>
<p>关键库存记录可在诊断环境附带更新时间、reservation 最新 ID 或业务版本，应用响应也记录读取节点。发现页面数值回退时，对比版本即可证明是否从新值读回旧值。不要把这些内部字段直接暴露给客户，日志同样要限制权限。</p>
<h3>不要让健康检查只验证连接成功</h3>
<p>副本能接受 SELECT 不代表可用于交易读取。读池健康检查应包含复制线程状态、延迟/位点、只读属性和最近错误；超过阈值就摘除，并把流量回退到可用节点。恢复加入前要持续观察一段时间，防止节点反复抖动。</p>
<h3>隔离一次完整下单链路</h3>
<p>在预发布给测试 SKU 设置已知库存，记录下单前后 source item、reservation、salable quantity、订单状态与每次读取节点。再人为制造可控延迟，验证结账最终校验走权威数据、目录展示在允许窗口内收敛，取消订单也能正确补偿。</p>]]></description>
      <pubDate>Tue, 24 Dec 2024 07:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[多网站订单号重复了，Magento 2 Sales Sequence 配置有问题吗？]]></title>
      <link>https://www.360magento.com/blog/duplicate-order-increment-id/</link>
      <description><![CDATA[<p>网站 A 和网站 B 都出现订单号 100000123，客服认为&ldquo;订单重复&rdquo;。Magento 的 entity_id 是全局数据库主键，increment_id 是业务展示编号，Sales Sequence 通常按 Store 生成；不同 Store 出现相同数字可能符合默认设计。</p>
<h3>先确认是否真冲突</h3>
<pre><code>SELECT entity_id, increment_id, store_id, created_at
FROM sales_order
WHERE increment_id = '100000123';</code></pre>
<p>同一 store_id 出现重复通常会受唯一约束阻止，需要查导入/直接 SQL；不同 store_id 相同则先核对业务要求。外部 ERP 若只用 increment_id 做唯一键，集成设计已经丢失 store 维度。</p>
<h3>查看 Sequence 映射</h3>
<p>sales_sequence_meta/profile 将实体类型与 Store 的序列表、前缀、后缀和步长关联。不要在生产直接 UPDATE 当前值或复制 sequence 表；并发下可能再次碰撞，下一次升级也难以审计。</p>
<h3>前缀比强行共享序列更清晰</h3>
<p>业务只需肉眼区分网站时，可为不同 Store 配置稳定前缀，例如 CN-/US-，并确保支付、邮件、发票和 ERP 字段支持字符。若必须全局连续，要设计单一原子序列、容量、回滚和多节点并发，而不是把多个 Store 指向同一旧表后祈祷。</p>
<h3>迁移与历史订单</h3>
<p>更改规则通常只影响新订单。不要批量重编号已发送给客户或支付平台的历史订单；可以在集成层使用 entity_id/store_id 或独立全局键。任何重编号都涉及发票、退款、物流和审计引用。</p>
<p>修复后并发创建多 Store 订单，验证唯一约束、前缀、邮件、支付回调与 ERP 幂等。订单号可读性不能牺牲交易唯一性。</p>
<h3>Invoice、Shipment 也有独立序列</h3>
<p>订单号修好不代表发票/发货编号满足外部要求。不同实体有各自 meta/profile 与序列表，前缀策略要整体设计。财务系统若要求发票号法定连续，不能用订单序列配置替代合规方案。</p>
<h3>Sequence 空洞不是重复</h3>
<p>事务回滚、预取或失败下单可能让编号跳号。为消除空洞而手工回退当前值，会与并发请求碰撞并制造真正重复。先区分&ldquo;缺号&rdquo;&ldquo;跨 Store 同号&rdquo;&ldquo;同 Store 重复&rdquo;三种现象。</p>
<h3>监控接近容量上限</h3>
<p>序列表自增字段与格式长度应有足够容量。前缀、start_value、step 调整前在预发布生成样本，检查支付平台、物流和客服搜索是否接受。上线后监控唯一约束错误和序列增长，不要等溢出才处理。</p>
<h3>API 与人工搜索要使用复合键</h3>
<p>集成接口应传 store_id/website code 与 increment_id，或直接使用不可变全局 ID。客服后台也应显示网站标识，避免处理错订单。支付回调若只有 merchant reference，需要在生成时保证该商户账号范围内唯一，并保存与 Magento 实体的映射。</p>
<h3>唯一约束要与业务范围一致</h3>
<p>数据库约束通常保护 store_id 与 increment_id 的组合，外部系统若要求全局唯一，应在其映射表增加明确约束与冲突告警。不要只在界面校验，因为 API、导入和并发请求都可能绕过。迁移前先扫描历史冲突并制定保留规则。</p>]]></description>
      <pubDate>Mon, 23 Dec 2024 01:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[一个小 Block 让整页缓存失效，cacheable=false 应该放在哪里？]]></title>
      <link>https://www.360magento.com/blog/cacheable-false-disables-page-cache/</link>
      <description><![CDATA[<p>商品页只增加了一个&ldquo;欢迎回来&rdquo;Block，Varnish 命中率却骤降。Magento 布局树中出现不可缓存 Block，往往会让整个页面响应绕过 Full Page Cache；一个很小的个性化组件，代价可能是每个请求都运行完整 PHP 页面。</p>
<h3>确认页面是否真的不可缓存</h3>
<p>比较响应中的 Cache-Control、X-Magento-Cache-Debug、Age，并连续请求同一匿名 URL。开发环境可检查布局合并与 profiler，搜索自定义 XML 的 <code>cacheable="false"</code>。不要只看 block_html cache，它与 FPC 是不同层。</p>
<h3>什么内容不该进公共 HTML</h3>
<p>客户姓名、购物车、愿望单、专属余额和一次性 Token 不能被共享缓存。标准做法是公共页面保留占位，通过 customer-data/private content 或受保护 AJAX 在浏览器端加载。CDN/FPC 页面本身必须不包含敏感值。</p>
<h3>公共但频繁变化的内容</h3>
<p>库存提示、倒计时或汇率未必需要关闭整页。可以用短 TTL、缓存标签精确失效、边缘 include 或异步接口，选择取决于一致性要求。不要把每秒变化的时间直接渲染进服务器 HTML。</p>
<h3>Block 缓存键也要完整</h3>
<p>移除 cacheable=false 后，如果 Block 自己缓存但 key 没有包含 store、currency、customer group 等维度，会返回错误内容。私有身份绝不能仅靠把 customer_id 放进公共缓存键，因为对象数量与泄露风险都很高。</p>
<p>修复后测试匿名、登录、两个客户组、不同币种与 Store；公共 HTML 应 HIT，私有组件正确更新，退出登录后旧客户数据立即清除。性能和隔离必须同时通过。</p>
<h3>定位是哪一个 Handle 加入</h3>
<p>同一 Block 可能只在某个 layout handle 或客户组条件下出现，导致部分 URL MISS。记录页面完整 handle 集和合并来源，搜索模块/主题 XML；第三方模块更新后新增的 cacheable=false 也要纳入版本对比。</p>
<h3>表单与 CSRF 不应嵌入缓存页状态</h3>
<p>包含 form key 的表单可以用 Magento 支持的占位/JS机制获取当前值，不能为了 form key 把整页设不可缓存。登录状态判断同理，应使用 HTTP context/private content，而不是模板直接读 session。</p>
<h3>量化收益</h3>
<p>修复前后比较 FPC hit rate、TTFB、PHP 请求数和后端 CPU，分别观察首页/分类/商品。若命中率恢复但私有 AJAX 数量暴增，首屏仍可能慢；可合并 section 请求和延迟非关键组件。</p>
<h3>不要把 ESI 当作默认答案</h3>
<p>Varnish ESI 可以单独刷新片段，但增加回源、Cookie 与失效复杂度，而且私有内容配置错误仍可能泄露。对小型客户组件，customer-data 往往更符合 Magento 机制；只有服务器端片段确有 SEO 或首屏要求时，再评估 ESI 与访问控制。</p>
<h3>缓存失效标签不要无限膨胀</h3>
<p>即使页面可缓存，Block 返回过多 identity tag 也会增加缓存对象头和 purge 成本。只声明真正影响输出的实体，避免把整个目录标签挂到一个小组件。商品更新后检查需要失效的页面被清除，其他热门页仍保持命中。</p>]]></description>
      <pubDate>Fri, 20 Dec 2024 06:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[setup:di:compile 报 Circular dependency，Magento 2 到底哪里循环了？]]></title>
      <link>https://www.360magento.com/blog/di-compile-circular-dependency/</link>
      <description><![CDATA[<p><code>setup:di:compile</code> 报 Circular dependency，开发模式下页面可能还能打开。循环依赖是对象图问题：A 构造时需要 B，而 B 直接或经过数层又需要 A，Object Manager 无法决定先实例化谁。</p>
<h3>完整异常链比最后两个类更重要</h3>
<p>保存编译输出中所有类名，画出 A&rarr;B&rarr;C&rarr;A。检查最近改动的 constructor、di.xml preference、virtualType 和 plugin。最终显示核心类不代表核心有错，自定义 preference 可能把实现替换成循环版本。</p>
<h3>不要用 ObjectManager 隐藏循环</h3>
<p>在方法里直接 getInstance 只是把编译期错误推迟到运行期，并破坏可测试性。先判断职责是否混在一起：把共同逻辑抽到更小服务、通过事件/接口反转依赖，通常比延迟加载更清晰。</p>
<h3>Proxy 的适用条件</h3>
<p>如果 A 只在某个方法路径偶尔使用重服务 B，可注入 B 的 Proxy，让真实对象在调用时创建，从而打破构造阶段循环。但若 A 方法调用 B、B 同一调用又立即回 A，Proxy 只会推迟无限递归，不能解决设计循环。</p>
<pre><code>&lt;argument name="service" xsi:type="object"&gt;
  VendorModuleModelHeavyServiceProxy
&lt;/argument&gt;</code></pre>
<h3>Plugin 也会制造隐形依赖</h3>
<p>对 A 的 plugin 构造函数注入 A 或注入依赖 A 的服务，插件列表生成时就可能循环。Plugin 应依赖更窄的接口，避免调用 subject 的公共方法重新进入同一拦截链。</p>
<p>修复后删除 generated/code、在干净构建中 compile，并运行实际业务路径与单元测试。成功编译只是第一步，还要确认没有递归调用和意外提前实例化。</p>
<h3>工厂与 Service Locator 不是结构修复</h3>
<p>Factory 每次 create 虽然延迟对象生成，但如果创建路径仍回到原服务，运行时依旧循环。只有业务流程天然需要新实例时使用 Factory；共享无状态服务应通过接口注入。把所有依赖都改成 Proxy/Factory 会让图更难理解。</p>
<h3>Observer/Command 分离</h3>
<p>两个服务互相调用常说明它们既做状态变更又做通知。可把核心写操作抽成 command，把后续反应发布事件或队列；事件处理器不得再次触发同一命令而无幂等保护。这样同时缩短事务并打破依赖。</p>
<h3>查生成代码不是改生成代码</h3>
<p>generated 中的 Interceptor/Factory 能帮助看最终类型，但不能直接编辑。修复源 di.xml/PHP 后清理生成目录重新编译，比较依赖图。部署产物必须由同一 composer.lock 和模块配置构建。</p>
<h3>用测试锁住依赖方向</h3>
<p>为拆分后的服务写构造测试和业务测试，保证接口依赖从高层业务指向稳定抽象。静态分析或架构测试可以禁止某些命名空间反向引用，避免下次改动再次形成 A&rarr;B&rarr;A。编译错误解决后，也要测异常路径与事务回滚。</p>
<h3>Area 配置差异也要检查</h3>
<p>frontend、adminhtml、webapi、graphql 可合并不同 di.xml，循环可能只在某个 area 的 preference/plugin 组合出现。编译会扫描更完整对象图，所以开发页偶尔正常并不能排除问题。分别运行受影响入口的集成测试，确认各 area 最终类型一致。</p>]]></description>
      <pubDate>Thu, 19 Dec 2024 03:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[可配置商品在一个 Store View 没有选项，另一个却正常]]></title>
      <link>https://www.360magento.com/blog/configurable-options-missing-store/</link>
      <description><![CDATA[<p>同一个可配置商品在中文 Store 可以选择颜色和尺码，英文 Store 却显示 &ldquo;Choose an Option&rdquo; 但下拉为空。父子关联通常是全局的，差异更多来自网站/Store 范围下子商品是否可售、属性选项标签是否存在，或主题生成配置 JSON 时过滤。</p>
<h3>先确认父子关联没有变</h3>
<p>在后台可配置商品的 Configurations 中查看关联简单商品，并确认它们分配到当前 Website。只在另一个 Website 有分配的子商品，不会成为当前 Store 的有效组合。</p>
<h3>检查 Store 级状态与属性值</h3>
<p>子商品 status 可能在目标 Store 被覆盖为禁用；颜色/尺码属性值也可能被导入为空。属性 option_id 应一致，Store View 只翻译 label。若翻译行缺失应回退默认标签，不应创建新的业务 option 代替翻译。</p>
<h3>库存筛选</h3>
<p>目标 Website 对应不同 Stock 时，所有子 SKU 可能在该 Stock 不可售。检查 sales channel、source、reservation 和&ldquo;Display Out of Stock Products&rdquo;配置。不要只看默认 Stock。</p>
<h3>查看页面的配置 JSON</h3>
<p>在页面源码或 Network 中找到 configurable 的 option/config 数据。JSON 已经没有子商品，问题在服务端集合与索引；JSON 正确而组件为空，查主题 JS、翻译字符和 mixin。这样比反复清缓存更快。</p>
<h3>索引与缓存</h3>
<p>重建 product EAV、price、inventory/search 相关索引可作为诊断；若重建后又失效，继续查增量触发。FPC/CDN 必须区分 Store 和必要上下文，不能把一个 Store 的空配置缓存给另一个。</p>
<p>修复后覆盖所有属性组合、缺货子项、两种语言、客户组价与加入购物车请求，确认选择的 simple SKU 正确。</p>
<h3>Super Attribute 配置</h3>
<p>父商品的 configurable attribute 必须属于属性集、用于创建 configurable，并与关联子商品的值对应。属性范围或 backend type 被修改后，一个 Store 的索引/缓存可能暴露异常。检查父商品 super attribute 记录，不要重新创建同 code 的第二个属性。</p>
<h3>价格缺失也会过滤组合</h3>
<p>某客户组/Website 的子商品 price index 缺行时，配置 JSON 可能排除该 SKU。对比 catalog_product_index_price 的 website_id/customer_group_id，并测试登录与匿名；如果只对一个客户组消失，问题不在翻译标签。</p>
<h3>导入流程</h3>
<p>CSV/ERP 更新子商品时要保留父子关联、网站分配和属性 option_id。用标签文本跨语言匹配容易创建错误值。导入后自动运行增量索引并抽查组合数量，防止一夜同步再次清空选项。</p>
<h3>对比两个 Store 的最小差异</h3>
<p>导出父商品、一个正常子商品和一个缺失子商品在两个 Store 的有效属性值、status、website、stock 与价格索引，做逐字段差异。不要一次重存全部商品，那会把问题暂时&ldquo;治好&rdquo;却丢掉根因，也可能覆盖翻译和人工配置。</p>]]></description>
      <pubDate>Wed, 18 Dec 2024 08:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[优惠券明明没人用，却提示 Usage limit has been reached]]></title>
      <link>https://www.360magento.com/blog/coupon-usage-limit-reached/</link>
      <description><![CDATA[<p>新建优惠券后少量测试，前台突然提示 <code>Usage limit has been reached</code>，后台列表看起来使用次数为零。Magento 同时存在规则总次数、单个 Coupon 次数和每客户次数，定制模块还可能在下单前预占，不能只看一个字段。</p>
<h3>先区分三个限制</h3>
<p>检查 Sales Rule 的 Uses per Customer、Coupon 的 Uses per Coupon，以及自动生成 Coupon 自身记录。没有登录的访客通常无法按 customer_id 精确限制，扩展可能改用邮箱或 Session。</p>
<pre><code>SELECT rule_id, code, usage_limit, usage_per_customer, times_used
FROM salesrule_coupon
WHERE code = 'TESTCODE';</code></pre>
<p>字段以实际版本结构为准，只读诊断。规则级使用统计还可能在其他表中。</p>
<h3>取消订单是否回退</h3>
<p>Coupon 一般在订单提交时计数；失败支付、取消、退款是否回退，取决于核心流程和扩展实现。按订单号追踪 applied_rule_ids、coupon_code 与状态历史，不能直接把 times_used 清零，否则可能让真实已用客户重复享受。</p>
<h3>并发最后一次额度</h3>
<p>两名客户同时使用仅剩一次的券时，简单&ldquo;先查次数再加一&rdquo;存在竞态。需要数据库原子更新/锁和幂等订单键。支付重试也不能为同一订单重复计数。</p>
<h3>客户记录不一致</h3>
<p>规则总次数未满，但某客户提示到限，检查 customer-rule usage 表是否因测试账号、网站范围或客户合并留下记录。多网站共享账号时，业务期望是全局一次还是每网站一次必须明确。</p>
<p>修复后测试访客、登录客户、最后一个名额的并发、支付失败、取消和重复回调。次数统计应可由订单审计解释，不能只让提示消失。</p>
<h3>规则 ID 与 Coupon ID 不要混淆</h3>
<p>一个 Sales Rule 可有大量自动 Coupon，每个 code 有独立 coupon_id。自定义统计若只按 rule_id 聚合，会把其他券使用次数算到当前 code；反过来只看 coupon 表会漏掉无券自动规则。对账需从订单 coupon_code、applied_rule_ids 和 usage 表建立对应。</p>
<h3>缓存与多节点</h3>
<p>使用次数更新到数据库后，某节点仍缓存旧 rule/coupon 对象，可能继续放行或错误拒绝。高并发限额必须以数据库原子条件为最终权威，缓存只能加速。规则变更后按支持方式失效缓存，并验证所有节点。</p>
<h3>恢复统计</h3>
<p>如果历史 times_used 已不一致，先从可确认的有效订单重算报表，列出差异和取消/失败策略，再以审计脚本修正。直接重置为零会改变促销成本和客户资格。</p>
<h3>错误文案可能掩盖真正条件</h3>
<p>第三方促销模块常把多种拒绝原因统一成 Usage limit reached，例如日期范围、客户组、网站或最小金额失败。对同一 quote 开启受控调试，记录规则逐条件结果，确认确实命中次数限制后再修统计，不能被前台一句提示带偏。</p>
<h3>高峰活动前做容量与竞态测试</h3>
<p>限量券最容易在秒杀流量下暴露并发问题。用多请求争夺最后几个名额，统计成功订单、失败订单与 times_used，三者必须能对账；再重复支付回调和取消流程，确认不会超发，也不会永久吃掉未成交额度。</p>]]></description>
      <pubDate>Tue, 17 Dec 2024 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[发布后商品图片全部 404，Magento 2 Image Cache 在哪一步断了？]]></title>
      <link>https://www.360magento.com/blog/product-images-404-after-deploy/</link>
      <description><![CDATA[<p>发布后商品页 HTML 正常，所有缩略图却 404。先不要重新上传商品图片：Magento 原图通常在 <code>pub/media/catalog/product</code>，前台 URL 可能指向按尺寸生成的缓存路径。原图存在而派生图缺失，与原图本身丢失是两类事故。</p>
<h3>从一个失败 URL 反查</h3>
<p>记录请求状态、响应服务器和路径；在媒体存储中找到对应原图。原图也不存在，检查共享存储挂载、发布脚本是否错误清理 media；原图存在，查派生生成、权限和 rewrite。</p>
<pre><code>bin/magento config:show web/unsecure/base_media_url
bin/magento config:show web/secure/base_media_url
find pub/media/catalog/product -type f -name 'example.jpg'</code></pre>
<h3>Media 不应跟 release 一起被替换</h3>
<p>蓝绿发布若每个 release 有独立 pub/media，却没有正确共享链接，新 release 会看到空目录。构建脚本可以清 pub/static，但不应递归删除客户上传的 media。核对软链接目标、挂载时机和运行用户。</p>
<h3>缓存生成需要写权限</h3>
<p>首次请求或预生成任务需要在 media cache 下创建目录和文件。PHP-FPM 用户与部署用户不一致、只读容器或 umask 错误，会导致 404/500。不要用 777 作为长期修复，应设置明确 owner/group 和最小写权限。</p>
<h3>Web server 与远程存储</h3>
<p>Nginx 示例配置会把不存在的缓存图交给 Magento 生成；自定义 location 顺序错误可能直接返回 404。使用对象存储/CDN 时，还要确认派生文件同步策略、origin path 和大小写。</p>
<p>修复后测试已有缓存图、新尺寸首次生成、后台上传新图、图片删除和 CDN purge。对比原图与派生图路径，确保下一次发布不会再次切断 media。</p>
<h3>数据库记录与文件路径</h3>
<p>查询 catalog_product_entity_media_gallery 及关联值，确认 value 路径与磁盘大小写完全一致。数据库有记录、文件缺失，可能是媒体迁移不完整；文件存在但记录指向旧扩展名，缓存生成也找不到。批量修复前导出 SKU&mdash;路径映射。</p>
<h3>缓存清理的正确范围</h3>
<p>删除派生缓存可以让 Magento 重建，但不要删除原图目录。大目录一次递归删除会产生 I/O 峰值，随后所有请求同时生成缩略图形成惊群。可在发布前按常用尺寸预热，并限制并发。</p>
<h3>图片处理依赖</h3>
<p>GD/Imagick 缺扩展、内存不足、超大原图或损坏 ICC 信息可能只让某些图片生成失败。查看 PHP 图像库、错误日志和单个原图尺寸，用问题文件在隔离环境复现，不能把全部 404 都归为权限。</p>
<h3>部署健康检查要覆盖一张新图</h3>
<p>只访问已有 CDN 缓存图无法发现源站生成权限问题。发布后上传或选择一张从未生成过目标尺寸的测试图片，请求缩略图并校验 Content-Type、尺寸和缓存头；随后删除测试数据。这样能同时验证 media 挂载、PHP 图像库、rewrite 与 CDN 回源。</p>]]></description>
      <pubDate>Mon, 16 Dec 2024 07:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[GraphQL 把 A 客户的数据缓存给 B 客户，Cache Identity 漏了什么？]]></title>
      <link>https://www.360magento.com/blog/graphql-customer-cache-leak/</link>
      <description><![CDATA[<p>A 客户登录后看到 B 客户的专属价格、愿望单或账户字段，这是安全事件，不是普通缓存过期。第一步应立即让所有带 Authorization、客户 Cookie 或私有字段的 GraphQL 请求绕过共享缓存，并 purge 已生成对象。</p>
<h3>确认泄露发生在哪一层</h3>
<p>用两个专门测试账号和匿名会话发送相同 query，比较响应头中的 Age、cache status、Vary、Cache-Control 与 request ID。若 CDN HIT 返回相同 body，重点在边缘规则；CDN bypass 仍串数据，查应用缓存和 Resolver 静态状态。</p>
<h3>公共 Query 与私有 Query 必须分开</h3>
<p>商品目录匿名查询可缓存，但只要结果受 customer group、共享目录、币种、store、购物车或客户 ID 影响，缓存键就必须包含正确上下文，或者完全禁止共享缓存。把 Authorization header 从 key 中剥离后 cache everything 是高危配置。</p>
<h3>Identity 不是客户隔离的万能键</h3>
<p>Cache identity 用于失效标签，不能替代访问控制。Resolver 仍需从受验证的 context 取得 user id，并确认请求实体属于该用户。绝不能信任客户端传入 customer_id 后直接加载。</p>
<h3>请求内缓存也会写错</h3>
<p>Data loader 若用 product_id 作为唯一键，却忽略客户组、网站或币种，同一请求中也可能返回错误价格。全局静态数组在长驻 PHP/Consumer 环境更危险，应把缓存限制在请求生命周期并覆盖全部业务维度。</p>
<h3>事件响应与回归</h3>
<p>保留脱敏证据、影响时间和缓存规则版本，按公司的安全与隐私流程评估通知。修复后在不同 POP、账号、客户组和 query 变量间交叉测试；公共目录仍可命中，任何私有结果都不得从另一身份缓存复用。</p>
<h3>立即止损后的缓存清理</h3>
<p>只修改规则不够，已缓存对象仍可能存活到 TTL。根据 CDN/FPC 的 purge 能力清除 GraphQL endpoint 对象，并轮换可能暴露的会话/token。不要为了省事清空所有基础设施缓存而破坏取证；先记录 key 规则、命中时间和受影响范围。</p>
<h3>查询持久化与 GET 请求</h3>
<p>Persisted query 或把 variables 放进 GET 时，CDN 更容易缓存响应。私有查询即使 operation name 相同，variables 与身份不同也不能共享。检查 POST 缓存规则、query hash 与 Authorization bypass，确保&ldquo;匿名目录缓存&rdquo;不会泛化到全部 GraphQL。</p>
<h3>服务端授权单测</h3>
<p>为 Resolver 写测试：匿名访问拒绝、客户 A 只能读取 A、管理员/Integration 按 ACL、伪造 customer_id 无效。缓存关闭和开启两套场景都要跑，因为权限正确但缓存错误仍会泄露。</p>
<h3>日志本身也要按敏感数据处理</h3>
<p>调试 GraphQL 时不要完整记录 Authorization、客户地址、邮箱、购物车 token 或响应 body。用查询哈希、字段名、客户测试账号代号和 cache key 摘要定位。事件结束后清理临时日志并缩短保留期，避免二次泄露。</p>
<h3>重新开放缓存要分阶段</h3>
<p>先仅对明确匿名、无客户上下文的目录 query 开启，观察命中与隔离测试，再逐步增加范围。每条规则都应有负面测试：带 token、客户组价、购物车、wishlist 的请求必须 bypass。不要一次恢复全局 cache everything。</p>]]></description>
      <pubDate>Fri, 13 Dec 2024 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台导出订单总是超时，Magento 2 Grid CSV 应该怎么拆？]]></title>
      <link>https://www.360magento.com/blog/order-grid-export-timeout/</link>
      <description><![CDATA[<p>在 Sales &rarr; Orders 选择一年数据导出 CSV，页面转圈后 504；把 PHP timeout 调大只能让请求占用 worker 更久。订单 Grid 导出通常同步加载筛选集合、格式化列并输出文件，自定义列的一对多 join 还可能放大行数。</p>
<h3>先证明慢在查询还是生成</h3>
<p>用一个月、一周、一天逐步缩小范围，记录 SQL 时间、结果行数、PHP 内存和生成阶段耗时。页面 Grid 快不代表导出快：导出可能绕过分页并执行不同 renderer。</p>
<h3>检查最终 SQL</h3>
<p>扩展把订单商品、地址或支付附加信息 join 到 Grid 时，可能让一张订单变多行并触发 DISTINCT/GROUP BY。用慢日志和 EXPLAIN 检查扫描行、临时表与排序；不要直接给所有字段加索引。</p>
<h3>分批要用稳定游标</h3>
<p>按 entity_id 或 created_at+entity_id 递增读取，每批固定数量，记录断点。大 OFFSET 越往后越慢，导出期间有新订单还会造成重复/遗漏。若需要严格快照，先固定最大 entity_id 和时间边界。</p>
<pre><code>WHERE entity_id &gt; :last_id
  AND entity_id &lt;= :max_id
ORDER BY entity_id ASC
LIMIT 1000</code></pre>
<h3>异步导出更适合大数据</h3>
<p>后台只创建任务，Consumer 分批生成到受保护存储，完成后通知管理员下载。文件应有短期有效期、权限校验和清理策略；订单 CSV 含客户信息，不能放在公开 pub 目录用可猜 URL 下载。</p>
<h3>资源参数只能作为容量保护</h3>
<p>适度提高内存/超时可辅助，但应配合批次释放集合、流式写 CSV 和限制最大范围。修复后用小、中、大三档数据验证行数、金额合计、字符编码和权限，确保性能优化没有漏单或重复订单。</p>
<h3>CSV 本身也要防公式注入</h3>
<p>订单中的姓名、公司、备注等用户输入若以 =、+、-、@ 开头，电子表格打开时可能当作公式执行。导出层应按安全策略转义，且保持 UTF-8/BOM 与分隔符一致。不要因为是后台管理员下载就忽略恶意订单数据。</p>
<h3>避免 N+1 格式化</h3>
<p>循环每行再加载 order repository、客户、商品或地址，会把一条导出变成数万次查询。让主查询批量选择所需列，对一对多数据先批量映射；敏感列只对有权限角色输出。记录 SQL 次数随行数的变化，比只看总时间更能确认优化。</p>
<h3>任务可恢复性</h3>
<p>异步导出中断后应从最后稳定游标继续或安全重跑，临时文件未完成不能对用户可见。最终文件生成后写校验和与行数，下载时再次检查任务所有者和有效期。</p>
<h3>导出字段要有明确口径</h3>
<p>&ldquo;订单金额&rdquo;可能是 grand_total、base_grand_total、已付或已退款；&ldquo;订单日期&rdquo;也有数据库 UTC 与后台时区之分。优化前先固定列定义、时区、币种和状态范围，用一小批人工对账样本做基准。否则性能变快后仍可能交付无法使用的数据。</p>
<h3>下载过程与生成过程分离</h3>
<p>文件生成完成后再开放下载，避免浏览器断线导致任务重做。反向代理可负责受控传输，但授权应由应用先验证；文件名不能暴露客户信息。管理员取消任务时只终止未完成批次，并清理临时文件与任务锁。</p>]]></description>
      <pubDate>Thu, 12 Dec 2024 06:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Bundle 商品价格显示为 0，Magento 2 是选项没配还是索引没算？]]></title>
      <link>https://www.360magento.com/blog/bundle-product-price-zero/</link>
      <description><![CDATA[<p>Bundle 商品详情页显示 0 元或 &ldquo;As low as 0&rdquo;，后台子商品明明有价格。Bundle 有 Fixed Price 与 Dynamic Price 两种模型，最终展示还取决于默认/必选选择、子商品可售性和价格索引，不能直接给父商品填一个价格就判断。</p>
<h3>确认 Price Type</h3>
<p>Fixed Price 使用父商品价格，再由选项做固定/百分比调整；Dynamic Price 汇总所选子商品价格。动态 Bundle 没有默认选择、所有选项非必选时，最低可选组合可能确实为零。先明确业务是否允许空组合。</p>
<h3>检查必选项与 Selection</h3>
<p>必选 option 必须至少有一个启用、分配当前网站且可售的 selection。子商品禁用、缺货、未分配 website 或价格范围错误，会让聚合结果缺失。数据库关系存在不代表当前 Store 可用。</p>
<h3>索引按 Website 和客户组计算</h3>
<pre><code>SELECT entity_id, website_id, customer_group_id,
       min_price, max_price, final_price
FROM catalog_product_index_price
WHERE entity_id = 1234
ORDER BY website_id, customer_group_id;</code></pre>
<p>索引中已是 0，回到 Bundle 配置、子价格和目录规则；索引正确而页面为 0，查 price renderer、FPC 和主题 JavaScript。手动 reindex 可诊断，但增量失效必须修 Cron/MView。</p>
<h3>税与币种不要混入根因</h3>
<p>含税显示、汇率和价格规则会改变数值，但通常不会把正常正价全部变成零。比较 base currency 未税 final price，先确定原始聚合是否正确，再处理展示。</p>
<p>修复后测试默认选择、切换选项、客户组价格、缺货 selection、购物车和订单行金额。详情页起价、选择后的动态总价与结账金额必须一致，不能只把页面上的 0 用模板条件隐藏。</p>
<h3>默认选择与最小价格</h3>
<p>动态 Bundle 的最低价不一定等于页面默认勾选组合。主题若先显示索引 min_price，JS 初始化后又计算默认选项，用户会看到价格跳变。业务若要求默认组合价格，应让展示文案明确&ldquo;起价&rdquo;或按默认选择计算，不能混用两套口径。</p>
<h3>目录规则与特殊价</h3>
<p>子商品 Special Price、Customer Group Price、Catalog Price Rule 都会进入动态聚合。规则刚更新而 price index backlog 未消费时，Bundle 可能仍显示旧/零值。按 website/customer group 检查索引，并修改一个子商品验证增量链路。</p>
<h3>选择配置数据</h3>
<p>查看前端 bundleConfig JSON 中 option、selection、price 数据。服务端 JSON 已缺价格，查产品类型 price model；JSON 正确而 UI 为零，查主题 mixin、格式化和币种转换。这样能把 PHP 与 JavaScript 问题分开。</p>
<h3>购物车金额才是最终事实</h3>
<p>价格区间用于列表和初始展示，真正加入购物车后由选项、数量、规则、税与币种重新计算。抓取 quote_item 的父子行和 option 数据，确认选择映射到正确 simple/bundle selection。若前端显示正常但购物车为零，问题已经不在 price renderer。</p>]]></description>
      <pubDate>Wed, 11 Dec 2024 02:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 在线退款和离线退款选错，会影响支付平台吗？]]></title>
      <link>https://www.360magento.com/blog/online-vs-offline-refund/</link>
      <description><![CDATA[<p>管理员创建 Credit Memo 时看到&ldquo;Refund Online&rdquo;和&ldquo;Refund Offline&rdquo;，如果选错，后台都可能显示已退款，但支付平台结果完全不同。在线退款调用支付模块的 refund/capture 交易；离线退款只在 Magento 记录财务变化，通常用于已经在外部完成退款或无需网关处理的场景。</p>
<h3>先确认订单支付能力</h3>
<p>支付方法是否支持 online refund、invoice 是否在线捕获、transaction 是否有可退款余额，决定按钮和执行。授权未捕获、已过退款期或网关交易 ID 缺失时，不能假设在线一定可用。</p>
<h3>退款前记录三组金额</h3>
<p>订单 paid/refunded、invoice 可退款、支付平台 captured/refunded。部分退款还要核对税、运费、折扣和手续费。币种站点同时记录 base 与 order currency，避免把汇率差当成少退款。</p>
<h3>网关超时是未知结果</h3>
<p>请求超时不代表退款失败，平台可能已受理。不要立刻重试；先按幂等键或交易查询接口确认。支付模块应保存网关 refund transaction ID，并使相同 Credit Memo 重放不会再次退款。</p>
<h3>离线退款的正确使用</h3>
<p>已经在支付后台人工退过款，再在 Magento 选择 Offline 记录对账是合理流程；若选择 Online，就可能重复退款。反过来，尚未在外部退款却选 Offline，客户不会收到钱。后台权限和操作提示应明确，敏感金额操作要有审核与历史。</p>
<h3>库存是独立决定</h3>
<p>Return to Stock 与在线/离线支付退款不是同一个开关。退钱可以不退货，退货入库也可能在仓库验收后发生。修复流程时分别设计财务、库存与邮件动作。</p>
<p>测试全额、部分、运费、外币、超时重试和已外部退款场景；最终 Magento Credit Memo、payment transaction 和平台账单三方金额一致，且同一退款事件只有一次。</p>
<h3>交易记录怎么对账</h3>
<p>查询 sales_payment_transaction，确认 txn_id、parent_txn_id、txn_type、is_closed 与附加信息。在线退款应产生与 capture 关联的 refund transaction；离线记录不应伪造网关 txn_id。支付扩展若把多个退款复用同一 ID，会导致后续查询和幂等失效。</p>
<h3>权限与审计</h3>
<p>只有授权角色可执行退款，金额、原因、操作者、时间和外部凭证要进入订单历史。高金额可增加双人审核。不要在 comment 中粘贴完整网关响应，其中可能含客户与商户敏感数据。</p>
<h3>Webhook 的后续更新</h3>
<p>有些网关退款先 accepted，稍后 Webhook 才确认 succeeded/failed。Magento 不应在 accepted 时永久标记最终成功，也不能让失败回调重复生成 Credit Memo。为退款建立状态机，并处理乱序、重复和部分成功。</p>
<h3>部分退款的数量和税费</h3>
<p>Credit Memo 可按商品数量、运费、调整退款和调整费用计算。网关通常只接收最终金额，不理解 Magento 的行级原因；金额、币种和小数精度必须与 capture 余额一致。多次部分退款之和不能超过已捕获金额，最后一次的舍入差额要可解释。</p>]]></description>
      <pubDate>Tue, 10 Dec 2024 08:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[OpenSearch 集群变 Red，Magento 2 搜索还能继续用吗？]]></title>
      <link>https://www.360magento.com/blog/opensearch-cluster-red/</link>
      <description><![CDATA[<p>监控显示 OpenSearch cluster status 为 red，Magento 分类页或搜索间歇 500。Red 表示至少一个 primary shard 未分配，不是简单的&ldquo;副本不足&rdquo;；依赖该主分片的索引可能无法查询或写入。</p>
<h3>先确定影响范围</h3>
<pre><code>GET /_cluster/health
GET /_cat/indices?v&amp;health=red
GET /_cat/shards?v&amp;h=index,shard,prirep,state,unassigned.reason,node</code></pre>
<p>只读获取集群状态，记录 Magento 当前别名指向哪些索引。不要看到 red 就删除全部索引，集群里可能还有其他应用数据。</p>
<h3>让集群解释为何不分配</h3>
<pre><code>GET /_cluster/allocation/explain
{
  "index": "affected_index",
  "shard": 0,
  "primary": true
}</code></pre>
<p>常见原因包括节点离线、磁盘超过水位、分片副本策略与节点数不匹配、索引数据损坏或 allocation filter。不同原因处理完全不同。</p>
<h3>磁盘满时先停止写入压力</h3>
<p>Magento 全量重建会创建新索引，短期占用旧索引之外的额外空间。磁盘已触发 flood stage 时反复 reindex 只会恶化。先释放可确认无用的快照/日志/旧索引，或扩容节点，再解除写保护并重建。</p>
<h3>是否可以由 Magento 重建</h3>
<p>目录搜索索引通常可由数据库重新生成，但前提是 red 的确只影响可重建 Magento 索引，并且集群恢复到可分配状态。先保留别名和索引清单，在维护窗口运行相关 indexer，确认新索引 green/yellow 且别名原子切换，再清理旧索引。</p>
<h3>恢复验证</h3>
<p>测试商品保存、增量索引、关键词搜索、分类筛选和排序；观察 unassigned shards、磁盘水位和 JVM/heap。Yellow 在单节点集群可能只是 replica 无处放，但 Red 不能作为稳定状态接受。最后补上节点、容量与快照告警，避免等前台报错才发现主分片丢失。</p>
<h3>快照与数据恢复边界</h3>
<p>如果 primary shard 因节点磁盘损坏且没有可用副本，重新分配空主分片会永久丢失该索引数据。对 Magento 可重建搜索索引可以从数据库重建；对非 Magento 索引必须从快照恢复。执行 allocation stale_primary 等危险操作前，先确认数据来源和可恢复性。</p>
<h3>分片设计</h3>
<p>大量小索引和过多 shard 会消耗 heap 与文件句柄；单个巨大 shard 又延长恢复。按商品规模、节点数与重建时间设计 shard/replica，而不是沿用默认值。Magento 部署生成的新索引也需要生命周期清理，避免旧版本一直占磁盘。</p>
<h3>应用侧降级</h3>
<p>搜索不可用时，是否允许分类页暂时使用有限数据库路径或展示维护提示，应提前设计。临时降级不能绕过价格、权限和库存过滤。错误必须可见，避免给客户返回空结果却显示&ldquo;没有商品&rdquo;。</p>
<h3>重建期间保护数据库与集群</h3>
<p>目录全量索引会同时读取大量商品数据并向 OpenSearch 批量写入。控制批次与并发，观察 reject、GC、磁盘和数据库负载；不要在交易高峰用多个节点同时触发相同 reindex。若别名切换前失败，旧索引应继续服务，并保留可诊断日志。</p>
<h3>确认 Magento 使用的是这一个集群</h3>
<p>后台配置、环境配置和容器 secret 可能指向不同 endpoint。命令行健康检查 green，而 PHP 实际连另一套 red 集群并不少见。用应用节点解析出的主机、端口、认证与索引前缀核对，输出时对凭据脱敏。</p>]]></description>
      <pubDate>Mon, 09 Dec 2024 01:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[cron_schedule 大量 Missed，服务器时间正常为什么任务仍迟到？]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-many-missed/</link>
      <description><![CDATA[<p><code>cron_schedule</code> 中大量状态变成 missed，主机时间、PHP 时区看起来都正常。Missed 的含义不是&ldquo;系统时间错误&rdquo;，而是调度器实际处理这条记录时，已经晚于其 <code>scheduled_at</code> 加允许寿命。</p>
<h3>先看迟到分布</h3>
<pre><code>SELECT job_code, status, COUNT(*) AS jobs,
       MIN(scheduled_at) AS oldest, MAX(scheduled_at) AS newest
FROM cron_schedule
WHERE created_at &gt; UTC_TIMESTAMP() - INTERVAL 6 HOUR
GROUP BY job_code, status
ORDER BY jobs DESC;</code></pre>
<p>只有一个 job missed，查该 Group 或任务；所有任务按同一时间段 missed，查系统 Cron 没运行、部署暂停或 PHP 资源耗尽。</p>
<h3>系统入口频率要匹配</h3>
<p>Magento 通常需要每分钟触发 cron:run。系统 crontab 写成每五分钟，而 schedule_lifetime 很短，任务自然在被扫描前过期。检查实际运行用户、环境 PATH、日志重定向和旧 release 的残留入口。</p>
<h3>长任务能拖住同 Group</h3>
<p>一个导出或同步占用数十分钟，后续任务排队。记录 executed_at 到 finished_at 的 P95，并考虑把独立业务放到单独 Cron Group、队列或分批任务。仅增加 lifetime 会让 missed 变少，却不会减少业务延迟。</p>
<h3>调度生成参数</h3>
<p>schedule_generate_every 与 schedule_ahead_for 控制何时生成未来记录，history 清理参数控制表规模。生成窗口太短且调度器中断，恢复后可能根本没有应执行记录；窗口过长又会堆积大量 pending。配置要与任务频率和故障恢复目标匹配。</p>
<h3>锁与多节点</h3>
<p>多个节点运行同一 Cron Group 必须共享正确锁；锁残留或本地锁不一致会出现一边不执行、一边争抢。结合进程列表、锁后端和 cron_schedule 判断，不能直接把 missed 全改 pending。修复后故意暂停系统入口数分钟再恢复，确认任务能按预期补跑或明确跳过，且不会重复执行业务动作。</p>
<h3>表太大也会拖慢调度</h3>
<p>cron_schedule 长期不清理，查询 pending 与插入未来记录会变慢。统计表行数、索引和 history cleanup 是否成功；清理应按状态和时间分批执行，不能在生产高峰 truncate，因为正在运行任务与诊断证据都会丢失。</p>
<h3>资源饥饿的证据</h3>
<p>把 missed 时间与 PHP-FPM/CLI 进程数、CPU、内存、I/O、MySQL 连接和队列积压对齐。CLI memory_limit 与 Web 不同，任务被 OOM kill 时可能没有正常 finished_at。系统日志中的 exit code 比 cron_schedule 一列更能说明原因。</p>
<p>对关键任务定义&ldquo;最晚完成时间&rdquo;和独立告警，例如库存同步迟到十分钟与 Sitemap 迟到一天的业务影响不同，不能只用统一 missed 数量阈值。</p>
<h3>任务的幂等决定能否补跑</h3>
<p>Missed 任务是否可以手工重跑，要看业务动作是否幂等。清缓存和生成报表通常可重复；扣库存、发券、推送订单若没有业务唯一键，补跑会产生第二次副作用。为关键 job 记录处理游标和唯一事件 ID，再制定补偿方案。</p>]]></description>
      <pubDate>Fri, 06 Dec 2024 06:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[一张订单收到两封发货邮件，Magento 2 是重复发信还是重复 Shipment？]]></title>
      <link>https://www.360magento.com/blog/duplicate-shipment-email/</link>
      <description><![CDATA[<p>客户反馈同一订单收到两封&ldquo;已发货&rdquo;邮件。不要先关闭邮件：两封邮件可能对应两张合法的部分发货，也可能是同一 Shipment 被重复发送，甚至后台真的重复创建了发货单并扣减库存。</p>
<h3>先对比邮件里的 Shipment 与 Tracking</h3>
<p>记录订单号、Shipment increment_id、发送时间、物流单号和邮件 Message-ID。两个不同 Shipment 需要检查是否为部分发货；同一 Shipment 内容相同，再查发送调用与队列。</p>
<pre><code>SELECT entity_id, increment_id, order_id, created_at, email_sent
FROM sales_shipment
WHERE order_id = 123
ORDER BY entity_id;</code></pre>
<h3>谁创建了 Shipment</h3>
<p>管理员、ERP/WMS、支付/物流 Webhook 和 Cron 都可能调用 shipment service。外部系统超时重试时必须以物流事件 ID 或订单&mdash;发货批次为幂等键。只检查 canShip 仍有并发窗口，两个请求可同时看到可发数量。</p>
<h3>同一实体被 send 两次</h3>
<p>自定义 observer 在 shipment save 后发信，同时标准流程也勾选 Email Copy，便会重复。异步邮件模式下，生产者重复入队或消费者在发送成功、确认消息前崩溃，也会再次投递。邮件发送本身难以回滚，应记录 shipment_id 与模板动作唯一键。</p>
<h3>不要仅依赖 email_sent</h3>
<p>两个进程同时读取 email_sent=0，都可能发送后再置 1。需要原子状态转换或可靠 outbox。若 SMTP 接受邮件后客户端超时，Magento 不知道是否成功，盲目重试也可能重复；可结合 Message-ID 与邮件服务日志判断。</p>
<p>修复后模拟外部回调重复、消费者中途终止、部分发货与管理员重发邮件。预期是合法的每张 Shipment 最多自动发送一次，人工重发有明确记录，库存和 shipment 数量始终正确。</p>
<h3>邮件副本与收件人配置</h3>
<p>后台 Sales Emails 可以配置 Send Shipment Email Copy To，并选择 Bcc 或独立邮件。客户邮箱同时出现在订单地址和 copy 列表时，可能收到两封不同 Message-ID。先核对收件人头与配置，不要把合法 Bcc 流程误判为重复任务。</p>
<h3>队列与 Outbox 对账</h3>
<p>为发信动作建立唯一业务键，例如 shipment_id + template_type + recipient，记录 queued/sent/failed 与 Message-ID。SMTP 响应成功后再崩溃时，系统可通过该记录判断是否需要人工核对，而不是自动无限重发。</p>
<h3>部分发货边界</h3>
<p>订单包含多仓或分批发货时，每张 Shipment 可以发送一封；客户觉得重复可能是模板没有列出本次发货商品。邮件标题和内容应包含 Shipment 编号、当次商品和物流号，使合法的多封邮件可区分。</p>
<h3>区分客户真的收到两封与后台显示两次</h3>
<p>邮件服务商可能对一次提交做重试或转发，Magento 日志也可能因同一个传输异常写两条。以收件箱完整邮件头、Message-ID、服务商事件 ID 和 shipment_id 关联，才能定位重复发生在应用、SMTP 中继还是收件方规则。</p>]]></description>
      <pubDate>Thu, 05 Dec 2024 03:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Composer 更新后 Magento 2 补丁不再适用，应该重做还是强行跳过？]]></title>
      <link>https://www.360magento.com/blog/composer-patch-no-longer-applies/</link>
      <description><![CDATA[<p>执行 Composer 安装或更新时，自定义补丁报 <code>Hunk FAILED</code>、<code>Cannot apply patch</code>。这不是应该自动忽略的噪声：补丁修改的上游文件已经不同，可能官方已修复，也可能代码结构变化后原补丁只应用了一半。</p>
<h3>先确认补丁解决的原问题</h3>
<p>记录补丁来源、适用包与版本、业务缺陷、测试用例和计划移除条件。没有这些信息的&ldquo;神秘补丁&rdquo;会成为每次升级的风险。对比新版本 release notes 与实际源码，判断修复是否已合入，而不是只看文件相似。</p>
<pre><code>composer show vendor/package
git apply --check path/to/fix.patch
git apply --stat path/to/fix.patch</code></pre>
<p>在干净的目标包副本上检查，不能直接修改 vendor 后再判断。Composer 安装目录通常不是业务源码仓库的一部分。</p>
<h3>三种正确处理</h3>
<p>上游已等价修复：删除补丁并运行原回归；问题仍在但代码移动：以新版本为基线重做最小补丁；模块已经不再使用相关路径：证明无影响后移除。不要用降低 fuzz、删除失败 hunk 或在脚本里永远返回成功来&ldquo;通过部署&rdquo;。</p>
<h3>重做补丁要保持最小</h3>
<p>只包含必要代码和测试，不混入格式化、调试日志或生成文件。补丁头记录目标版本与原因，CI 在 composer install 后验证目标行为。能通过 plugin/preference 安全扩展的业务改动，优先移出 vendor patch，减少升级冲突。</p>
<h3>生产发布边界</h3>
<p>补丁失败后部署必须停止，不能继续用半更新 vendor。构建产物应在独立目录完成并经过依赖锁文件验证，再切换流量。修复后从空 vendor 目录执行两次可重复构建，并测试与补丁直接相关的场景及核心结账流程。</p>
<h3>补丁顺序也会制造假冲突</h3>
<p>同一文件有多个补丁时，前一个改变上下文，后一个才失败。逐个在原始新版本上检查，再按声明顺序应用，确认是否应该合并。两个补丁修改同一方法但解决不同问题时，重做后的最终代码必须同时保留两项行为。</p>
<h3>锁文件与构建缓存</h3>
<p>composer.lock 未更新、插件缓存了旧 patch 文件或构建节点复用 vendor，可能让不同机器产生不同结果。CI 应从锁文件与空 vendor 构建，记录补丁哈希和实际包版本；产物推广到生产，不在生产服务器临时 composer update。</p>
<h3>回归范围</h3>
<p>除了原缺陷用例，还要运行该类周围的单元/集成测试和关键交易路径。补丁应用成功只说明文本匹配，不说明逻辑仍适配新 API。若新版本改变方法签名、返回类型或事务边界，旧修复可能编译通过却造成数据错误。</p>
<h3>给每个补丁设置退出条件</h3>
<p>在补丁清单写明：首次引入版本、覆盖包版本区间、对应测试和预计移除版本。升级评审时逐项判断，而不是让补丁永久累积。若官方实现与本地修复不同但目标相同，应以行为测试证明可移除，避免两套逻辑叠加。</p>
<h3>保留可逆的升级提交</h3>
<p>依赖升级、锁文件变化、补丁重做和业务代码修改应拆成可审查提交。这样可以精确比较补丁移除前后的行为，也能在验证失败时回退整个构建产物，而不是在线编辑 vendor。发布记录中保存包版本、补丁哈希与测试结果。</p>]]></description>
      <pubDate>Wed, 04 Dec 2024 08:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[重置密码链接刚收到就失效，Magento 2 Token 时间怎么算？]]></title>
      <link>https://www.360magento.com/blog/password-reset-token-expired/</link>
      <description><![CDATA[<p>客户点击刚收到的重置密码邮件，却提示链接已过期或 Token 无效。不要立即把 Token Lifetime 调到几天：如果链接复制错误、网站范围不匹配或服务器时钟漂移，再长的有效期也不会解决。</p>
<h3>检查邮件中的完整 URL</h3>
<p>比较邮件源码和浏览器最终地址，确认 token、customer id/email 参数没有被换行、转义或营销跟踪系统截断。不要在日志和聊天中公开真实重置链接，它在有效期内等同于账号恢复凭据。</p>
<h3>重复申请会让旧邮件失效</h3>
<p>客户连续点击&ldquo;忘记密码&rdquo;，通常只应使用最新一封。邮件队列延迟会造成先申请的邮件后到达，看起来像&ldquo;刚收到就失效&rdquo;。记录申请时间、邮件发送时间和客户 reset_at/token 更新时间，避免只看收件箱顺序。</p>
<h3>时间必须一致</h3>
<pre><code>date -u
mysql -e 'SELECT UTC_TIMESTAMP(), NOW();'
bin/magento config:show customer/password/reset_link_expiration_period</code></pre>
<p>应用、数据库和主机应使用可靠时间同步。Magento 以存储时间和配置计算过期，显示时区可以不同，但不能有实际时钟偏差。容器暂停恢复后时间异常也要检查。</p>
<h3>多网站账号范围</h3>
<p>密码重置链接来自网站 A，客户却打开网站 B；若客户账号按 Website 共享范围隔离，系统可能找不到对应客户。邮件模板 Base URL、Store 参数和反向代理 host 必须属于发起请求的网站。</p>
<h3>安全扫描器会不会消耗链接</h3>
<p>某些邮件网关会自动访问链接做安全检查。正常 GET 预览不应直接完成重置，但定制模块若把验证或 token 清除放在首次访问，就会被扫描器提前触发。检查访问日志 user-agent 与时间，并把状态改变放到用户提交新密码的 POST。</p>
<p>修复后测试单次申请、连续两次申请、队列延迟、跨网站和链接预览。成功重置后旧 Token 必须失效，且日志不能暴露新密码或完整 Token。</p>
<h3>数据库字段只能用于诊断</h3>
<p>客户实体中的 rp_token 与 rp_token_created_at 可以帮助确认最新申请时间，但不要复制完整 token 到日志，也不要手工延长某个客户的时间戳。手工修改会绕过安全审计，且可能与缓存/账号锁定状态不一致。</p>
<h3>邮件模板与编码</h3>
<p>自定义模板若对 URL 再做一次 urlencode、HTML escape 或添加跟踪参数，token 中的特殊字符可能变化。查看最终 href 属性，而不是邮件可见文字；客户端自动把长 URL 换行时，点击与复制行为也可能不同。</p>
<h3>安全回归</h3>
<p>验证 token 只能使用一次、改密后现有会话是否按策略失效、旧密码不能登录、同一 IP 的申请有合理限速。错误提示不应泄露邮箱是否注册；客户收到邮件与攻击者枚举账号是两个需要同时处理的问题。</p>
<h3>代理与 HTTPS 也可能改坏链接</h3>
<p>反向代理没有正确传递 Host 或 HTTPS 状态时，邮件会生成内部域名、HTTP 地址或错误 Store 的 Base URL。浏览器随后被跳转到另一个网站，token 参数可能在跳转规则中丢失。检查代理头、secure base URL 和最终 Location 链，并确保 token 不进入第三方分析日志。</p>]]></description>
      <pubDate>Tue, 03 Dec 2024 01:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[分类 URL Key 改完全部 404，Magento 2 Rewrite 为什么没生成？]]></title>
      <link>https://www.360magento.com/blog/category-url-key-404/</link>
      <description><![CDATA[<p>后台修改分类 URL Key 后保存成功，新 URL 404，旧 URL 也没有跳转。分类实体还在，问题发生在&ldquo;分类路径&mdash;请求路径&mdash;Store&rdquo;之间的 URL rewrite 生成链路。</p>
<h3>先确认改的是哪个 Store View</h3>
<p>分类 URL Key 可以有 store 级覆盖。默认范围改了，但某个 Store View 仍勾着旧的自定义值，新前台不会继承。确认分类属于当前网站使用的 Root Category，并在准确 store scope 查看 URL Key 与 URL Path。</p>
<h3>查询 Rewrite 是否存在</h3>
<pre><code>SELECT url_rewrite_id, entity_id, request_path, target_path,
       redirect_type, store_id, is_autogenerated
FROM url_rewrite
WHERE entity_type = 'category' AND entity_id = 42
ORDER BY store_id, url_rewrite_id;</code></pre>
<p>没有新 request_path，说明生成阶段失败或被插件跳过；有记录但 store_id 不对，属于范围问题；有正确记录仍 404，再查 Web server、store code 路由和缓存。不要手工插入一行就结束，下一次分类保存会再次覆盖。</p>
<h3>重复路径会阻止生成</h3>
<p>同一 Store 下 CMS 页面、商品、分类或自定义 rewrite 占用了目标 request_path，保存时应有冲突提示，但批量导入和旧扩展可能留下异常记录。先找出占用者，决定谁应该保留；不要直接删除未知 rewrite，可能影响线上入口。</p>
<h3>旧 URL 是否生成 301</h3>
<p>&ldquo;Create Permanent Redirect for Old URL&rdquo;决定修改时是否保留旧地址跳转。它不能修复新地址 404，只负责旧 request_path。SEO 上应确认旧地址一跳到新地址，避免 301 链和全部跳首页。</p>
<h3>重新生成要使用支持的流程</h3>
<p>核心版本并没有一个适用于所有 URL 的通用&ldquo;reindex url_rewrite&rdquo;命令。可在测试环境重新保存分类或使用当前版本/扩展明确支持的再生工具；执行前备份并检查规模。修复后测试新 URL 200、旧 URL 301、canonical 指向新 URL、Sitemap 更新，并在两个 Store View 分别验证。</p>
<h3>层级路径会影响子分类</h3>
<p>父分类 URL Key 改变时，配置可能要求重新生成所有子分类与商品路径。目录很大时保存超时，部分 rewrite 已更新、部分仍旧，便会出现局部 404。按父分类路径抽样子分类和商品，统计新旧 request_path 数量，不能只验证父页面。</p>
<h3>Web Server Rewrite 仍要工作</h3>
<p>数据库记录正确但请求没有进入 Magento，检查 Nginx/Apache 的 try_files、子目录 Base URL、尾斜杠和 store code。直接访问 target_path 能开并不能证明 SEO URL 路由正常。CDN 若缓存旧 404，修复后需要精确 purge，新 URL 的 404 TTL 不应过长。</p>
<p>为防止再次发生，可在分类保存或发布后运行 URL 健康检查：验证状态码、跳转次数、canonical 和 store 对应关系，并对重复 request_path 阻止上线。</p>
<h3>不要用跳转首页掩盖 404</h3>
<p>把所有旧 URL 统一 301 到首页会变成软 404，也丢失分类主题相关性。找不到一一对应的新地址时应保留明确 404/410；存在新分类时才做精确跳转。上线后从访问日志提取高频旧路径，逐条校验状态码与落地页。</p>]]></description>
      <pubDate>Mon, 02 Dec 2024 07:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[结账页突然没有任何支付方式，Magento 2 先查哪些条件？]]></title>
      <link>https://www.360magento.com/blog/checkout-no-payment-methods/</link>
      <description><![CDATA[<p>结账页正常加载地址和运费，进入付款步骤却没有任何选项，或只显示 <code>No Payment Methods</code>。支付方式不是简单的&ldquo;启用/禁用&rdquo;开关：Magento 会结合当前 store、国家、币种、订单总额、客户组、配送方式和支付模块自身验证逐个筛选。</p>
<h3>先看 payment-information 之前的接口</h3>
<p>在 Network 中找到 payment-methods 或 shipping-information 响应。若接口 500，页面空白只是前端结果；先查响应 message、exception.log 和支付模块日志。若返回 200 且数组为空，说明所有 method 都被业务条件排除。</p>
<h3>配置范围最容易看错</h3>
<p>在 Stores &rarr; Configuration 切到发生问题的 Website/Store View，检查 method enabled、适用国家、最小/最大订单金额、允许币种和 sort order。默认范围显示启用，不代表子范围没有覆盖。保存后确认配置缓存已刷新。</p>
<pre><code>bin/magento config:show payment
bin/magento cache:clean config</code></pre>
<p>完整 payment 配置可能包含敏感商户参数，不要把命令输出原样发到工单或文章；只检查必要键并脱敏。</p>
<h3>用 Quote 数据还原筛选条件</h3>
<p>记录 quote 的 store_id、base_currency_code、quote_currency_code、grand_total、billing/shipping country 和 customer_group_id。优惠把总额降到零后，某些网关会隐藏而 Zero Subtotal Checkout 应接管；虚拟商品没有配送地址，依赖 shipping country 的自定义验证也可能误判。</p>
<h3>第三方模块可能在 isAvailable 中失败</h3>
<p>支付模块常在可用性检查时访问 API、读取 vault token 或验证地区。网络超时若被捕获后直接返回 false，前端只会看到方法消失。为每个 method 记录&ldquo;被哪个条件排除&rdquo;，比只记录最终空数组更容易维护，但日志不能包含卡号、token 或完整客户地址。</p>
<h3>验证矩阵</h3>
<p>分别测试访客/登录客户、国内/国外地址、零元/正常/超限金额、默认/外币、实体/虚拟商品。修复后应只有不满足条件的方法隐藏，至少一个合法方式可用；不能通过删除所有限制让原本不支持的交易进入网关。</p>
<h3>支付方法排序与前端状态</h3>
<p>接口已经返回 method，但 Knockout 组件注册失败、method code 与 renderer 映射不一致时，界面仍为空。检查 <code>renderer-list</code>、RequireJS 错误和自定义 checkout mixin；不要在 Console 里手工推入一个 method 后就判定后端正常，因为真实提交还需要 payment data 与 additional_data。</p>
<h3>生产排查的安全边界</h3>
<p>支付配置可能含 merchant ID、签名密钥和网关 URL。日志只保留 method code、可用性条件和脱敏 request ID，不能记录卡号、CVV、完整 token。若某方式只在生产消失，在网关沙箱复现同一金额/地区，并确认生产账号能力与币种已开通。</p>
<p>最后还要完成一次真实测试支付、失败支付和返回结账页，确认方法不仅出现，而且订单、transaction 与状态都正确。</p>
<h3>从一次失败请求建立证据链</h3>
<p>保留测试 quote ID、store、customer group、币种、金额和地址国家，再按同一组条件复现。配置截图只能说明&ldquo;现在看起来启用&rdquo;，不能说明请求当时通过了所有检查。若启用了配置分离或环境变量覆盖，还要确认运行节点读到的最终值一致。</p>]]></description>
      <pubDate>Fri, 29 Nov 2024 02:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据库 Deadlock 频发，从订单保存和索引任务找竞争点]]></title>
      <link>https://www.360magento.com/blog/database-deadlock-order-index/</link>
      <description><![CDATA[<p>日志出现 <code>Deadlock found when trying to get lock; try restarting transaction</code>，请求重试后可能成功，所以问题很容易被忽略。偶发死锁是并发数据库可以预期的现象，应用应有限重试；但同一表、同一路径持续出现，通常说明事务过长或两个流程以相反顺序锁定资源。</p>
<h3>先保存最近一次死锁图</h3>
<pre><code>SHOW ENGINE INNODB STATUSG</code></pre>
<p>找到 LATEST DETECTED DEADLOCK，保存两个事务的 SQL、持有锁、等待锁、索引名和线程信息。状态只保留最近一次，生产可配置把全部死锁写入错误日志，但要评估日志量和敏感 SQL。</p>
<p>不要只看被回滚的事务。MySQL 选择代价较小的一方作为 victim，真正需要优化的也可能是另一方。</p>
<h3>订单链路为什么容易冲突</h3>
<p>提交订单同时更新 quote、sales sequence、inventory reservation、payment transaction 和订单表；支付 Webhook、Cron 与管理员操作又可能并发处理同一订单。自定义 observer 在事务里调用外部 API，会把数据库锁持有到网络返回，显著扩大冲突窗口。</p>
<h3>索引和批处理的影响</h3>
<p>全量索引、价格规则、批量导入在高峰运行，会扫描或更新大量行。它们不一定直接锁 sales_order，但可能争用库存、产品关系和 changelog。检查死锁 SQL 中的实际表与索引，不能因为时间上同时运行就认定索引是原因。</p>
<h3>统一锁顺序，缩短事务</h3>
<p>多个实体更新时按稳定主键顺序处理；批量任务分小批提交；外部 HTTP 放到事务外或可靠队列；确保 WHERE 条件使用合适索引，避免锁住远多于目标的记录。先在预发布用 EXPLAIN 与并发测试验证，增加索引也会提高写成本。</p>
<h3>重试必须知道操作是否幂等</h3>
<p>数据库事务被回滚后可以重新执行，但外部支付捕获、邮件和 ERP 请求可能已经发生。将外部副作用与本地事务分离，用事件 ID/业务键去重。对 deadlock 进行有限次数、带抖动的重试，超过阈值进入可观察失败队列，不要无限循环占满 worker。</p>
<h3>验证修复</h3>
<p>用与生产相同的并发模式复现：两单争抢同一 SKU、Webhook 与管理员同时更新订单、导入与增量索引重叠。比较修复前后的 deadlock 次数、事务时长、锁等待和业务重复数。真正完成的标准是竞争窗口缩小、有限重试可控，并且没有重复扣款、开票或库存。</p>
<h3>锁等待与死锁不是同一个告警</h3>
<p>Lock wait timeout 表示等待超过阈值，不一定形成循环；Deadlock 是事务互相等待并被数据库立即选出牺牲者。两者都可能来自长事务，但证据不同。把错误类型、SQL 指纹、表与索引分别统计，避免用同一条&ldquo;增加超时&rdquo;建议处理。提高 lock wait timeout 只会让 worker 等得更久，不能解除循环依赖。</p>
<p>如果死锁只在特定扩展启用后出现，先在预发布用相同并发关闭其 observer/plugin 对比，再根据死锁图修改事务边界。不要在生产直接禁用支付或库存模块做试验；应保持可回滚变更并监控订单完整性。</p>
<h3>索引选择会改变锁的范围</h3>
<p>UPDATE/DELETE 的 WHERE 条件没有合适索引时，InnoDB 可能扫描并锁住远多于目标的记录。查看死锁日志里的 index name，再用 EXPLAIN 分析相同条件。复合索引列顺序要匹配过滤方式；仅添加多个单列索引未必能缩小锁范围。</p>
<h3>Gap Lock 与隔离级别</h3>
<p>范围查询、外键检查和不存在行的插入可能涉及 gap/next-key lock。不要为了减少死锁直接改变全局事务隔离级别，这会影响一致性语义。先把范围缩小、统一访问顺序、减少事务内无关读取，再在数据库副本验证隔离级别调整对 Magento 核心流程的影响。</p>
<h3>订单号和库存是两个热点</h3>
<p>高并发下 sales sequence 行、同一 SKU reservation/source item、同一订单 payment 记录都可能成为热点。按死锁图分类统计，而不是把所有 1213 错误归到一个工单。不同热点需要不同修复：序列配置、库存幂等和订单级串行化不能互相替代。</p>]]></description>
      <pubDate>Thu, 28 Nov 2024 08:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品属性 Scope 改错后数据乱了，Global、Website、Store View 怎么修？]]></title>
      <link>https://www.360magento.com/blog/attribute-scope-data-wrong/</link>
      <description><![CDATA[<p>一个自定义商品属性原本是 Store View 范围，后来改成 Global。后台默认视图显示正确，英文店铺却仍出现旧值；反向从 Global 改成 Store View 后，又发现所有店铺暂时相同。Scope 不是简单的界面开关，它决定 Magento 从哪些 store_id 行读取和回退。</p>
<h3>先确认属性与值表</h3>
<pre><code>SELECT attribute_id, attribute_code, backend_type
FROM eav_attribute
WHERE attribute_code = 'custom_label';

SELECT is_global
FROM catalog_eav_attribute
WHERE attribute_id = 123;</code></pre>
<p><code>is_global</code> 的具体常量值应以代码定义为准，不要凭记忆直接 UPDATE。backend_type 决定值在 varchar、int、decimal、text 或 datetime 表。</p>
<h3>Store View 覆盖如何残留</h3>
<pre><code>SELECT entity_id, store_id, value
FROM catalog_product_entity_varchar
WHERE attribute_id = 123
ORDER BY entity_id, store_id;</code></pre>
<p>store_id=0 是默认值，其他行是覆盖。Scope 改为 Global 后，旧覆盖行可能仍在数据库，当前读取逻辑可能忽略它们，但以后再次改范围或某个导入脚本按 store 写入时会重新暴露。</p>
<h3>Website Scope 不是直接用 website_id 存值</h3>
<p>EAV 商品值仍通过 store_id 表达，网站级写入通常落在网站默认 store 的语义中，由 Magento 服务层处理。手工按 website_id 插入 EAV 行是错误做法。价格等特殊属性还有索引与计算逻辑，不能照搬普通文本属性迁移。</p>
<h3>先定义保留哪一个值</h3>
<p>从 Store View 收敛到 Global 时，不同店铺可能有不同业务内容，必须由业务决定使用哪个作为默认值；不能简单选择最新一行。扩大到 Store View 时，通常保留 store_id=0 作为回退，只在确实不同的店铺建立覆盖。</p>
<h3>通过服务层或数据补丁迁移</h3>
<p>先导出 attribute_id、entity_id、SKU、store_id、旧值；在预发布生成转换计划；通过 Magento repository/import 或经过审计的数据补丁更新。变更属性定义后重建相关 EAV/搜索/价格索引并清理精确缓存。直接删除所有非零行不可逆，也可能丢掉翻译内容。</p>
<p>回归测试至少选择有覆盖、无覆盖、多个 Website 和可配置商品各一个。分别在默认、网站与 Store View 范围保存并读取，确认后台&ldquo;Use Default Value&rdquo;行为、前台展示和 API 返回都一致。</p>
<h3>导入模板必须同步 Scope 设计</h3>
<p>属性迁移正确后，旧 CSV/ERP 作业仍可能按 store_view_code 写入，从而重新制造覆盖。更新字段映射与导入说明，明确空值是&ldquo;清除覆盖&rdquo;还是&ldquo;保持不变&rdquo;。先用少量 SKU 验证导入，再检查 EAV 表的 store_id 分布，不能只看默认后台视图。</p>]]></description>
      <pubDate>Wed, 27 Nov 2024 05:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[消息队列 Consumer 一直重启，是 max-messages 设置还是内存泄漏？]]></title>
      <link>https://www.360magento.com/blog/consumer-keeps-restarting/</link>
      <description><![CDATA[<p>监控显示某个 Magento Consumer 每隔几分钟出现一个新 PID，运维判断为&ldquo;进程不稳定&rdquo;。但 <code>--max-messages</code> 本来就会让 Consumer 处理到指定数量后正常退出，再由 Supervisor 拉起。需要先看退出码、处理消息数和内存曲线，不能仅凭 PID 变化。</p>
<h3>正常轮换是什么样</h3>
<p>进程处理固定数量消息，退出码为 0，日志没有异常，Supervisor 按配置重新启动；每轮耗时随队列流量变化。这种轮换能释放长进程积累的内存。max-messages 太小会频繁启动，太大又可能让泄漏持续放大，需要按启动成本与内存稳定性选择。</p>
<pre><code>bin/magento queue:consumers:start consumer.name --max-messages=500
supervisorctl status
journalctl -u supervisor --since '30 minutes ago'</code></pre>
<p>命令名称与服务管理方式以当前环境为准。</p>
<h3>OOM Kill 的证据在系统层</h3>
<p>进程突然消失、应用没有完整异常，退出码 137 或系统日志出现 killed process，优先查容器/主机内存限制。记录 RSS 随处理消息数是否持续增长；如果每条消息后不回落，检查静态缓存、大对象数组、未释放集合和第三方 SDK。</p>
<h3>毒消息造成固定点崩溃</h3>
<p>每次重启后立刻处理同一消息并异常，队列长度不下降，说明某条 payload 可重复触发失败。记录 message ID、topic、重试次数和脱敏错误，把它送入失败队列或隔离后修消费者。直接删除整队列会丢掉正常业务。</p>
<h3>数据库与 Broker 断线</h3>
<p>长连接经过空闲超时后失效，下一条消息可能抛 connection gone away；RabbitMQ heartbeat、网络设备超时和 MySQL wait_timeout 都要对齐。消费者应能在可恢复错误后重连，但不能对已部分执行的业务无限重试，幂等键仍然必要。</p>
<h3>一张判断表</h3>
<p>退出码 0 且固定消息数：正常轮换；137 且内存顶格：OOM；固定 payload 重现：毒消息；随机网络异常：连接与重试；启动即退出且无消息：命令、权限或配置。修复后同时观察处理速率、队列积压、RSS 和重启原因，不能只把 Supervisor 的 restart 次数清零。</p>
<h3>优雅停止避免重复消费</h3>
<p>部署或扩容时给 Consumer 足够时间完成当前消息并确认 ack。强制 kill 发生在业务已写库、消息尚未确认之间时，Broker 会重新投递；消费者若没有幂等保护，就会重复发邮件、扣积分或推 ERP。测试 SIGTERM、进程超时和重启流程，确认未完成消息能安全重试。</p>
<h3>确认 Cron 不在重复启动同一 Consumer</h3>
<p>Magento 的 consumers runner、Supervisor、Kubernetes Deployment 可能同时管理进程。如果三处都启用，就会产生超出预期的并发和重启日志。列出每个 consumer 的唯一主管理器、期望副本数与启动参数；扩容应改这一处，而不是在多个系统分别增加进程。</p>
<p>同一队列提高并发前还要确认处理顺序是否有业务要求。订单状态事件若乱序消费，吞吐提高反而会制造回退。</p>]]></description>
      <pubDate>Tue, 26 Nov 2024 01:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[XML Sitemap 里还有已禁用商品，索引和缓存谁没有更新？]]></title>
      <link>https://www.360magento.com/blog/sitemap-disabled-products/</link>
      <description><![CDATA[<p>后台把商品禁用后，前台 URL 已经 404，但 XML Sitemap 里几天后仍有它。Sitemap 是生成的静态文件，不会在每次商品保存时逐行更新。首先要确认看到的是哪一个文件、最后何时生成，以及是否被 CDN 缓存。</p>
<h3>确认商品在目标 Store 的真实状态</h3>
<p>Magento 的 status、visibility 和 website assignment 有范围。管理员在一个 store view 禁用，不代表另一个 sitemap 对应的 store 也禁用；只从分类移除也不会让商品自动退出 sitemap。用正确 store scope 检查状态与网站分配。</p>
<h3>看文件，不只看后台&ldquo;成功&rdquo;</h3>
<p>检查 Sitemap 配置的路径、文件名、后台 Last Generated At 与服务器文件 mtime。多节点部署若生成到本地磁盘，Cron 在节点 A 写入，Web 流量在节点 B 读取旧文件。应使用共享存储或把生成与发布设计成一致流程。</p>
<pre><code>stat pub/sitemap.xml
grep -n 'old-product-url' pub/sitemap.xml
bin/magento cron:run</code></pre>
<p>大文件 grep 要控制资源；若 Sitemap 是索引文件，还要继续检查对应子文件。</p>
<h3>CDN 可能继续返回旧对象</h3>
<p>比较源站文件与公网响应的 Last-Modified、ETag、Age 和内容。生成任务完成后应 purge 精确 sitemap URL 或设置合理短 TTL。URL 带同名但 CDN 忽略 query 的&ldquo;版本参数&rdquo;不一定能绕过缓存。</p>
<h3>生成失败会保留旧文件</h3>
<p>Cron 运行到一半遇到权限、磁盘或数据库错误时，旧文件可能继续存在，管理员只看到线上可访问而误以为更新成功。查看 cron_schedule messages、系统日志与临时文件。可靠做法是在临时路径完整生成后原子替换，避免爬虫读到半个 XML。</p>
<h3>搜索引擎移除还有延迟</h3>
<p>从 Sitemap 删除不会立刻清除已收录 URL。已下架且无替代商品时返回合适 404/410；有明确替代时使用一对一 301。不要把所有下架商品重定向首页。修复后重新生成，确认目标 URL 不在任何 sitemap 子文件，并在站长平台观察重新抓取。</p>
<h3>分片 Sitemap 要核对索引引用</h3>
<p>大型目录常把商品、分类和 CMS 拆成多个文件。旧子文件即使不再被 sitemap index 引用，仍可能通过固定 URL 被爬虫访问；反过来，新子文件生成了但 index 仍指向旧名称，也不会生效。生成任务完成后校验 XML 格式、URL 数量、lastmod 和所有子文件的可访问状态。</p>
<h3>Canonical 与 Sitemap 必须表达同一版本</h3>
<p>多 Store、HTTP/HTTPS 或尾斜杠配置不一致时，Sitemap 可能输出一个 URL，页面 canonical 却指向另一个。即使商品状态正确，也会浪费抓取并产生重复信号。抽样比较 Sitemap URL、最终跳转、HTTP 状态与 canonical，确认 host、协议和路径格式一致。</p>
<p>生成任务还应排除需要登录、noindex 或仅对特定客户组可见的页面。Sitemap 是希望被索引的 URL 清单，不是站内所有路由的导出。</p>]]></description>
      <pubDate>Mon, 25 Nov 2024 07:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 API 返回 401 和 403，到底是 Token 失效还是 ACL 不够？]]></title>
      <link>https://www.360magento.com/blog/api-401-vs-403/</link>
      <description><![CDATA[<p>同一个 REST 请求在测试环境返回 401，换一个 Token 后变成 403。两者都叫&ldquo;没权限&rdquo;，但定位层级不同：401 通常说明认证凭据缺失、过期或无法验证；403 通常说明系统已经知道你是谁，却不允许访问目标 ACL 资源。</p>
<h3>401 先查请求有没有正确携带身份</h3>
<p>确认 <code>Authorization: Bearer ...</code> 没被反向代理剥离，Token 没有多余空格，调用域名与环境匹配。管理员 Token、客户 Token 和 Integration OAuth 的适用端点不同，不能互换。</p>
<pre><code>curl -i -H 'Authorization: Bearer REDACTED'   'https://www.example.com/rest/V1/store/storeConfigs'</code></pre>
<p>不要在终端历史、工单或文章中保存真实 Token。日志只记录哈希片段和请求 ID。</p>
<h3>403 查 Web API resource ACL</h3>
<p>打开目标模块的 <code>webapi.xml</code>，查看 route 对应 resource。Integration 在后台选择的资源必须包含它；修改权限后重新授权/激活流程是否需要生成新 Token，取决于集成类型。自定义接口若把 resource 写错或引用不存在 ACL，也会一直 403。</p>
<h3>客户身份还有业务级授权</h3>
<p>客户 Token 只能访问自己的购物车、订单和地址。尝试读取另一个 customer_id，即使 ACL 名称相同，也应被拒绝。不要为了让移动端工作把接口 resource 改成 anonymous，这会把数据暴露给所有人。</p>
<h3>WAF 与代理可能伪装状态码</h3>
<p>响应体不是 Magento JSON、响应头带边缘 request ID，说明 401/403 可能来自 CDN、Basic Auth 或 WAF。比较应用日志是否出现同一请求，确认请求有没有到 Magento。浏览器 CORS preflight 的 403 也与 API Token 权限不同。</p>
<h3>建立最小权限测试</h3>
<p>用同一身份先调用一个确定允许的端点，再调用目标端点；用只读与写入请求分别测试。修复后撤销临时全权限，重新用最小 Integration 资源验证。最终不仅要返回 200，还要证明 Token 无法访问未授权资源。</p>
<h3>接口版本与 Store Code 也会改变结果</h3>
<p><code>/rest/default/V1/...</code> 与其他 store code 可能进入不同网站范围，自定义授权插件会据此限制资源。确认调用方没有把环境 Base URL、store code 或 API 前缀写死。端点不存在通常应是 404，但某些安全层会统一返回 403，因此仍需结合 Magento 路由日志判断。</p>
<p>自动化测试应覆盖 Token 过期、被撤销、权限减少和跨客户访问，防止升级后把原本的 403 变成数据泄露。</p>
<p>调用方对 401 可以触发一次受控的重新认证，对 403 则不应无限刷新 Token；权限不足不会因换一个同身份 Token 自动消失。把两种状态都当成&ldquo;重新登录&rdquo;会形成请求风暴，也会掩盖 Integration ACL 的真实缺口。</p>]]></description>
      <pubDate>Fri, 22 Nov 2024 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[sales_order 已经有数据，Magento 2 订单 Grid 为什么迟迟不更新？]]></title>
      <link>https://www.360magento.com/blog/sales-order-grid-not-updated/</link>
      <description><![CDATA[<p>支付成功、订单邮件也发出，直接用订单 ID 打开详情正常，但后台 Sales &rarr; Orders 列表没有这张订单。后台 Grid 为了查询速度使用扁平化表 <code>sales_order_grid</code>，它与主表 <code>sales_order</code> 不是同一张；异步更新或扩展写入失败时，两者会暂时分叉。</p>
<h3>先做主键差集</h3>
<pre><code>SELECT o.entity_id, o.increment_id, o.created_at, o.status
FROM sales_order AS o
LEFT JOIN sales_order_grid AS g ON g.entity_id = o.entity_id
WHERE g.entity_id IS NULL
ORDER BY o.entity_id DESC
LIMIT 50;</code></pre>
<p>只有一两张最近订单缺失，可能是队列延迟；持续累积说明更新链路停止。Grid 有记录却后台看不到，则检查筛选器、权限、store scope 和 Grid 数据值。</p>
<h3>同步还是异步更新</h3>
<p>Magento 可配置 Grid 异步索引。异步时依赖 Cron/消息队列按计划把主表数据复制到 Grid。检查相关配置、cron_schedule、消费者状态和失败日志。不要把异步关闭当唯一修复；高订单量站点同步更新可能增加结账延迟。</p>
<h3>自定义 Grid 列常让整次插入失败</h3>
<p>扩展给 sales_order_grid 添加列，并通过 join/observer 填值。列 NOT NULL 却没有默认值、字符串超长、join 返回多行或 schema 未在所有节点升级，会导致更新异常。对照最近部署与异常堆栈，查看 <code>SHOW CREATE TABLE sales_order_grid</code> 和模块 declarative schema。</p>
<h3>重建前先评估规模</h3>
<p>某些版本提供相应索引/同步命令，扩展也可能提供 repair。全表重建会产生大量写入和锁，不能在订单高峰直接执行。先在副本确认耗时和磁盘，备份缺失范围，再按官方支持方式补齐。</p>
<p>不要用 <code>INSERT ... SELECT *</code> 手工复制，两表字段和扩展列并不完全一致，也会绕过转换逻辑。</p>
<h3>验证增量链路</h3>
<p>补齐历史记录后新建一张测试订单，记录 sales_order 写入时间、Grid 出现时间与队列处理时间。再执行取消、开票等状态变更，确认 Grid 状态同步。修复历史而不验证新订单，只会让问题隔天再次出现。</p>
<h3>Grid 延迟要有可量化阈值</h3>
<p>异步模式并不要求零延迟，但应定义可接受范围，例如订单创建后若干分钟内出现，并对差集数量与最老缺失时间告警。单看消费者&ldquo;正在运行&rdquo;不够；它可能不断失败又重启。监控应同时覆盖成功处理速率、失败消息和主表&mdash;Grid 差集。</p>
<p>后台 Grid 的书签和保存视图也可能隐藏记录。先清除日期、店铺和状态筛选，再用 increment_id 搜索；若 SQL 表中有行而 Grid UI 仍不显示，检查 UI component data provider 与管理员角色范围，不要继续重建数据库表。</p>]]></description>
      <pubDate>Thu, 21 Nov 2024 08:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[优惠码提示使用成功，购物车总价却一分钱没变]]></title>
      <link>https://www.360magento.com/blog/coupon-success-total-unchanged/</link>
      <description><![CDATA[<p>页面提示&ldquo;优惠券代码已应用&rdquo;，Coupon 输入框也保留了代码，但订单摘要没有折扣。这条成功消息只可能说明代码被写进 Quote，不一定说明规则最终对任何商品产生折扣。</p>
<h3>先看 Quote 是否真的有折扣</h3>
<pre><code>SELECT entity_id, coupon_code, subtotal, subtotal_with_discount,
       grand_total, applied_rule_ids
FROM quote
WHERE entity_id = 123;

SELECT item_id, sku, qty, row_total, discount_amount, applied_rule_ids
FROM quote_item
WHERE quote_id = 123;</code></pre>
<p>Quote 有 coupon_code、applied_rule_ids 为空，规则没有匹配；有规则 ID 但 discount_amount 为零，可能是 action、上限、免费商品或自定义 collector 影响。数据库只用于诊断，不要手工写 discount_amount，它会在下一次 collectTotals 时被覆盖。</p>
<h3>Conditions 和 Actions 不是一回事</h3>
<p>Conditions 决定购物车是否有资格，Actions 下的条件决定哪些行项目享受折扣。常见配置是购物车条件匹配某分类，但 Actions 又排除了同一商品；或者&ldquo;后续规则停止处理&rdquo;让目标规则没有机会执行。</p>
<h3>范围与时间</h3>
<p>确认规则分配到当前 Website 和客户组，From/To 日期按 Magento 时区是否有效，Coupon 使用次数与每客户次数是否耗尽。访客没有 customer_id，基于客户属性或历史订单的条件可能永远不匹配。</p>
<h3>数量和折扣步长</h3>
<p>Buy X get Y、固定金额、每 N 件等 action 对数量和 step 有要求。购物车只有一件时，应用代码成功但折扣为零可能完全符合配置。把规则预期写成具体算式，用三组边界数量测试，而不是只用一个购物车。</p>
<h3>Totals 被扩展覆盖</h3>
<p>自定义费用、第三方结账或多币种扩展可能在 salesrule 之后重新设置 grand_total，或者前端没有刷新 totals。比较数据库 quote、REST/GraphQL totals 响应与页面显示：数据库已有 discount 但页面没变，是前端状态问题；数据库也为零，回到规则计算。</p>
<p>修复后测试访客与登录客户、含税与不含税显示、多个商品、部分商品不满足、移除 Coupon 和下单后的 sales_order_item 折扣。页面提示、Quote 和订单三处金额必须一致。</p>
<h3>缓存规则对象也可能过期</h3>
<p>修改 Sales Rule 后，如果长驻 Consumer、PHP 进程或自定义规则缓存仍持有旧对象，不同请求会得到不同结果。对照规则 updated_at 与计算节点，按 Magento 支持方式清理相关缓存并重启需要重载代码的长进程。不要在 totals 每次计算时无条件清缓存，那会把配置问题变成性能事故。</p>
<p>若 Coupon 来自自动生成池，还要核对它关联的 rule_id 与状态。导入脚本可能创建了能被查询到的 coupon 记录，却关联到已禁用或另一个网站的规则，于是代码校验通过、金额计算失败。抽查数据库关联比反复新建优惠码更快。</p>]]></description>
      <pubDate>Wed, 20 Nov 2024 03:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[管理员登录成功又跳回登录页，Magento 2 Cookie Path 怎么检查？]]></title>
      <link>https://www.360magento.com/blog/admin-login-loop-cookie-path/</link>
      <description><![CDATA[<p>输入正确的管理员账号密码，POST 返回 302，看起来已经进入 Dashboard，紧接着又回到登录页。没有&ldquo;密码错误&rdquo;提示时，应先把它当作 Session cookie 未被后续请求发送或服务端找不到，而不是重置管理员密码。</p>
<h3>浏览器里看两次请求</h3>
<p>检查登录响应的 <code>Set-Cookie</code>，再看 Dashboard 请求是否带回同名 cookie。重点比较 Domain、Path、Secure、SameSite、Expires。后台 URL 带自定义 frontName 时，错误的 Cookie Path 可能只覆盖前台根路径或旧后台路径。</p>
<p>若浏览器拒绝 Cookie，开发者工具通常会给出原因，例如 Secure cookie 经 HTTP 设置、Domain 不匹配或 SameSite 限制。</p>
<h3>Base URL 与反向代理必须一致</h3>
<p>外部访问 HTTPS、Magento 却认为是 HTTP，可能生成错误 cookie 和重定向。检查 secure/unsecure Base URL、offloader header、可信代理与 Host 转发。不要在生产直接把 Secure 关闭当长期修复，应让应用正确识别原始协议。</p>
<pre><code>bin/magento config:show web/cookie/cookie_domain
bin/magento config:show web/cookie/cookie_path
bin/magento config:show web/secure/use_in_adminhtml</code></pre>
<p>配置值为空不一定错误，Magento 可以使用默认范围；要与实际响应头结合判断。</p>
<h3>多节点 Session 漂移</h3>
<p>登录 POST 落到节点 A，Dashboard 落到节点 B；若使用本地文件 Session，B 找不到刚创建的数据。临时启用负载均衡粘性只能验证，长期应使用正确的共享 Session 存储并保证所有节点 crypt key 一致。</p>
<h3>旧 Cookie 冲突</h3>
<p>同一域名存在两个同名 cookie、不同 Path 时，浏览器可能同时发送，服务器选择结果不符合预期。用无痕窗口测试能发现，但真正修复要调整 Domain/Path 并让旧 cookie 过期，而不是要求所有管理员永久清浏览器。</p>
<p>修复后测试直接打开后台 URL、登录、刷新、跨后台页面、退出和重新登录，并在两个节点间切换。确认每次请求使用同一 Session，才不是一次偶然成功。</p>
<h3>安全日志能排除账号层问题</h3>
<p>查看管理员用户是否被锁定、失败次数和登录事件，但不要为了排查关闭二次验证或修改密码策略。若 POST 之后已经产生成功登录事件，随后请求立即变成匿名，证据更支持 Cookie/Session；若从未产生成功事件，才回到账号状态、验证码和认证插件。</p>
<h3>只在一个浏览器失败时</h3>
<p>检查该浏览器是否阻止第三方 Cookie、安装了改写请求的扩展，或保存着旧域名的 HSTS/代理规则。用新建干净浏览器配置做对照可以定位客户端因素，但站点仍应返回可理解的提示，不能让管理员在无提示循环中反复提交密码。</p>]]></description>
      <pubDate>Tue, 19 Nov 2024 06:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[静态内容部署报 Unable to resolve the source file，主题继承哪里断了？]]></title>
      <link>https://www.360magento.com/blog/unable-resolve-source-file/</link>
      <description><![CDATA[<p>开发机页面正常，生产执行 <code>setup:static-content:deploy</code> 却报 <code>Unable to resolve the source file</code>。这类错误往往被&ldquo;删除 pub/static 再试&rdquo;暂时掩盖，真正原因是某个资产引用无法沿模块和主题回退链找到文件。</p>
<h3>完整路径决定排查方向</h3>
<p>保存错误中请求的逻辑路径、area、theme 与 locale。<code>Vendor_Module::images/a.svg</code> 走模块资源解析；<code>css/source/_extend.less</code> 走主题继承；相对 import 又以当前 Less 文件为基准。不要只复制最后的文件名。</p>
<h3>Linux 大小写会揭露本地错误</h3>
<p>Windows/macOS 开发环境可能容忍 <code>Logo.svg</code> 与 <code>logo.svg</code>，Linux 生产会认为是不同文件。检查 Git 中真实大小写，并用一次明确 rename 提交修复；只在本地改大小写有时不会进入版本记录。</p>
<pre><code>git ls-files | grep -i 'logo.svg'
bin/magento dev:source-theme:deploy --type=less frontend/Vendor/theme</code></pre>
<p>第二条命令是否可用取决于版本和模式，生产部署仍应使用正式静态内容命令。</p>
<h3>主题父级和模块依赖</h3>
<p><code>theme.xml</code> 的 parent 指向未安装主题，或 composer 包在生产被排除，回退链会中断。确认模块在 <code>app/etc/config.php</code> 启用，资源文件确实进入当前 release。代码引用另一个模块资产时，模块依赖也应在 module sequence/composer 中明确。</p>
<h3>locale 并不只是翻译</h3>
<p>只部署 <code>en_US</code>，store 使用 <code>zh_Hans_CN</code> 时，某些本地化静态文件和 JS 翻译可能缺失。确认部署命令覆盖实际启用 locale。不要无差别部署所有语言来逃避配置问题，这会显著延长发布时间和占用磁盘。</p>
<h3>Less import 最容易留下相对路径</h3>
<p>扩展升级后移动了变量文件，旧主题仍 import 原路径。搜索整个代码库中的报错路径，确认来源是自定义主题而非生成文件。不要直接编辑 <code>pub/static</code> 或 <code>var/view_preprocessed</code>，它们下次部署会重建。</p>
<p>修复后在干净构建目录对所有生产主题和 locale 部署，确认命令返回成功，再原子切换 release。前台至少检查首页、分类、商品、结账和后台登录，避免&ldquo;命令成功但关键 bundle 缺失&rdquo;。</p>
<h3>并行部署要注意共享目录</h3>
<p>多台机器同时向同一个 pub/static 写入，可能一台清理而另一台仍在复制，最终留下混合版本。更安全的方式是在独立 release 目录完成构建，校验文件清单后一次切换软链接或发布到对象存储。静态签名版本应与文件集合同时更新，避免 HTML 指向尚未上传完成的新版本。</p>]]></description>
      <pubDate>Mon, 18 Nov 2024 01:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[客户地址保存后省份变空，Magento 2 Address 属性是否缺失？]]></title>
      <link>https://www.360magento.com/blog/customer-address-region-empty/</link>
      <description><![CDATA[<p>客户在地址簿里选择省份，保存提示成功；再次编辑时省份却变空，结账又要求重新选择。Magento 地址同时存在 <code>region_id</code> 与 <code>region</code> 两种表达：有标准地区目录的国家通常保存 ID，自由输入地区的国家保存文本。主题或 API 只处理其中一个字段，就会出现&ldquo;提交有值、读取没值&rdquo;。</p>
<h3>先比较请求和数据库</h3>
<p>在 Network 中保存 customer address 请求体，核对 country_id、region_id、region_code 与 region。然后只读查询地址实体：</p>
<pre><code>SELECT entity_id, parent_id, country_id, region_id, region, postcode
FROM customer_address_entity
WHERE entity_id = 456;</code></pre>
<p>若请求里的 region_id 已经为空，问题在表单数据绑定或国家切换；请求正确但数据库为空，查 repository plugin、extension attribute 转换和保存异常。</p>
<h3>确认地区 ID 属于该国家</h3>
<pre><code>SELECT region_id, country_id, code, default_name
FROM directory_country_region
WHERE region_id = 611;</code></pre>
<p>前端切换国家后保留旧 region_id，服务端可能清理不匹配值。地址联想扩展把省份名称写进 region_id，也会被转换失败。不要通过关闭校验接受错误国家&mdash;地区组合，税率和运费都可能依赖它。</p>
<h3>EAV 属性异常通常来自迁移或旧扩展</h3>
<p>Magento 客户地址使用 EAV 元数据与实体表字段协作。检查 region、region_id 属性是否存在、backend/frontend 配置是否被扩展修改，以及属性是否被错误设为不可见或从 form code 移除。只有某个 website/store 失败时，还要比较表单属性集和主题覆盖。</p>
<h3>API 数据结构必须一致</h3>
<p>REST/GraphQL/Headless 前端常把 region 作为对象。序列化时若只保留显示名称，编辑表单重新加载后无法匹配下拉选项。定义清晰的前端模型：有 ID 时同时保存 code/name，切换国家时清空全部地区字段，再让新国家组件重建。</p>
<p>修复后测试标准省份国家、无省份目录国家、切换国家、默认账单/收货地址与结账中保存到地址簿。后台、客户中心和订单地址都能读到一致值，才算完成。</p>
<h3>旧地址数据也要批量巡检</h3>
<p>修好表单只会保证新保存的数据正确，历史地址里 country_id 与 region_id 不匹配的记录仍会在下次结账触发错误。用只读查询统计孤立 region_id，按客户和地址 ID 导出待修清单。批量修复前必须保留原文本并建立国家&mdash;地区映射，不能把所有空值统一写成一个默认省份。</p>
<p>还要区分客户地址与已下单地址。sales_order_address 是订单快照，修客户地址不应回写历史订单；客服需要更正履约地址时，应走订单允许的业务流程并留下记录，不能用一次 SQL 同时改两类表。</p>]]></description>
      <pubDate>Fri, 15 Nov 2024 08:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[搜索不到带连字符的 SKU，OpenSearch Analyzer 把它拆成什么了？]]></title>
      <link>https://www.360magento.com/blog/hyphenated-sku-search/</link>
      <description><![CDATA[<p>商品 SKU 是 <code>ABC-123-X</code>，后台能找到，直接打开商品页也正常，但前台搜索完整 SKU 返回空；搜索 <code>ABC</code> 反而有结果。SKU 已经进入数据库，问题多半发生在搜索索引的字段 mapping、分析器分词和查询构造。</p>
<h3>先确认索引文档中有没有这个商品</h3>
<p>从 Magento 当前使用的搜索索引别名开始，按实体 ID 或 SKU 查询文档。不要猜实际索引名，也不要直接改 mapping；Magento 重建时会创建新索引并切换别名，手工修改很容易丢失。</p>
<p>文档里没有 SKU，检查 catalogsearch_fulltext 索引状态、商品网站分配、状态与可见性；文档存在但搜不到，再分析 token 和查询。</p>
<h3>连字符通常会影响 token 边界</h3>
<p>标准分析器可能把 <code>ABC-123-X</code> 拆成 <code>abc</code>、<code>123</code>、<code>x</code>。keyword 类型则保留整个值，但大小写处理取决于 normalizer。索引时和搜索时 analyzer 不一致，会出现完整输入被拆成另一组 token。</p>
<pre><code>POST /YOUR_INDEX/_analyze
{
  "analyzer": "standard",
  "text": "ABC-123-X"
}</code></pre>
<p>在受控工具中执行并使用实际 analyzer。文章示例不代表应把生产索引统一改成 standard。</p>
<h3>精确 SKU 应有独立策略</h3>
<p>商品名称适合全文分词，SKU 更接近标识符。常见设计是保留一个 normalized keyword 子字段用于精确匹配，同时保留可分词字段支持输入片段；查询时给精确 SKU 更高 boost。若只对整个查询使用 match_phrase，短横线与空格变体仍可能失败。</p>
<h3>扩展层可能先清洗输入</h3>
<p>搜索建议、同义词或第三方模块可能在发送 OpenSearch 前删除标点、替换连字符或转义错误。记录最终搜索请求 JSON，而不是只看用户输入。PHP 层对 <code>-</code> 当负号、query_string 查询未转义，也会改变语义。</p>
<h3>Mapping 变更必须重建</h3>
<p>已有字段的 analyzer 通常不能原地改变。通过 Magento 支持的搜索配置或自定义模块声明后创建新索引并全量重建，再验证别名切换。先在预发布比较索引大小、构建时间和常用关键词结果，避免为 SKU 修复破坏自然语言搜索。</p>
<p>回归用例应包含完整 SKU、去掉连字符、大小写变体、前缀、相似商品名和不存在的 SKU。精确命中应排在前面，同时普通关键词相关性不能明显退化。</p>
<h3>同义词不要承担标识符修复</h3>
<p>为每个 SKU 建同义词既难维护，又可能让旧型号错误匹配新商品。SKU 规范化应该发生在字段与查询策略层，同义词只处理真实语言等价关系。若业务允许用户省略连字符，可在查询时生成受控的 normalized 变体，并给完全一致的原始值最高权重。</p>
<p>搜索建议与正式结果页也要使用相同规范化逻辑。若下拉建议能找到、回车后结果为空，说明两个接口的查询模板或索引字段不同。把同一组 SKU 用例同时跑过 Suggest、Search API 和前台结果页，避免只修一个入口。</p>]]></description>
      <pubDate>Thu, 14 Nov 2024 05:55:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[分类页商品顺序乱了，Position 为什么不按后台设置显示？]]></title>
      <link>https://www.360magento.com/blog/category-position-order-wrong/</link>
      <description><![CDATA[<p>在分类后台把重点商品拖到最前，前台刷新后顺序没有变化，甚至每个客户看到的都不同。Position 只是分类与商品关系上的排序值，只有列表当前 order 选择&ldquo;Position&rdquo;时才会生效。</p>
<h3>先把 URL 参数清干净</h3>
<p>分类页的 <code>product_list_order</code>、<code>product_list_dir</code> 可能被浏览器、主题或 Session 保留。用无痕窗口打开不带 query 的分类 URL，观察 Toolbar 当前选项。后台 Category &rarr; Display Settings 的 Default Product Listing Sort By 必须允许并选择 Position。</p>
<h3>数据库确认位置值</h3>
<pre><code>SELECT cp.product_id, p.sku, cp.position
FROM catalog_category_product AS cp
JOIN catalog_product_entity AS p ON p.entity_id = cp.product_id
WHERE cp.category_id = 42
ORDER BY cp.position ASC, cp.product_id ASC
LIMIT 50;</code></pre>
<p>多个商品 position 相同，数据库对并列行不保证业务期望的次序，应有稳定的第二排序键。导入程序若每次把 position 重置为 0，后台手工调整会在下一轮同步后丢失。</p>
<h3>主题可能覆盖默认 order</h3>
<p>检查 Toolbar、collection plugin 和 layout 参数。某些主题为了&ldquo;新品优先&rdquo;强制 created_at，或从 Cookie/localStorage 恢复上次排序。先临时切到标准逻辑对比，再修自定义模块，不要直接改核心 Toolbar。</p>
<h3>搜索引擎参与时的差异</h3>
<p>部分版本/扩展让分类集合经过搜索引擎，相关性、库存和置顶规则可能与 position 组合。检查最终 collection 的 order 条件与搜索请求，而不是只看关系表。分类索引陈旧时可以重建作为诊断；若之后再次错乱，要修增量索引或导入触发。</p>
<h3>缓存与客户端渲染</h3>
<p>FPC/CDN 可能返回旧 HTML，Ajax 分页又可能从 API 取得新顺序。分别看初始源码和滚动加载请求。清缓存后正确不代表根因已解决，需要确认分类保存会产生正确的缓存失效标签。</p>
<p>修复后调整三个商品为明确不同的 Position，验证第一页、第二页、升降序切换、登录/未登录和缓存命中。默认顺序正确，同时用户主动选择价格排序仍应有效，这才是完整结果。</p>
<h3>分页边界需要稳定次排序</h3>
<p>大量商品 position 相同又没有第二排序键时，同一商品可能在翻页时重复或消失，因为数据库每次对并列行的返回顺序不保证一致。自定义排序应追加 entity_id 等稳定字段，同时确保 Ajax 与初始页面使用同一 order。修复后连续刷新并翻页，结果集合和顺序都应稳定。</p>
<p>如果使用 Visual Merchandiser 或第三方置顶规则，还要记录规则运行时间和手工 Position 的优先级。自动规则重新执行后覆盖人工排序属于配置结果，不是数据库随机变化；运营侧需要明确哪一种排序拥有最终控制权。</p>]]></description>
      <pubDate>Wed, 13 Nov 2024 01:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 退款成功但库存没回来，真的只是 Return to Stock 没勾吗？]]></title>
      <link>https://www.360magento.com/blog/refund-stock-not-returned/</link>
      <description><![CDATA[<p>后台显示退款成功，Credit Memo 也存在，但 SKU 库存没有增加。退款金额与退货入库是两个动作：财务上退钱，不代表商品物理上已经回到可销售仓库。Magento 允许在 Credit Memo 行项目上选择 Return to Stock；MSI 和外部 WMS 又会进一步决定回到哪个 Source。</p>
<h3>先看 Credit Memo 行项目</h3>
<pre><code>SELECT cm.increment_id, cm.state, cm.created_at,
       item.sku, item.qty, item.back_to_stock
FROM sales_creditmemo AS cm
JOIN sales_creditmemo_item AS item ON item.parent_id = cm.entity_id
WHERE cm.order_id = 123;</code></pre>
<p><code>back_to_stock</code> 能说明创建贷项通知时的选择，但还要结合商品是否已经发货、商品类型和库存模块。虚拟商品没有物理库存；Bundle/Configurable 应检查实际扣减的简单子 SKU。</p>
<h3>退款入口改变执行链</h3>
<p>从 Magento invoice 创建在线退款，支付模块与库存逻辑通常按服务层执行；只在支付平台后台退款，Magento 根本不知道；第三方 ERP 直接创建 Credit Memo 若绕过标准 API，也可能没有触发库存回补。记录是谁、从哪个系统、通过哪个接口发起。</p>
<h3>MSI 要找原扣减 Source</h3>
<p>订单下单先写 reservation，发货时从具体 Source 扣减。退货时是否回原 Source、默认 Source 还是等待仓库验收，取决于流程和扩展。查询 shipment source、source item 数量与 reservation 时间线，避免只看聚合 salable quantity。</p>
<p>若商品尚未发货，取消/退款通常通过 reservation 补偿恢复可售量，而不是增加某个 Source 的物理 quantity；因此&ldquo;Source 数量没变&rdquo;可能是正确的。已发货退货则需要明确实物入库。</p>
<h3>不要手工加库存掩盖流程</h3>
<p>直接在 source item 上加数量，随后 WMS 回传一次退货，库存会重复增加。先确定 Magento 与 WMS 谁是物理库存主系统，并用退货单号建立幂等记录。需要临时修复时，也要记录原数量、事件和调整原因。</p>
<h3>一张订单做全链路测试</h3>
<p>测试未发货取消、已发货全额退款、部分数量退款、不同 Source 发货和可配置商品。每一步记录 order/invoice/shipment/credit memo、reservation 汇总、source quantity 与 salable quantity。库存是否&ldquo;回来&rdquo;必须与实物和订单阶段一致，而不是只看退款按钮成功提示。</p>
<h3>部分退款要核对数量，不只看金额</h3>
<p>管理员可以只退运费或调整金额而不退商品数量；这种 Credit Memo 不应增加库存。反过来，退两件只勾一件 Return to Stock，也只能回补一件。比较 credit memo item qty、back_to_stock、订单已退款数量和 shipment 数量，防止按总退款金额推断库存动作。</p>]]></description>
      <pubDate>Tue, 12 Nov 2024 08:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[同一条 GraphQL 查询有时快有时慢，Resolver 的 N+1 问题藏在哪里？]]></title>
      <link>https://www.360magento.com/blog/graphql-resolver-n-plus-one/</link>
      <description><![CDATA[<p>一条 GraphQL 查询在测试时 200ms，生产偶尔超过 5 秒；增加 pageSize 后，耗时近似线性甚至成倍增长。若每返回一个商品，自定义 Resolver 都重新加载产品、库存或 ERP 数据，就形成 N+1：先查一次列表，再为 N 个节点各查一次。</p>
<h3>不要只看总耗时</h3>
<p>在测试环境为一次请求记录 SQL 数量、相同 SQL 模板出现次数、外部 HTTP 调用数和每个 Resolver 耗时。分别用 pageSize 1、10、50 比较。如果 SQL/调用次数随实体数等比例增长，证据比&ldquo;服务器很忙&rdquo;更明确。</p>
<h3>Resolver 收到的 value 通常已有上下文</h3>
<p>父 Resolver 可能已经提供 model 或所需字段。自定义字段若仅为了一个属性又调用 repository-&gt;getById，会重复加载。先查看 <code>$value</code> 中的 model 与已选字段，缺少数据时让集合层批量选择，而不是逐项补查。</p>
<pre><code>public function resolve(Field $field, $context, ResolveInfo $info,
    array $value = null, array $args = null) {
    if (!isset($value['model'])) {
        throw new LocalizedException(__('Product model is missing.'));
    }
    return $value['model']-&gt;getData('custom_label');
}</code></pre>
<h3>需要外部数据时使用批量思想</h3>
<p>收集当前请求中的实体 ID，一次查询映射表或一次调用支持批量的外部 API，再按 ID 分发结果。Magento GraphQL 提供批量 Resolver 机制时，应按接口约定实现。数据加载器的缓存范围要限制在请求内，避免把客户专属值共享给另一请求。</p>
<h3>缓存为何让同一查询忽快忽慢</h3>
<p>GraphQL 响应和 Resolver 结果可能受缓存、身份标签、客户 token、store 与 currency 影响。匿名请求命中、登录请求绕过，或者自定义 Resolver 没提供正确 cache identity，会造成时间差。比较响应头和上下文，不要把一次暖缓存与一次冷缓存直接对比。</p>
<h3>字段选择也决定成本</h3>
<p>GraphQL 客户端可以请求大量嵌套字段。前端只显示标题和价格，却同时获取媒体库、可配置选项、库存明细和评论，会触发更多 provider。用最小查询逐个加字段，找到成本陡增的节点；为 pageSize 和查询复杂度设置合理限制，防止一个请求拖垮 PHP worker。</p>
<h3>验证优化是否真实</h3>
<p>优化前后在相同 store、客户身份、pageSize 和缓存状态下比较 P50/P95、SQL 数量和外部调用数。理想结果不是&ldquo;50 个商品快了&rdquo;，而是查询次数从随 N 增长变成近似固定。随后测试错误与超时，批量 API 部分失败时不能让所有实体静默返回错误数据。</p>
<h3>观察生产请求但避免记录敏感变量</h3>
<p>可按 operation name、字段集合哈希和耗时建立指标，避免把客户 token、邮箱、搜索词或完整 variables 写入普通日志。对慢请求采样时记录 Resolver 路径和批次大小，这样既能找到 N+1，也不会为了性能诊断扩大数据暴露面。</p>
<h3>批处理 Key 必须包含业务维度</h3>
<p>批量加载器若只按 product_id 缓存，却忽略 store、customer group、currency 或 website，会把一次请求中的不同上下文合并成错误结果。Key 至少要覆盖决定返回值的维度；客户专属价格和权限数据不应进入跨请求共享缓存。批次分发时还要保持输入顺序和缺失 ID 的占位，否则结果会错配到另一个商品。</p>
<h3>外部服务要限制 fan-out</h3>
<p>即使数据库查询已经批量化，Resolver 为每个商品并发调用 ERP 也会形成网络 N+1，并可能瞬间触发对方限流。优先使用批量端点；没有批量端点时设置请求级并发上限、短超时和明确的降级字段。不要在一个可选推荐字段失败时让整条商品查询返回 500。</p>
<p>性能回归测试可把商品数逐步提高到 1、10、25、50，绘制耗时与 SQL/HTTP 次数曲线。批量化后曲线仍随 N 急剧上升，说明还有嵌套字段或序列化成本未处理，而不是继续盲目增加缓存。</p>]]></description>
      <pubDate>Mon, 11 Nov 2024 02:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[自定义模块升级卡在 setup:upgrade，Data Patch 执行一半怎么恢复？]]></title>
      <link>https://www.360magento.com/blog/data-patch-half-finished/</link>
      <description><![CDATA[<p><code>bin/magento setup:upgrade</code> 在自定义 Data Patch 中报错退出。修好一行代码后直接重跑，新的错误却变成 duplicate key。这是因为 Patch 是否完成由 <code>patch_list</code> 登记决定，而业务表里的部分写入不一定随异常回滚。</p>
<h3>先停止重复执行并保留现场</h3>
<p>记录完整堆栈、Patch 类名、当前 release、数据库备份点和已经修改的行。不要手工向 patch_list 插入类名来&ldquo;跳过&rdquo;，除非已经证明 Patch 的所有预期结果完整存在；否则环境会永久处于半升级状态。</p>
<pre><code>SELECT patch_name
FROM patch_list
WHERE patch_name LIKE '%Vendor%';

bin/magento setup:db:status</code></pre>
<h3>判断哪些写入已经发生</h3>
<p>阅读 Patch 的 apply 方法，列出每一步会新增或更新的实体：CMS 页面、属性、配置、分类或自定义表。对每一步写只读查询，形成&ldquo;预期&mdash;实际&rdquo;对照。Repository save、外部 API 和多次循环可能不在同一个数据库事务内。</p>
<h3>让 Patch 可重复运行</h3>
<p>新增记录前按稳定业务键查找；存在则校验并更新，不存在才创建。不要把自动递增 ID 当跨环境固定标识。属性、CMS identifier 等已有唯一业务键时，应利用它们。</p>
<pre><code>$page = $this-&gt;pageFactory-&gt;create()-&gt;load('shipping-help', 'identifier');
if (!$page-&gt;getId()) {
    $page-&gt;setIdentifier('shipping-help');
}
$page-&gt;setTitle('Shipping Help');
$this-&gt;pageRepository-&gt;save($page);</code></pre>
<p>示例只表达幂等思路，实际还要设置 store、content 与 active 等必需字段。若业务不允许覆盖人工编辑内容，Patch 应仅创建缺失记录，后续变更用新的 Patch。</p>
<h3>事务边界要现实</h3>
<p>Data Patch 接口不保证所有服务调用都自动处在一个可回滚的大事务里。大量数据迁移可以按批次记录进度，但进度表本身也要设计一致性。外部 API 不应直接放进不可重放的数据库升级；更适合在升级后由可重试任务执行。</p>
<h3>恢复选择</h3>
<p>如果部分数据可安全回滚，先用可审计脚本撤回，再运行修正版 Patch；如果数据应保留，让修正版识别并补齐缺失项。不要修改已经在其他环境成功执行过的 Patch 逻辑却保持同一类名，否则环境行为会分叉；通常应增加修复 Patch，并明确依赖关系。</p>
<p>在数据库副本演练从原始失败点恢复，连续执行两次 setup:upgrade，第二次应无数据变化。随后检查 patch_list、schema status 和业务页面。只有重复运行安全，才算真正解决中断问题。</p>
<h3>部署流程要能识别半完成状态</h3>
<p>setup:upgrade 失败后不应继续编译、切换流量或清理旧 release。流水线需要立即停止并保留日志；健康检查不仅看首页 200，还要检查数据库版本状态。回滚代码却保留新数据库结构也可能不兼容，因此每个 Patch 上线前都应明确向前修复方案，而不是假定数据库可以无损回滚。</p>
<h3>Patch 依赖必须是有向无环关系</h3>
<p><code>getDependencies()</code> 应只声明真正的数据前置条件。循环依赖会让升级无法排序，漏依赖则可能在不同模块加载顺序下偶发失败。跨模块依赖还要保证 composer/module 依赖存在，否则某环境卸载了被依赖模块，Patch 类本身就无法加载。</p>
<h3>Revertable 不等于生产可安全回滚</h3>
<p>实现 PatchRevertableInterface 后，模块卸载可能调用 revert，但删除属性、CMS 页面或业务数据可能已经有人工修改和关联记录。只有能明确识别&ldquo;本 Patch 创建且未被业务使用&rdquo;的数据才适合自动删除。否则保留向前修复 Patch，并在卸载文档中说明人工步骤。</p>
<p>Patch 中需要特定 area code、store context 或 indexer 时，应显式建立最小上下文并恢复状态；不要依赖 setup:upgrade 当时恰好加载了 adminhtml。测试应从全新数据库和已经运行多个旧版本的数据库两条路径执行，因为升级路径问题往往不会在全新安装出现。</p>]]></description>
      <pubDate>Fri, 08 Nov 2024 06:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 使用 Redis 后频繁 Connection timed out，先看连接池和超时]]></title>
      <link>https://www.360magento.com/blog/redis-connection-timeout/</link>
      <description><![CDATA[<p>切换 Redis 后页面偶发 500，日志出现 <code>Connection timed out</code>。重启 Redis 后暂时恢复，并不能证明 Redis 软件本身有缺陷。超时可能发生在建立 TCP 连接、等待命令响应或读取数据，每一种都对应不同指标。</p>
<h3>先识别出问题的是哪个用途</h3>
<p>Magento 常把 default cache、page cache 和 session 放到不同 Redis DB 或实例。页面缓存超时可能导致后端变慢，Session 超时会让登录、购物车直接失败。根据异常堆栈中的 frontend/resource 与 <code>env.php</code> 配置确认实例，日志中不要输出密码。</p>
<pre><code>redis-cli -h REDIS_HOST -p 6379 PING
redis-cli -h REDIS_HOST -p 6379 INFO clients
redis-cli -h REDIS_HOST -p 6379 INFO stats
redis-cli -h REDIS_HOST -p 6379 INFO persistence</code></pre>
<p>从与 PHP-FPM 相同的网络环境测试。运维机 PING 很快，不代表应用容器到 Redis 的路径正常。</p>
<h3>连接数耗尽时，重启只是清场</h3>
<p>观察 <code>connected_clients</code>、<code>rejected_connections</code>、<code>blocked_clients</code> 与 maxclients。PHP-FPM worker 数、后台消费者和 Cron 会共同建立连接。错误的持久连接使用、连接未及时释放或突发扩容都可能冲过上限。</p>
<p>不要只把 maxclients 调大。操作系统文件描述符、Redis 内存和客户端并发也要匹配；连接数增长曲线若不随请求结束回落，应查客户端库和进程生命周期。</p>
<h3>慢命令与大 Key</h3>
<pre><code>redis-cli -h REDIS_HOST SLOWLOG GET 20
redis-cli -h REDIS_HOST --latency
redis-cli -h REDIS_HOST INFO commandstats</code></pre>
<p><code>KEYS *</code> 会阻塞大型实例，不要用于生产排查。需要观察 Key 分布时使用受控 SCAN 或离线工具。巨型 Session、缓存标签集合和一次删除大量 Key 都会造成延迟尖峰。</p>
<h3>持久化和内存压力</h3>
<p>RDB fork、AOF rewrite、内存 swap、淘汰风暴会让响应暂停。查看 latest_fork_usec、used_memory、used_memory_rss、evicted_keys 与主机 I/O。Cache 可以按策略淘汰，Session 实例通常不应随意淘汰活跃会话；两者混用一个内存上限会互相影响。</p>
<h3>超时参数不是越大越好</h3>
<p>connect timeout 太短会放大轻微网络抖动，read timeout 过长则会占满 PHP worker，让故障扩散。根据正常 P95/P99 延迟与业务容忍度设置，并配合有限重试。非幂等写操作不能在未知结果时无限重放。</p>
<h3>验证恢复</h3>
<p>在峰值并发下分别测试页面缓存、登录 Session、购物车和后台消费者；观察连接数、延迟、fork 与错误率同一时间轴。修复目标是超时尖峰有明确根因且容量有余量，不是把错误日志通过无限延长 timeout 隐藏。</p>
<h3>网络路径与 DNS 也要单独测</h3>
<p>使用主机名连接时，容器 DNS 抖动、服务发现切换和跨可用区路由都可能只影响新连接。分别记录 DNS、TCP connect 和 Redis command latency；若已有连接正常、新连接慢，重点不在命令执行。云 Redis 的 TLS 握手、连接代理和故障切换也会产生短时尖峰，客户端必须支持重连但限制重试次数。</p>
<h3>Cache 与 Session 的降级策略不同</h3>
<p>页面缓存短暂失败可以回源重建，但 Session 写入失败不能悄悄当作空会话，否则客户会登出或购物车丢失。为两个用途使用独立 DB/实例、前缀和监控；容量规划按 PHP-FPM、Consumer、Cron 的总并发计算。发生故障时，应优先保护结账和登录，而不是让缓存预热占满全部连接。</p>
<p>最后做一次受控故障切换，观察客户端能否在旧主节点断开后连接新主节点、是否出现长时间 DNS 缓存，以及恢复期间有没有重复业务操作。只在稳定状态跑压测，无法证明高可用配置真的有效。</p>]]></description>
      <pubDate>Thu, 07 Nov 2024 03:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台保存 CMS 页面直接 404，是 WAF 拦截还是 URL Key 有问题？]]></title>
      <link>https://www.360magento.com/blog/cms-page-save-404/</link>
      <description><![CDATA[<p>CMS 页面可以打开编辑，标题和内容也能正常输入，但点击保存后直接看到 404。这个 404 可能由 Magento 路由返回，也可能是 WAF 为隐藏拦截原因而伪装的响应；两者的处理方向完全不同。</p>
<h3>先保存请求证据</h3>
<p>在 Network 中找到保存 POST，记录 Request URL、状态码、响应头、响应体开头、请求体大小和服务器 request ID。若响应是完整 Magento 404 页面，优先查后台 secret key、Form Key 与路由；若响应头带 CDN/WAF 标记或是一段简短拦截页，去查边缘安全日志。</p>
<h3>用内容二分法找 WAF 规则</h3>
<p>复制页面到测试记录，先只保留一段普通文本。如果能保存，再逐块加入原 HTML。<code>&lt;script&gt;</code>、内联事件、SQL 关键词、iframe、长 base64 图片和某些模板指令容易触发安全规则。二分法能找到最小触发片段，但不要为了通过而关闭整站 WAF；应对后台保存路径和已认证管理员制定精确例外。</p>
<h3>请求体大小也可能表现成异常页面</h3>
<p>页面内直接粘贴 base64 图片会迅速增大 POST。比较 CDN、Nginx/Apache、PHP 的 body/upload 限制与后台实际请求大小。413 被自定义错误页改写为 404 时，浏览器只看最终状态容易误判。</p>
<pre><code>php -i | egrep 'post_max_size|max_input_vars|max_execution_time'
tail -n 100 var/log/exception.log
tail -n 100 var/log/system.log</code></pre>
<h3>URL Key 冲突通常有业务提示</h3>
<p>相同 store view 下 identifier 冲突、空值或非法格式，多数会返回表单错误，而非真正 404。仍应检查 CMS Page 的 identifier、store assignment 和 URL rewrite 扩展。不要删除另一页面来试错，先确认它是否正在提供线上内容。</p>
<h3>Form Key 与后台会话</h3>
<p>编辑页面打开太久、Cookie 域不一致或负载均衡 Session 漂移，提交时 Form Key 可能失效。正常应回到登录或显示无效 key，但定制后台可能改写。用新开的编辑页立即保存最小内容；若成功，再查会话寿命与节点共享。</p>
<p>修复后分别保存短文本、长 HTML、包含允许模板指令的页面，并检查前台 URL、store view 和缓存刷新。目标不是让 POST 返回 200，而是页面记录正确更新且 WAF 仍保护其他入口。</p>
<h3>别忽略后端 Secret Key</h3>
<p>Magento 后台 URL 的 key 与当前管理员会话绑定。扩展若把保存 action 写成固定 URL、JavaScript 长时间缓存旧 action，或反向代理去掉路径片段，POST 会落到无效路由。比较表单 action 与点击时请求 URL，并确认没有跨域跳转。修复后重新登录获取新 key，不能把 URL key 验证整体关闭。</p>
<p>如果只有某个管理员角色失败，还应对比 CMS 保存 ACL 与变量/Widget 权限。内容里允许的 Magento directive 受权限白名单影响，拒绝时应返回明确错误；不要通过给所有编辑者完整管理员权限来绕过。</p>]]></description>
      <pubDate>Wed, 06 Nov 2024 09:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品页显示有货，结账却提示 Out of Stock：MSI Reservation 怎么查？]]></title>
      <link>https://www.360magento.com/blog/in-stock-checkout-out-of-stock/</link>
      <description><![CDATA[<p>商品页显示&ldquo;有货&rdquo;，顾客也能加入购物车，点击提交订单却收到 Out of Stock。这不一定是前端缓存错误。MSI 中 Source 的物理数量、Stock 的可售数量、购物车加载时的校验与下单瞬间的校验是不同概念；高并发时，几秒钟就可能产生新的 reservation。</p>
<h3>确认网站使用哪个 Stock</h3>
<pre><code>SELECT stock_id, type, code
FROM inventory_stock_sales_channel
WHERE type = 'website';

SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001';</code></pre>
<p>另一个 Stock 的 Source 有货，并不能支持当前网站销售。先核对 website code 与 stock_id，再看该 Stock 关联的 Source。商品 source item 的 status 为禁用时，quantity 大于零也不能贡献可售量。</p>
<h3>Reservation 是增量，不是当前库存快照</h3>
<pre><code>SELECT reservation_id, stock_id, sku, quantity, metadata
FROM inventory_reservation
WHERE sku = 'SKU-001'
ORDER BY reservation_id DESC
LIMIT 30;</code></pre>
<p>下单通常产生负 reservation，取消或退款等流程产生补偿记录。不要把表中负数当&ldquo;错误&rdquo;，应按 stock_id 和 SKU 求和后理解。订单状态被自定义流程跳过、消费者未运行或脚本绕过库存 API，都可能留下未补偿 reservation。</p>
<p>使用官方命令列出不一致时，先读输出并关联订单，再创建补偿。不要直接 DELETE reservation，因为它是审计链的一部分。</p>
<h3>商品页为什么仍显示有货</h3>
<p>商品详情页可能来自 FPC/CDN，库存消息又由自定义接口或旧 stock item 字段提供。可配置商品还可能因另一个子商品有货而显示父级可售，但顾客选中的具体组合已经售罄。检查请求中的 sku 与后台观察的 sku 是否同一个。</p>
<h3>结账校验是最后一道并发保护</h3>
<p>两名顾客同时看到最后一件商品时，前端不可能永久保证两人都能买到。结账重新验证是正确行为。业务可通过更及时的库存接口、购物车保留策略和清晰提示减少挫败，但不能关闭最终校验。</p>
<h3>验证一条完整数量链</h3>
<p>记录 Source quantity、reservation 汇总、salable quantity、购物车数量与下单结果；随后取消测试订单，确认补偿写入且可售量恢复。再测试并发两单、可配置子 SKU 和不同网站 Stock。只有数量在每个动作后按预期变化，才说明不是缓存碰巧刷新。</p>
<h3>最小销售数量也会伪装成缺货</h3>
<p>错误文案如果被主题统一翻译为 Out of Stock，实际可能是最小/最大购买数量、增量步长或购物车已有数量超限。查看接口原始 message 与 quote item qty，不要只相信页面提示。B2B 按客户组配置的数量限制，也要用发生问题的客户身份复现。</p>]]></description>
      <pubDate>Tue, 05 Nov 2024 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[订单状态改了又被改回去，Magento 2 是谁在更新 state 和 status？]]></title>
      <link>https://www.360magento.com/blog/order-status-changed-back/</link>
      <description><![CDATA[<p>管理员把订单改为&ldquo;处理中&rdquo;，刷新后正常，过几分钟又回到&ldquo;待付款&rdquo;。表面看是后台没有保存，实际更多是另一个流程随后保存了订单。Magento 2 的 <code>state</code> 表示业务阶段，<code>status</code> 是该阶段下展示给运营人员的标签；两者可以映射，但不能任意组合。</p>
<h3>先读取订单与历史时间线</h3>
<pre><code>SELECT entity_id, increment_id, state, status, updated_at,
       total_paid, total_due
FROM sales_order
WHERE increment_id = '000000123';

SELECT created_at, status, is_customer_notified, comment
FROM sales_order_status_history
WHERE parent_id = 123
ORDER BY created_at DESC;</code></pre>
<p>历史表只记录通过正常业务代码添加的 comment/status，不保证捕获所有直接赋值。若状态变化没有历史，重点搜索直接调用 <code>setState</code>、<code>setStatus</code> 后保存订单的扩展，以及外部 SQL。</p>
<h3>支付流程会根据交易结果推进订单</h3>
<p>异步支付通常先创建 pending_payment 订单，Webhook 到达后捕获并进入 processing；超时或失败回调又可能取消。测试平台重复推送、事件乱序或商户号映射错误，会把旧事件应用到新状态。对照支付 transaction ID、Webhook event ID、平台发生时间和 Magento 接收时间，不能只按到达顺序处理。</p>
<p>状态改变后又回退，尤其要检查回调是否具有幂等和单调性：已 capture 的订单不应被较早的 authorization pending 事件覆盖。</p>
<h3>Cron 与 ERP 同步可能使用旧快照</h3>
<p>同步任务在开始时加载订单，处理几分钟后用旧对象整体 save，会覆盖期间由管理员或支付模块更新的字段。应只写确实由该系统负责的字段，保存前重新加载并检查版本/当前状态。外部 ERP 也需要明确 Magento 与 ERP 谁是状态主系统，避免双向循环。</p>
<h3>找出代码入口</h3>
<p>搜索自定义模块中的订单保存 observer、plugin、repository save 和 resource model save；按订单 ID 增加临时结构化日志，记录调用来源、旧 state/status、新值和 correlation ID。不要长期记录完整订单对象，其中可能包含客户信息。</p>
<pre><code>$logger-&gt;info('order_status_change', [
    'order_id' =&gt; (int)$order-&gt;getEntityId(),
    'from' =&gt; $order-&gt;getOrigData('status'),
    'to' =&gt; $order-&gt;getStatus(),
    'source' =&gt; 'vendor_webhook'
]);</code></pre>
<h3>不要靠锁死状态解决</h3>
<p>around plugin 阻止所有状态改变，会让发票、发货、退款等合法流程失效。正确做法是定义允许转换、事件优先级和负责系统。修复后用乱序 Webhook、重复事件、管理员手工修改与 ERP 并发四种场景验证，订单历史应能解释每一次变化。</p>
<p>同时检查前台展示用的是 state 还是 status label。修复写入竞争后，如果主题按 state 硬编码中文而后台按 status 显示，客户和客服仍会看到不同结果。状态映射、邮件文案和 API 输出应使用同一业务定义。</p>]]></description>
      <pubDate>Mon, 04 Nov 2024 07:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 加入购物车报 No such entity with cartId，Quote 到底丢在哪？]]></title>
      <link>https://www.360magento.com/blog/no-such-entity-cartid/</link>
      <description><![CDATA[<p>点击&ldquo;加入购物车&rdquo;后接口返回 <code>No such entity with cartId = ...</code>，很多人会先清缓存或重建索引。这个异常中的实体通常是 Quote，不是商品。Magento 2 对访客购物车使用 masked ID，对登录客户又会通过会话和 customer_id 找活动 Quote；只要前端保留了旧 ID、Quote 已失活或多节点 Session 不一致，就会出现&ldquo;浏览器认为购物车存在，服务器却找不到&rdquo;。</p>
<h3>先确认报错来自哪一个端点</h3>
<p>在 Network 中记录请求 URL、方法和返回体。<code>/rest/V1/guest-carts/{cartId}/items</code> 里的 cartId 应是 mask；<code>/rest/V1/carts/mine/items</code> 依赖登录 token；GraphQL 的 cart_id 同样通常使用 masked ID。不要把数字 quote_id 暴露给访客接口，也不要把 mask 当数据库主键查询。</p>
<h3>从 mask 找到真实 Quote</h3>
<pre><code>SELECT qm.masked_id, qm.quote_id,
       q.is_active, q.customer_id, q.store_id, q.updated_at, q.items_count
FROM quote_id_mask AS qm
LEFT JOIN quote AS q ON q.entity_id = qm.quote_id
WHERE qm.masked_id = 'REQUEST_CART_ID';</code></pre>
<p>没有 mask 行，说明 ID 可能来自另一个环境、数据库被清理，或前端缓存了旧值。mask 存在但 quote 不存在，是孤立关系；quote 存在但 <code>is_active=0</code>，可能已经转成订单或被购物车合并。不要把已下单 Quote 强行改回 active，这会制造重复下单风险。</p>
<h3>登录切换时最容易失配</h3>
<p>访客登录后，Magento 会尝试把访客 Quote 与客户现有活动 Quote 合并。自定义登录、单点登录或前端应用若仍继续使用登录前 mask，而后台已经关闭旧 Quote，下一次写入就会失败。成功登录后应以服务端返回的新购物车身份刷新客户端状态，清理 localStorage 中旧 cart_id，并重新加载 customer-data。</p>
<p>如果问题只在负载均衡后出现，检查 Session 是否共享、Cookie 域与 path 是否一致，以及 API 请求是否发送正确 cookie/token。轮询不同节点得到不同结果，通常不是 Quote 表随机丢数据。</p>
<h3>过期清理与自定义 Cron</h3>
<p>长期未更新的 Quote 会按配置清理。第三方&ldquo;数据库优化&rdquo;任务若按 created_at 而不是 updated_at 删除，可能误删活跃长周期购物车。对照异常时间、Quote 清理日志和数据库备份，确认是否有 DELETE。生产环境不要为避免报错无限保留所有 Quote，应修正清理条件和客户端过期处理。</p>
<h3>修复标准</h3>
<p>分别测试新访客建车、刷新页面、登录合并、退出后重新建车、完成订单后再次购物五条路径。每一步记录客户端 cart_id、mask 映射、真实 quote_id 与 is_active。接口遇到过期 cart 时应明确创建新车或提示刷新，而不是在后端猜测并复活旧 Quote。</p>
<p>对于移动端和 Headless 前端，还要测试应用被系统挂起数天后恢复、切换账号和多 Store View。客户端应给 cart_id 设业务有效期，收到明确的不存在响应时只重建一次，避免拦截器在循环重试中不断创建空购物车。</p>]]></description>
      <pubDate>Fri, 01 Nov 2024 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[数据库升级后出现 Illegal mix of collations，Magento 2 应该改哪里？]]></title>
      <link>https://www.360magento.com/blog/illegal-mix-of-collations/</link>
      <description><![CDATA[<p>迁移数据库或升级 MySQL 后，搜索、保存客户或运行自定义报表突然报 <code>Illegal mix of collations for operation '='</code>。错误说明参与比较的字符串使用了不兼容或不同优先级的 collation。把 SQL 临时加上 <code>COLLATE</code> 可以让一次查询通过，却可能让索引失效，也没有修复后续写入。</p>
<h3>从错误 SQL 找到具体两列</h3>
<p>保存完整异常与 SQL，定位等号、JOIN、UNION、CASE 或排序中的字符串表达式。随后查看这些列的字符集与 collation：</p>
<pre><code>SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE,
       CHARACTER_SET_NAME, COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
  AND TABLE_NAME IN ('customer_entity', 'vendor_mapping')
  AND COLUMN_NAME IN ('email', 'external_email');</code></pre>
<p>表的默认 collation 只影响新列，已有列可能仍保留旧值。因此 <code>SHOW CREATE TABLE</code> 与 information_schema 都要看。</p>
<h3>连接设置也能制造冲突</h3>
<pre><code>SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
SELECT @@character_set_connection, @@collation_connection;</code></pre>
<p>CLI 客户端、PHP PDO 与复制任务可能使用不同连接字符集。错误只在后台 Web 请求出现、CLI 不出现时，应比较两个连接，而不是立即转换全库。检查 <code>env.php</code> 数据库初始化命令和驱动选项，同时确认代理层没有改 session variables。</p>
<h3>自定义表是高发区域</h3>
<p>Magento 核心表通常遵循安装版本的数据库要求，手写 SQL 创建的扩展表可能继承服务器默认值。数据库服务器升级后默认 collation 改变，新建扩展表与旧核心列 join 就会冲突。修复应写入模块 declarative schema 或 patch，保证新环境也得到一致定义。</p>
<h3>不要直接 CONVERT 全库</h3>
<p><code>ALTER TABLE ... CONVERT TO CHARACTER SET</code> 会重建大表、持锁、增加磁盘和复制压力，还可能改变唯一索引的比较规则。例如大小写或重音敏感性变化后，原本不同的两个值可能变成重复。先在副本统计冲突，估算表大小与额外空间，并设计回滚。</p>
<pre><code>SELECT LOWER(email), COUNT(*)
FROM customer_entity
GROUP BY LOWER(email)
HAVING COUNT(*) &gt; 1;</code></pre>
<p>该查询只是检查一种可能的等价冲突，实际规则取决于目标 collation。大表执行前先看执行计划和资源窗口。</p>
<h3>选择目标不能只看&ldquo;最新&rdquo;</h3>
<p>目标字符集与 collation 必须符合当前 Magento/Adobe Commerce 版本和数据库版本支持范围。不要因为 MySQL 新默认值看起来更现代，就在未验证的情况下切到另一套排序规则。尤其要检查索引键长度、JSON、临时表和复制节点兼容性。</p>
<h3>安全迁移步骤</h3>
<p>先列出所有非目标 collation 的列；按实际 join 关系确定优先级；在恢复副本或预发布环境转换；运行 <code>setup:upgrade</code>、索引、导入、客户登录和搜索回归；生产环境按表大小安排在线 DDL 或维护窗口。转换后再次查询 information_schema，并检查慢查询是否因隐式转换而失去索引。</p>
<p>真正的修复不是让报错的那条 SQL 成功，而是让数据库默认值、现有列、应用连接和自定义 schema 使用一致且受支持的规则，确保下一次部署不会重新创建冲突表。</p>]]></description>
      <pubDate>Thu, 31 Oct 2024 07:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付 Webhook 重复推送，Magento 2 如何避免重复开票？]]></title>
      <link>https://www.360magento.com/blog/webhook-duplicate-invoice/</link>
      <description><![CDATA[<p>支付平台没有在规定时间收到 2xx，会重试同一个 Webhook；有的平台即使收到成功响应，也会在网络不确定时再次投递。重复推送不是异常，无法依赖&ldquo;平台只发一次&rdquo;。Magento 2 的回调处理必须保证同一支付事件无论到达一次还是十次，最终只产生一张应有的发票和一次业务副作用。</p>
<h3>先验签，再讨论幂等</h3>
<p>在读取事件内容后使用平台规定的原始 body、时间戳和签名算法验证，拒绝超出时间窗口或签名错误的请求。不要把解析后重新序列化的 JSON 用于验签，字段顺序和空格可能改变。签名密钥只从安全配置读取，日志中不得输出。</p>
<h3>用平台事件 ID 做唯一键</h3>
<p>支付流水号、事件 ID 或 payment intent ID 应保存到独立事件表，并建立唯一约束。订单号本身不够，因为同一订单可能有授权、支付、退款等多个合法事件。</p>
<pre><code>CREATE TABLE vendor_payment_event (
  event_id varchar(128) NOT NULL,
  event_type varchar(64) NOT NULL,
  order_id int unsigned DEFAULT NULL,
  status varchar(32) NOT NULL,
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (event_id)
);</code></pre>
<p>这只是设计示例。Magento 模块应通过 declarative schema 创建表，并考虑事件 ID 的字符集、长度与平台范围。收到事件时先尝试登记；唯一键冲突表示已经处理或处理中，读取状态后返回合适的 2xx，而不是再开票。</p>
<h3>&ldquo;先查有没有发票&rdquo;仍有竞态</h3>
<p>两个请求几乎同时执行，都可能在第一步看到没有发票，然后各自创建。需要数据库事务、唯一事件键和对订单/支付状态的锁定组合。Magento service 层的 <code>canInvoice()</code> 是必要检查，但单独调用不能消除并发窗口。</p>
<p>一种稳妥流程是：登记事件为 processing；在事务内锁定对应订单或业务幂等记录；重新加载订单；确认支付金额、币种、交易 ID 和可开票数量；创建并登记发票；提交后把事件标记为 complete。失败则记录可重试状态和安全错误摘要。</p>
<h3>金额和状态必须再次验证</h3>
<p>不能因为签名正确就按 Webhook 提供的订单号开票。应从平台元数据和 Magento payment additional information 找到订单，比较 merchant account、currency、authorized/captured amount 与已有 transaction。部分捕获、分批发货和多发票订单不能简单判断&ldquo;存在发票就跳过&rdquo;。</p>
<h3>外部事件与本地动作分开记录</h3>
<p>如果开票后还要发邮件、推 ERP、扣积分，这些副作用也要有各自幂等键。发票保存成功、邮件发送超时后重试 Webhook，不能再创建发票；应从事件状态继续未完成步骤，或投递到内部可靠队列。</p>
<h3>快速响应，不在回调里做重活</h3>
<p>Webhook 入口完成验签和可靠入队后即可返回 2xx，后续由消费者处理。若必须同步处理，确保平台超时大于最坏执行时间并正确处理数据库锁。无论哪种方式，都不要先返回成功再把事件放进不可靠的内存队列。</p>
<h3>重放测试比单次成功更重要</h3>
<p>在测试环境保存一份脱敏事件，连续发送十次，并发发送两次，再模拟&ldquo;发票已保存但事件状态未更新&rdquo;与&ldquo;邮件失败&rdquo;。预期是发票数量和 captured amount 始终正确，事件表能说明每次请求结果。最后检查后台订单历史、payment transaction、invoice grid 和外部平台账单，不能只看接口返回 200。</p>]]></description>
      <pubDate>Wed, 30 Oct 2024 05:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[每次发布后客户都被登出，Magento 2 Session 为什么会失效？]]></title>
      <link>https://www.360magento.com/blog/customers-logged-out-after-deploy/</link>
      <description><![CDATA[<p>代码发布完成，页面没有报错，但所有登录客户都回到未登录状态。很多团队把它当成&ldquo;清缓存的正常现象&rdquo;，其实 Magento 页面缓存与客户 Session 是不同数据。正常的静态资源发布、DI 编译和页面缓存刷新，不应该必然删除所有会话。</p>
<h3>确认 Session 存在哪里</h3>
<p>查看 <code>app/etc/env.php</code> 的 session 配置：文件、Redis 或其他存储。多 Web 节点若用本地文件且没有粘性会话，客户请求切到另一节点就像被登出；蓝绿发布切换节点后现象会更明显。</p>
<p>Redis 环境重点比较发布前后的 host、port、database、prefix 和连接参数。部署模板如果每次生成随机前缀，旧 Session 仍在 Redis 中，但新代码找不到。不要为了排查在聊天或日志中暴露 Redis 密码。</p>
<h3>发布脚本是否误清 Session</h3>
<pre><code>grep -R 'cache:flush|FLUSHDB|session' deploy/ .github/ 2&gt;/dev/null
redis-cli -n 2 DBSIZE</code></pre>
<p>路径和 Redis DB 仅为示例。<code>cache:flush</code> 可能清理共享 Redis 实例中的其他数据，若 cache 与 session 使用同一 DB 或错误前缀，影响更大。发布流程应使用精确的 Magento cache clean，并把 session 独立隔离。</p>
<h3>Cookie 是否在发布时改变</h3>
<p>比较发布前后的 <code>Set-Cookie</code>：域名、Path、Secure、HttpOnly、SameSite 和过期时间。Base URL、HTTPS offloader 或 Cookie Domain 被配置管理覆盖后，浏览器可能不再发送旧 cookie。用浏览器 Network 看请求 Cookie，比只看 Application 面板更可靠。</p>
<h3>加密密钥与节点配置必须一致</h3>
<p><code>env.php</code> 中的 crypt key 不应在每次部署重建。多节点 key 不一致会破坏依赖加密的数据，并可能表现为会话异常。部署包应保留环境专属密钥，通过安全配置注入；不能把新环境的 env.php 直接覆盖生产。</p>
<h3>会话寿命和 GC</h3>
<p>若不是所有客户同时退出，而是发布后活跃用户更容易失效，检查 session lifetime、Redis TTL、PHP gc_maxlifetime 与 Magento Cookie Lifetime。长时间维护模式导致 TTL 到期属于另一种情况。记录 session key 的 TTL 随请求是否刷新，能区分超时与主动删除。</p>
<h3>修复验证</h3>
<p>在发布前建立两个测试会话，记录脱敏后的 session 标识；执行与生产相同的蓝绿切换、缓存清理和流量迁移；发布后确认 cookie 仍发送、后端 key 仍存在、TTL 合理且客户保持登录。再分别测试购物车和后台管理员会话。目标不是永不让 Session 过期，而是代码发布不应成为无条件失效事件。若必须主动失效，应作为安全变更明确通知，而不是发布脚本的副作用。</p>]]></description>
      <pubDate>Tue, 29 Oct 2024 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[MSI 自动选择了错误仓库，Source Selection Algorithm 怎么检查？]]></title>
      <link>https://www.360magento.com/blog/msi-selected-wrong-source/</link>
      <description><![CDATA[<p>客户在华东下单，系统却建议从华南仓发货；或者明明 A 仓有库存，创建 shipment 时只列出 B 仓。MSI 中&ldquo;可售&rdquo;和&ldquo;从哪个 Source 扣减&rdquo;是两步。前者由销售渠道关联的 Stock 聚合并结合 reservation 得到，后者由 Source Selection Algorithm 在发货阶段给出分配建议。</p>
<h3>先确认订单属于哪个 Stock</h3>
<p>Website 通过 sales channel 关联到一个 Stock，Stock 再关联多个 Source。商品在某个 Source 有数量，不等于当前网站能使用它。检查后台 Stores &rarr; Inventory &rarr; Stocks 与 Sources，确认网站没有绑到测试 Stock，Source 也没有被禁用。</p>
<pre><code>SELECT stock_id, type, code
FROM inventory_stock_sales_channel
WHERE type = 'website';

SELECT link.stock_id, link.source_code, link.priority
FROM inventory_source_stock_link AS link
ORDER BY link.stock_id, link.priority;</code></pre>
<p>不同版本表字段可能存在差异，查询前先看结构。这里只做读取，不要直接改 link 表；库存配置应通过后台或服务接口保存，使索引和缓存同步更新。</p>
<h3>Priority 算法只认识顺序与可用数量</h3>
<p>按优先级选择时，算法从优先级高的 Source 开始满足请求，必要时拆分。若优先级配置与业务理解相反，结果就会&ldquo;选错&rdquo;。还要检查 source item 的 status，不是只有 quantity 大于零就能用。</p>
<pre><code>SELECT source_code, sku, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001'
ORDER BY source_code;</code></pre>
<p>Source 本身启用、商品 source item 启用、数量足够，三者缺一不可。Threshold 与 reservation 影响 salable quantity，但 SSA 读取的数据与前台可售判断并非完全同一个简单字段。</p>
<h3>Distance 算法依赖可解析的地址</h3>
<p>距离算法可能使用 Google Maps 或离线 geonames，取决于安装与配置。收货地址缺少国家、邮编、城市，仓库经纬度或地址错误，API key 无权限或配额耗尽，都会导致无法正确计算。检查日志中地理编码请求与回退行为，并确认隐私政策允许把必要地址发送给外部服务。</p>
<p>不要拿直线距离代替运输成本的全部含义。偏远地区、跨境清关、仓库截单时间和承运商服务范围都可能让&ldquo;最近仓&rdquo;不是最佳仓。若业务规则更复杂，需要自定义算法或在 WMS 中决策，而不是强行修改 source priority。</p>
<h3>Reservation 解释了&ldquo;看起来有货&rdquo;</h3>
<p>下单时 MSI 通常写 reservation，实际 Source quantity 在 shipment/deduction 时变化。未完成订单、取消补偿失败或导入脚本绕过库存服务，可能造成 salable quantity 与物理数量差异。使用官方命令检查库存不一致并在确认后补偿，不能随意删除 reservation 表记录。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies -r
bin/magento inventory:reservation:create-compensations</code></pre>
<p>第二条命令需要把审查过的输出作为输入流程的一部分，不能空跑后假定安全。先备份并核对订单状态。</p>
<h3>谁最终覆盖了算法建议</h3>
<p>SSA 返回的是建议，管理员创建 shipment 时可以调整，ERP/WMS 扩展也可能重新分配。记录订单号、算法名称、输入地址、候选 Source、建议数量和最终 shipment source。若数据库中的 shipment 已是错误仓，要查调用链而非只改算法配置。</p>
<h3>构造边界测试</h3>
<p>至少测试单仓足量、多个仓拆单、最高优先级缺货、地址缺邮编、Source 被禁用、取消订单后 reservation 补偿六种情况。每次先记录 salable quantity，再运行选择并创建测试 shipment。只有建议结果和最终扣减都符合预期，才能确认多仓链路已修复。</p>]]></description>
      <pubDate>Mon, 28 Oct 2024 09:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台导入一直显示 Please wait，文件到底有没有开始处理？]]></title>
      <link>https://www.360magento.com/blog/admin-import-stuck-please-wait/</link>
      <description><![CDATA[<p>选择 CSV 后点击&ldquo;检查数据&rdquo;或&ldquo;导入&rdquo;，后台遮罩一直显示 <code>Please wait...</code>，管理员不知道任务是否开始。此时不要重复点击。一次导入若已经到达服务端，第二次请求可能并发写同一批 SKU，让锁等待和重复处理更加严重。</p>
<h3>Network 先回答有没有发出请求</h3>
<p>打开浏览器开发者工具，查看导入按钮触发的 POST。没有请求，检查 Console、form key 与管理后台 JS；请求返回 413，说明 Web server 限制上传体积；返回 504，说明代理等待超时；返回 200 但响应不是预期 JSON，常见于 PHP warning 或登录页被当作结果。</p>
<h3>确认上传文件真的进入服务器</h3>
<p>检查 PHP 的 <code>upload_max_filesize</code>、<code>post_max_size</code>、临时目录权限和磁盘空间。post_max_size 小于文件时，PHP 可能收到空表单，表现不一定是清晰的&ldquo;文件过大&rdquo;。Nginx/Apache 与 CDN 也有各自限制，要看最小的一层。</p>
<pre><code>php -i | egrep 'upload_max_filesize|post_max_size|max_execution_time|memory_limit'
df -h
df -i</code></pre>
<p>CLI 的 php.ini 可能与 PHP-FPM 不同，命令输出只能作为线索，应从实际 FPM pool 或 phpinfo 的受控页面确认。</p>
<h3>校验和正式导入是两步</h3>
<p>Magento 先分析列、行为、错误阈值和样本数据，再执行写入。大文件在校验阶段就可能读取大量属性和 SKU。检查 <code>var/log/system.log</code>、<code>exception.log</code>、PHP-FPM 与 Web server error log，按点击时间对齐，而不是只搜&ldquo;import&rdquo;。</p>
<h3>异步导入要看消费者</h3>
<p>若站点启用了异步批量处理，后台请求可能只是创建任务，真正执行依赖消息队列 consumer。查看消费者、队列积压与 Cron，不要因为页面遮罩还在就认为 PHP 一直处理。</p>
<pre><code>bin/magento queue:consumers:list
bin/magento queue:consumers:start async.operations.all --max-messages=100
bin/magento cron:run</code></pre>
<p>示例中的消费者名称要以当前安装版本和模块列表为准。生产环境启动常驻 consumer 应由 supervisor/systemd 管理，不要在 SSH 会话里无限运行。</p>
<h3>用小文件切分问题</h3>
<p>保留相同列头，只放一个已知 SKU 测试。小文件成功、大文件失败，重点查资源与数据规模；小文件也失败，重点查字段映射、权限和代码异常。按实体 ID 或 SKU 稳定分批，记录每批结果，避免用随机拆分导致难以重跑。</p>
<p>恢复后检查几条商品的 EAV 值、网站分配、库存和索引，不要只相信&ldquo;导入完成&rdquo;提示。若页面仍不关闭遮罩但后台数据已写入，则要单独修复前端响应处理；业务已经执行与界面是否结束是两个问题。</p>]]></description>
      <pubDate>Fri, 25 Oct 2024 04:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[REST API 报 The signature is invalid，OAuth 1.0 怎么定位？]]></title>
      <link>https://www.360magento.com/blog/rest-oauth-signature-invalid/</link>
      <description><![CDATA[<p>集成拿到了 consumer key、consumer secret、access token 与 token secret，但请求 Magento 2 REST API 返回 <code>The signature is invalid. Verify and try again.</code>。重新创建 Integration 有时会暂时&ldquo;解决&rdquo;，更多时候只是把原有参数覆盖。OAuth 1.0 的签名对每一个字符敏感，必须比较双方实际参与计算的内容。</p>
<h3>固定一条最简单的请求</h3>
<p>先用 GET 请求一个权限允许、没有复杂 body 的端点，保存 HTTP method、完整 URL、Authorization header 与响应。调试日志中密钥必须脱敏，nonce 和 timestamp 可以保留用于复现。</p>
<p>签名基础字符串由大写方法、规范化 base URL、规范化参数三部分组成。以下差异都会产生完全不同的 HMAC：</p>
<ul>
<li>客户端签的是 http，代理外部访问却是 https；</li>
<li>URL 带默认端口或尾斜杠，服务端规范化后不同；</li>
<li>query 参数排序、重复参数或空值处理不同；</li>
<li>空格用加号编码，而 OAuth 需要 RFC 3986 百分号编码；</li>
<li>把 <code>oauth_signature</code> 本身放进待签参数。</li>
</ul>
<h3>打印 base string，不要打印 secret</h3>
<p>在客户端库签名前增加临时调试，输出 normalized URL、参数排序结果和 signature base string。Magento 侧在隔离测试环境增加对应日志，比较第一个不同字符。生产环境不要记录完整 Authorization header，因为 token 可被重放利用。</p>
<pre><code>GET&amp;https%3A%2F%2Fwww.example.com%2Frest%2FV1%2Fstore%2FstoreConfigs&amp;oauth_consumer_key%3D...</code></pre>
<p>这只是结构示例，不可直接作为签名输入。实际字符串必须包含本次请求的全部 OAuth 参数和查询参数。</p>
<h3>代理和 Base URL 经常是根因</h3>
<p>Magento 部署在负载均衡后时，如果 secure/offloader header 配置错误，应用认为请求来自 HTTP，而客户端按 HTTPS 签名。检查 Web server、trusted proxy、Base URL 与 Host 转发。客户端签名 URL 必须与 Magento 用来验证的有效请求 URL 一致，不能用容器内部主机名签名再通过公网域名发送。</p>
<h3>时间戳与 nonce 是另一类错误</h3>
<p>服务器和客户端时间偏差过大、重复 nonce、秒和毫秒混用，也会让鉴权失败。先使用 NTP/chrony 校时，确认 timestamp 是 Unix 秒。若错误信息明确为 nonce 已使用，不要把它混同为 HMAC 计算错误。</p>
<h3>密钥组合顺序</h3>
<p>HMAC-SHA256/HMAC-SHA1 具体实现取决于客户端与 Magento 支持配置，但 signing key 的组成应是编码后的 consumer secret 与 token secret，中间用 <code>&amp;</code> 连接。常见错误是交换 key/secret、使用 Integration 激活前的旧 token，或把显示时复制到的空格一并保存。</p>
<h3>POST body 是否进入签名</h3>
<p>JSON body 通常不按表单参数加入 OAuth 1.0 参数归一化；<code>application/x-www-form-urlencoded</code> 则需要按规范处理。客户端库如果不区分 Content-Type，会出现 GET 成功、POST 失败。先比较请求头和库版本，再决定是否调整参数收集。</p>
<h3>最后再轮换凭据</h3>
<p>只有确认 base string 一致仍无法验证，或密钥可能泄露时，才撤销并重新激活 Integration。轮换会中断现有调用方，应先盘点使用者。修复完成后用固定测试请求通过，再测试带 query、JSON POST 和反向代理路径；同时删除临时签名日志。这样才能证明问题不是被新 token 偶然掩盖。</p>]]></description>
      <pubDate>Thu, 24 Oct 2024 08:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 修改 layout XML 不生效，先检查 handle 和缓存]]></title>
      <link>https://www.360magento.com/blog/layout-xml-change-not-working/</link>
      <description><![CDATA[<p>把一个 block 加进 <code>catalog_product_view.xml</code>，清了浏览器缓存却没有出现；或者 remove 指令对某个页面始终无效。layout XML 是按 handle 合并的，文件存在并不代表当前请求加载了它。先确定 handle，再谈缓存。</p>
<h3>文件名必须对应当前 handle</h3>
<p>商品详情常用 <code>catalog_product_view</code>，分类页是另一个 handle，自定义 controller 还会按 frontName、controller、action 生成名称。打开开发者工具或在测试环境启用布局调试，确认实际 handle。不要靠 URL 字面猜文件名。</p>
<h3>reference 的 name 不是模板别名</h3>
<pre><code>&lt;referenceContainer name="content"&gt;
    &lt;block class="VendorModuleBlockNotice"
           name="vendor.product.notice"
           template="Vendor_Module::notice.phtml" /&gt;
&lt;/referenceContainer&gt;</code></pre>
<p><code>referenceContainer</code> 必须指向已经存在的 container name。主题或扩展改过结构后，网上示例中的 name 可能不存在。搜索合并来源里的声明，注意同名 block 可能被后加载模块移除。</p>
<h3>清正确的缓存</h3>
<pre><code>bin/magento cache:clean layout block_html full_page
bin/magento cache:status</code></pre>
<p>XML 结构变化通常不需要删除所有 generated 代码。生产环境清 full_page 会影响命中率，应该在维护窗口或精确 purge。若文件根本没有部署到当前 release，清多少次都无效。</p>
<h3>确认主题与模块加载顺序</h3>
<p>查看当前 store 使用的主题及其父主题，确认 XML 放在正确模块目录。模块之间需要顺序时，在 <code>module.xml</code> 声明 sequence，但不要为了&ldquo;让我的 XML 最后执行&rdquo;随意依赖大量模块。</p>
<h3>生成了却看不见，是另一类问题</h3>
<p>页面源码里已经有目标 HTML，而视觉上没有变化，应检查模板条件、CSS 的 <code>display:none</code>、响应式断点和 JavaScript 是否把节点移走。Block 类构造失败或模板文件路径错误时，则查看 <code>var/log/exception.log</code> 与 PHP 日志。把一个带固定文本的最小模板放入相同位置，可以快速区分数据逻辑和布局结构。</p>
<p>修复后不要只刷新已经打开的页面。用无痕窗口访问同一 store view，再测试不同商品类型和客户组。若 XML 仅对某个 product attribute 条件生效，确认条件数据在当前 store scope 存在。最终以布局结构中出现目标 block、模板成功渲染、FPC 命中后仍显示正确为完成标准。</p>]]></description>
      <pubDate>Wed, 23 Oct 2024 01:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[robots.txt 屏蔽了 CSS/JS，Magento 2 页面还能被正确收录吗？]]></title>
      <link>https://www.360magento.com/blog/robots-blocked-css-js/</link>
      <description><![CDATA[<p>为了减少&ldquo;无用抓取&rdquo;，有人在 robots.txt 里加入 <code>Disallow: /static/</code> 或屏蔽所有带版本号的资源路径。页面 URL 仍可能被搜索引擎发现并收录，但抓取器无法获得布局 CSS、响应式样式和由 JavaScript 呈现的内容，最终可能误判移动端体验、隐藏文本或页面主体。</p>
<h3>能收录不等于能正确渲染</h3>
<p>robots.txt 控制抓取许可，不是可靠的 noindex 工具。HTML 能抓取时，搜索引擎可能把 URL 放进索引；但渲染阶段若 CSS/JS 被阻止，看到的页面与用户不同。Magento 主题依赖 RequireJS、动态 bundle 和部署后的静态文件，粗暴屏蔽整个 <code>/static/</code> 风险很高。</p>
<h3>先获取搜索引擎实际看到的 robots.txt</h3>
<pre><code>curl -sS -D - https://www.example.com/robots.txt -o /tmp/robots.txt
sed -n '1,160p' /tmp/robots.txt</code></pre>
<p>检查状态码、Content-Type、CDN 缓存年龄和是否发生跳转。多网站、多域名环境中，每个 host 都有自己的 robots.txt；后台配置正确，不代表 CDN 没在返回旧文件。生产环境若不便使用临时路径，可直接输出到终端并注意日志。</p>
<h3>版本化静态资源路径不要逐个写死</h3>
<p>Magento 生产部署常使用类似 <code>/static/version123456/frontend/Vendor/theme/locale/...</code> 的 URL。版本号变化是缓存失效机制的一部分。robots 规则应基于稳定路径并保持 CSS、JS、字体和必要图片可抓取，而不是允许某个版本号。</p>
<p>同时检查静态资源的 HTTP 状态：</p>
<pre><code>curl -sSI https://www.example.com/static/version123/frontend/Vendor/theme/zh_Hans_CN/css/styles-m.css
curl -sSI https://www.example.com/static/version123/frontend/Vendor/theme/zh_Hans_CN/requirejs/require.js</code></pre>
<p>200 只说明服务器能返回文件，还需要用 robots 测试工具或站长平台 URL 检查确认对应 user-agent 被允许。CDN 防盗链、WAF 和地域策略也可能对爬虫返回 403，这不是 robots 规则能解决的。</p>
<h3>什么内容才适合阻止抓取</h3>
<p>站内搜索结果、客户账户、购物车、结账和某些参数组合通常没有搜索价值，但处理方式应结合 noindex、canonical、登录权限和 URL 参数策略。仅靠 Disallow 会让搜索引擎无法看到页面上的 noindex；已经收录的 URL 也不会因此立即消失。</p>
<p>Magento 的 layered navigation 会生成大量筛选组合，不能因为担心抓取预算就连公共资源一起屏蔽。应明确哪些筛选页有独立搜索需求，哪些统一 canonical 或 noindex，并保持规则与 sitemap 一致。</p>
<h3>改完后检查渲染，而不是只检查语法</h3>
<p>选择首页、分类页、商品页各一个 URL，用站长平台的实时测试查看抓取与渲染截图，确认主内容、导航、价格和移动布局可见。再查看服务器日志中 CSS/JS 是否返回 200，以及是否出现大量 404 旧版本资源。</p>
<p>robots.txt 修改通常需要等待重新抓取，CDN 还可能缓存。发布时记录旧规则、purge 对象并持续观察。页面可以被&ldquo;收录&rdquo;不代表 SEO 问题已解决；真正目标是让抓取器获得与正常用户基本一致的可渲染页面，同时控制低价值 URL 的索引策略。</p>]]></description>
      <pubDate>Tue, 22 Oct 2024 06:57:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单邮件里的总价为什么和后台不同？]]></title>
      <link>https://www.360magento.com/blog/order-email-total-differs/</link>
      <description><![CDATA[<p>客户收到的订单确认邮件总价是 1,020 元，后台订单却显示 1,000 元。遇到这种问题，不应先修改邮件模板里的数字，因为订单邮件通常读取订单实体的金额快照；真正差异可能来自币种字段、税费展示配置、折扣分摊，或邮件发送时间早于后续调整。</p>
<h3>先比较同一组金额字段</h3>
<pre><code>SELECT entity_id, increment_id, order_currency_code, base_currency_code,
       subtotal, discount_amount, shipping_amount, tax_amount, grand_total,
       base_subtotal, base_discount_amount, base_shipping_amount,
       base_tax_amount, base_grand_total
FROM sales_order
WHERE increment_id = '000000123';</code></pre>
<p>后台可能按订单货币显示 <code>grand_total</code>，自定义邮件却错误使用 <code>base_grand_total</code>。多币种站点汇率不是 1 时，两者当然不同。还要确认邮件中的数字是小计、应付金额还是已付款金额，名称翻译错误也会造成误解。</p>
<h3>模板不应该自行重新计算</h3>
<p>标准 totals block 会按订单 totals 顺序渲染小计、折扣、运费、税费和总计。自定义模板如果用商品行价格相加再加运费，容易漏掉购物车规则、Weee、礼品卡、store credit、舍入差额或含税价格。邮件应展示订单已经保存的金额，而不是在模板层复制一套计算器。</p>
<p>检查主题覆盖的邮件模板和 layout handle，特别是自定义 block 是否调用 <code>getBaseGrandTotal()</code>、对负数折扣又减一次，或者把格式化后的字符串当数字运算。临时切回标准模板可用于对比，但不要直接在生产环境丢弃品牌模板。</p>
<h3>税费显示配置会让行项目看起来对不上</h3>
<p>后台 Stores &rarr; Configuration &rarr; Sales &rarr; Tax 中，订单、发票、贷项通知与邮件有独立显示配置。行价格含税、小计不含税时，读者手算可能得不到邮件总计，但底层订单金额仍正确。应把邮件每一项的含税口径标清，而不是调整 grand total 去迎合手算。</p>
<h3>确认邮件发送时机</h3>
<p>订单创建后，支付扩展可能更新运费、手续费或附加费；如果邮件在更新前入队，邮件使用的是当时序列化或加载的订单状态。检查异步邮件队列、支付回调和观察者执行顺序。重复发送同一订单后金额正确，通常说明第一次发送过早。</p>
<h3>验证不能只看一封旧邮件</h3>
<p>在测试环境建立含税、折扣、运费和外币的订单，对照数据库、后台、邮件和支付请求四处金额。模板修复后新建订单，不能用已经生成的旧邮件缓存判断。若支付平台扣款金额也不同，优先按交易事故处理；若仅展示不同，则修复模板与发送时机，并保留订单原始金额审计。还要各做一次部分开票和退款，确认后续邮件没有把订单总额、发票总额与退款金额混为一谈。</p>]]></description>
      <pubDate>Mon, 21 Oct 2024 03:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[搜索结果和分类页商品对不上，Magento 2 到底读了哪套数据？]]></title>
      <link>https://www.360magento.com/blog/search-category-products-mismatch/</link>
      <description><![CDATA[<p>同一个 SKU 能在搜索结果中找到，却不出现在所属分类；或者分类显示 120 件，搜索同一关键词只有 113 件。两种页面看起来都是&ldquo;商品列表&rdquo;，但候选商品来源和过滤条件并不完全相同。简单清缓存可能暂时改变结果，却无法说明是哪一层不一致。</p>
<h3>先选三个具体 SKU 做集合差异</h3>
<p>不要从总数开始猜。分别找&ldquo;只在搜索出现&rdquo;&ldquo;只在分类出现&rdquo;&ldquo;两边都有但排序异常&rdquo;的 SKU，记录 store view、客户组、库存地点、币种和登录状态。总数还可能受分页、聚合和近似计数影响，具体实体更容易追踪。</p>
<h3>分类页先看关联与网站范围</h3>
<pre><code>SELECT cp.category_id, cp.product_id, cp.position
FROM catalog_category_product AS cp
JOIN catalog_product_entity AS p ON p.entity_id = cp.product_id
WHERE p.sku = 'SKU-001';</code></pre>
<p>有关系行还不够。分类与商品都必须分配到当前 website/store，商品状态启用，visibility 允许出现在 catalog。可配置商品还要看父商品状态与至少一个可售子商品。后台&ldquo;选择了分类&rdquo;但导入后索引未更新，也会出现关系存在、前台缺失。</p>
<h3>搜索读的是搜索引擎文档</h3>
<p>Magento 2 的目录搜索会把商品字段写入 OpenSearch/Elasticsearch 索引。文档可能仍保留已经删除的分类或旧状态，也可能因为批量索引失败而缺少新商品。先看 indexer 状态与 backlog：</p>
<pre><code>bin/magento indexer:status
bin/magento indexer:show-mode
bin/magento indexer:reindex catalogsearch_fulltext catalog_category_product
bin/magento cron:run --group=index</code></pre>
<p>全量重建只能作为诊断和一次性恢复。若重建后两边一致，随后又分叉，应检查 mview_state、changelog 消费、Cron 和导入程序是否触发变更。不要安排每五分钟全量重建来掩盖增量链路故障。</p>
<h3>可见性条件本来就不同</h3>
<p>商品 visibility 可以是 Not Visible Individually、Catalog、Search、Catalog/Search。设为 Search 的商品可以在搜索出现而分类页隐藏；设为 Catalog 则相反。这是配置行为，不是索引错误。先在正确 store scope 查看 visibility，因为默认范围与 store override 可能不同。</p>
<h3>库存与价格会进一步过滤</h3>
<p>开启隐藏缺货商品后，库存可售性会影响集合。MSI 环境下不要只查 legacy stock item 的 qty，应确认当前 sales channel 对应 stock、source item 状态、reservation 和 salable quantity。客户组权限、共享目录、价格为零的自定义过滤也可能只挂在某一种列表 provider 上。</p>
<p>若主题或扩展对分类 collection 加了额外 plugin，例如排除无图片商品，而搜索 adapter 没有同样规则，两边永远不会一致。搜索代码时查 collection processor、layer、search criteria 与 around plugin，不要只查模板。</p>
<h3>URL 参数会悄悄改变集合</h3>
<p>分类页可能保留 <code>?color=</code>、price、mode、order 参数；搜索页有 query text、同义词、最小匹配和拼写修正。测试时从干净 URL 开始，清空 localStorage 中的自定义筛选状态。Canonical 是否去掉参数只影响搜索引擎理解，不会替你修复运行时集合。</p>
<h3>正确的验证方式</h3>
<p>对三个样本 SKU 逐层记录：数据库分类关联、store 级状态与可见性、website 分配、当前 stock 可售性、搜索文档是否存在、最终查询是否包含。修复后修改其中一个商品的分类与状态，等待增量索引，再看两页是否同步变化。只有增量路径通过，才能说明两套数据重新对齐。</p>]]></description>
      <pubDate>Fri, 18 Oct 2024 07:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[CDN 把客户页面缓存了，会出现哪些危险现象？]]></title>
      <link>https://www.360magento.com/blog/cdn-cached-customer-pages/</link>
      <description><![CDATA[<p>Magento 2 接入 CDN 后，偶尔有人反馈&ldquo;登录后看到别人的名字&rdquo;&ldquo;购物车数量跳来跳去&rdquo;或&ldquo;退出后账户页还能打开&rdquo;。这不是普通缓存不一致，而是潜在的数据泄露事件。公共 HTML 缓存一旦包含客户专属内容，影响可能跨账号、跨地区持续扩散。</p>
<h3>最危险的信号</h3>
<p>不同浏览器请求同一 URL，响应 HTML 中出现相同客户姓名、邮箱、地址片段或订单号；<code>/customer/account/</code>、checkout、wishlist、compare 等路径带有 CDN HIT；响应包含 <code>Set-Cookie</code> 却仍被共享缓存；登录与未登录请求使用相同 cache key。这些现象出现任何一个，都应按安全事件止损，而不是等用户刷新。</p>
<h3>先旁路，再保留证据</h3>
<p>立即对账户、购物车、结账、API 和自定义会员路径设置 bypass/no-store，并 purge 相关缓存对象。保留 CDN 请求 ID、时间、POP、cache status、URL、匿名化后的请求头和响应头，避免保存不必要的个人数据。若确认跨客户泄露，应启动公司的隐私与安全响应流程。</p>
<pre><code>curl -sSI https://www.example.com/customer/account/
curl -sSI -H 'Cookie: PHPSESSID=REDACTED' https://www.example.com/customer/account/</code></pre>
<p>不要把真实 session cookie 写进工单或 shell history。测试应使用专门测试账号和短期会话。</p>
<h3>Magento 的 private content 解决不了错误的整页规则</h3>
<p>标准可缓存页面把迷你购物车等客户信息放在浏览器端 customer-data section 中，公共 HTML 本身不应包含敏感值。但自定义 block 直接读取 customer session、模板输出姓名，同时仍允许整页缓存，就会污染 FPC。即使 Magento 源站返回正确的 <code>private/no-cache</code>，CDN 的&ldquo;cache everything&rdquo;规则也可能覆盖它。</p>
<p>检查布局 XML 中 block 的 cacheable 设置、自定义 controller 的响应头，以及 CDN 是否尊重 <code>Cache-Control: private, no-store, no-cache</code>。不要用给所有页面加随机参数的方式规避，这会摧毁缓存命中率且仍可能遗漏入口。</p>
<h3>缓存键不能只由 URL 组成</h3>
<p>可公开缓存的 Magento 页面还会受 store、currency、客户组等上下文影响。CDN 如果剥离必要 cookie 却不把等价上下文加入 cache key，会把一个维度的页面发给另一个维度。客户个人身份通常不应该进入公共 cache key，而应直接绕过缓存；否则对象数量爆炸，也更难彻底 purge。</p>
<h3>检查重定向和错误页</h3>
<p>账户页未登录时常返回登录页或重定向。CDN 若缓存 302，可能导致已登录客户持续被送回登录；反过来，缓存鉴权后的 200 会暴露内容。支付回调、失败页、订单成功页也不能被共享缓存。尤其要检查忽略 query string 的规则，成功页 token 被删掉后可能发生串页。</p>
<h3>如何证明修复有效</h3>
<p>准备测试账号 A、B 和无痕访客，在不同会话、不同 POP 条件下依次访问公共商品页与私有页面。公共页应按设计 HIT，私有页应 bypass/dynamic；A 的响应体与 customer-data 不能出现于 B。再测试登录、退出、切换币种、切换 store、购物车更新和订单成功路径。</p>
<p>最后检查 CDN 配置变更的版本记录和自动化测试。可以在部署后用合成监控断言账户路径从不返回 HIT，并扫描响应中是否出现测试账号标记。这样的监控比等真实客户截图更早发现回归。</p>]]></description>
      <pubDate>Thu, 17 Oct 2024 02:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[删除属性选项后商品保存报错，Magento 2 脏数据怎么找？]]></title>
      <link>https://www.360magento.com/blog/deleted-attribute-option-dirty-data/</link>
      <description><![CDATA[<p>管理员删除一个颜色选项后，部分商品保存报错，或者前台筛选出现空白项。这通常不是缓存问题，而是某处仍保存着已经不存在的 <code>option_id</code>。Magento 的属性定义、选项、商品值和可配置商品关系分布在不同表中，必须先确认引用链。</p>
<h3>确定属性和后端值表</h3>
<pre><code>SELECT attribute_id, attribute_code, backend_type, frontend_input
FROM eav_attribute
WHERE attribute_code = 'color';</code></pre>
<p>单选 select 常见 backend_type 为 int，对应 <code>catalog_product_entity_int</code>；多选通常存为 varchar 中的逗号分隔值。不要假定所有选项属性都在 int 表。</p>
<h3>查找已经没有定义的值</h3>
<p>对于 int 类型，可先做只读查询：</p>
<pre><code>SELECT v.entity_id, v.store_id, v.value AS option_id
FROM catalog_product_entity_int AS v
LEFT JOIN eav_attribute_option AS o ON o.option_id = v.value
WHERE v.attribute_id = 93
  AND v.value IS NOT NULL
  AND o.option_id IS NULL;</code></pre>
<p>把 93 换成实际 attribute_id。多选属性不能直接等值 join，需要在应用层拆分每个 option_id，或在副本上用受控 SQL 检查。用 <code>LIKE '%12%'</code> 会把 12、112、120 混在一起，不适合清理。</p>
<h3>可配置商品还要查 super attribute</h3>
<p>若该属性用于 configurable product，确认配置属性记录和子商品组合是否仍有效。删除一个选项不等于应该删除子商品；很多时候应给商品改成新的选项值，并同步外部 ERP 映射。</p>
<p>先导出受影响 entity_id、SKU、store_id、旧值，和业务负责人确认替代方案。直接删除 EAV 行会使商品回退到默认范围或空值，可能改变前台可见性、分层导航和变体选择。</p>
<h3>为什么保存时才暴露</h3>
<p>旧数据可能一直能被读取，但商品保存会重新运行属性验证、扩展 plugin 或搜索索引更新，于是抛出 &ldquo;option not found&rdquo;。查看完整堆栈，区分核心属性验证与第三方映射表报错。若扩展自己保存 option_id，还要一起迁移。</p>
<h3>安全修复顺序</h3>
<p>在测试环境还原同一商品；为孤立值建立旧值到新值的映射；通过 repository/批量导入更新商品；确认可配置组合、筛选和搜索正常；最后才移除不再需要的残留关系并重建相关索引。所有修改前备份目标行，生产 SQL 要限定 attribute_id、entity_id 与 store_id。修复后重新保存一个受影响商品，验证错误确实不再出现，而不是仅靠全量索引隐藏空白选项。</p>]]></description>
      <pubDate>Wed, 16 Oct 2024 05:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[MySQL 临时表写满磁盘，Magento 2 哪些查询最容易触发？]]></title>
      <link>https://www.360magento.com/blog/mysql-temp-table-disk-full/</link>
      <description><![CDATA[<p>Magento 2 运行索引或后台报表时出现 <code>The table is full</code>、<code>No space left on device</code>，第一反应往往是清理 <code>var/cache</code>。但错误如果来自 MySQL，Web 节点还有空间也没有用。MySQL 的磁盘临时文件可能写在独立 <code>tmpdir</code>，InnoDB 内部临时表还可能进入 <code>ibtmp1</code>，必须先确定满的是哪个文件系统。</p>
<h3>先停止制造更多写入</h3>
<p>索引、导入和大型报表仍在运行时，删除零散日志只能争取几秒。先暂停触发问题的 job 或把后台入口临时限制给管理员，保留订单等核心流量。不要在磁盘 100% 时盲目重启 MySQL，崩溃恢复同样需要空间。</p>
<pre><code>df -h
df -i
mysql -e "SHOW VARIABLES LIKE 'tmpdir'; SHOW VARIABLES LIKE 'innodb_temp_data_file_path';"
mysql -e "SHOW GLOBAL STATUS LIKE 'Created_tmp%';"</code></pre>
<p><code>df -i</code> 能发现 inode 耗尽。<code>Created_tmp_disk_tables</code> 是累计值，要间隔一分钟采样增量并结合请求量判断，不能只看数字大就下结论。</p>
<h3>哪些 Magento 查询容易落盘</h3>
<p>商品集合同时 join 多个 EAV 属性、使用 <code>DISTINCT</code>、<code>GROUP BY</code> 和大范围 <code>ORDER BY</code> 时，结果无法利用合适索引，容易生成临时表。价格与目录规则全量索引会处理大量 website/customer group 组合；后台销售报表按长时间段聚合；第三方导出把全部订单一次取出，也常形成大排序。</p>
<p>另一个信号是查询选择了 TEXT/BLOB 列。即使 <code>tmp_table_size</code> 很大，某些结构也会直接使用磁盘临时表。把参数无限增大不仅占内存，还可能导致并发连接同时申请大量空间。</p>
<h3>抓住正在执行的 SQL</h3>
<pre><code>mysql -e 'SHOW FULL PROCESSLIST'
mysql -e "SELECT THREAD_ID, EVENT_NAME, SQL_TEXT, TIMER_WAIT
FROM performance_schema.events_statements_current
WHERE SQL_TEXT IS NOT NULLG"</code></pre>
<p>生产环境应限制输出并保护其中的客户数据。若问题已经结束，查慢查询日志与 Performance Schema 历史。Magento 的异常堆栈能指出 collection 或 indexer，但真正需要优化的是生成的 SQL、访问行数与执行计划。</p>
<pre><code>EXPLAIN FORMAT=JSON
SELECT /* 从慢日志复制并脱敏后的查询 */ 1;</code></pre>
<p>不要对生产库直接运行来源不明的完整 SELECT，尤其是可能再次创建巨型临时表的查询。可在副本或相同数据量的测试环境分析。</p>
<h3>观察 InnoDB 临时表空间</h3>
<p>在兼容版本中，可查看 InnoDB 临时表相关的 information_schema/performance_schema 指标以及数据目录的 <code>ibtmp1</code> 大小。这个文件增长后通常不会像普通临时文件一样立即缩回操作系统。计划重启才能回收时，必须先确认复制、备份、恢复空间与维护窗口，不能把&ldquo;重启会变小&rdquo;当作在线修复。</p>
<h3>从代码侧减少数据集</h3>
<p>自定义 collection 只选择需要字段；分页导出时使用稳定的主键游标，不要用越来越大的 OFFSET；聚合报表使用预计算表；对高频过滤与关联列添加经过验证的复合索引。Magento EAV 查询里随意增加 joinAttribute 可能把一行商品扩成多行，先确认关联基数。</p>
<pre><code>// 使用主键游标分批，而不是一次加载所有实体
$collection-&gt;addFieldToFilter('entity_id', ['gt' =&gt; $lastId])
    -&gt;setOrder('entity_id', 'ASC')
    -&gt;setPageSize(500);</code></pre>
<p>循环内必须清理已加载集合和大对象，记录 lastId，并让任务可从断点继续。</p>
<h3>数据库参数只能在证据之后调整</h3>
<p><code>tmp_table_size</code> 与 <code>max_heap_table_size</code> 取较小值作为相关上限，但增大它们会放大每连接内存风险。<code>tmpdir</code> 迁移到更大磁盘也需要权限、挂载和安全策略。先用查询计划减少写入量，再按并发容量调整参数。</p>
<p>恢复后应记录磁盘增长曲线、触发 job、SQL 摘要、检查行数与修复前后耗时。只清空临时文件而不定位查询，下一次全量索引或月末报表仍会把磁盘写满。</p>]]></description>
      <pubDate>Tue, 15 Oct 2024 08:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[结账提示 Email already exists，访客还能继续下单吗？]]></title>
      <link>https://www.360magento.com/blog/checkout-email-already-exists/</link>
      <description><![CDATA[<p>顾客忘记自己注册过账号，直接以访客身份下单，结账页却提示 <code>A customer with the same email address already exists</code>。这个提示有时是安全设计，有时是扩展把&ldquo;检查邮箱是否存在&rdquo;误当成&ldquo;禁止结账&rdquo;。能不能继续下单，取决于站点的访客结账策略和本次流程是否创建客户实体。</p>
<h3>先确认配置目标</h3>
<p>在 Stores &rarr; Configuration &rarr; Sales &rarr; Checkout 检查 Allow Guest Checkout，并确认配置范围是当前 website/store view。标准访客订单可以使用与已有客户相同的邮箱，因为订单地址与客户账号不是同一实体；但强制登录、B2B 公司账号、订阅或支付风控扩展可能主动禁止。</p>
<h3>看请求正在保存 quote 还是创建 customer</h3>
<p>Network 中找到 payment-information、guest-carts 或自定义 register 请求。若堆栈进入 customer repository 的 save，并尝试创建新 customer，就要查主题里的&ldquo;结账时创建账号&rdquo;勾选项是否默认开启，或扩展是否无条件执行注册。</p>
<p>数据库只做只读确认：</p>
<pre><code>SELECT entity_id, email, website_id, is_active
FROM customer_entity
WHERE email = 'customer@example.com';</code></pre>
<p>同一邮箱在不同 website 是否允许复用，受客户账号共享范围影响。不要为让结账通过而直接改 customer email，这会破坏登录与订单归属。</p>
<h3>邮箱存在性接口不能泄露账号信息</h3>
<p>某些一页结账扩展在输入邮箱后立即显示&ldquo;该邮箱已注册&rdquo;。这会被用于枚举客户账号。更安全的交互是提示用户可以登录获得订单历史，同时仍按配置允许访客结账；需要强制登录时，也应使用统一文案与速率限制，而不是暴露明确的注册状态。</p>
<h3>修复后验证订单归属</h3>
<p>分别测试全新邮箱、已注册但未登录、登录客户三种情况。访客订单的 <code>customer_is_guest</code> 应为真且不应凭邮箱自动挂到客户账号；登录订单则必须保存 customer_id。支付成功后再确认邮件收件人、地址和后台订单客户类型。能进入成功页但错误关联客户，同样是严重的数据问题。</p>
<p>如果业务要求已有邮箱必须登录，还要验证密码重置、社交登录和多网站账号范围，避免客户被卡在无法完成的循环：结账要求登录，登录页却在错误 website 查不到账号。错误文案应告诉客户下一步，而不是只抛异常。修复后检查访客订单不会意外出现在同邮箱客户的账户历史中；需要合并订单时，应走明确、可审计并经过授权的业务流程。</p>
<p>最后检查支付快捷按钮。Apple Pay、PayPal 等快捷流程可能在标准邮箱组件之外创建 quote，若只修普通 Checkout，快捷支付仍可能触发同一冲突。把三类邮箱状态与所有启用的结账入口做成回归用例，才不会在主题升级后重新出现。</p>]]></description>
      <pubDate>Mon, 14 Oct 2024 01:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重建价格索引报 Duplicate entry，先别删索引表]]></title>
      <link>https://www.360magento.com/blog/price-index-duplicate-entry/</link>
      <description><![CDATA[<p><code>bin/magento indexer:reindex catalog_product_price</code> 报 <code>SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry</code>，最危险的做法是马上 truncate 索引表。价格索引本来会重建，删除看似合理，但冲突往往发生在临时索引写入阶段，源数据或自定义 SQL 不修正，下一次仍会失败。</p>
<h3>先完整保存错误里的键名和值</h3>
<p>错误通常包含冲突值与唯一索引名称。先查看表结构，把拼接值对应回列：</p>
<pre><code>SHOW CREATE TABLE catalog_product_index_priceG
SHOW INDEX FROM catalog_product_index_price;</code></pre>
<p>标准价格索引的唯一维度通常涉及实体、客户组与网站。若冲突表带有 <code>_temp</code>、<code>_replica</code> 或扩展前缀，要以实际表结构为准。只复制最后一行&ldquo;Duplicate entry&rdquo;会丢掉上方正在执行的 INSERT SELECT，排查前应保留完整异常。</p>
<h3>确认是不是两个重建同时进行</h3>
<p>部署脚本、Cron、管理员手动命令可能同时触发全量索引。检查进程和数据库活动，不要在未确认的情况下 kill 线程：</p>
<pre><code>ps -ef | grep '[m]agento indexer'
mysql -e 'SHOW FULL PROCESSLIST' | grep -i catalog_product</code></pre>
<p>若确有并发重建，先停止重复入口并等待当前事务结束，再进行一次受控重建。不要把数据库锁等待误判为重复数据。</p>
<h3>从生成 SQL 追到源数据</h3>
<p>冲突常见于自定义模块 join 了一张一对多表，却没有聚合，导致同一实体、网站、客户组组合产生两行。搜索对价格 indexer、table strategy、dimension collection 和 price modifier 的 preference/plugin。最近安装模块后才出现问题，先在测试环境禁用该模块对比，而不是在生产环境直接改 vendor 代码。</p>
<p>如果错误指向目录规则临时表，检查规则与网站、客户组关联；指向可配置或捆绑价格表，则检查父子关联是否重复。可先用唯一维度分组找出重复候选：</p>
<pre><code>SELECT entity_id, customer_group_id, website_id, COUNT(*) AS rows_count
FROM suspected_source_table
GROUP BY entity_id, customer_group_id, website_id
HAVING COUNT(*) &gt; 1
ORDER BY rows_count DESC;</code></pre>
<p><code>suspected_source_table</code> 必须替换为错误堆栈中实际的源表。不要把这段示例直接对未知表执行删除。</p>
<h3>检查实体关系，而不是只看产品 SKU</h3>
<p>重复 SKU 与价格索引的冲突键不是同一回事。应检查 <code>catalog_product_relation</code>、super link、website assignment，以及导入程序是否重复插入关联。标准表通常有唯一约束保护，绕过 service contract 的旧脚本可能留下异常关系。</p>
<h3>清理必须有证据和回滚</h3>
<p>确定是无效重复关系后，先备份目标行，记录实体 ID 与业务含义，再通过模块数据补丁或可审计 SQL 修复。修复源数据后依次运行 <code>setup:db:status</code>、价格索引和缓存清理。若只是索引临时表残留，也应先确认没有索引进程，再按当前版本的索引表交换机制处理。</p>
<p>完成标准不是命令这一次显示成功，而是再保存一个相关商品、等待增量索引、检查各客户组与网站价格都正确。这样才能证明唯一键冲突的来源已经消失，而不是被一次全量重建暂时覆盖。</p>]]></description>
      <pubDate>Fri, 11 Oct 2024 06:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[登录后商品价格变了，Magento 2 客户组价格从哪里算出来？]]></title>
      <link>https://www.360magento.com/blog/customer-group-price-changed/</link>
      <description><![CDATA[<p>同一个商品，未登录时显示 199 元，客户登录后变成 179 元；或者后台明明没有设置 Group Price，某个客户组仍看到不同价格。Magento 2 的最终价格不是从商品表里读取一个数字，而是商品基础价、特殊价、客户组价、目录价格规则、网站范围、税与币种共同计算后的结果。</p>
<h3>先确认差异发生在&ldquo;价格&rdquo;还是&ldquo;显示&rdquo;</h3>
<p>把两个身份的商品页、购物车和接口价格分别记录下来。若不含税金额相同、含税金额不同，优先查客户组对应的税务类别、地址和跨境税规则；若 final_price 本身不同，再进入价格索引。不要只截取页面上的大号数字，主题可能同时显示 regular、final、minimal price。</p>
<p>可以在 GraphQL 中带不同客户 token 查询 <code>price_range</code>，或在 REST/服务层以相同 store view 比较。关键是保证网站、币种、数量和时间一致，否则对比没有意义。</p>
<h3>索引表能告诉你是哪一维不同</h3>
<pre><code>SELECT entity_id, customer_group_id, website_id,
       tax_class_id, price, final_price, min_price, max_price, tier_price
FROM catalog_product_index_price
WHERE entity_id = 1234
ORDER BY website_id, customer_group_id;</code></pre>
<p>这里每个 website 与 customer_group 都有独立行。某组的 final_price 已经不同，说明差异发生在索引计算之前或之中；索引一致而前端不同，应查税、币种转换、自定义 price renderer 与缓存私有内容。</p>
<h3>客户组价只是候选价格之一</h3>
<p>商品 Advanced Pricing 中的 Customer Group Price、Tier Price 会与 Special Price、Catalog Price Rule 等候选值比较。对可配置商品，父商品展示价还会由可售子商品聚合；某客户组看不到最低价子商品时，最小价格也会改变。B2B 环境的 Shared Catalog 还能覆盖公共目录价格。</p>
<p>排查时列出该 SKU 的所有价格来源，而不是只查一个属性：</p>
<pre><code>bin/magento indexer:status catalog_product_price
bin/magento indexer:show-mode catalog_product_price
bin/magento indexer:reindex catalog_product_price</code></pre>
<p>手动重建可用于验证索引是否陈旧，但如果重建后恢复、随后又失效，根因通常在 Cron、MView changelog 或某个导入程序没有正确触发变更。不能把定时 reindex 当长期修复。</p>
<h3>缓存必须按正确上下文变化</h3>
<p>Magento 的页面缓存会通过 HTTP context 区分客户组等上下文。自定义 block 如果直接读取 session，又声明为 cacheable，可能把某个客户组的 HTML 缓存给另一个组。反过来，把整个商品页设为不可缓存也不是修复，只会让性能下降。</p>
<p>检查自定义价格 block 是否使用标准 price renderer；检查 plugin 是否修改 <code>getFinalPrice</code> 却没有提供正确的缓存身份；检查 CDN 是否忽略 Magento 的缓存 cookie。若错误价格只在第一次登录后出现，刷新又正常，重点看 customer-data 与页面缓存切换。</p>
<h3>数量、日期和时区也会改变结论</h3>
<p>Tier Price 依赖数量，Special Price 与规则可能有起止日期。后台时区、应用时区和数据库 UTC 混用时，切换点附近常出现&ldquo;某组提前生效&rdquo;。记录服务器时间、store locale 与价格规则状态，再对比索引生成时间。</p>
<h3>一段安全的定位思路</h3>
<p>先比较未税 final_price，再用索引表按 website/customer_group 确认差异是否已被计算；然后逐一排除 Group/Tier Price、Catalog Rule、Shared Catalog；最后才查税显示和缓存。修复后至少覆盖访客、普通组、特殊组、不同数量与购物车重算。价格页正确但购物车错误，说明 quote totals 链路仍未修好，不能算完成。</p>]]></description>
      <pubDate>Thu, 10 Oct 2024 03:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[cron_schedule 为什么会生成重复任务？Magento 2 Cron 并发分析]]></title>
      <link>https://www.360magento.com/blog/cron-schedule-duplicate-jobs/</link>
      <description><![CDATA[<p>打开 <code>cron_schedule</code>，看到同一个 <code>job_code</code> 连续几十行，很容易判断为&ldquo;Cron 重复生成&rdquo;。先别删表。Magento 会提前为未来时间窗口创建 schedule，同一任务按分钟运行时，本来就会有多条 pending 记录。真正需要处理的是同一计划时间被重复执行，或业务结果被重复写入。</p>
<h3>用时间字段区分正常排程</h3>
<pre><code>SELECT schedule_id, job_code, status, created_at,
       scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE job_code = 'vendor_sync_orders'
ORDER BY scheduled_at DESC
LIMIT 40;</code></pre>
<p><code>scheduled_at</code> 每分钟递增、状态分布为 pending/success，通常正常。两个行具有不同 schedule_id 但完全相同的 scheduled_at，需要再看它们是否真的都进入 running。若只是一条 success、一条 missed，往往是部署或系统 Cron 在临界时间切换造成。</p>
<h3>确认操作系统有没有启动两套入口</h3>
<p>常见事故是 crontab 和 systemd timer 同时运行，或者旧 release 与新 release 各保留一条命令。分别检查运行用户的 crontab、系统级 cron、容器定时任务与平台调度器：</p>
<pre><code>crontab -l
systemctl list-timers --all
ps -ef | grep '[m]agento cron:run'
grep -R 'cron:run' /etc/cron.d /etc/crontab 2&gt;/dev/null</code></pre>
<p>Magento 的 Cron 组会使用锁防止同组不安全地并行调度，但锁依赖正确的部署配置与共享资源。多节点分别使用本地文件锁、容器时钟偏差较大、任务运行时间超过锁预期，都可能造成争用。</p>
<h3>不要忽略 cron group 配置</h3>
<p><code>cron_groups.xml</code> 中的 <code>schedule_generate_every</code>、<code>schedule_ahead_for</code>、<code>schedule_lifetime</code> 决定多久生成一次、提前生成多远、迟到多久算 missed。把 ahead_for 设得很大只会制造更多未来记录，不会提高可靠性。把 lifetime 设得过短，机器短暂繁忙就会产生大量 missed。</p>
<p>如果自定义 job 使用单独 group，系统 Cron 必须实际运行这个组。只配置 default 与 consumers，新增 group 可能永远 pending；为&ldquo;补救&rdquo;而再加一条宽泛的 <code>cron:run</code>，又会制造并发入口。</p>
<h3>业务重复不等于调度重复</h3>
<p>即使 schedule 只运行一次，任务也可能在调用外部系统成功后、本地标记前崩溃。下一次重试会再次发送订单或开票。因此同步任务必须有幂等键，例如 Magento 订单实体 ID 加业务动作，并在数据库中以唯一索引保护。</p>
<pre><code>CREATE UNIQUE INDEX UNQ_VENDOR_EXPORT_ACTION
ON vendor_export_log (entity_id, action_code);</code></pre>
<p>不要直接在生产库执行示例索引。应先检查已有重复数据、字段长度和部署声明，再通过模块 schema patch 发布。外部 API 也支持幂等键时，两端都要使用同一业务键。</p>
<h3>卡死任务的判断</h3>
<p>大量 running 且没有 finished_at，可能是 PHP 进程被杀、数据库连接中断或代码没有捕获致命错误。对照系统进程与任务执行时间；确认进程已不存在后，才考虑把陈旧记录改为 error，并修复根因。直接把所有 running 更新为 success 会掩盖未完成业务，直接 truncate 则失去诊断证据。</p>
<p>最终应回答三个问题：是否存在两个系统级入口；相同 scheduled_at 是否被两个进程领取；业务动作是否有幂等保护。只有第三个问题也解决，才不会在重试、部署和网络抖动时再次出现&ldquo;重复任务&rdquo;的表象。</p>]]></description>
      <pubDate>Wed, 09 Oct 2024 09:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[安装模块后后台菜单消失了，不一定是 ACL 配错]]></title>
      <link>https://www.360magento.com/blog/admin-menu-missing-after-module/</link>
      <description><![CDATA[<p>新模块已经显示为 enabled，<code>setup:upgrade</code> 也没有报错，但后台左侧完全看不到菜单。很多人会直接修改 <code>acl.xml</code>，反复清缓存后仍然没有结果，因为菜单是否出现至少经过模块加载、XML 合并、父节点定位、ACL 授权四道判断。</p>
<h3>确认代码真的属于当前运行版本</h3>
<pre><code>bin/magento module:status Vendor_Module
bin/magento setup:di:compile
bin/magento cache:clean config</code></pre>
<p>生产模式下编译失败不能用旧 generated 目录掩盖。先确认 <code>app/code/Vendor/Module/etc/adminhtml/menu.xml</code> 的大小写、目录层级和模块名完全一致，再查看 <code>app/etc/config.php</code> 是否启用。部署机器若使用只读发布包，还要确认文件确实进入当前 release。</p>
<h3>menu.xml 的父节点是否存在</h3>
<p>最小菜单项通常包含唯一 id、title、module、sortOrder、parent、action 与 resource。若 <code>parent</code> 指向一个未安装扩展的节点，子项也会消失。临时把 parent 改到确认存在的核心节点，只适合定位，最终仍应根据产品信息架构选择正确位置。</p>
<pre><code>&lt;add id="Vendor_Module::report"
     title="Sales Audit"
     module="Vendor_Module"
     sortOrder="80"
     parent="Magento_Sales::sales"
     action="vendor/report/index"
     resource="Vendor_Module::report" /&gt;</code></pre>
<p><code>resource</code> 必须能在合并后的 ACL 树中找到。它不要求与菜单 id 相同，但保持一致更容易维护。父资源层级错误、重复 id 被另一个模块覆盖、XML schema 无效，都会让结果与预期不同。</p>
<h3>角色权限有缓存，也有范围</h3>
<p>用全权限管理员能看到、普通管理员看不到，才优先检查角色授权。进入 System &rarr; Permissions &rarr; User Roles，重新保存角色后退出再登录。不要仅用同一个已打开多小时的后台会话判断权限是否生效。</p>
<p>如果所有管理员都看不到，检查 <code>var/log/system.log</code> 和部署时的 XML 验证输出。还可用 <code>bin/magento dev:urn-catalog:generate</code> 配合 IDE 校验配置文件。某些扩展通过配置关闭自身输出或动态移除菜单，因此也要搜索 <code>menu</code> 事件、plugin 和 backend model。</p>
<h3>别把能访问路由当作菜单正常</h3>
<p>直接输入后台 action URL 能打开，只证明 controller 与 ACL 可能允许访问，不证明菜单节点成功合并。反过来，菜单出现但点击 404，则要查 <code>routes.xml</code>、controller 路径和 admin frontName。把&ldquo;菜单生成&rdquo;和&ldquo;路由分发&rdquo;分开验证，通常十几分钟就能确定问题在哪一层。</p>]]></description>
      <pubDate>Tue, 08 Oct 2024 01:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Varnish 已经 HIT，Magento 2 页面为什么还是慢？]]></title>
      <link>https://www.360magento.com/blog/varnish-hit-page-still-slow/</link>
      <description><![CDATA[<p><code>X-Magento-Cache-Debug: HIT</code> 很容易让人得出一个过早的结论：既然没有运行 Magento PHP，页面就应该瞬间返回。实际上，HIT 只回答&ldquo;Varnish 是否找到了对象&rdquo;，没有回答对象在什么时候可用、请求在它前后等待了多久，也没有说明浏览器完成首屏需要下载多少资源。</p>
<h3>先把&ldquo;慢&rdquo;拆成三个时间</h3>
<p>用 curl 同时记录 DNS、连接、TLS、首字节和总时间，避免只看浏览器瀑布图的一个色块：</p>
<pre><code>curl -sS -o /dev/null   -w 'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} start=%{time_starttransfer} total=%{time_total}
'   https://www.example.com/category.html</code></pre>
<p>若 <code>time_starttransfer</code> 很高而 connect、TLS 很低，等待发生在 CDN、负载均衡或 Varnish 一侧。若首字节很快、total 很高，应查响应体大小、压缩和网络吞吐。HTML 很快而页面可交互很慢，则要转向 JS bundle、字体、图片和第三方脚本，继续调 Varnish 没有意义。</p>
<h3>HIT 也可能包含等待</h3>
<p>查看响应中的 <code>Age</code>、<code>Via</code>、<code>X-Varnish</code> 和自定义 cache debug 头，同一个 URL 连续请求五到十次。只有部分请求慢，常见原因是连接池耗尽、线程排队、磁盘存储延迟，或 CDN 到源站偶发重连。全部请求稳定偏慢，则检查 VCL 中是否执行了昂贵的正则、DNS 查询、日志管道阻塞或外部 VMOD。</p>
<pre><code>for i in $(seq 1 8); do
  curl -sSI https://www.example.com/category.html     | egrep -i 'HTTP/|age:|x-varnish:|x-magento-cache-debug:'
done</code></pre>
<p>还要注意请求合并。一个对象过期时，首个请求去后端刷新，其余请求可能等待 busy object；最终响应依然可能表现为命中或使用 grace，但这段等待真实存在。结合 <code>varnishstat</code> 观察 <code>MAIN.sess_queued</code>、<code>MAIN.threads_limited</code>、<code>MAIN.cache_hit</code>、<code>MAIN.cache_miss</code>，不要只截取命中率。</p>
<h3>确认是否在用过期对象和 grace</h3>
<p>Varnish 的 grace 能在后端异常或刷新期间继续返回旧内容，是稳定性工具，不是免费性能。若健康探测把后端标记为 sick，站点可能长时间依赖 grace；若对象频繁过期，刷新请求会持续打到 PHP。检查后端健康状态、对象 TTL 以及 Magento 发出的缓存标签清理频率。</p>
<pre><code>varnishadm backend.list
varnishstat -1 | egrep 'cache_hit|cache_miss|backend_fail|threads_limited|sess_queued'
varnishlog -g request -q 'ReqHeader:host eq "www.example.com"'</code></pre>
<p>日志量很大时应限制时间和 URL，生产环境不要长时间运行无过滤的 <code>varnishlog</code>。</p>
<h3>ESI、私有内容和 AJAX 是另外三条请求</h3>
<p>Magento 的标准 private content 主要通过浏览器端 customer-data 更新，但站点可能自己增加 ESI 或 AJAX 区块。HTML 命中不代表这些子请求命中。迷你购物车、推荐、库存、地区价格等接口只要有一个串行等待，用户就会感觉页面慢。</p>
<p>在 Network 中按 Initiator 排序，看首个 HTML 后谁触发了 XHR；对慢接口单独用 curl 测量。若接口依赖客户会话，不能简单纳入公共缓存。应减少同步依赖、设置合理超时，或者把非首屏信息延迟加载。</p>
<h3>响应压缩与静态资源不能忽略</h3>
<p>同一份缓存 HTML 可能在 CDN 与浏览器之间没有 Brotli/gzip，或者 <code>Vary: Accept-Encoding</code> 处理不当导致对象变体混乱。检查实际传输大小，而不是模板源文件大小。静态资源方面，数百个小文件、巨型 source map、未优化图片和阻塞字体都会让&ldquo;缓存页&rdquo;显得很慢。</p>
<pre><code>curl -sS --compressed -D - -o /dev/null https://www.example.com/category.html
curl -sS -H 'Accept-Encoding: identity' -D - -o /dev/null https://www.example.com/category.html</code></pre>
<p>比较两次的 <code>Content-Encoding</code>、<code>Content-Length</code> 与 <code>Vary</code>。如果 CDN 会重新压缩，分别从公网域名和绕过 CDN 的受控源站地址测试，但不要在公开环境泄露源站入口。</p>
<h3>一条可执行的判断顺序</h3>
<p>先用 Timing 明确慢在连接、首字节还是下载；再确认慢请求究竟是 HTML、接口还是静态资源；只有 HTML 首字节慢时才深入 Varnish 队列、busy object、grace 与后端健康。最后用相同 URL、相同设备、相同地区重复测量 P50 与 P95。单次 HIT 截图只能证明那一次有缓存头，不能证明缓存链路没有排队。</p>]]></description>
      <pubDate>Mon, 07 Oct 2024 07:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账地址保存失败，region_id 和 postcode 应该怎么查？]]></title>
      <link>https://www.360magento.com/blog/checkout-address-region-postcode/</link>
      <description><![CDATA[<p>结账页填写完地址，点击&ldquo;下一步&rdquo;后按钮转一圈又停住，页面却不给出明确提示，这是 Magento 2 里很常见的一类问题。它看起来像 JavaScript 失效，实际上经常是前端提交的 <code>region</code>、<code>region_id</code>、<code>country_id</code> 与服务器端 Directory 数据对不上。</p>
<h3>先看失败的是哪一个请求</h3>
<p>在浏览器 Network 中筛选 <code>shipping-information</code>。若请求根本没有发出，查看 Console 里的 Knockout 校验错误；若请求已经返回 400 或 500，展开响应中的 <code>message</code> 和 <code>trace</code>。不要把前端红框当成唯一依据，某些主题隐藏了消息容器，真正错误仍在接口响应里。</p>
<p>把请求载荷里的地址对象单独保存下来，重点核对以下字段：</p>
<pre><code>shippingAddress: {
  countryId: "CN",
  regionId: 611,
  regionCode: "SH",
  region: "上海市",
  postcode: "200000"
}</code></pre>
<p>选择下拉省份的国家，通常应提交有效的数字 <code>regionId</code>；允许自由输入省份的国家，<code>region</code> 可以是文本而 <code>regionId</code> 为空。最危险的是主题组件把省份名称塞进 <code>regionId</code>，或者用户切换国家后仍保留上一个国家的 ID。</p>
<h3>数据库确认 ID 是否属于当前国家</h3>
<pre><code>SELECT dcr.region_id, dcr.country_id, dcr.code, dcrn.name
FROM directory_country_region AS dcr
LEFT JOIN directory_country_region_name AS dcrn
  ON dcrn.region_id = dcr.region_id AND dcrn.locale = 'zh_Hans_CN'
WHERE dcr.region_id = 611;</code></pre>
<p>如果查出的 <code>country_id</code> 与结账地址不同，问题不是&ldquo;省份不存在&rdquo;，而是前端状态没有在国家切换时清空。修复自定义组件的订阅关系，比在服务端跳过校验安全得多。数据库中根本没有这个 ID，则要检查导入的地址数据、旧浏览器 localStorage 或第三方地址联想模块。</p>
<h3>postcode 不是所有国家都按同一规则</h3>
<p>Magento 会根据国家配置决定邮编是否必填，前端还可能加载国家专用格式。后台 Stores &rarr; Configuration &rarr; General &rarr; Country Options 与 State Options 决定默认国家和必须选择省份的国家；主题若写死了 required 规则，就会与服务端配置冲突。</p>
<p>可在控制台临时查看结账数据源，而不要直接修改生产数据：</p>
<pre><code>require(['Magento_Checkout/js/model/quote'], function (quote) {
    console.log(quote.shippingAddress());
});</code></pre>
<p>这里若已经是正确值，继续查 <code>var/log/exception.log</code>、<code>var/log/system.log</code> 以及 PHP-FPM 日志；若值不正确，则回到自定义 checkout component、mixin 和地址联想扩展。</p>
<h3>修复后要覆盖三种路径</h3>
<p>至少分别测试新访客手输地址、登录客户选择地址簿、切换国家后重新选择省份。还要清空浏览器中的 checkout-data，避免旧缓存让修复看似无效。不要用&ldquo;删除省份必填&rdquo;作为通用修复，因为税率、运费表格和支付风控都可能依赖正确的地区字段。真正完成的标准，是三种路径提交的载荷都与国家配置一致，并能正确生成 quote address。</p>]]></description>
      <pubDate>Fri, 04 Oct 2024 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[商品 URL 改了却没有 301 跳转，Magento 2 哪个配置没生效？]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-url-no-redirect/</link>
      <description><![CDATA[<p>商品 URL Key 从 old-product 改成 new-product，新地址能访问，但旧地址直接 404，没有自动 301。Magento 是否保留旧路径受 Catalog SEO 配置、编辑作用域和保存流程影响；并非每次修改数据库值都会自动生成 Rewrite。</p>
<h3>先确认保存时启用了永久重定向</h3>
<p>在 Catalog SEO 配置中检查&ldquo;Create Permanent Redirect for URLs if URL Key Changed&rdquo;，注意 Website/Store View 是否覆盖。商品编辑页也可能有&ldquo;Create Permanent Redirect for old URL&rdquo;选项。默认 scope 开启，不代表当前商店视图实际开启。</p>
<h3>比较旧路径和新路径的 Rewrite</h3>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id, metadata
FROM url_rewrite
WHERE request_path IN ('old-product.html','new-product.html')
ORDER BY store_id, redirect_type;</code></pre>
<p>新路径通常是 redirect_type 0 的规范记录，旧路径应是 301 并指向新目标。若旧路径已经被其他商品、分类或自定义 Rewrite 占用，Magento 可能无法创建。先确定冲突所有权，不能强行覆盖。</p>
<h3>直接 SQL 或错误的导入流程不会触发生成服务</h3>
<p>脚本直接更新 EAV URL Key、导入器跳过 Product Repository/URL Persist、ERP 同步只改属性表，都可能让商品值变化但 Rewrite 未生成。批量更新应使用 Magento 支持的服务与索引流程，并在测试环境确认历史重定向行为。</p>
<h3>多商店需要在每个 Store View 验证</h3>
<p>商品 URL Key 可以按商店视图覆盖。默认商店已创建 301，英文或子品牌商店仍可能没有。请求旧 URL 时要带正确域名和 Store Code，查询对应 store_id，不能拿一个商店的记录解释另一个。</p>
<h3>分类路径会产生多个旧地址</h3>
<p>启用分类路径时，同一商品可能有多个 request_path。修改商品 Key 或移动分类后，是否为每条旧路径保留 301 取决于生成配置和历史记录。统计该 entity_id 的所有 Rewrite，检查是否形成 301 链或多个旧地址直达最终路径。</p>
<h3>CDN 可能缓存了修改前的 404</h3>
<p>数据库已有 301，公网仍返回 404 时，绕过 CDN 请求源站并比较响应头。CDN 缓存旧 404 或边缘规则优先处理路径，会让 Magento 的 Rewrite 根本没有机会执行。清除精确旧 URL，而不是无目的全站 purge。</p>
<p>修复后检查旧地址一次 301 到新地址、新地址返回 200、canonical 指向自身、Sitemap 与内部链接只使用新 URL。若旧地址仍有外链，持续监控 404 与重定向命中，避免后续清理 Rewrite 时再次丢失。</p>]]></description>
      <pubDate>Thu, 03 Oct 2024 08:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 日志每天几十 GB，如何找到真正的重复错误？]]></title>
      <link>https://www.360magento.com/blog/magento-2-log-growth/</link>
      <description><![CDATA[<p><code>var/log/system.log</code>、<code>exception.log</code> 或第三方模块日志每天增长几十 GB，很快占满磁盘并拖慢站点。直接删除日志只能释放一次空间；如果同一错误每秒写数百行，文件几分钟又会回来。第一步是找出最高频的错误指纹和触发来源。</p>
<h3>先按文件和时间确认增长点</h3>
<pre><code>du -h var/log/* | sort -h
tail -n 5000 var/log/system.log
find var/log -type f -printf '%s %p\n' | sort -n | tail</code></pre>
<p>生产日志可能在其他目录、容器 stdout 或集中系统中，先确认真正占磁盘的位置。不要对仍在写入的大文件直接反复复制，否则会加重 I/O。</p>
<h3>把动态值去掉后统计错误指纹</h3>
<p>同一个异常可能因订单号、SKU、时间或 request ID 不同，看起来每行都不一样。抽样后识别异常类、文件行号、SQL 错误码和固定消息，用日志系统聚合计数。重点是每分钟出现多少次、从何时开始、与哪个发布或流量来源相关。</p>
<p>常见放大器包括：机器人访问不存在 URL、Cron 每分钟失败、消费者遇到坏消息无限重试、模板每个商品循环记录 warning、第三方 API 超时后无退避重试。</p>
<h3>先停止重复触发，再讨论日志级别</h3>
<p>如果消费者处理同一消息不断失败，暂停该 consumer 或隔离坏消息比关闭日志安全；如果机器人制造异常，可在保持正确状态码的前提下通过 WAF/速率限制控制；如果 Cron 配置错误，应修复任务而不是删除 cron_schedule。</p>
<p>把 logger 调到更高等级会隐藏症状，但业务仍在失败。只有确认信息没有行动价值时，才降低某条可预期日志的等级或增加去重/采样。</p>
<h3>检查是否记录了敏感数据</h3>
<p>支付、API 和登录模块可能把 Authorization、Token、客户地址或完整请求写入日志。日志暴涨同时扩大泄露面。立即脱敏并轮换可能暴露的凭据，访问日志文件应受最小权限控制。</p>
<h3>正确轮转避免应用继续写旧 inode</h3>
<p>使用 logrotate 或日志平台生命周期按大小和日期轮转、压缩、保留。直接 <code>rm</code> 一个被进程打开的文件，磁盘空间可能直到进程重启才释放。轮转方案要支持当前 PHP/consumer 的 reopen 或 copytruncate 策略，并评估 I/O。</p>
<p>异常修复后继续记录关键错误，但设置告警：增长速率、磁盘水位、单一指纹频率和丢日志。验证至少覆盖一个 Cron 周期和队列高峰，确认日志回到正常基线，业务功能也恢复。</p>]]></description>
      <pubDate>Wed, 02 Oct 2024 02:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 批量更新商品很慢，异步 Bulk API 值得用吗？]]></title>
      <link>https://www.360magento.com/blog/magento-2-bulk-api-performance/</link>
      <description><![CDATA[<p>ERP 逐个调用 Magento 2 商品 REST API，更新一万条库存或价格需要数小时，于是考虑改成异步 Bulk API。Bulk 能减少客户端等待并把操作放入队列，但它不是&ldquo;自动加速开关&rdquo;。如果单条更新会加载完整商品、触发大量插件和索引，后台消费者仍要付出相同甚至更高成本。</p>
<h3>先确认业务需要实时结果还是最终一致</h3>
<p>同步 API 在响应时给出成功或错误，适合少量关键更新；异步 Bulk 通常先接受请求并返回 bulk UUID，后续由消费者处理，调用方必须查询状态并处理部分失败。价格、库存是否允许延迟几分钟，要由业务决定。</p>
<h3>不要把巨大 Payload 当成一个 Bulk</h3>
<p>单次包含过多操作会增加 Web 请求体、JSON 解析、队列消息和数据库事务压力。按 SKU 范围或业务批次分组，每批有稳定 ID，便于重试和对账。父子商品、网站关系和分类依赖要保持顺序，不能随机切割后并发覆盖。</p>
<h3>消费者能力决定真实吞吐</h3>
<p>异步 API 依赖消息队列和对应 consumer。检查队列 Ready/Unacked、consumer 数、处理速率和失败日志。盲目增加并发会把瓶颈转移到 MySQL、OpenSearch、Redis 或 ERP 回调。</p>
<pre><code>bin/magento queue:consumers:list
bin/magento queue:consumers:start async.operations.all --max-messages=500</code></pre>
<p>实际 consumer 名称和启动方式应以当前版本配置为准。生产环境要由进程管理器自动重启，而不是手工终端常驻。</p>
<h3>使用正确的更新粒度</h3>
<p>只更新库存却调用完整 ProductRepository save，会执行不必要的 EAV、URL、媒体和索引逻辑。优先使用针对库存、价格或属性的正式批量接口。自定义接口也应定义最小 service contract，不要接收整个商品对象后把空字段覆盖到数据库。</p>
<h3>索引模式会影响导入节奏</h3>
<p>大量更新期间若索引设为 Update on Save，每条操作同步更新索引，吞吐会明显下降。生产通常使用 Update by Schedule，但前提是 Cron 与 MView 能持续消费积压。导入结束后观察 changelog，而不是立即同时启动多个全量 reindex。</p>
<h3>失败必须做到可定位、可重试、幂等</h3>
<p>一个 Bulk 中可能只有部分 SKU 失败。调用方应按 operation 状态记录错误，而不是整批重新发送。每条更新带版本或业务时间戳，可以避免旧批次晚到后覆盖新值。重复消息不能重复创建属性选项或网站关系。</p>
<p>评估时用真实字段和插件，在 100、1000、10000 条规模下测量接收时间、最终完成时间、失败率、队列深度、数据库负载和索引延迟。Bulk 的价值是解耦与可控吞吐，最终指标应是数据在约定时间内一致，而不只是 HTTP 很快返回。</p>]]></description>
      <pubDate>Tue, 01 Oct 2024 08:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[发票金额和订单金额不一致，Magento 2 先查部分开票与折扣分摊]]></title>
      <link>https://www.360magento.com/blog/magento-2-invoice-total-mismatch/</link>
      <description><![CDATA[<p>订单 Grand Total 是 1000，后台创建发票时却只显示 850，或多张部分发票相加与订单差 0.01。先不要直接修改发票金额。Magento 发票只包含本次可开票的商品数量及其分摊税费、折扣、运费和调整金额，订单总额还可能包含已取消、已退款或尚未开票的部分。</p>
<h3>逐行比较 ordered、invoiced、refunded 与 canceled</h3>
<pre><code>SELECT item_id, sku, qty_ordered, qty_invoiced,
       qty_refunded, qty_canceled, row_total,
       tax_amount, discount_amount
FROM sales_order_item
WHERE order_id=100001;</code></pre>
<p>可配置商品同时有父子行，金额通常只落在其中一层，不能把两行相加。Bundle 动态价格与固定价格的金额分布也不同。先找出本次实际开票的实体行和数量，再比较金额。</p>
<h3>部分开票会按比例分摊折扣和税</h3>
<p>固定购物车折扣需要分配到多条商品行。第一次只开其中一部分时，Magento 会把对应折扣计入发票，并保留剩余金额给后续发票。逐次舍入可能产生小额 delta，通常在最后一张发票中调整，确保累计不超过订单。</p>
<p>第三方 Total Collector 如果只在 Quote 保存自定义费用，却没有把字段复制到 Order、Invoice 和 Credit Memo，就会出现订单有费用、发票没有，或退款无法还原。自定义金额必须同时维护 base 与订单币字段。</p>
<h3>运费是否进入第一张发票要看操作</h3>
<p>后台创建部分发票时可以选择是否包含运费。第一张已把全部运费开票，后续发票不会再次包含。税费是否随运费计算也受税配置影响。</p>
<h3>在线捕获与离线发票不能混淆</h3>
<p>点击 Submit Invoice 时选择 Capture Online，会向支付网关捕获本次金额；Capture Offline 只更新 Magento，不一定向网关收款。订单已在下单时全额捕获，后台发票只是账务记录时，也不应再次捕获。</p>
<p>检查支付 transaction 与发票：</p>
<pre><code>SELECT entity_id, increment_id, order_id, grand_total,
       base_grand_total, state, created_at
FROM sales_invoice
WHERE order_id=100001;

SELECT txn_id, txn_type, is_closed, created_at
FROM sales_payment_transaction
WHERE order_id=100001;</code></pre>
<h3>0.01 差异要追踪到首次舍入位置</h3>
<p>比较 base 与 display currency、单价、行总计、税和折扣。不要在最终 grand_total 上硬加一分钱，这会让订单、发票、支付和退款不一致。应修复自定义 collector 的 delta round 或外部系统的重算规则。</p>
<p>验证时创建包含多数量、固定折扣、百分比折扣、税、运费和多币种的订单，分两次开票，再做部分退款。累计 Invoice、Capture 与 Credit Memo 都应与订单可收可退金额一致。</p>]]></description>
      <pubDate>Mon, 30 Sep 2024 01:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 定时索引一直 suspended，MView 状态怎么恢复？]]></title>
      <link>https://www.360magento.com/blog/magento-2-indexer-suspended/</link>
      <description><![CDATA[<p>Magento 2 索引设置为 Update by Schedule 后，后台或 CLI 长期显示 suspended，商品修改不再自动反映到前台。直接执行一次全量 reindex 可能让页面暂时更新，但 suspended 的调度状态没有恢复，下一次增量更新仍会停止。</p>
<h3>先记录每个索引器的模式和状态</h3>
<pre><code>bin/magento indexer:show-mode
bin/magento indexer:status
bin/magento indexer:info</code></pre>
<p>确认是一个 indexer suspended，还是依赖链上的多个索引一起停止。价格、库存、分类和搜索索引可能存在依赖，上游失败会影响下游。不要一上来 reset 全部索引器，否则会丢失定位证据并制造昂贵的全量重建。</p>
<h3>查看 MView 状态和版本进度</h3>
<pre><code>SELECT view_id, mode, status, version_id, updated
FROM mview_state
ORDER BY view_id;</code></pre>
<p>再查看对应 changelog 表的最大 version_id，与 mview_state 记录比较。差距持续扩大说明变更在积压；状态显示 working 但没有活跃进程，可能是上次进程异常退出留下状态；suspended 则要追查是谁挂起以及此前的错误。</p>
<h3>确认 index Cron 组持续运行</h3>
<p>定时索引依赖 Cron 消费 changelog。检查 <code>cron_schedule</code> 中 index 相关任务的 pending、running、missed 和 error，结合 messages 与日志判断。系统 crontab 正常不代表 index 组一定成功，长任务、锁或 PHP 内存仍可能让它退出。</p>
<pre><code>SELECT job_code, status, scheduled_at, executed_at,
       finished_at, messages
FROM cron_schedule
WHERE job_code LIKE 'index%'
ORDER BY schedule_id DESC
LIMIT 50;</code></pre>
<h3>部署挂起与故障挂起处理不同</h3>
<p>某些部署流程会主动 suspend scheduled indexer，避免代码切换时写入不一致。若部署脚本异常中断，恢复步骤没有执行，索引就一直挂起。检查部署记录和自动化脚本，保证失败分支也能明确恢复或告警。</p>
<p>如果是数据错误导致消费者失败，先单独运行相关索引并保留第一条异常。常见根因包括孤立实体、重复键、搜索服务不可用、内存不足和数据库锁。修复根因后，再按当前 Magento 版本支持的命令恢复状态并重建相关索引。</p>
<h3>reset 不是修复，只是重置状态</h3>
<p><code>indexer:reset</code> 会把状态改为需要重建，不会清除坏数据、恢复 Cron 或解决锁。执行前确认影响范围，随后针对性 reindex，并观察是否能回到 Ready。对于大目录，应在维护窗口处理，避免全量索引与营业高峰争用资源。</p>
<p>最终再修改一个商品价格、库存和分类，等待 Cron 自动处理，比较 changelog 与 mview_state version_id 是否追平。只有增量更新连续成功，才说明 suspended 真正恢复。</p>]]></description>
      <pubDate>Fri, 27 Sep 2024 07:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Checkout totals 不刷新，Knockout 哪些地方最容易出错？]]></title>
      <link>https://www.360magento.com/blog/magento-2-checkout-totals-not-refreshing/</link>
      <description><![CDATA[<p>结账页切换配送方式、使用优惠码或修改地址后，总价仍显示旧金额，刷新页面才正确。问题可能在后端 Quote 没有重算，也可能接口已经返回新 totals，但 Knockout 组件没有更新。先区分数据与显示，才能避免在错误层修补。</p>
<h3>以接口响应判断后端是否正确</h3>
<p>在 Network 中查看 estimate-shipping-methods、shipping-information、payment-information 或 totals-information 请求。响应中的 subtotal、shipping、tax、discount 和 grand_total 已更新，说明后端计算正确；响应仍旧则查 Quote、地址和 total collector。</p>
<p>不要只看页面文本。一步结账扩展可能显示自己的汇总，却仍发送核心接口。</p>
<h3>Knockout totals 是 observable 数据</h3>
<p>核心 checkout 使用 quote totals observable。自定义组件如果在 initialize 时读取一次普通值，后续不会响应变化。正确方式是订阅 totals 或使用计算属性，并处理 segment 暂时不存在的状态。</p>
<pre><code>define(['Magento_Checkout/js/model/quote'], function (quote) {
    'use strict';
    return function () {
        var totals = quote.getTotals()();
        return totals ? totals.grand_total : 0;
    };
});</code></pre>
<p>示例只说明数据来源，真实组件应避免在模板每次渲染中创建重复订阅。</p>
<h3>自定义 Total 必须前后端名称一致</h3>
<p>PHP Total Collector 的 code、REST totals segment、jsLayout 组件与模板取值必须对应。后端返回 <code>custom_fee</code>，前端却查 <code>custom-fee</code>，组件就会一直显示空。排序值还会决定它在税、折扣和 grand total 周围的位置。</p>
<h3>Promise 链未完成会阻止下一次更新</h3>
<p>配送或支付模块覆盖 action 后，如果没有 return 原 Promise，调用方无法等待完成；失败分支没有 reject/always，也可能让 loader 和 totals 更新卡住。检查 mixin 是否保留函数返回值，并从 Console 第一条异常开始修复。</p>
<h3>竞争请求会让旧响应覆盖新响应</h3>
<p>客户快速切换地址或配送方式时，多个 totals 请求并发。较早请求较晚返回，就可能覆盖新选择。自定义组件应取消过期请求或根据当前状态忽略旧响应，不能简单在每次键盘输入都发完整 totals。</p>
<h3>缓存不能缓存客户专属 totals</h3>
<p>结账数据属于 Quote 私有状态。CDN、Service Worker 或错误的 Ajax 缓存规则如果缓存 totals API，会让不同请求得到旧数据。确认接口响应使用合适的私有/不缓存策略。</p>
<p>修复后按顺序测试地址、运费、优惠码、支付方式、数量和货币切换，观察每一步接口与页面金额一致。还要验证下单后的 Order、Invoice 与页面最终金额相同，不能只让 UI 看起来更新。</p>]]></description>
      <pubDate>Thu, 26 Sep 2024 02:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Google 提示重复网页，Magento 2 尾斜杠和参数 URL 怎么统一？]]></title>
      <link>https://www.360magento.com/blog/magento-2-trailing-slash-duplicate-url/</link>
      <description><![CDATA[<p>Google Search Console 报&ldquo;重复网页，Google 选择了不同的规范网页&rdquo;，同一分类或 CMS 页面既能通过带尾斜杠地址访问，也能通过不带斜杠、不同协议、www 或参数版本访问。只加 canonical 不能替代服务器层的 URL 统一。</p>
<h3>列出每种可访问版本的真实响应</h3>
<p>对一个代表页面检查 HTTP、HTTPS、www、非 www、带斜杠、不带斜杠和常见参数：</p>
<pre><code>curl -I '页面版本A'
curl -I '页面版本B'
curl -IL --max-redirs 10 '页面版本A'</code></pre>
<p>记录每一步状态和 Location。目标通常是非规范版本一次 301 到规范版本，规范页面返回 200。多次跳转会增加抓取与用户延迟，HTTP&rarr;HTTPS&rarr;www&rarr;尾斜杠三跳应尽量合并。</p>
<h3>Base URL 与 Web 服务器规则必须一致</h3>
<p>Magento Secure/Unsecure Base URL、Use Secure URLs 与 Nginx/Apache/CDN 重定向要选择同一个协议和主域。如果 CDN 强制 www，Magento 又生成非 www，会形成循环或不断产生两套内链。</p>
<p>尾斜杠策略要按路由类型测试。首页通常自然带斜杠，商品 URL 可能以 <code>.html</code> 结尾，分类和 CMS 可能不同。不要写一个粗暴规则给所有包含扩展名的文件追加斜杠。</p>
<h3>Canonical 应输出最终规范 URL</h3>
<p>页面最终 HTML 中 canonical 要与 301 目标、站点地图和内部链接一致。若页面 A 301 到 B，但 B canonical 到 C，搜索引擎仍要处理冲突信号。第三方 SEO 模块和主题模板可能重复输出两个 canonical，需要查看渲染后的 head。</p>
<h3>参数 URL 要按功能分类</h3>
<p>UTM 跟踪、排序、每页数量、筛选、分页和站内搜索参数的处理不能相同。跟踪参数通常不改变主体内容；分页和筛选可能改变商品集合。先制定规则，再决定 canonical、noindex 或可索引落地页。不要把所有带问号 URL 都 301 到无参数页面，这会破坏筛选与营销归因。</p>
<h3>内链和站点地图是持续信号</h3>
<p>导航、面包屑、分页、hreflang 和 Sitemap 应直接使用规范版本，避免站内先链接非规范 URL 再依赖 301。多语言站点的 hreflang 也必须引用各语言最终 200 页面。</p>
<p>上线后抓取一组商品、分类、CMS、分页和筛选 URL，确认重定向不循环、canonical 唯一、状态正确。Search Console 的重复报告消退需要时间，可结合服务器日志观察搜索引擎是否逐步减少抓取旧版本。</p>]]></description>
      <pubDate>Wed, 25 Sep 2024 08:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多网站共用客户账号，为什么登录状态不共享？]]></title>
      <link>https://www.360magento.com/blog/magento-2-multisite-login-not-shared/</link>
      <description><![CDATA[<p>Magento 2 配置了 Share Customer Accounts = Global，同一邮箱可以在多个 Website 登录，但客户从站点 A 跳到站点 B 仍显示未登录。这里容易混淆两个概念：客户账户数据共享与浏览器登录 Session 共享。Global 只表示多个 Website 使用同一个 customer 实体，并不会让两个域名自动拥有同一 Cookie。</p>
<h3>先看两个站点是否处于可共享 Cookie 的域范围</h3>
<p><code>shop.example.com</code> 与 <code>brand.example.com</code> 可以在谨慎配置下使用父域 Cookie；<code>example-a.com</code> 与 <code>example-b.com</code> 无法通过普通 Cookie Domain 直接共享浏览器 Cookie。浏览器的同源和 SameSite 策略会阻止跨无关域名读取。</p>
<p>检查 customer session Cookie 的 Domain、Path、Secure、HttpOnly 和 SameSite。把 Cookie Domain 设得过宽会影响其他子域安全，也可能与后台或旧 Cookie 冲突。</p>
<h3>所有节点必须使用同一 Session 存储与加密配置</h3>
<p>即使 Cookie 能被两个子域发送，站点 A 与 B 如果连接不同 Redis Session、使用不同 cookie name 或加密密钥，仍无法识别登录状态。确认 <code>app/etc/env.php</code> 的 Session 配置、crypt key 和部署环境一致。</p>
<p>共享 Session 也会把故障域连接起来：一个站点清 Session 可能让全部站点客户退出。应评估容量、隔离与回滚，而不是只追求&ldquo;看起来像单点登录&rdquo;。</p>
<h3>Store、Website 和客户组上下文仍然不同</h3>
<p>客户实体可以共享，但购物车、价格、客户组、地址可用范围和授权逻辑可能按 Website 变化。客户在 B 站登录后，不能默认沿用 A 站的 Quote 和所有权限。跨站共享购物车需要单独业务设计。</p>
<h3>不同主域名应使用真正的 SSO</h3>
<p>对两个独立域名，安全方案通常是中心身份提供方、一次性授权码或受签名的短期交换流程。不要把 customer_id、邮箱或长期 token 放进 URL。回调必须验证 state、nonce、来源和重放，登录成功后由各站建立自己的 Session。</p>
<p>自定义&ldquo;自动登录&rdquo;接口如果接受简单邮箱参数，会导致账户接管。应使用经过验证的 OAuth/OIDC 或等价安全协议，并明确退出登录、密码修改和账户锁定如何同步。</p>
<h3>先决定共享的业务边界</h3>
<p>用户真正需要的可能只是同一账号密码，而不是无感跨站登录。Global customer scope 已满足前者。后者会引入 Cookie、隐私、购物车和安全复杂度，必须作为单点登录项目设计。</p>
<p>验证时使用两个子域或两个主域，覆盖登录、退出、密码修改、Remember Me、购物车与客户组。任何一个站点退出后，其他站点是否应同时退出，也要在需求中明确并测试。</p>]]></description>
      <pubDate>Tue, 24 Sep 2024 01:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台上传图片成功，保存商品后却消失是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-image-disappears-after-save/</link>
      <description><![CDATA[<p>在商品编辑页选择图片后立即能看到预览，但点击保存再打开商品，图片不见了。预览成功只证明浏览器把文件上传到临时位置，不代表 Magento 已把它移动到正式媒体目录并写入商品 Media Gallery。</p>
<h3>观察临时上传与商品保存两个请求</h3>
<p>Network 中先找到图片上传请求，再看商品保存请求。上传接口返回的临时文件名、cookie 和 form key 必须被保存表单带回。保存返回 200 但响应体是错误页、Session 过期或部分字段被截断时，图片元数据可能没进入后端。</p>
<h3>检查 tmp 与正式目录的文件流转</h3>
<p>商品图片通常先进入临时目录，再在保存时移动到 <code>pub/media/catalog/product</code>。Web 用户需要读写相关目录。多节点后台若上传请求落在节点 A、保存请求落在节点 B，而 media/tmp 不共享，节点 B 找不到临时文件。</p>
<p>检查文件所有者、目录执行权限、共享存储与同步延迟，不要通过 777 长期解决。对象存储或远程媒体适配器还要检查 rename/copy 能力和失败日志。</p>
<h3>数据库需要同时保存 Gallery 与角色属性</h3>
<p>图片库记录和 image、small_image、thumbnail 角色不是同一份数据。可查询指定商品的 Gallery 关联：</p>
<pre><code>SELECT mg.value_id, mg.value, mg.media_type,
       mgv.store_id, mgv.label, mgv.position, mgv.disabled
FROM catalog_product_entity_media_gallery mg
JOIN catalog_product_entity_media_gallery_value mgv
  ON mgv.value_id=mg.value_id
WHERE mgv.entity_id=123;</code></pre>
<p>不同版本的关联表结构可能变化，先确认 schema。文件存在但没有 Gallery 记录，问题在保存；记录存在但 disabled 或 Store View 覆盖，也会在后台看似消失。</p>
<h3>商店作用域与&ldquo;Use Default Value&rdquo;容易混淆</h3>
<p>在某个 Store View 上传或删除图片时，值可能只对该视图生效。默认视图有图，子商店把 Gallery 禁用，前台仍不显示；反过来子视图上传后切回默认，也可能看不到。确认编辑器顶部的 scope 和角色覆盖状态。</p>
<h3>图片验证和插件可能在保存阶段拒绝</h3>
<p>文件扩展名、实际 MIME、尺寸、内存、特殊字符或损坏图片可能通过浏览器预览，却在后端处理时失败。安全模块和图片优化扩展也可能移动或删除文件。按保存时间查看 exception、system、PHP 与安全扫描日志。</p>
<p>修复后上传一张新图，设置三个角色、保存、刷新后台，并在另一个 Web 节点和前台访问。再删除和重新排序一次，确认文件、Gallery 数据、角色和 Store View 状态保持一致。</p>]]></description>
      <pubDate>Mon, 23 Sep 2024 07:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 自定义 CLI 报 Area code is not set，应该在哪里设置？]]></title>
      <link>https://www.360magento.com/blog/magento-2-area-code-not-set/</link>
      <description><![CDATA[<p>自定义 <code>bin/magento</code> 命令运行时报 <code>Area code is not set</code>，很多示例会建议在任意位置调用 <code>setAreaCode('adminhtml')</code>。这有时能让异常消失，却可能把错误区域固定到构造阶段，影响其他 CLI 命令、测试和长进程。</p>
<h3>Area 决定哪些配置和设计被加载</h3>
<p>Magento 的 frontend、adminhtml、crontab、webapi_rest、graphql 等 area 会影响事件、DI 配置、翻译和布局。CLI 本身没有天然的前台或后台上下文。只有当命令使用需要特定 area 的服务时，才需要明确设置或模拟。</p>
<h3>不要在构造函数中设置 Area</h3>
<p>Symfony Console 启动时会实例化多个命令。一个命令在构造函数里设置 adminhtml，可能导致另一个命令再设置时抛 <code>Area code is already set</code>。应在当前命令的 <code>execute()</code> 中、真正使用相关服务前处理。</p>
<pre><code>try {
    $this-&gt;state-&gt;setAreaCode(Area::AREA_ADMINHTML);
} catch (LocalizedException $exception) {
    // 仅在已经由当前运行上下文设置时决定是否继续
}</code></pre>
<p>不要无条件吞掉异常。Area 已被设置成 frontend 与已设置成 adminhtml 的含义不同，命令应明确自己需要什么。</p>
<h3>更小的边界可以使用 emulateAreaCode</h3>
<p>如果只是一段代码需要特定区域，可以用 App State 的 area 模拟包装回调，让执行结束后恢复原状态。它比在长进程一开始永久设置更安全，尤其是消费者或一次处理多个 Store 的命令。</p>
<p>不过 area 模拟不会自动切换 Store。邮件模板、价格、URL 和配置读取还可能依赖 Store Manager，需要分别设置明确的 Store 上下文，并在循环后恢复。</p>
<h3>异常往往暴露了不适合 CLI 的依赖</h3>
<p>命令如果注入 Block、Layout、Session 或依赖 HTTP 请求的类，很容易要求 area。把核心业务提取到不依赖展示层的 service，CLI、Cron 和 API 都能复用。命令只负责解析参数、选择 Store、调用服务和返回退出码。</p>
<h3>不要用 ObjectManager 临时创建服务</h3>
<p>运行到一半才通过 ObjectManager 取对象，会隐藏依赖并让 area 初始化顺序更难控制。使用构造注入和明确的 service contract，单元测试也能覆盖。</p>
<p>修复后从全新的 CLI 进程运行命令，再连续运行其他核心命令，确认没有污染全局 State。测试不同 Store、异常重试和长批次，确保区域与商店上下文在每次迭代中一致。</p>]]></description>
      <pubDate>Fri, 20 Sep 2024 03:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 购物车价格规则运行很慢，Conditions 应该怎么查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cart-rule-slow/</link>
      <description><![CDATA[<p>商品加入购物车、修改数量或进入结账都要等待数秒，性能跟踪显示 SalesRule 占用大量时间。购物车价格规则会在 collect totals 时反复验证，规则数量、条件复杂度和购物车行数相乘后，开销会快速扩大。</p>
<h3>先确认慢请求是否重复 collect totals</h3>
<p>一个正常操作可能因地址、运费、支付或自定义组件触发多次 totals。记录同一请求中 collector 的执行次数。第三方一步结账如果每个字段变化都保存 Quote 并重算，优化单条规则也无法解决整体抖动。</p>
<h3>统计当前真正有效的规则</h3>
<p>后台长期积累的停用或过期规则通常不应参与，但配置错误、日期和 Website 范围会让规则仍被加载。检查当前时间、客户组、Website 和优先级，减少同时有效的规则集合。不要用&ldquo;全部网站、全部客户组&rdquo;作为方便的默认值。</p>
<p>可从数据库查看基础范围，但 conditions 是序列化结构，修改应通过服务层和后台完成：</p>
<pre><code>SELECT rule_id, name, is_active, from_date, to_date,
       sort_order, stop_rules_processing
FROM salesrule
WHERE is_active=1
ORDER BY sort_order, rule_id;</code></pre>
<h3>Conditions 树越深，逐行验证越昂贵</h3>
<p>大量嵌套 ALL/ANY、分类、SKU、属性、购物车金额和地址条件会触发不同数据加载。Actions 区域的商品条件还会对每个 Quote Item 验证。能在顶层快速排除的 Website、客户组、日期条件应由规则范围承担，不要全部塞进复杂树。</p>
<p>用于规则的商品属性必须配置为可用于促销规则并被正确索引。自定义 condition 如果每次验证都加载完整 Product 或远程 API，会形成 N&times;M 查询，应批量预取或缓存当前请求内结果。</p>
<h3>规则优先级和停止后续规则处理能减少工作，但要符合业务</h3>
<p>高优先级互斥规则在命中后可停止后续处理，减少验证，也避免优惠叠加。但不能为了性能随意开启，否则订单金额会改变。先建立规则组合测试，再调整。</p>
<h3>索引不是所有规则性能问题的答案</h3>
<p>目录价格规则有专门索引，购物车价格规则更多在 Quote totals 阶段动态计算。看到优惠慢就全量 reindex 往往无效。应通过 profiler/APM 找出具体 validator、SQL 和调用次数。</p>
<p>优化后用 1 行、20 行和含可配置/Bundle 的购物车测试，覆盖访客、不同客户组、有效和无效优惠码。比较 P95 响应时间与最终折扣明细，确保性能提升没有改变规则结果。</p>]]></description>
      <pubDate>Thu, 19 Sep 2024 06:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[客户可以登录，却看不到历史订单，Magento 2 应该查什么？]]></title>
      <link>https://www.360magento.com/blog/magento-2-customer-orders-missing/</link>
      <description><![CDATA[<p>客户能正常登录账户中心，但 My Orders 显示没有订单，后台按邮箱却能找到历史记录。订单列表不是单纯按 email 查询，它主要依赖当前登录客户的 <code>customer_id</code>、订单可见状态和网站上下文。相同邮箱并不保证自动关联。</p>
<h3>先比较订单 customer_id 与当前客户实体</h3>
<pre><code>SELECT entity_id, increment_id, customer_id, customer_email,
       store_id, state, status, is_active, created_at
FROM sales_order
WHERE customer_email='customer@example.test'
ORDER BY entity_id DESC;</code></pre>
<p>访客订单的 <code>customer_id</code> 可能为空，即使下单邮箱与后来注册客户相同，也不会自动出现在账户中。Magento 不应仅按邮箱展示订单，否则共享邮箱或邮箱变更会造成隐私泄露。</p>
<h3>多 Website 的客户实体可能不同</h3>
<p>客户账户共享范围为 Per Website 时，同一邮箱可以在不同 Website 拥有不同 customer_id。订单属于另一个 Website/Store 的客户实体，当前站点登录后可能看不到。检查 customer_entity 的 website_id 与订单 store 对应关系。</p>
<p>如果业务要求跨网站共享订单，需要明确身份映射与权限，不能简单去掉 website 过滤。统一账户范围的配置变更也可能影响重复邮箱和现有客户，必须先评估迁移。</p>
<h3>订单状态和扩展会改变列表条件</h3>
<p>核心订单历史通常会显示多数有效订单，但主题、B2B、Marketplace 或隐私模块可能过滤 canceled、closed、归档订单或特定渠道。切换原生主题/停用相关插件做对照，查看订单集合最终 SQL 与过滤条件。</p>
<p>后台能看见但前台 GraphQL/REST 查询看不见时，检查当前 customer token 与 customer_id 是否匹配，以及接口的 Store 头。不要使用管理员 Token 的结果判断客户权限。</p>
<h3>合并访客订单必须有安全规则</h3>
<p>有些扩展在客户注册或登录后按邮箱把 guest orders 绑定到账户。实现必须验证客户对邮箱的所有权，处理历史邮箱变更和多网站范围，并保留审计。直接批量更新 <code>sales_order.customer_id</code> 会遗漏订单 Grid、扩展索引或第三方映射。</p>
<h3>缓存问题通常只影响显示，不影响集合</h3>
<p>账户页面属于私有内容，但前端 customer-data 或自定义全页缓存配置错误，也可能缓存空列表。检查实际订单接口响应：数据已返回而页面为空，问题在模板/JS；接口本身为空，继续查权限和集合。</p>
<p>修复后测试已有客户订单、访客订单、不同 Website 同邮箱、取消订单和邮箱变更。确认客户只能看到属于自己的订单，订单详情、下载产品、发票和退款入口也遵循同一授权规则。</p>]]></description>
      <pubDate>Wed, 18 Sep 2024 02:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[OpenSearch 返回 429，Magento 2 的 bulk queue 满了怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-opensearch-429/</link>
      <description><![CDATA[<p>Magento 2 重新索引或批量更新商品时出现 HTTP 429、<code>es_rejected_execution_exception</code> 或 bulk queue capacity exceeded。它表示搜索集群当前无法按速度处理新请求并主动拒绝，不等同于普通认证失败。无限重试会继续压垮集群，必须先降低输入或提升真实处理能力。</p>
<h3>确认拒绝发生在 bulk、search 还是 write</h3>
<pre><code>SEARCH_ENDPOINT='搜索服务地址'
curl -sS \"$SEARCH_ENDPOINT/_cat/thread_pool?v\"
curl -sS \"$SEARCH_ENDPOINT/_nodes/stats/thread_pool,jvm,fs?pretty\"
curl -sS \"$SEARCH_ENDPOINT/_cluster/health?pretty\"</code></pre>
<p>观察 active、queue 与 rejected 的增长，结合 JVM heap、GC、CPU、磁盘 I/O 和可用空间。只看一次 429 无法判断是短峰值还是持续容量不足。</p>
<h3>先避免多个全量索引同时运行</h3>
<p>部署、手工 reindex、Cron 增量索引和批量商品导入可能同时向集群写入。检查进程与 <code>cron_schedule</code>，保证同一环境只有预期的索引任务。不要在全量重建卡住时反复启动新的 reindex。</p>
<h3>调整 Magento 批次，而不是只扩大服务端队列</h3>
<p>搜索索引批次过大，会制造单次内存和队列峰值；过小又会增加往返。根据商品文档大小和集群吞吐逐步调整 batch size，并记录每批耗时、拒绝率和堆内存。直接把 OpenSearch queue 调得很大可能只把拒绝变成长时间排队，最终触发超时和更高内存。</p>
<h3>分片设计和节点资源决定实际吞吐</h3>
<p>大量小分片会增加管理和合并成本，单个巨大分片又限制并行。Magento 索引数量还受 Store View 和索引前缀影响。检查当前主分片、replica、文档数与段合并，不要照搬另一站点的分片数量。</p>
<p>磁盘接近水位、JVM 持续高 GC、节点间网络慢时，增加 PHP 超时不能解决。先释放安全空间、修复节点健康或扩容，再执行全量索引。</p>
<h3>客户端重试必须有退避和上限</h3>
<p>对 429 可采用指数退避与有限重试，但重试批次必须可幂等，且不能所有 worker 同时立即重试。加入随机抖动能避免惊群。若达到上限，应清楚记录失败批次，让后续恢复而不是静默丢文档。</p>
<p>恢复后单独运行 <code>catalogsearch_fulltext</code>，确认 rejected 计数不再快速增长，再修改一个商品验证增量索引。前台还应测试搜索、排序和筛选，确保不是&ldquo;索引命令成功但部分 bulk 被拒绝&rdquo;。</p>]]></description>
      <pubDate>Tue, 17 Sep 2024 08:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台保存配置提示 Invalid Form Key，问题不只是 Session]]></title>
      <link>https://www.360magento.com/blog/magento-2-invalid-form-key-admin/</link>
      <description><![CDATA[<p>Magento 2 后台修改配置后点击保存，突然提示 <code>Invalid Form Key. Please refresh the page.</code>。Form Key 是防止跨站请求伪造的令牌，它必须与当前管理员 Session 匹配。刷新一次偶尔能恢复，但如果持续出现，说明会话或请求链路不稳定。</p>
<h3>先判断是所有页面还是某个大表单</h3>
<p>如果简单配置也失败，重点查 Session、Cookie 与代理；只有商品、分类或包含大量字段的页面失败，检查 PHP 请求限制。<code>post_max_size</code>、<code>max_input_vars</code> 或 Web 服务器 body 限制可能截断 POST，使 form_key 字段根本没到应用。</p>
<pre><code>php --ini
php -r 'echo ini_get("post_max_size"), PHP_EOL;
         echo ini_get("max_input_vars"), PHP_EOL;'</code></pre>
<p>CLI PHP 配置不一定等于 PHP-FPM，最终要核对处理后台请求的 SAPI 配置和错误日志。</p>
<h3>观察 admin Session Cookie 是否变化</h3>
<p>在浏览器 Network 中比较打开表单与提交时的 Cookie。Domain、Path、Secure、SameSite 配错，HTTP 与 HTTPS 混用，或后台在 www/非 www 之间跳转，都会让提交使用另一会话。</p>
<p>清除浏览器 Cookie 只能验证旧 Cookie 冲突，不是长期修复。应检查 Base URL、Cookie Domain、后台路径和代理传递的原始协议。</p>
<h3>多节点必须共享或固定 Session</h3>
<p>页面由节点 A 生成 Form Key，保存请求落到节点 B，而两个节点使用各自本地文件 Session，就会校验失败。生产集群应使用共享 Session 存储，或在明确方案下使用粘性会话；同时保证所有节点加密配置一致。</p>
<p>Redis Session 连接不稳定、键被淘汰或 TTL 过短，也会造成相同现象。查看 Redis rejected connections、evicted keys 和 Magento Session 日志，不要只延长后台 lifetime。</p>
<h3>页面停留太久和并发标签页也会影响</h3>
<p>后台页面打开数小时后提交，Session 可能已过期。多个标签页跨登录、退出或切换账号，旧页面中的 Form Key 也会失效。系统应提示重新登录，而不是通过关闭 Form Key 验证解决。</p>
<h3>不要禁用安全校验</h3>
<p>Form Key 保护后台写操作。修改核心代码跳过校验、把任意 form_key 视为有效，会引入真实的 CSRF 风险。自定义后台表单应使用 Magento 提供的 FormKey Block/Provider，并通过标准后台路由提交。</p>
<p>修复后分别测试小配置、大表单、页面停留超过短期窗口、多节点轮询和 HTTPS 入口。提交时 Form Key 与 Session 始终一致，且错误日志没有请求截断，才能确认问题消失。</p>]]></description>
      <pubDate>Mon, 16 Sep 2024 01:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据库表越来越大，先别急着清日志]]></title>
      <link>https://www.360magento.com/blog/magento-2-database-growth/</link>
      <description><![CDATA[<p>Magento 2 数据库从几十 GB 增长到数百 GB，第一反应往往是删除日志表。但真正占空间的可能是订单、URL Rewrite、索引临时表、队列消息、搜索查询、第三方审计记录或未清理的 staging 数据。没有先做归因就删除，会损失业务和审计信息。</p>
<h3>先按数据与索引大小排序</h3>
<pre><code>SELECT table_name,
       ROUND(data_length/1024/1024,1) AS data_mb,
       ROUND(index_length/1024/1024,1) AS index_mb,
       table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
ORDER BY data_length + index_length DESC
LIMIT 30;</code></pre>
<p><code>table_rows</code> 对 InnoDB 可能是估算值，但足以筛选大表。再按天记录大小，增长速度比当前体积更有价值：订单表很大但稳定可能合理，一张第三方日志表每天增加 5 GB 才是紧急问题。</p>
<h3>区分必须保留的业务数据</h3>
<p><code>sales_order</code>、invoice、shipment、creditmemo、customer 与支付相关表通常受财务、售后和合规要求约束，不能按&ldquo;超过一年&rdquo;直接删除。归档策略必须覆盖关联表、报表、退款和外部 ERP 引用。</p>
<p>Quote、Report、Search Query、Visitor、Cron Schedule、队列和日志类数据往往有可配置生命周期，但不同版本和模块的清理任务不同。先确认官方 Cron 是否运行，再决定历史保留期限。</p>
<h3>DELETE 后文件不一定立即变小</h3>
<p>InnoDB 删除记录会释放页供同表复用，磁盘上的表空间文件未必收缩。<code>OPTIMIZE TABLE</code> 或在线重建可能需要与原表接近的额外磁盘，并产生锁或复制压力。生产操作前必须在副本测量时间、空间和锁影响。</p>
<h3>检查失败的索引临时表和队列积压</h3>
<p>异常中断的 reindex、导入或扩展升级可能留下大型临时表。不要按名字带 tmp 就删除，先确认没有活动进程引用。消息队列 Ready/Unacked 长期增长，也会把消息数据库或相关表推大，根因是消费者故障而不是保留策略。</p>
<h3>第三方日志最容易失控</h3>
<p>支付、API、ERP 和调试模块可能把完整请求响应写入数据库。除了容量，还存在敏感数据风险。确认是否记录 token、客户地址或支付信息，立即调整脱敏、日志级别和保留期。不要把数据库当长期原始日志仓库，可转移到有生命周期管理的日志系统。</p>
<p>清理方案应包含：表级备份、精确 WHERE 条件、分批删除、复制延迟监控、回滚方法和业务验收。完成后继续监控两周，确认增长曲线改变；如果只是一次性清空但写入速度没变，数据库很快会再次膨胀。</p>]]></description>
      <pubDate>Fri, 13 Sep 2024 07:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[支付已经成功，Magento 2 订单为什么还停在 Pending？]]></title>
      <link>https://www.360magento.com/blog/magento-2-paid-order-still-pending/</link>
      <description><![CDATA[<p>支付平台显示交易成功，Magento 2 订单却一直停在 Pending，客服不敢发货，客户还可能重复支付。处理这类问题的第一原则是先核对真实资金状态，再决定订单如何恢复，不能直接把数据库 status 改成 processing。</p>
<h3>先区分授权成功还是捕获成功</h3>
<p>Authorize Only 只冻结或授权金额，Magento 订单可能仍等待后续 Capture；Authorize and Capture 通常在付款成功后生成发票并进入 Processing。支付平台界面中的&ldquo;成功&rdquo;可能代表 authorization、capture 或已结算，必须查看具体 transaction type。</p>
<p>后台订单 Payment Information 与 <code>sales_payment_transaction</code> 中的交易记录可以帮助判断：</p>
<pre><code>SELECT transaction_id, parent_txn_id, txn_id, txn_type,
       is_closed, created_at
FROM sales_payment_transaction
WHERE order_id=100001
ORDER BY transaction_id;</code></pre>
<p>不要把真实卡号、签名密钥或完整网关响应输出到日志。</p>
<h3>异步支付依赖 Webhook 或 Return URL</h3>
<p>客户浏览器跳回成功页不等于服务器已经确认付款。可靠集成通常由支付平台向 Magento Webhook 发送服务器回调。检查回调 URL 的状态码、签名校验、事件 ID 和重试记录。WAF、Basic Auth、维护模式或错误 Base URL 都可能让支付平台无法访问。</p>
<p>如果支付平台多次重试同一事件，Magento handler 必须幂等。同一个 capture 事件不能重复开票；已处理事件应安全返回成功，而不是再次改变订单。</p>
<h3>交易匹配失败时回调找不到订单</h3>
<p>支付请求中的 merchant reference、increment_id、quote_id 或自定义 metadata 必须能唯一找到订单。多 Store 使用相同显示订单号、自定义编号被修改，或回调只传了旧 quote 引用，都可能导致&ldquo;支付成功但无订单可更新&rdquo;。</p>
<p>关联时优先使用网关 transaction ID 与内部保存的引用，不要只按客户邮箱和金额猜测。人工恢复前确认这笔支付没有已经关联到另一订单。</p>
<h3>状态标签和内部 state 必须正确映射</h3>
<p>支付模块可能把成功事件设置为自定义 status，但该 status 错误绑定在 <code>new</code> state，后台仍表现为 Pending。Magento 的 state 控制可开票、发货、取消等能力，status 主要用于业务展示。修正配置和代码后让服务层执行状态转换，不要只改标签。</p>
<h3>故障恢复要防止二次扣款和重复发票</h3>
<p>如果资金已捕获，先阻止客户再次支付，核对金额、币种、订单和网关交易；然后通过支付模块提供的同步或 webhook replay 功能恢复。没有安全工具时，应在测试环境验证恢复流程并保留审计记录。</p>
<p>最终测试至少覆盖授权、捕获、支付拒绝、Webhook 延迟、重复 Webhook 和客户未返回网站。每种情况都应得到唯一订单、唯一交易和可解释的 state/status，邮件与库存也要随正确事件发生。</p>]]></description>
      <pubDate>Thu, 12 Sep 2024 03:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[部署后前台 CSS 全乱了：Magento 2 静态资源版本与权限排查]]></title>
      <link>https://www.360magento.com/blog/magento-2-css-broken-after-deploy/</link>
      <description><![CDATA[<p>代码部署完成后页面能打开，但样式全部丢失，Network 中 CSS/JS 返回 404、403 或错误 MIME。这个问题看似是前端，根因常在静态内容部署、文件所有者、静态签名版本与多节点发布不一致。</p>
<h3>从一个失败资源开始，不要先全站清缓存</h3>
<p>复制失败的 CSS URL，查看状态码、响应体和 Content-Type。404 表示文件或路由不存在；403 多与权限、Web 规则有关；200 但返回 HTML，说明请求被 Magento 错误页或登录页接管；浏览器报 MIME 拒绝通常就是最后一种情况。</p>
<p>把 URL 中的主题、区域和语言拆开，例如 frontend、Vendor/theme、zh_Hans_CN。部署只生成 en_US，而当前商店使用中文区域时，文件可能缺失。</p>
<h3>部署模式决定静态资源的生成方式</h3>
<pre><code>bin/magento deploy:mode:show
bin/magento setup:static-content:deploy -f zh_Hans_CN en_US
bin/magento cache:clean</code></pre>
<p>生产模式应在发布流程中预生成静态内容。开发模式可能通过符号链接或按请求生成，权限与开发配置不同。不要在生产 Web 请求高峰临时生成全部主题和语言。</p>
<h3>静态文件签名必须与所有节点一致</h3>
<p>启用静态内容签名后，HTML 中的资源 URL 带版本段。多台 Web 节点如果 <code>deployed_version.txt</code> 不一致，用户从节点 A 得到 HTML，却到节点 B 请求一个不存在的版本，就会出现间歇性 404。</p>
<p>构建产物应一次生成后分发到所有节点，或使用一致的共享静态存储。不要在每个节点独立执行部署后立即加入负载均衡，这容易产生短暂版本分裂。</p>
<h3>文件权限要区分构建用户与 Web 用户</h3>
<p>静态部署由 root 执行后，文件可能归 root，后续 Magento 用户无法更新；反过来目录不可读取也会让 Nginx 返回 403。检查 <code>pub/static</code>、<code>var/view_preprocessed</code>、<code>generated</code> 的所属用户和目录执行权限。不要用全目录 777 作为永久方案。</p>
<p>如果 <code>pub/static/.htaccess</code> 或 Nginx 示例规则缺失，请求可能无法按预期回退和设置 MIME。Web 根目录必须指向 <code>pub</code>，并使用与当前 Magento 版本匹配的配置。</p>
<h3>主题继承和 LESS 编译错误也会导致缺文件</h3>
<p>部署命令返回成功前的警告不能忽略。自定义主题引用不存在的父主题、LESS 变量或导入文件，会让某个 locale 的 CSS 生成失败。单独部署一个主题与语言并使用详细输出，更容易定位第一条编译错误。</p>
<p>恢复后用无痕窗口检查首页、分类、商品和结账，确认 CSS、RequireJS、字体和图片全部返回正确 MIME 与缓存头。再滚动发布一个节点，验证负载均衡切换时版本仍一致，才说明部署流程真正可靠。</p>]]></description>
      <pubDate>Wed, 11 Sep 2024 08:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 提示 The requested qty is not available，明明还有库存]]></title>
      <link>https://www.360magento.com/blog/magento-2-requested-qty-not-available/</link>
      <description><![CDATA[<p>后台某个 Source 显示还有 20 件，客户加入 1 件却提示 <code>The requested qty is not available</code>。Magento 2 的可购买判断使用当前 Website 所属 Stock 的 Salable Quantity，并结合购物车中已存在数量、最小/最大销售数量和库存阈值；它并不直接读取某一行 Source Quantity。</p>
<h3>确认报错针对哪个 SKU</h3>
<p>可配置、Bundle 和 Grouped 商品在页面上显示父 SKU，但库存校验可能发生在关联简单商品。记录选中的颜色、尺码或 Bundle 选项，找出最终 simple SKU。只有某个组合失败时，不要只检查父商品。</p>
<h3>查看当前销售渠道的 Salable Quantity</h3>
<p>先确认 Website 绑定的 Stock，以及 Stock 包含哪些 Source。可使用 Magento 库存命令或读取对应的库存索引：</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies
SELECT sku, quantity, is_salable
FROM inventory_stock_1
WHERE sku='TEST-SKU';</code></pre>
<p><code>inventory_stock_1</code> 只是示例，实际表后缀应使用当前 Stock ID。索引 quantity 已经小于请求数量时，继续查 reservation、阈值和来源分配；索引正确而仍报错，再查购物车与插件。</p>
<h3>购物车里的旧数量也会参与校验</h3>
<p>客户购物车可能已经有同一 SKU，页面再次加入 1 件时，系统校验的是合并后的数量。迷你购物车缓存没有刷新，会让用户以为购物车为空。检查 active quote：</p>
<pre><code>SELECT item_id, sku, qty, parent_item_id
FROM quote_item
WHERE quote_id=12345;</code></pre>
<p>可配置父子行不能重复相加。自定义 Add to Cart 接口如果没有正确合并 buy request，可能创建多个行或传入异常小数数量。</p>
<h3>Min/Max Sale Qty 与数量增量容易被忽略</h3>
<p>Inventory 配置可以限定最小销售数量、最大销售数量和 Qty Increments。例如库存 20，但最大购买数为 5，购物车已有 5，再加 1 就会失败；商品要求每次按 6 的倍数购买，输入 1 同样不合法。配置可能按客户组生效，因此访客与批发客户结果不同。</p>
<h3>Out-of-Stock Threshold 会预留安全库存</h3>
<p>物理数量 5，阈值为 5 时，Salable Quantity 可能已经是 0。启用 Backorders 后计算又会不同。不要为了让商品可买就把阈值随意设成负数，这会改变全站超卖策略。</p>
<h3>Reservation 不一致要按订单处理</h3>
<p>取消、退款、导入订单或第三方 ERP 绕过标准流程，可能留下未补偿 reservation。先列出不一致并关联具体订单，再生成官方补偿。直接删除 reservation 会破坏其他未发货订单的预留。</p>
<p>修复后清空测试 Quote，分别加入简单商品、可配置子项和达到最大数量的商品；完成下单与取消，再观察 Source Quantity、Reservation 和 Salable Quantity 的变化。只有完整生命周期正确，错误才不会过几天再次出现。</p>]]></description>
      <pubDate>Tue, 10 Sep 2024 01:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[客户重置密码邮件收不到，Magento 2 问题出在哪一层？]]></title>
      <link>https://www.360magento.com/blog/magento-2-reset-password-email-missing/</link>
      <description><![CDATA[<p>客户在 Forgot Password 页面提交邮箱后看到成功提示，却一直收不到邮件。出于安全考虑，Magento 通常不会明确告诉访客该邮箱是否存在，因此页面成功提示不能证明系统已经找到客户并发送。排查时要从账户范围开始，而不是直接归因于 SMTP。</p>
<h3>确认客户属于当前 Website</h3>
<p>Magento 客户账户共享范围可以是 Global 或 Per Website。同一邮箱在另一个 Website 存在，但当前站点按 Website 隔离时，前台不会把它当作可重置账户。后台查看客户 Website，并核对表单所在 Store View 与 Base URL。</p>
<p>只读查询时不要把客户隐私输出到公共日志：</p>
<pre><code>SELECT entity_id, website_id, email, confirmation,
       rp_token_created_at
FROM customer_entity
WHERE email = 'customer@example.test';</code></pre>
<p>有 confirmation 状态或账户被锁定时，还要区分确认邮件、解锁流程和密码重置流程，不能混用模板。</p>
<h3>查看令牌是否生成，而不是查看令牌内容</h3>
<p>提交后 <code>rp_token_created_at</code> 应更新。为了安全，不要记录或复制真实 reset token。时间未变化说明请求没有走到令牌生成，检查网站、表单 key、限流、自定义 controller 和异常日志；时间已变化而邮件未到，则继续查模板与传输。</p>
<h3>商店作用域会决定发件人与模板</h3>
<p>Customer Configuration 中的 Password Options、邮件模板、发件人身份和令牌有效期都可能按 scope 覆盖。多品牌站常见问题是 Default Config 正确，而子 Store View 选择了已删除模板或无效发件地址。</p>
<p>模板中的重置链接必须使用客户提交请求时对应的安全 Base URL。反向代理协议识别错误、旧域名或错误 Store Code 会导致邮件即使收到也无法打开。不要在模板中手工拼接 token 链接。</p>
<h3>重置密码邮件通常不是普通销售邮件队列</h3>
<p>订单邮件的异步设置与客户密码邮件不是同一条链路。查看请求当时的 Magento、PHP 和邮件传输日志，确认 sendmail/SMTP 是否接受消息。第三方 SMTP 模块可能拦截 TransportBuilder，要测试客户模板而不是只点模块的&ldquo;测试邮件&rdquo;。</p>
<p>如果邮件服务显示 accepted，再查退信、抑制列表、SPF、DKIM 和 DMARC。客户邮箱写错、历史硬退信或企业网关策略都会让应用层显示发送成功但实际不投递。</p>
<h3>避免用枚举账户的方式测试</h3>
<p>前台对存在和不存在邮箱应返回相近提示与耗时，防止攻击者枚举客户。排查应在受控后台和日志中完成，不要修改前台提示暴露账户存在性。频繁请求还应受限流保护，防止邮件轰炸。</p>
<p>修复后使用当前 Website 的测试客户请求一次，确认令牌时间更新、邮件服务收到、链接域名和 Store 正确，并在有效期内完成修改。旧链接和重复使用的链接应失效，新密码登录后原有敏感会话也应按安全策略处理。</p>]]></description>
      <pubDate>Mon, 09 Sep 2024 07:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 保存商品报 URL key for specified store already exists 怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-url-key-already-exists/</link>
      <description><![CDATA[<p>后台保存商品时报 <code>URL key for specified store already exists</code>，最直接的反应是修改商品 URL Key。但有时换了一个完全不同的 Key 仍然失败，因为冲突对象不一定是另一个商品，也可能是分类、CMS、自定义 Rewrite 或旧的 301 记录。</p>
<h3>先确定冲突发生在哪个 Store View</h3>
<p>URL Rewrite 的唯一性通常与 <code>request_path + store_id</code> 组合有关。相同路径可以存在于不同商店，但不能在同一个 store 中同时指向两个目标。多商店编辑商品时，Default Config 看起来正常，某个 Store View 的覆盖值却可能仍是旧 Key。</p>
<p>保存前记录商品 ID、当前商店、URL Key 和预期完整路径。若启用了分类路径，还要把所属分类的 URL Path 计算进去，不能只查商品 Key。</p>
<h3>直接查询 request_path 的占用者</h3>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id, metadata
FROM url_rewrite
WHERE request_path IN ('sample.html','category/sample.html')
ORDER BY store_id, url_rewrite_id;</code></pre>
<p>如果结果指向另一个有效商品或分类，应调整业务 URL；如果是旧 301，先确认该旧路径是否仍有外链和自然流量；如果指向已删除实体，才考虑作为孤立数据处理。不要看到冲突就直接删整张表，也不要去掉数据库唯一索引。</p>
<h3>&ldquo;为旧 URL 创建永久重定向&rdquo;会保留历史路径</h3>
<p>修改商品 URL Key 时，Magento 可以自动为旧地址生成 301。频繁改名后，历史路径会持续占用 request_path。若现在想把旧路径分配给另一商品，必须先决定旧流量应该去哪里，再修改或移除对应 Rewrite。</p>
<p>检查 Catalog SEO 中的&ldquo;Create Permanent Redirect for URLs if URL Key Changed&rdquo;，但不要为了解决一次冲突就全局关闭。是否保留历史重定向应由站点 SEO 策略决定。</p>
<h3>分类路径和多分类分配会放大冲突</h3>
<p>启用商品分类路径后，同一商品可能生成多个路径。两个分类具有相同 URL Path，或商品在移动分类后保留旧路径，都可能让保存过程批量生成时失败。查询同一 entity_id 的所有 rewrite，比较系统生成记录与自定义记录：</p>
<pre><code>SELECT request_path, target_path, redirect_type, store_id, metadata
FROM url_rewrite
WHERE entity_type='product' AND entity_id=123
ORDER BY store_id, request_path;</code></pre>
<p>第三方导入或 URL 模块可能绕过 Magento 服务直接插表，留下 metadata 不完整的数据。修复时应优先通过正式 URL Rewrite 服务重新生成，而不是拼 SQL 批量写入。</p>
<h3>保存成功之后还要验证旧地址</h3>
<p>处理冲突后，清理相关缓存并检查新 URL 返回 200、规范标签正确、旧 URL 按预期 301，且没有形成多跳或循环。再在同一 Store View 重新保存商品，确认冲突没有再次生成。真正解决的是 URL 所有权，而不是让一次保存勉强通过。</p>]]></description>
      <pubDate>Fri, 06 Sep 2024 02:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 URL Rewrite 数量暴涨，会拖慢哪些功能？]]></title>
      <link>https://www.360magento.com/blog/magento-2-url-rewrite-growth/</link>
      <description><![CDATA[<p><code>url_rewrite</code> 表从几十万增长到数百万甚至更多，后台保存商品和分类越来越慢，导入、索引或前台路由也开始出现延迟。URL Rewrite 多并不自动等于异常：商品数、分类路径、多商店和历史重定向都会扩大记录量。关键是判断增长速度、记录类型和是否存在重复业务路径。</p>
<h3>先按类型、商店和重定向统计</h3>
<pre><code>SELECT entity_type, store_id, redirect_type, COUNT(*) AS total
FROM url_rewrite
GROUP BY entity_type, store_id, redirect_type
ORDER BY total DESC;</code></pre>
<p>再按创建来源、目标路径或实体抽样。系统生成的商品/分类 rewrite、CMS rewrite 和自定义 rewrite 的处理方式不同。不要直接按 redirect_type 删除，因为 301 可能承载有效的历史 SEO 权重。</p>
<h3>分类路径会让商品 Rewrite 成倍增加</h3>
<p>启用&ldquo;Use Categories Path for Product URLs&rdquo;后，同一商品可能在多个分类路径下生成 URL；多 Store View 会再乘以商店数量。频繁移动分类或修改 URL Key，如果同时保存旧 URL 重定向，会继续累积历史记录。</p>
<p>先根据真实 SEO 策略决定是否需要分类路径和永久历史重定向。关闭配置只影响后续生成并不一定清理旧数据，任何清理都要先导出样本、确认外部链接与流量。</p>
<h3>异常增长常来自重复保存和自定义插件</h3>
<p>批量导入器如果每次运行都保存所有商品，即使 URL 未变化，也可能触发 rewrite 生成。Observer 或 plugin 在保存后再次 save 同一实体，会把问题放大。检查日志中同一商品的保存次数，并分析最近一次增长与导入、分类调整或扩展上线的时间关系。</p>
<p>数据库唯一索引会阻止完全相同的 request_path/store_id，但不同历史路径、随机后缀或无效 redirect 仍可不断增加。不要通过移除唯一索引来让任务跑完。</p>
<h3>表变大影响的不只是前台路由</h3>
<p>保存商品/分类需要查找、删除和插入相关 rewrite；大事务会增加锁与 redo。导入和索引可能因批量生成耗时；前台每次请求也需要按 request_path 与 store_id 匹配。确认这些列的索引存在且未损坏，并用 EXPLAIN 检查真实慢查询。</p>
<pre><code>SHOW INDEX FROM url_rewrite;
EXPLAIN SELECT target_path, redirect_type
FROM url_rewrite
WHERE request_path = 'sample.html' AND store_id = 1;</code></pre>
<p>表空间很大时，删除记录并不会自动把磁盘空间全部归还。OPTIMIZE 或在线表重建可能锁表、需要额外磁盘，必须安排维护窗口并评估数据库版本能力。</p>
<h3>清理必须有可回滚规则</h3>
<p>可以优先识别已不存在实体的孤立 rewrite、指向无效目标的自定义记录和明确过期的历史链，但应先在副本验证查询。对 301 链，尽量把外部入口直接指向最终规范 URL，避免多跳；对仍有流量的旧路径，保留或建立明确替代。</p>
<p>处理后重新统计记录数量和增长速度，测试商品保存、分类移动、CSV 导入、旧链接 301、规范 URL 200 与多商店路由。真正的优化目标是控制后续增长和保存耗时，而不仅是让表暂时变小。</p>]]></description>
      <pubDate>Thu, 05 Sep 2024 08:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[RabbitMQ 消费者跑一会儿就停：Magento 2 消息队列排查]]></title>
      <link>https://www.360magento.com/blog/magento-2-rabbitmq-consumer-stops/</link>
      <description><![CDATA[<p>Magento 2 RabbitMQ 消费者启动后能处理一段时间，随后进程消失，队列消息继续增长。先不要默认它崩溃。消费者可能因为达到 <code>--max-messages</code> 正常退出，也可能被操作系统 OOM Kill、连接中断、业务异常或进程管理器停止。</p>
<h3>确认退出是预期还是异常</h3>
<pre><code>bin/magento queue:consumers:list
bin/magento queue:consumers:start consumer.name --max-messages=100 -vvv</code></pre>
<p>在前台运行一个受控消费者，观察退出码和最后一条日志。<code>max_messages</code> 适合让进程定期重启、释放内存，但前提是 Supervisor、systemd 或其他进程管理器会自动拉起。只配置退出上限却没有守护进程，队列必然停止消费。</p>
<h3>从 RabbitMQ 看 Ready 与 Unacked</h3>
<p>管理界面或命令行中，Ready 持续增长表示消息没有被取走；Unacked 很高表示消费者已经取得消息但迟迟没有确认。后者通常指向业务处理慢、外部接口等待、数据库锁或消费者卡死。</p>
<p>同时观察 consumer 数量、连接、channel、redelivered 和 publish/deliver rate。连接频繁创建和断开，要检查心跳、网络、TLS、负载均衡空闲超时和 RabbitMQ 日志。</p>
<h3>业务异常必须决定重试与失败去向</h3>
<p>一条坏消息如果每次抛异常后立即重新入队，可能形成无限重试，占满日志并阻塞同类消息。消费者应区分暂时错误与永久数据错误，设置有限重试、退避和死信策略。消息处理还要幂等：同一消息因连接中断被再次投递时，不能重复扣款、发邮件或创建实体。</p>
<p>Magento 日志中记录 topic、message ID 和异常类别，但不要输出完整客户或支付数据。自定义 handler 应捕获可预期异常并保留上下文，不能只返回成功来吞掉失败消息。</p>
<h3>内存增长要用周期指标判断</h3>
<p>消费者是长进程。循环中保留大型对象、静态缓存、未释放的实体集合或第三方 SDK 连接，会让 RSS 持续增长。记录处理每 100 条消息后的内存，而不是只看启动值。适当 max-messages 可以降低长期碎片，但仍应修复明显泄漏。</p>
<p>如果进程被系统杀死，查看 kernel/OOM 日志和容器限制。提高 memory_limit 不能解决容器没有可用内存的问题。</p>
<h3>Cron 启动消费者也有边界</h3>
<p>Magento 可以通过 Cron 运行消费者，配置中是否等待消息、每个 consumer 最大消息数和允许列表都会影响行为。高吞吐生产环境常用独立进程管理器，以获得更稳定的重启、日志和并发控制。并发数不能盲目增加，数据库和外部系统必须承受相同吞吐。</p>
<p>修复后投递正常消息、可重试失败消息和永久失败消息三组测试，确认成功确认、有限重试、死信/失败记录和自动重启都符合设计。最终以队列积压能在正常流量下回落、重复业务为零作为判断。</p>]]></description>
      <pubDate>Wed, 04 Sep 2024 03:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Composer 补丁突然应用失败，Magento 2 升级前怎么定位？]]></title>
      <link>https://www.360magento.com/blog/magento-2-composer-patch-failed/</link>
      <description><![CDATA[<p>Magento 2 项目在 <code>composer install</code> 或升级时突然提示 patch cannot be applied，不能直接把补丁配置删掉继续部署。补丁可能仍在修复业务 Bug 或安全问题；也可能上游新版本已经包含同等修复。先确定补丁针对哪个包、哪一版源码，以及失败发生在哪一个文件块。</p>
<h3>锁定实际安装版本与补丁目标</h3>
<pre><code>composer show vendor/package
composer why vendor/package
composer validate
composer install -vvv</code></pre>
<p><code>composer.lock</code> 决定 install 的准确版本。开发环境能应用、生产失败时，比较 lock 文件、Composer 版本、patch plugin 版本和 PHP 平台配置，不要只比较 <code>composer.json</code>。</p>
<p>补丁标题和文件名不是可靠依据。打开 patch header，确认路径指向目标包中的真实文件，并检查源码上下文是否仍存在。上游只改了几行空格、命名空间或方法签名，就可能让 hunk 无法匹配。</p>
<h3>区分已经合入与发生冲突</h3>
<p>搜索补丁新增的关键代码。如果新版本已经包含同样逻辑，重复应用会失败，此时可以在确认发布说明和实际源码后移除补丁；如果上游实现不同，必须重新评估旧补丁是否仍适用，不能机械刷新行号。</p>
<p>对安全补丁，要核对 Adobe 对当前 Magento 版本的适用范围和替代版本。不要因为构建失败就悄悄跳过，也不要把一个为旧版本生成的补丁强行应用到新版本。</p>
<h3>patch level 和工作目录会改变路径</h3>
<p>补丁里的 <code>a/</code>、<code>b/</code>、包根目录和 Composer 插件的 depth/level 配置必须匹配。可以在目标包副本中使用 dry run 观察：</p>
<pre><code>patch --dry-run -p1 &lt; fix.patch
patch --dry-run -p0 &lt; fix.patch</code></pre>
<p>只在隔离的构建目录执行，不要直接修改生产 vendor。dry run 能说明路径层级和具体失败 hunk，但最终仍应让 Composer 构建流程自动、可重复地应用。</p>
<h3>注意同一文件上的补丁顺序</h3>
<p>多个补丁按顺序修改同一区域，前一个成功后会改变后一个的上下文。列出实际应用顺序，检查不同模块是否携带重复补丁。升级 patch plugin 后顺序规则变化，也可能导致过去能构建的项目失败。</p>
<h3>不要把修改后的 vendor 提交成解决方案</h3>
<p>手工修改 vendor 能让当前服务器运行，却无法在下一次 install、扩容节点或 CI 构建中复现。正确做法是更新补丁、升级目标包、改为自有模块扩展，或在确认上游已修复后移除补丁，并让干净环境重新安装。</p>
<p>完成处理后删除构建产物，在全新目录使用同一 lock 文件执行 install、编译和自动测试。特别验证补丁原本修复的场景，而不是只以&ldquo;Composer 没报错&rdquo;作为成功标准。</p>]]></description>
      <pubDate>Tue, 03 Sep 2024 07:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么前台总价会差 0.01？Magento 2 舍入规则解析]]></title>
      <link>https://www.360magento.com/blog/magento-2-price-rounding-cent/</link>
      <description><![CDATA[<p>商品单价乘数量后，购物车、支付页面或 ERP 的总额相差 0.01，通常不是数据库&ldquo;算错了&rdquo;，而是不同系统在不同阶段舍入。Magento 的价格计算会经过基础币、显示币、税、折扣、行总计和订单总计；每一步使用的精度与先后顺序都会影响最后一分钱。</p>
<h3>用一条订单行还原计算过程</h3>
<p>不要只比较 grand_total。读取订单与订单行中的 base 和 display 字段：</p>
<pre><code>SELECT item_id, sku, qty_ordered, price, base_price,
       row_total, base_row_total, tax_amount, base_tax_amount,
       discount_amount, base_discount_amount,
       row_total_incl_tax, base_row_total_incl_tax
FROM sales_order_item
WHERE order_id = 100001;</code></pre>
<p>再比较 <code>sales_order</code> 的 subtotal、tax_amount、discount_amount、shipping_amount 和 grand_total。找到差异第一次出现在哪个阶段，比修改最终总额安全得多。</p>
<h3>单价舍入与行总计舍入结果不同</h3>
<p>假设未舍入单价为 3.333，数量为 3。先把单价显示为 3.33 再乘，得到 9.99；先乘得到 9.999 再舍入，得到 10.00。两种方法都可解释，但必须在目录、购物车、订单、支付和发票中一致。</p>
<p>税费也可以按单价、行或总计计算。Magento 的 Tax Calculation Method、Catalog Prices 是否含税、Discount 是否在税前应用等配置共同决定顺序。不要仅修改显示模板的小数位，它只改变用户看到的值，不会改变订单内部计算。</p>
<h3>多币种会增加一次转换舍入</h3>
<p>Base Currency 转 Order Currency 时，汇率结果可能包含更多小数。支付网关通常只接受货币规定的小数位，ERP 可能又从原始单价重新计算。集成应以 Magento 订单传出的最终金额为准，还是在目标系统重算，必须在接口契约中明确。</p>
<p>零小数货币或三小数货币不能统一按两位处理。使用自定义货币格式时，也要区分展示精度与账务精度。</p>
<h3>折扣按比例分摊最容易留下余数</h3>
<p>固定购物车折扣需要分配到多条订单行。逐行舍入后会有余数，Magento 通常需要把差额分配到某一行，保证订单总额一致。第三方 Total Collector 如果每行独立 round，却没有处理最后的 delta，就会让发票、退款或支付金额相差一分钱。</p>
<p>检查自定义金额是否同时维护 base_amount 与 amount，并使用 Magento 的 PriceCurrency、DeltaRound 等机制，而不是到处直接调用 PHP <code>round()</code>。不同舍入模式也会产生边界差异。</p>
<p>建立包含 3 件同价商品、百分比优惠、含税价格、运费和非整数汇率的测试订单，从 Quote、Order、Invoice、Credit Memo 到支付请求逐项对账。正确目标不是每个中间显示都没有小数误差，而是所有业务单据遵循同一规则，最终应收、实收与可退款金额一致。</p>]]></description>
      <pubDate>Mon, 02 Sep 2024 01:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[订单号偶尔重复？Magento 2 Sequence 表不能这样改]]></title>
      <link>https://www.360magento.com/blog/magento-2-duplicate-order-number/</link>
      <description><![CDATA[<p>Magento 2 创建订单时偶发 Duplicate entry，或后台看到不同订单使用相同的显示订单号，很多人会直接修改 <code>sequence_order_*</code> 表的 AUTO_INCREMENT。这样可能暂时绕过一条错误，却让订单、发票、发货和退款编号继续错位。先分清实体主键与业务 increment_id，再处理 Sequence。</p>
<h3>entity_id 与 increment_id 不是同一个编号</h3>
<p><code>sales_order.entity_id</code> 是数据库实体主键；<code>increment_id</code> 是客户和管理员看到的订单号。Magento 会根据 store 对应的 sales sequence profile 生成 increment_id，前缀、后缀、步长和起始值都可能参与计算。</p>
<pre><code>SELECT entity_id, increment_id, store_id, created_at
FROM sales_order
ORDER BY entity_id DESC
LIMIT 20;</code></pre>
<p>如果 entity_id 正常递增而 increment_id 冲突，问题在业务编号生成或迁移；如果主键也异常，则要调查数据库复制、导入或人工写表。</p>
<h3>确认 Store 与 Sequence 元数据映射</h3>
<p>查看 sequence 相关元数据和 profile，找到当前 store 的实体类型与实际 sequence 表。不同安装的表后缀可能与 store ID 对应，但不要仅凭表名猜测关系。多商店克隆、删除后重建 Store、数据库合并时，最容易留下错误映射。</p>
<p>检查实际订单号是否在两个 store 之间重复。业务上如果允许各店独立编号，显示相同数字未必违反数据库唯一索引；但 ERP 或支付系统若把 increment_id 当作全局唯一键，就必须在集成层加入 store 维度或配置不同前缀。</p>
<h3>不要在有并发写入时手工重置 AUTO_INCREMENT</h3>
<p>直接把 sequence 表的 AUTO_INCREMENT 改小，下一笔编号可能与历史订单冲突。改大虽然通常不重复，但会产生跳号，也可能与 profile 的 start_value、step 计算不一致。任何调整前都要查历史最大编号、当前 sequence 值、商店前缀和外部系统已使用范围。</p>
<p>数据迁移时不要把旧站订单导入后又让新站从默认 1 开始。迁移脚本应在停止写入的窗口完成，建立明确的新编号起点，并验证所有销售实体。</p>
<h3>自定义订单号模块要保证原子性</h3>
<p>使用&ldquo;查询最大值再加一&rdquo;的代码在并发下必然有竞争：两个请求可能读到同一个最大值。正确实现应依赖数据库原子自增或锁定的 sequence 服务，并在事务和失败重试中保持唯一。</p>
<p>模块如果只改订单号，没有同步发票、Shipment、Credit Memo 或支付 merchant reference，也会造成运营混乱。检查它是否通过公开扩展点实现，而不是 around plugin 完全替换核心 sequence 逻辑。</p>
<p>修复后并发创建多笔测试订单，覆盖至少两个 Store View 和两种支付方式，确认数据库无重复、编号前缀符合规则、支付与 ERP 收到的引用唯一。编号允许跳跃，但不应倒退、复用或因失败订单而强行补齐。</p>]]></description>
      <pubDate>Fri, 30 Aug 2024 08:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级 Magento 2.4.7 后支付脚本被 CSP 拦截，该怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-csp-blocks-payment-script/</link>
      <description><![CDATA[<p>升级到 Magento 2.4.7 系列后，结账页支付按钮不出现、第三方 SDK 加载失败，浏览器 Console 显示 Content Security Policy 拒绝脚本、iframe 或连接。CSP 是浏览器执行的安全边界，正确处理方式是识别业务真正需要的来源和执行方式，而不是把策略整体关闭。</p>
<h3>先保存完整的 CSP 违规信息</h3>
<p>Console 中要记录被阻止的资源 URL、违反的 directive、页面路径和是否为 inline script。常见 directive 包括 <code>script-src</code>、<code>frame-src</code>、<code>connect-src</code>、<code>img-src</code> 和 <code>style-src</code>。支付 SDK 可能同时需要脚本域、API 域、3DS iframe 域和图片域，只允许其中一个仍会在后续步骤失败。</p>
<p>确认报错确实由当前 Magento 响应头产生。CDN、WAF 或 Web 服务器也可能追加第二个 CSP 头；浏览器会同时执行多条策略，后一层放宽并不能覆盖前一层限制。</p>
<h3>Report-Only 与 Restrict 模式要分清</h3>
<p>Report-Only 只记录违规，不应阻止资源；Restrict 会直接拦截。不同页面区域和 Magento 版本可能采用不同模式。不要看到 Console 警告就断定它是页面故障根因，应同时检查资源是否实际加载和 Network 状态。</p>
<h3>为可信来源添加最小白名单</h3>
<p>模块可以在 <code>etc/csp_whitelist.xml</code> 中声明允许来源。示例结构：</p>
<pre><code>&lt;?xml version=\"1.0\"?&gt;
&lt;csp_whitelist xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
 xsi:noNamespaceSchemaLocation=\"urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd\"&gt;
  &lt;policies&gt;
    &lt;policy id=\"script-src\"&gt;
      &lt;values&gt;
        &lt;value id=\"payment-sdk\" type=\"host\"&gt;支付服务脚本域名&lt;/value&gt;
      &lt;/values&gt;
    &lt;/policy&gt;
  &lt;/policies&gt;
&lt;/csp_whitelist&gt;</code></pre>
<p>实际域名必须来自支付服务官方集成要求，并区分沙盒与正式环境。不要允许通配的所有 HTTPS 来源，也不要照抄 Console 中出现的未知域名；被注入的恶意脚本同样会请求外部域。</p>
<h3>内联脚本优先改为 nonce 或 hash 兼容方式</h3>
<p>直接加入 <code>'unsafe-inline'</code> 会显著削弱 CSP。自定义模板中的内联脚本应迁移到 RequireJS/外部模块，或使用 Magento 提供的 SecureHtmlRenderer、nonce/hash 机制。动态变化的内联内容无法稳定使用固定 hash，需要从渲染方式解决。</p>
<h3>结账验证要覆盖完整支付流程</h3>
<p>脚本初次加载成功不代表问题结束。测试支付方式展示、tokenize、3DS challenge、弹窗、回调、成功跳转和失败重试，并在每一步观察新的 CSP 报告。钱包支付还可能使用 worker、frame ancestor 或表单提交相关策略。</p>
<p>上线后可把违规报告发送到受控端点并监控新增来源，但报告中可能包含页面信息，需按隐私要求处理。最终白名单应进入自有模块和版本控制，避免直接改 vendor 文件导致下次升级丢失。</p>]]></description>
      <pubDate>Thu, 29 Aug 2024 02:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API 返回 400：请求 JSON 看起来没错，错在哪里？]]></title>
      <link>https://www.360magento.com/blog/magento-2-rest-api-400/</link>
      <description><![CDATA[<p>Magento 2 REST API 返回 400 Bad Request，请求体在 JSON 校验工具中完全合法，却仍提示输入异常。这里的&ldquo;合法 JSON&rdquo;只证明语法能解析，不代表结构符合 Magento 路由对应的 Service Contract。字段层级、参数名、数据类型和扩展属性只要有一处不匹配，都可能被输入处理器拒绝。</p>
<h3>保留 Magento 返回的完整错误对象</h3>
<p>响应中的 <code>message</code>、<code>parameters</code> 和 <code>trace</code>（仅开发环境）通常会指出无法处理的字段。先使用最小请求复现：</p>
<pre><code>BASE_URL='站点地址'
TOKEN='访问令牌'
curl -i -X POST \
  -H \"Authorization: Bearer $TOKEN\" \
  -H 'Content-Type: application/json' \
  --data @payload.json \
  \"$BASE_URL/rest/V1/目标接口\"</code></pre>
<p>不要把真实 Token 和客户数据贴到公共日志。检查实际发送的字节，而不是只看代码中构造 JSON 的对象；代理、SDK 或字符串拼接可能改变请求体。</p>
<h3>最外层参数名必须匹配方法签名</h3>
<p>如果接口方法是 <code>save(ItemInterface $item)</code>，请求体通常需要以 <code>item</code> 为外层键；若方法参数不同，结构也随之变化。自定义接口在 <code>webapi.xml</code> 中绑定的 service method 必须与接口定义、实现和生成代码一致。</p>
<p>更新 Service Contract 后，应清理生成代码、重新编译依赖注入并验证接口 schema。只修改实现类而不修改 API 接口，Web API 输入映射仍可能沿用旧类型。</p>
<h3>类型错误经常被 JSON 外观掩盖</h3>
<p>数字字符串、布尔字符串、null、空对象和空数组在 PHP 转换中含义不同。接口期望数组却收到对象，或期望整数却收到带格式文本，会报类似&ldquo;无法处理参数&rdquo;。日期要符合接口接受的格式，金额不要带货币符号。</p>
<p>Extension Attributes 必须先在 <code>extension_attributes.xml</code> 声明，并通过对应数据接口暴露。随意把自定义字段塞进 <code>extension_attributes</code> 不会自动保存。字段名与生成的 getter/setter 映射也必须一致。</p>
<h3>区分 400、401、403 和 404</h3>
<p>400 主要指输入或业务校验；401 是认证失败；403 是资源权限；404 可能是路由或实体不存在。WAF、反向代理也可能返回自己的 400 HTML 页面，因此要检查 Content-Type 和响应来源，确认错误真的来自 Magento。</p>
<h3>多商店上下文会改变校验结果</h3>
<p>路径中的 store code 会影响网站、属性选项、货币、客户和库存上下文。同一个 SKU 在 default store 可处理，在另一个 store 报输入错误时，检查实体归属和作用域，而不是只比较 JSON。</p>
<p>修复后保存一组契约测试：最小合法请求应成功，缺少必填字段、错误类型和无权限令牌应返回预期错误。这样升级 Magento 或扩展后，能够在生产接口失败前发现 Service Contract 变化。</p>]]></description>
      <pubDate>Wed, 28 Aug 2024 06:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[筛选页面被搜索引擎大量收录，Magento 2 SEO 应该怎么控制？]]></title>
      <link>https://www.360magento.com/blog/magento-2-layered-navigation-seo/</link>
      <description><![CDATA[<p>分类页的颜色、品牌、价格等筛选被搜索引擎大量收录，索引报告中出现成千上万个参数 URL。问题不只是 Meta Title 重复。多属性组合、排序、每页数量和分页会让 URL 数量呈乘法增长，消耗抓取预算，还可能让权重分散到没有搜索价值的页面。</p>
<h3>先给参数分组，而不是一刀切</h3>
<p>把 URL 分成真实分页、排序与显示参数、单属性筛选、多属性组合、价格区间和站内搜索结果。不同类型的用户价值不同。某些&ldquo;品牌 + 分类&rdquo;页面有明确搜索需求，可以做独立落地页；随机颜色、尺码、价格组合通常不值得索引。</p>
<p>从服务器日志和搜索平台数据中统计搜索引擎实际抓取的参数、状态码、收录量和自然流量。不要只凭 URL 数量决定策略。</p>
<h3>Canonical、noindex 和 robots.txt 作用不同</h3>
<p>Canonical 是对规范版本的提示；noindex 是索引指令；robots.txt 阻止抓取后，搜索引擎可能无法看到页面中的 noindex。把三者随意叠加，会让信号互相冲突。若筛选页需要被抓取但不希望进入索引，可让页面可访问并输出 noindex；若页面具有独立价值，则应使用自引用 canonical、独特内容和稳定内链。</p>
<p>不要把所有分页都 canonical 到第一页。分页承载不同商品，全部归一可能削弱深层商品发现。排序与每页数量参数通常更适合 canonical 到不带这些参数的同页集合。</p>
<h3>Magento 原生配置不能覆盖所有组合</h3>
<p>Magento 的分类 canonical 配置主要处理分类和商品规范 URL。第三方 Layered Navigation 模块可能把参数改成路径段、创建可索引筛选页或自行输出 canonical。检查最终 HTML 的 <code>canonical</code>、<code>robots</code> 和页面标题，不能只看后台开关。</p>
<p>自定义实现应建立白名单：只有被业务批准的筛选组合生成可索引页面，其余组合统一 noindex 或规范化。白名单还要按商店、语言和属性 option ID 管理，不能只依赖可变的显示标签。</p>
<h3>内链决定搜索引擎会持续发现什么</h3>
<p>即使页面 noindex，站内仍向数百万种组合输出可抓取链接，也会持续消耗资源。对无价值组合可以避免生成可跟踪链接，或通过前端交互控制发现路径，但不能破坏用户筛选和可访问性。已经存在外链或历史流量的 URL，应评估重定向而不是突然全部 404。</p>
<h3>站点地图只放规范 URL</h3>
<p>Sitemap 不应包含排序、每页数量、会 canonical 到其他页面或 noindex 的筛选 URL。若少数筛选页被升级为 SEO 落地页，应提供稳定 URL、独立标题描述、正文和可持续的商品集合。</p>
<p>上线策略前抽样抓取分类首页、分页、一个允许索引的筛选和一个禁止索引的组合，检查状态、canonical、robots、内链及渲染后 HTML。随后观察抓取日志与索引报告数周，因为旧参数页退出索引不会立即完成。</p>]]></description>
      <pubDate>Tue, 27 Aug 2024 01:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品图片批量 404，问题可能不在图片文件]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-images-404/</link>
      <description><![CDATA[<p>商品列表和详情页突然出现大量破图，直接查看 <code>pub/media/catalog/product</code> 又能找到原图。此时不要急着重新上传全部图片。Magento 前台请求的通常是经过尺寸、主题角色和哈希目录处理后的缓存图片，404 可能发生在 URL 生成、缓存派生、Web 服务器路由或 CDN 任一层。</p>
<h3>先比较数据库路径、原图和请求 URL</h3>
<p>商品媒体属性通常保存相对路径，例如 <code>/a/b/image.jpg</code>。页面可能请求 <code>media/catalog/product/cache/...</code> 下的派生文件。记录一个失败 SKU、数据库 value、服务器原图路径和浏览器请求 URL，确认是所有尺寸都失败，还是只有某个 image role。</p>
<pre><code>SELECT cpev.entity_id, cpev.value
FROM catalog_product_entity_varchar cpev
JOIN eav_attribute ea ON ea.attribute_id = cpev.attribute_id
WHERE ea.attribute_code IN ('image','small_image','thumbnail')
  AND cpev.entity_id = 123;</code></pre>
<p>不同 Magento 版本的实体键结构可能不同，查询前先确认表结构。数据库值为 <code>no_selection</code> 与文件 404 也不是同一问题。</p>
<h3>检查媒体 Base URL 和商店作用域</h3>
<p>多商店或 CDN 环境中，Secure/Unsecure Media Base URL 可能在网站、商店视图被覆盖。HTML 生成了旧域名、错误协议或重复 media 路径时，原图存在也无法访问。使用后台配置或 CLI 查看各 scope 的生效值，不要只检查 Default Config。</p>
<h3>图片缓存需要 Web 用户能够生成</h3>
<p>首次请求某个尺寸时，Magento 可能读取原图并生成缓存。Web 用户对 <code>pub/media/catalog/product/cache</code> 没有写权限、PHP 缺少图像库、源文件损坏或内存不足，都会让派生失败。查看 Magento、PHP 和 Web 服务器日志，确认请求是 Magento 返回 404，还是 Nginx 在进入 PHP 前直接拒绝。</p>
<p>清理目录前先判断影响范围。后台的 Flush Catalog Images Cache 会删除派生图，随后流量会重新生成；在商品量大或高峰期执行会造成明显 CPU 与 I/O 峰值。可以通过官方图片 resize 命令预生成，再逐步切换。</p>
<h3>Nginx、CDN 与多节点经常造成&ldquo;有时能打开&rdquo;</h3>
<p>如果刷新后图片时好时坏，检查请求是否落到不同 Web 节点。共享 media 未挂载、文件同步延迟或某节点权限不同，会产生随机 404。CDN 还可能长期缓存第一次的 404，即使源站后来已经生成文件。</p>
<p>Web 规则应允许真实媒体文件直接返回，并让需要动态生成或占位图的路径按 Magento 推荐配置处理。不要写一个把所有 media 404 都重定向到首页的规则，这会把错误状态变成 200，影响缓存和搜索引擎诊断。</p>
<h3>文件名大小写和迁移后的路径也值得检查</h3>
<p>从大小写不敏感系统迁移到 Linux 后，<code>Image.JPG</code> 与 <code>image.jpg</code> 是不同文件。数据库路径、文件名和 CDN URL 必须完全一致。含空格、非标准字符的旧文件在不同编码或同步工具中也可能被改名。</p>
<p>修复后选择原先失败的商品，在列表、详情、购物车和邮件中检查不同 image role；再清除一个精确 CDN URL，确认新请求返回正确 MIME、200 状态和合理缓存头。只有原图与派生图的生成链路都稳定，才不需要再次人工补图。</p>]]></description>
      <pubDate>Mon, 26 Aug 2024 09:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[cron_schedule 出现 missed，Magento 2 定时任务到底卡在哪一步？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cron-missed/</link>
      <description><![CDATA[<p><code>cron_schedule</code> 中大量任务变成 <code>missed</code>，与 <code>error</code> 不是同一种故障。error 表示任务已经开始执行并抛出错误；missed 通常表示调度器发现这条计划时，它已经超过允许启动的时间窗口。要解决问题，必须判断计划有没有按时生成、系统 Cron 有没有按分钟启动、以及前一批任务是否把进程堵住。</p>
<h3>先看一段完整时间线</h3>
<pre><code>SELECT schedule_id, job_code, status, scheduled_at,
       executed_at, finished_at, messages
FROM cron_schedule
WHERE scheduled_at &gt; NOW() - INTERVAL 2 HOUR
ORDER BY schedule_id DESC;</code></pre>
<p>如果完全没有未来的 pending 记录，计划生成器没有正常运行；有 pending 但没有 executed_at，系统 crontab 或 Cron 进程可能没有启动；前面大量 running 且长期没有 finished_at，则要查长任务和锁。</p>
<p>单看一条 missed 没有意义。比较同一 job_code 连续多条记录，确认是所有组同时中断，还是只有 index、consumers、default 或自定义组异常。</p>
<h3>系统 crontab 必须使用正确的 PHP 与文件用户</h3>
<pre><code>crontab -l
php -v
php --ini
bin/magento cron:run</code></pre>
<p>Web PHP 与 CLI PHP 版本、扩展和 php.ini 可能不同。计划由错误用户执行时，会出现 <code>var</code>、<code>generated</code>、日志或锁文件权限问题。不要用 root 长期运行 Magento Cron 来绕过权限，它会继续生成 Web 用户无法写入的文件。</p>
<h3>一个慢任务能拖垮同组后续任务</h3>
<p>导入、邮件、第三方同步或全量数据处理如果没有批次和超时控制，可能长期占用 Cron 组。查看进程、PHP-FPM/CLI 资源和任务日志，找出最早开始却未结束的 job。自定义任务应避免一次读取全部集合，使用分页或游标，并记录每批进度。</p>
<p>需要隔离时，可为重要 Cron group 配置独立进程。但独立运行并不等于可以忽略并发锁；同一任务如果上一次还没结束，下一次又启动，可能重复发送、重复导入或争用数据库。</p>
<h3>服务器时间和配置窗口也会制造 missed</h3>
<p>操作系统时区、数据库时间与 Magento 配置不一致时，排查会非常混乱。<code>scheduled_at</code> 通常按数据库时间记录，后台显示还可能转换时区。同步 NTP，并比较：</p>
<pre><code>date
php -r 'echo date("c"), PHP_EOL;'
mysql -e 'SELECT NOW(), @@system_time_zone, @@session.time_zone;'</code></pre>
<p>Cron 组中的 schedule_generate_every、schedule_ahead_for 和 schedule_lifetime 决定生成频率、提前量与错过窗口。不要为了隐藏 missed 就无限增大 lifetime；这会让本应过期的任务在很晚之后集中执行。</p>
<p>清理历史 cron_schedule 记录可以改善表大小，但不能修复调度链路。恢复后观察至少两个完整周期，确认未来计划持续生成、pending 能转为 success，且积压数量不再增长。对订单邮件、索引和队列消费者还要验证业务结果，而不是只看状态变绿。</p>]]></description>
      <pubDate>Fri, 23 Aug 2024 02:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[优惠码在购物车有效，到了结账页却失效是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-coupon-invalid-checkout/</link>
      <description><![CDATA[<p>客户在购物车输入优惠码后看到折扣，进入结账或选择配送方式后折扣消失。这个现象不一定是前端丢了 coupon code，很多购物车价格规则要等地址、运费、客户组和支付信息完整后重新验证；重算后条件不满足，Magento 会合法地移除折扣。</p>
<h3>确认 coupon code 是否还在 Quote 上</h3>
<p>先在结账接口响应和数据库中查看 quote：</p>
<pre><code>SELECT entity_id, store_id, customer_group_id, coupon_code,
       subtotal, base_subtotal, grand_total, updated_at
FROM quote
WHERE entity_id = 12345;</code></pre>
<p>coupon_code 仍在但 discount_amount 变为 0，说明规则重新计算后未命中；coupon_code 本身被清空，则检查前端调用、扩展插件或规则校验返回。不要直接修改 quote 表恢复优惠码，下一次 collect totals 仍会覆盖。</p>
<h3>地址条件只有在结账时才完整</h3>
<p>规则可能限制国家、地区、邮编、配送方式或运费金额。购物车阶段使用默认地址估算，客户在结账输入真实地址后条件变化，折扣自然失效。Free Shipping、Payment Method 条件也可能在选择相应步骤后才确定。</p>
<p>检查规则 Conditions 与 Actions 的区别：Conditions 决定整个购物车是否符合，Actions 下面的条件决定哪些商品行参与折扣。常见错误是把 SKU、分类或属性条件放在错误区域，导致购物车预览与最终行折扣看起来不一致。</p>
<h3>客户登录会改变客户组和历史次数</h3>
<p>访客在购物车使用成功，登录后进入结账失效，要检查规则允许的 Customer Groups、每位客户使用次数和全局使用次数。使用相同邮箱的历史订单、取消订单处理和异步更新都可能影响计数。规则的 From/To 日期还依赖商店时区。</p>
<h3>其他规则和 Stop Further Rules Processing</h3>
<p>结账时命中另一条优先级更高的规则，并启用&ldquo;停止后续规则处理&rdquo;，会让原优惠不再应用。按优先级检查所有当前有效规则，而不是只看用户输入的那一条。多个优惠能否叠加必须由业务规则明确决定。</p>
<h3>前端显示也可能滞后</h3>
<p>接口 totals 中已有折扣而页面没有显示，检查 checkout totals segment、自定义 total renderer 和 customer-data。一步结账扩展可能没有在地址或配送方式变化后正确重新加载 totals。以 REST/GraphQL 返回和 quote totals 为证据，区分计算错误与显示错误。</p>
<p>验证时构造边界用例：访客与登录客户、允许与不允许地区、最低金额前后、含特价商品、切换配送方式和支付方式。每次观察 coupon_code、discount segment 和 grand total，才能确认规则在结账全过程稳定。</p>]]></description>
      <pubDate>Thu, 22 Aug 2024 07:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[后台商品列表一直加载不出来：Magento 2 Admin Grid 排查思路]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-grid-loading/</link>
      <description><![CDATA[<p>进入 Magento 2 后台商品列表，表头出现但加载图标一直转，或者页面空白没有数据。Admin Grid 由 UI Component、数据源请求、Bookmark 状态和后台集合共同组成，问题不一定在商品数量。</p>
<h3>先找到 mui/index/render 请求</h3>
<p>在 Network 中筛选 XHR，查看类似 <code>mui/index/render</code> 的请求。它返回 200 且包含 JSON，问题通常在前端组件；返回 302 到登录页，检查后台会话和 form key；403 检查管理员 ACL；500 则按时间查看 exception 和 PHP 日志。</p>
<p>响应体如果是完整 HTML 而不是 JSON，说明请求被重定向或服务器错误页面替换。不要只看状态码，有些代理会把上游错误包装成 200。</p>
<h3>清理个人 Bookmark 可验证列状态问题</h3>
<p>Magento 会在 <code>ui_bookmark</code> 中保存管理员对列、排序、筛选和视图的设置。安装扩展或删除列后，旧 Bookmark 可能引用不存在的字段，导致网格异常。先让受影响管理员使用默认视图或重置网格；只有一位管理员失败而其他人正常，是 Bookmark 问题的重要线索。</p>
<pre><code>SELECT bookmark_id, user_id, namespace, identifier
FROM ui_bookmark
WHERE namespace LIKE '%product%';</code></pre>
<p>删除记录属于写操作，必须先确认 user_id、namespace 并备份。不要清空所有管理员的 Bookmark。</p>
<h3>自定义列可能破坏集合 SQL</h3>
<p>最近增加的 extension_attribute、join 或 filter strategy 是重点。普通页面打开时集合可能尚未真正加载，等数据源请求应用筛选和排序才触发 SQL。查看异常中的 unknown column、ambiguous column、duplicate alias 或 GROUP BY 错误。</p>
<p>对慢 SQL 执行 EXPLAIN，确认筛选列和 join 条件有索引。后台网格使用大量 LEFT JOIN、计算列或逐行 repository 加载，会随商品量增长迅速变慢。自定义列如果能从主查询批量获得，就不要在每一行渲染时重新加载商品。</p>
<h3>前端错误要从第一条开始处理</h3>
<p>请求已经返回正确 JSON，但加载动画不结束时，检查 Console 的 RequireJS、Knockout 和 UI registry 错误。主题一般不影响后台，但自定义 adminhtml 模块可能覆盖 listing XML 或 JS mixin。运行静态内容部署与缓存清理前，先确认代码和生成目录的所属用户一致。</p>
<p>修复后测试默认视图、保存视图、筛选、排序、分页、批量选择和 CSV 导出。一个网格能显示第一屏并不代表 filter mapping 与批量操作已经正确。</p>]]></description>
      <pubDate>Wed, 21 Aug 2024 01:54:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 GraphQL 查询越来越慢，瓶颈通常在哪里？]]></title>
      <link>https://www.360magento.com/blog/magento-2-graphql-slow-query/</link>
      <description><![CDATA[<p>同一个 Magento 2 GraphQL 接口上线初期很快，商品量或前端功能增加后逐渐变慢，通常不是 GraphQL 协议本身的问题。真正耗时来自查询请求了什么字段、每个 Resolver 如何取数、是否发生 N+1 查询，以及响应能否被正确缓存。</p>
<h3>先固定查询与变量再测量</h3>
<p>不要只说&ldquo;products 查询慢&rdquo;。保存完整 operation name、query、variables、商店头和响应大小，用相同条件测试。分类第一页请求 20 个商品，与一次请求 200 个商品并展开媒体、价格、库存和自定义属性，负载完全不同。</p>
<pre><code>curl -sS -X POST \
  -H 'Content-Type: application/json' \
  -H 'Store: default' \
  --data @query.json \
  'GraphQL接口地址' -o response.json</code></pre>
<p>分别记录 TTFB、总时间、返回字节数和服务端执行时间。只看浏览器瀑布图容易把网络下载与后端计算混在一起。</p>
<h3>自定义 Resolver 最容易产生 N+1</h3>
<p>列表返回 50 个商品，如果自定义字段 Resolver 对每个商品各调用一次 repository 或执行 SQL，就会产生几十到几百次重复查询。优先使用批量 Resolver、Data Provider 或一次集合查询，并按实体 ID 批量加载所需字段。</p>
<p>不要在 Resolver 中调用 <code>ObjectManager</code>、重复加载完整 Product 模型，或为每个字段触发外部 HTTP 请求。外部数据应有明确超时、批量接口和缓存策略。应用性能监控中如果同一 SQL 只替换 entity_id 重复出现，就是典型信号。</p>
<h3>检查查询选择集是否过大</h3>
<p>GraphQL 的优势是客户端选择字段，但这也意味着客户端能请求昂贵的嵌套结构。前端页面只展示名称和价格，却同时请求 description、所有媒体、reviews、options 和大量自定义属性，会增加数据库、搜索服务与序列化成本。拆分首屏必需字段和延迟加载字段，通常比服务器盲目加资源有效。</p>
<p>分页也要合理。极大的 pageSize 会放大商品加载与响应体；深页 offset 查询可能越来越慢，具体策略要结合 Magento 当前接口能力和业务场景。</p>
<h3>缓存命中依赖身份与上下文</h3>
<p>匿名查询与登录客户查询的缓存条件不同。价格、客户组、Store、Currency 和授权头都会影响结果。自定义 Resolver 如果没有返回正确的 cache identity，可能出现不能缓存或缓存串数据。先验证响应头和 Magento GraphQL resolver result cache 状态，再决定 CDN 是否安全缓存。</p>
<h3>SQL、搜索与 PHP 都要有证据</h3>
<p>对一次慢请求抓取 SQL 数量与累计耗时、OpenSearch 查询耗时、PHP CPU 和内存。数据库慢时检查集合过滤和索引；搜索慢时检查聚合字段与分片；PHP 时间高则检查 Resolver 循环和序列化。不要把所有慢查询都归因于 Redis。</p>
<p>优化后用相同 query/variables 做冷缓存与热缓存对比，并增加一个较大分类和一个登录客户场景。除平均值外还要观察 P95/P99，因为偶发外部调用或锁等待往往不会体现在平均响应时间中。</p>]]></description>
      <pubDate>Tue, 20 Aug 2024 08:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[搜索突然报 all shards failed，Magento 2 站点怎么恢复？]]></title>
      <link>https://www.360magento.com/blog/magento-2-opensearch-all-shards-failed/</link>
      <description><![CDATA[<p>Magento 2 搜索页突然返回错误，OpenSearch 或 Elasticsearch 响应 <code>search_phase_execution_exception: all shards failed</code>。这句话只表示参与当前查询的分片全部失败，并没有说明原因。真正可操作的信息在响应里的 <code>root_cause</code> 和每个 shard failure。</p>
<h3>先确认是整个集群还是一个索引</h3>
<pre><code>SEARCH_ENDPOINT='搜索服务地址'
curl -sS \"$SEARCH_ENDPOINT/_cluster/health?pretty\"
curl -sS \"$SEARCH_ENDPOINT/_cat/indices?v\"
curl -sS \"$SEARCH_ENDPOINT/_cat/shards?v\"</code></pre>
<p>集群 red 表示至少有主分片不可用；yellow 在单节点环境可能只是副本未分配，不一定阻止查询。查找状态为 UNASSIGNED 的 Magento 索引，并通过 allocation explain 确认是节点离线、磁盘水位、分片数量还是版本兼容问题。</p>
<p>如果只有当前 Magento 索引异常，先识别实际索引前缀，不要删除整个搜索集群。一个服务可能同时承载多个站点或其他应用。</p>
<h3>查看失败分片给出的具体异常</h3>
<p>常见根因包括：查询了不存在或类型不兼容的字段、文本字段被用于不允许的排序/聚合、脚本错误、解析异常、损坏分片或节点断开。把 Magento 发送的请求与失败响应在搜索服务慢日志或应用调试日志中关联，才能知道是哪一个属性触发。</p>
<p>如果新增或修改商品属性后出现，检查该属性在 Magento 中是否用于搜索、分层导航、排序，以及不同文档是否产生冲突类型。索引映射一旦把字段确定为某种类型，后续写入另一种结构可能失败。</p>
<h3>磁盘水位与只读索引会连锁出现</h3>
<p>磁盘接近阈值时，分片可能无法分配，索引还可能被设为只读。查看节点磁盘和集群设置。释放空间时优先清理明确可删除的旧索引、日志或快照，不要直接删除当前线上别名指向的索引。</p>
<p>恢复可写后再重建搜索索引：</p>
<pre><code>bin/magento indexer:reset catalogsearch_fulltext
bin/magento indexer:reindex catalogsearch_fulltext
bin/magento indexer:status catalogsearch_fulltext</code></pre>
<p>如果重建仍失败，继续处理第一条具体 bulk 或 mapping 错误。反复 reset 不会修复数据与集群问题。</p>
<h3>搜索恢复后还要验证增量更新</h3>
<p>全量重建成功只证明当前数据能写入。修改一个商品名称和一个可搜索属性，等待按计划索引后再次搜索，确认增量链路正常。还要测试分类页、价格排序、分层导航和自动建议，因为它们可能使用不同查询与聚合。</p>
<p>对高可用集群，补充节点、合理配置副本和监控未分配分片比故障后手工重建更重要。告警至少应覆盖 cluster status、磁盘水位、rejected requests、索引延迟和 Magento indexer 状态。</p>]]></description>
      <pubDate>Mon, 19 Aug 2024 03:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis 报 max number of clients reached，先查这几处]]></title>
      <link>https://www.360magento.com/blog/magento-2-redis-max-clients/</link>
      <description><![CDATA[<p>Magento 2 前台偶发 500，日志中出现 <code>ERR max number of clients reached</code>，说明 Redis 已拒绝新的客户端连接。直接把 <code>maxclients</code> 调大可能短暂恢复，但如果连接持续泄漏或服务器文件描述符不足，问题很快会再次出现。</p>
<h3>先确认哪一个 Redis 实例耗尽</h3>
<p>Magento 常把 default cache、page cache 和 session 配置到 Redis，它们可能使用同一实例的不同 database，也可能完全分离。查看 <code>app/etc/env.php</code> 中实际主机、端口和 database 编号，不要把敏感密码输出到工单。再从 Redis 查看：</p>
<pre><code>redis-cli INFO clients
redis-cli CONFIG GET maxclients
redis-cli CLIENT LIST</code></pre>
<p>关注 connected_clients、blocked_clients、最长空闲时间和客户端来源地址。database 编号只能隔离键空间，不能隔离连接数和内存；三个用途共享同一进程时，仍共同消耗 maxclients。</p>
<h3>PHP-FPM 并发会放大连接数量</h3>
<p>每个 PHP-FPM worker 可能同时持有缓存、FPC 和 session 连接。Web 节点数量、<code>pm.max_children</code>、Cron 与消费者进程相加后，理论连接上限可能远高于单机观察值。先估算所有节点最大并发，再与 Redis、操作系统文件描述符限制比较。</p>
<pre><code>redis-cli INFO clients | grep connected_clients
redis-cli INFO stats | grep rejected_connections
ulimit -n</code></pre>
<p>如果 rejected_connections 持续增加，说明不是一次偶发峰值。不要只在 Redis 提高 maxclients，系统的 <code>nofile</code> 限制和服务单元限制也必须能支持新值。</p>
<h3>区分连接过多与命令太慢</h3>
<p>慢 Lua、巨大的 tag 清理或阻塞命令会让连接长时间占用。检查 slowlog、命令统计和延迟：</p>
<pre><code>redis-cli SLOWLOG GET 20
redis-cli INFO commandstats
redis-cli --latency</code></pre>
<p>Magento 缓存清理在键量很大时可能造成峰值；session 数据过大、机器人制造大量会话，也会增加内存与连接压力。若 CLIENT LIST 中大量连接来自未知主机，检查网络访问控制，Redis 不应直接暴露到公网。</p>
<h3>持久连接不是越多越好</h3>
<p>某些客户端支持 persistent connection。它能减少频繁建连，但配置不当会让每个 worker 长期占用多条连接。比较启用前后的连接曲线，并确认连接 ID 或持久标识不会在 cache 与 session 间冲突。升级客户端库后出现问题，还应核对 phpredis、Magento 版本和连接参数兼容性。</p>
<p>必要时将 session、default cache 和 page cache 分到独立 Redis/Valkey 实例，以隔离内存和故障域，但迁移要安排维护窗口并考虑现有会话失效。缓存实例通常可以重建，session 丢失会让客户退出登录，两者风险不同。</p>
<p>修复后在正常流量和 Cron 高峰观察 connected_clients、rejected_connections、内存、命令延迟和 PHP-FPM 队列。只有连接数在可预测范围内回落，并且没有新的拒绝记录，才说明不是单纯把上限往后推。</p>]]></description>
      <pubDate>Fri, 16 Aug 2024 06:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[可配置商品有库存却显示缺货：从子商品到 Salable Quantity]]></title>
      <link>https://www.360magento.com/blog/magento-2-configurable-in-stock-but-out-of-stock/</link>
      <description><![CDATA[<p>后台看到可配置商品和子商品都有数量，前台却显示 Out of Stock，最常见的误区是只查看父商品。可配置商品本身不承担具体库存，它是否可售由当前网站可用的关联简单商品决定。只要子商品在状态、网站、来源或可销售数量上不满足条件，父商品就可能整体显示缺货。</p>
<h3>先确认子商品真的属于当前销售渠道</h3>
<p>逐个检查关联简单商品是否启用、分配到当前网站、具有必需属性值，并且没有被删除或解除关联。子商品可见性可以是&ldquo;单独不可见&rdquo;，这不会阻止它作为可配置选项销售。真正关键的是网站归属与状态。</p>
<p>使用 Multi-Source Inventory 时，Source Quantity 不是前台直接使用的 Salable Quantity。销售渠道关联的是 Stock，Stock 再包含一个或多个 Source。子商品有 10 件数量，但这 10 件位于没有分配给当前网站 Stock 的 Source，前台仍不可售。</p>
<h3>Salable Quantity 还会扣除 Reservation</h3>
<p>下单会创建负 reservation，发货时再通过库存扣减和补偿完成链路。检查不一致：</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies
bin/magento inventory:reservation:list-inconsistencies -r</code></pre>
<p>输出表示订单状态与 reservation 计算不一致时，先确认异常订单，再决定是否生成补偿。不要直接删除 <code>inventory_reservation</code> 表记录，也不要看到数量不同就全部补偿；未发货订单存在负 reservation 本来就是正常状态。</p>
<p>还要检查 Backorders、Out-of-Stock Threshold 和 Manage Stock。可销售数量并不总等于物理数量减已下单数量，阈值与允许超卖会改变判断。</p>
<h3>索引表能告诉你前台看到了什么</h3>
<p>在确定 stock ID 后，检查库存索引：</p>
<pre><code>SELECT sku, quantity, is_salable
FROM inventory_stock_1
WHERE sku IN ('CHILD-S', 'CHILD-M');</code></pre>
<p>表名中的数字与 Stock ID 对应，不一定总是 1。索引中 <code>is_salable=0</code> 而后台 Source 数量大于 0，说明问题还在 Stock、Reservation 或索引链路；索引正确而页面缺货，则继续检查全页缓存、主题和自定义库存插件。</p>
<pre><code>bin/magento indexer:status inventory
bin/magento indexer:reindex inventory</code></pre>
<p>不同版本的 inventory indexer 名称可能有差异，可先运行 <code>bin/magento indexer:info</code> 查看实际列表。</p>
<h3>父商品状态由可售子项聚合</h3>
<p>颜色、尺码属性配置错误会让前端组合无法解析到正确子 SKU。检查商品页的 configurable JSON，选择每组属性后确认映射到的 simple product 与后台一致。第三方 swatch 或库存扩展如果缓存了旧的 salable 状态，也可能只让某些组合错误。</p>
<p>修复后不要只刷新父商品页面。分别测试每个子选项、不同网站和一个登录客户组，完成下单并取消一次，再确认 reservation、Source Quantity 与 Salable Quantity 的变化符合预期。库存显示恢复且生命周期闭环正确，才算解决。</p>]]></description>
      <pubDate>Thu, 15 Aug 2024 01:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[订单邮件已经生成，Magento 2 为什么迟迟不发送？]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-email-not-sent/</link>
      <description><![CDATA[<p>后台已经出现新订单，客户却一直收不到确认邮件。先不要立刻重发，也不要只测试 SMTP 连接。Magento 的订单邮件会经过&ldquo;是否允许发送、是否异步、Cron 是否处理、传输是否成功、邮件服务是否投递&rdquo;多个阶段，任何一处断开都会得到相同的用户反馈。</p>
<h3>先看订单是否被标记为需要发送</h3>
<p>在只读数据库连接中检查订单的邮件状态：</p>
<pre><code>SELECT entity_id, increment_id, customer_email,
       send_email, email_sent, created_at
FROM sales_order
WHERE increment_id = '000000123';</code></pre>
<p><code>send_email</code> 表示业务流程是否请求发送，<code>email_sent</code> 表示 Magento 是否认为发送已完成。字段值不能证明客户邮箱最终收到邮件，但能帮助确定问题发生在发送前还是传输后。不要直接把 <code>email_sent</code> 改成 0 作为重试方式，重复发送会影响客户体验，也可能触发营销或 ERP 流程。</p>
<h3>异步发送依赖 sales Cron 组</h3>
<p>启用 Asynchronous sending 后，订单、发票、发货和退款邮件不会都在 Web 请求内立即发送。检查 Cron 安装与计划：</p>
<pre><code>bin/magento cron:run --group default
bin/magento cron:run --group sales
SELECT job_code, status, scheduled_at, executed_at, finished_at, messages
FROM cron_schedule
WHERE job_code LIKE '%email%'
ORDER BY schedule_id DESC
LIMIT 30;</code></pre>
<p>不同版本和模块的 job code 可能不同，因此还要按执行时间和 sales 组确认。若计划根本没有生成，检查系统 crontab；计划存在但长期 pending，检查 cron 进程锁和消费者资源；状态 error 则读取 messages 与 Magento 日志。</p>
<h3>邮件传输成功不等于投递成功</h3>
<p>Magento 把消息交给 sendmail、Postfix 或 SMTP 服务后，应用层可能已经标记成功。继续查看邮件服务器日志或 SMTP 服务的 message ID、退信和抑制列表。发件域 SPF、DKIM、DMARC 错误，收件地址被 suppression，或服务商限流，都会导致 Magento 日志看似正常而客户收不到。</p>
<p>第三方 SMTP 模块可能记录完整邮件内容和凭据。生产日志应隐藏认证信息和客户隐私，只保留必要的请求 ID、收件域、响应码与 message ID。</p>
<h3>只有某类邮件失败时查模板与事件</h3>
<p>订单邮件正常、发票邮件失败，通常不是 SMTP 全局故障。检查对应 Sales Emails 配置、商店作用域、模板是否存在，以及自定义模板变量是否抛出异常。多商店站点要确认订单所属 Store View 的发件人和模板，而不是只看 Default Config。</p>
<p>支付扩展也可能故意延迟订单邮件，直到支付回调把订单更新为允许状态。对照支付 webhook 时间与 <code>send_email</code> 变化，避免在未付款状态提前发送错误的确认内容。</p>
<p>恢复后用受控测试邮箱完成一笔新订单，记录订单创建、Cron 执行、SMTP 接受和最终收件四个时间点。再测试发票与发货邮件，确认不是仅靠后台&ldquo;重发邮件&rdquo;绕过了异步链路。</p>]]></description>
      <pubDate>Wed, 14 Aug 2024 08:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 导入商品报 Duplicate entry，数据还能继续导吗？]]></title>
      <link>https://www.360magento.com/blog/magento-2-import-duplicate-entry/</link>
      <description><![CDATA[<p>Magento 2 导入商品时出现 <code>SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry</code>，说明数据库准备写入的组合违反了唯一索引。它不一定只是 CSV 中有两个相同 SKU。错误里通常会给出重复值和索引名，索引名比最后那串数字更重要。</p>
<h3>先把错误拆成&ldquo;表、索引、键值&rdquo;</h3>
<p>完整异常中找到目标表，例如 <code>catalog_product_entity</code>、<code>catalog_product_website</code>、EAV value 表或 URL rewrite 表。再查看表结构中的唯一索引：</p>
<pre><code>SHOW CREATE TABLE catalog_product_website\G
SHOW INDEX FROM catalog_product_website;</code></pre>
<p>如果唯一索引由 <code>product_id + website_id</code> 组成，重复代表同一商品与网站关联被写入两次；如果是 SKU 唯一索引，则要查数据库是否已有大小写或空格差异的 SKU。不要只根据错误值猜测列顺序。</p>
<h3>CSV 内部重复和数据库历史重复要分开</h3>
<p>先在导入文件中按 SKU 排序，检查前后空格、不可见字符、全角符号和大小写。多行更新同一个商品是允许还是冲突，取决于导入行为和列结构；可配置商品关联、媒体行和多商店行也会故意重复 SKU，因此不能简单删除所有重复行。</p>
<p>数据库侧用精确 SKU 查询实体，并核对目标网站、分类、属性选项关联。升级失败或第三方导入中断可能留下孤立关系，下一次导入才触发唯一索引。发现脏数据时先备份并确认业务含义，不要使用 <code>INSERT IGNORE</code> 或删除唯一索引绕过约束。</p>
<h3>URL Key 重复不总是同一种错误</h3>
<p>商品 URL Key 冲突常表现为 URL rewrite 保存异常，而不是 SKU 唯一键。多商店下同一个 URL Key 是否冲突取决于 store、request_path 和 redirect 记录。可查询冲突路径：</p>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, store_id, redirect_type
FROM url_rewrite
WHERE request_path = 'sample-product.html';</code></pre>
<p>删除 rewrite 前要确认它不是有效的历史重定向。更稳妥的方式是修正商品 URL Key，再让 Magento 的 URL Rewrite 服务重新生成。</p>
<h3>属性选项也会制造&ldquo;看不见的重复&rdquo;</h3>
<p>导入脚本如果每次都创建颜色或品牌选项，却没有按属性与 store label 查询已有 option，就会插入重复业务值。数据库 ID 不同不代表前台含义不同。自定义导入器应使用属性选项管理接口，明确默认标签和商店标签，不能在循环里直接写 EAV 表。</p>
<h3>能否继续导入取决于导入行为</h3>
<p>Append/Add、Replace 和 Delete 对已有商品的处理不同。正式执行前先使用 Check Data，确认错误数量和允许跳过策略。大批量导入建议按稳定边界拆分，例如按商品类型或 SKU 范围，而不是随机切割可配置父子商品。</p>
<p>处理后用一小份包含简单商品、可配置父子、分类、网站和图片的样本重新导入。核对导入历史、商品数量、网站归属、URL 和索引状态，再继续全量数据。目标不是让 SQL 不再报错，而是保证重复关系没有被静默忽略。</p>]]></description>
      <pubDate>Tue, 13 Aug 2024 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么 Magento 2 点击 Place Order 后一直转圈？]]></title>
      <link>https://www.360magento.com/blog/magento-2-place-order-spinner/</link>
      <description><![CDATA[<p>结账信息都已填写，点击 Place Order 后按钮变灰、加载图标一直不消失，这是 Magento 2 结账中很常见、也很容易误判的问题。页面转圈只是前端状态，真正原因可能是请求根本没发出、REST 接口返回异常、支付 SDK 没有回调，或者订单已经创建但前端没有收到成功跳转。</p>
<h3>先看有没有网络请求</h3>
<p>打开 Network，点击一次 Place Order，重点观察 <code>payment-information</code>、<code>set-payment-information</code> 或支付模块自定义接口。如果完全没有请求，查看 Console 中最早出现的 JavaScript 错误。RequireJS 依赖加载失败、mixin 返回值错误、Knockout 校验异常，都可能让 action 的 Promise 在发送请求前中断。</p>
<p>如果请求返回 400，展开响应 JSON。地址字段缺失、支付 method code 不一致、extension_attributes 结构错误都可能触发输入校验。如果返回 500，立刻按请求时间查看 <code>var/log/exception.log</code>、<code>var/log/system.log</code> 和 PHP-FPM 日志，不要只看浏览器里笼统的服务器错误。</p>
<h3>确认订单到底有没有创建</h3>
<p>用户多次点击或刷新页面前，先在后台按客户邮箱、购物车和时间查找新订单。也可以只读查询最近订单：</p>
<pre><code>SELECT entity_id, increment_id, quote_id, state, status, created_at
FROM sales_order
WHERE quote_id = 12345
ORDER BY entity_id DESC;</code></pre>
<p>如果订单已存在但页面仍在结账，问题位于成功响应、重定向或支付回调。此时让按钮重新可点可能造成重复订单。修复前要确保支付请求有幂等键，订单创建也能识别已提交的 quote。</p>
<h3>第三方支付常卡在 Promise 和回调</h3>
<p>很多支付模块在下单前执行 tokenization、3DS、设备指纹或风控。SDK 弹窗被 CSP 拦截、回调域名不允许、用户关闭验证窗口后没有 reject Promise，都会让 full-screen-loader 永久显示。查看 Console 的 CSP、跨域和未捕获 Promise 错误，并在支付模块日志中对照同一 transaction reference。</p>
<p>不要把 <code>full-screen-loader.stopLoader()</code> 加到任意位置当作修复。加载动画消失不代表下单链路恢复，反而可能让客户重复提交。正确做法是每条成功、失败、取消分支都明确 resolve 或 reject，并向用户返回可理解的错误。</p>
<h3>排除 totals 与库存锁等待</h3>
<p>接口长时间 pending 而不是立即报错时，检查数据库 processlist、库存 reservation、优惠规则和运费重新计算。复杂购物车在 place order 时会再次 collect totals；自定义 total collector 如果查询远程接口或重复保存 quote，会明显放大耗时。</p>
<pre><code>SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G</code></pre>
<p>若只有高并发时卡住，重点查看行锁、外部支付超时和 PHP-FPM 工作进程是否耗尽。</p>
<p>验证修复不能只下一个普通订单。至少覆盖访客、登录客户、优惠券、不同配送方式、支付成功、支付拒绝和用户取消 3DS。每种路径都应恢复按钮状态，只创建一笔订单，并让 quote、支付交易和订单状态保持一致。</p>]]></description>
      <pubDate>Mon, 12 Aug 2024 07:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 清缓存后页面还是旧的？别漏掉 Varnish、CDN 和浏览器缓存]]></title>
      <link>https://www.360magento.com/blog/magento-2-cache-still-old/</link>
      <description><![CDATA[<p>商品价格、CMS 内容或模板已经修改，执行 <code>bin/magento cache:clean</code> 后前台仍显示旧版本，这不一定说明 Magento 缓存命令失效。一个生产站点往往同时存在应用缓存、Block HTML、Full Page Cache、Varnish、CDN、浏览器缓存和静态资源缓存。只清理其中一层，其他层仍可能返回旧响应。</p>
<h3>先判断旧的是 HTML 还是静态文件</h3>
<p>打开浏览器开发者工具，禁用浏览器缓存后重新请求页面。如果 HTML 源代码里已经是新内容，但页面样式或脚本仍旧，问题在静态资源；如果 HTML 本身就是旧的，才继续检查 FPC、Varnish 和 CDN。不要把&ldquo;页面看起来没变&rdquo;直接等同于 Full Page Cache。</p>
<p>对 HTML 请求查看响应头中的 Age、X-Cache、X-Magento-Cache-Debug 或 CDN 自定义头。不同基础设施头名不同，但核心判断是：响应由哪一层命中，Age 是否持续增加，以及绕过代理直连源站时内容是否更新。</p>
<pre><code>curl -I '页面地址'
curl -H 'Cache-Control: no-cache' -I '页面地址'</code></pre>
<p>第二条命令不保证所有代理都绕过缓存，只能作为对照。生产环境不要通过随意拼接查询参数长期解决，这会制造大量独立缓存键。</p>
<h3>cache:clean 和 cache:flush 不是同一个动作</h3>
<p><code>cache:clean</code> 按 Magento 的缓存类型和标签删除属于当前应用的数据；<code>cache:flush</code> 会清空整个缓存存储。如果 Redis 实例还被其他应用共用，flush 可能误删其他数据。先查看状态并针对类型清理：</p>
<pre><code>bin/magento cache:status
bin/magento cache:clean config layout block_html full_page</code></pre>
<p>修改产品或分类后，Magento 通常通过缓存标签使相关页面失效。自定义 Block 如果实现了错误的 <code>getCacheKeyInfo()</code>，或没有返回商品、分类的 identity 标签，就可能一直命中旧 HTML。此时反复 flush 只能暂时掩盖代码缺陷。</p>
<h3>Varnish 与 CDN 的清除链路要单独验证</h3>
<p>使用 Varnish 时，Magento 需要能向缓存节点发送 PURGE/BAN。检查 Full Page Cache 配置中的访问列表和后端地址，确认 Web 节点发出的清理请求能到达 Varnish。多台 Varnish 或 CDN 前置时，还要确认每个节点都收到失效消息。</p>
<p>如果源站和 Varnish 都已更新，公网仍旧，重点检查 CDN 缓存规则。CDN 可能忽略 Magento 的标签头、缓存带 Cookie 的页面，或把错误响应缓存过久。清理一个精确 URL 做对照，比一上来全站 purge 更容易判断规则是否生效，也能降低瞬间回源压力。</p>
<h3>静态文件旧，多半与部署版本有关</h3>
<p>CSS、JavaScript 和主题图片由 <code>pub/static</code> 与静态内容签名控制。修改源码后应按当前模式重新部署，不要直接编辑已发布文件：</p>
<pre><code>bin/magento deploy:mode:show
bin/magento setup:static-content:deploy -f zh_Hans_CN en_US
bin/magento cache:clean</code></pre>
<p>语言参数要与实际商店一致。多节点部署还必须保证生成文件和 <code>deployed_version.txt</code> 同步，否则请求可能在不同节点间交替得到新旧资源。浏览器 Service Worker、CDN 长缓存和 HTML 中的旧静态版本号也需要一起核对。</p>
<p>最后分别验证源站、Varnish/CDN 和普通浏览器三条访问路径。记录响应头、页面内容与静态文件 URL，确认修改后缓存能自动失效，而不是每次都依赖人工清空全部缓存。</p>]]></description>
      <pubDate>Fri, 09 Aug 2024 01:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 分类分页 Meta Title 重复如何优化？]]></title>
      <link>https://www.360magento.com/blog/magento-2-pagination-meta-title/</link>
      <description><![CDATA[<p>搜索引擎报告分类第 2 页、第 3 页与第一页 Meta Title 重复，不要只在标题末尾机械加页码。先决定这些分页是否需要被索引：有独立商品发现价值的真实分页可保留；由排序、显示数量和筛选组合产生的大量参数页则应控制抓取和索引。</p>
<h3>区分真实分页与参数组合</h3>
<p><code>p=2</code> 通常代表商品集合的第二页；<code>product_list_order</code>、<code>product_list_dir</code> 和 <code>product_list_limit</code> 只是相同集合的展示方式。标题可以对真实分页增加&ldquo;第 2 页&rdquo;，但排序参数不应生成新的标题版本，否则会扩大重复页面数量。</p>
<p>可通过 layout 或 observer 在分类结果确定后读取当前页码。下面示例仅演示标题处理，实际类名和事件应按项目版本注册：</p>
<pre><code>$page = (int)$this-&gt;request-&gt;getParam('p', 1);
if ($page &gt; 1) {
    $title = $pageConfig-&gt;getTitle()-&gt;get();
    $pageConfig-&gt;getTitle()-&gt;set(
        $title . __(' - Page %1', $page)
    );
}</code></pre>
<p>代码应放在自有模块，例如 Alwayly 的 SEO 模块中，不要直接修改主题或 Magento 核心文件。注意中文商店与英文商店的页码文案不同，必须使用翻译机制。</p>
<h3>Canonical 策略要与索引目标一致</h3>
<p>如果分页页希望被索引，canonical 通常应指向分页自身，避免所有页都指向第一页后让深层商品难以发现；如果业务选择 noindex 某类参数页，也要确保站内链接仍可抓取，不要同时用 robots.txt 阻止后又期待搜索引擎读取 noindex。不同站点商品规模和内链结构不同，没有一个可机械套用的规则。</p>
<p>Magento 的分类 canonical 配置主要处理分类与商品规范 URL，并不自动解决所有带参数页面。第三方筛选模块生成的友好 URL 还需要单独定义哪些组合可索引、哪些组合 canonical 或 noindex。</p>
<h3>缓存键必须包含页码与商店</h3>
<p>如果第 2 页偶尔显示第一页标题，检查全页缓存和自定义 Block 的 cache key。页码、商店视图和货币等必要维度没有进入缓存键时，一个页面的 head 配置可能污染另一个页面。CDN 也要保留真正影响内容的查询参数。</p>
<p>上线前抓取第一页、第二页、排序页和一个筛选页，比较 Title、canonical、robots、HTTP 状态和商品列表。再检查站点地图只包含计划索引的规范分类 URL。目标不是让所有 URL 的标题都唯一，而是让可索引页面有明确价值，让无价值的参数组合不制造抓取负担。</p>]]></description>
      <pubDate>Thu, 08 Aug 2024 08:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 分类页不显示属性筛选怎么解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-layered-navigation-filter-missing/</link>
      <description><![CDATA[<p>分类页有商品，但左侧没有颜色、品牌等属性筛选，先看是所有筛选都消失，还是只有某一个属性缺失。前者通常与分类设置、布局或主题有关；后者更常见于属性配置、商品赋值和索引。</p>
<h3>分类必须允许分层导航</h3>
<p>在分类 Display Settings 中确认 Anchor 已启用。非 Anchor 分类默认不会按普通分层导航方式聚合属性。还要确认该分类使用的页面布局没有移除 <code>catalog.leftnav</code>，自定义主题或 Page Builder 布局也可能把侧栏容器隐藏。</p>
<h3>属性要同时满足前台筛选条件</h3>
<p>用于筛选的属性一般应为 Dropdown、Multiple Select、Price 或兼容的输入类型，并将&ldquo;Use in Layered Navigation&rdquo;设为 Filterable。Filterable (with results) 只显示当前商品集合中确实有结果的选项；Filterable (no results) 的表现不同。属性还要分配到相关 Attribute Set，分类内商品必须实际保存了选项值。</p>
<p>多商店环境下，属性标签和商品值可能按商店视图覆盖。检查当前 Store View，而不是只看 All Store Views。若只有一个选项或所有商品值相同，主题或搜索实现也可能选择不显示没有区分度的筛选。</p>
<h3>数据正确后再处理索引</h3>
<pre><code>bin/magento indexer:status
bin/magento indexer:reindex catalog_product_attribute
bin/magento indexer:reindex catalogsearch_fulltext
bin/magento cache:clean block_html full_page</code></pre>
<p>如果依赖 OpenSearch/Elasticsearch 的聚合，搜索索引异常会让商品能从缓存中显示，但筛选聚合缺失。检查搜索服务日志和 Magento 异常，不要把&ldquo;重建成功&rdquo;当作唯一判断，还要确认前台请求使用的是新索引。</p>
<h3>用原生主题区分数据与展示问题</h3>
<p>HTML 中已有筛选数据但页面看不到，检查 CSS、折叠组件和 JavaScript；响应中根本没有对应 filter，则回到集合和索引。第三方搜索模块通常替换原生 LayerResolver 或 FilterList，需要按它自己的索引和配置检查。</p>
<p>修复后选择一个分类，准备至少两个拥有不同属性值的可售商品，分别测试访客、不同商店视图和带筛选参数的分页。筛选数量、结果商品数和 URL 参数都正确，才说明分层导航真正恢复。</p>]]></description>
      <pubDate>Wed, 07 Aug 2024 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API 返回 401 Unauthorized：认证与权限检查]]></title>
      <link>https://www.360magento.com/blog/magento-2-rest-api-401/</link>
      <description><![CDATA[<p>调用 Magento 2 REST API 返回 401 Unauthorized，首先区分&ldquo;没有通过身份认证&rdquo;和&ldquo;已经认证但没有资源权限&rdquo;。401 多数表示 Token 缺失或无效；权限不足也可能因接口配置和认证类型不同返回 401 或 403，因此要保留响应正文与请求路径。</p>
<h3>先发送一个最小、可重复的请求</h3>
<pre><code>BASE_URL='站点地址'
TOKEN='有效的访问令牌'
curl -i -H \"Authorization: Bearer $TOKEN\" \
  -H 'Content-Type: application/json' \
  \"$BASE_URL/rest/V1/store/storeViews\"</code></pre>
<p>确认 Authorization 中 Bearer 与 Token 之间有空格，Token 没有被引号、换行或日志模板截断。不要把真实 Token 写入代码仓库、工单或公开日志。若同一命令在服务器上成功、通过 CDN 失败，检查代理是否转发 Authorization 请求头。</p>
<h3>不同 Token 的权限来源不同</h3>
<p>管理员 Token 继承管理员角色权限；客户 Token 只能访问标记为 self 或允许客户的资源；Integration Token 则受该集成选择的 API Resources 控制。接口能用管理员 Token 访问，不代表客户 Token 也应该访问。确认令牌没有因管理员密码修改、集成停用或安全策略而失效。</p>
<p>自定义接口必须在 <code>etc/webapi.xml</code> 声明资源：</p>
<pre><code>&lt;route url=\"/V1/alwayly/items/:id\" method=\"GET\"&gt;
    &lt;service class=\"Alwayly\\Api\\Api\\ItemRepositoryInterface\" method=\"getById\"/&gt;
    &lt;resources&gt;
        &lt;resource ref=\"Alwayly_Api::items_read\"/&gt;
    &lt;/resources&gt;
&lt;/route&gt;</code></pre>
<p>对应 ACL 资源必须在 <code>etc/acl.xml</code> 存在，并分配给调用方角色。使用 <code>anonymous</code> 或 <code>self</code> 应基于真实业务边界，不能为了消除 401 就把管理接口公开。</p>
<h3>同时确认路由和商店代码</h3>
<p>REST 路径可包含商店代码。错误的 store code 通常返回其他错误，但自定义路由、URL Rewrite 或 WAF 也可能提前拦截。比较 Web 服务器 access log 中的路径、状态和上游响应，确认请求真正到达 Magento。</p>
<p>修复后至少验证四种结果：有效令牌访问允许资源成功；无令牌返回拒绝；权限不足的令牌不能越权；令牌被停用后立即失效。只有成功请求和拒绝请求都符合预期，认证配置才是安全的。</p>]]></description>
      <pubDate>Tue, 06 Aug 2024 06:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台登录提示 Too many redirects 怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-too-many-redirects/</link>
      <description><![CDATA[<p>访问 Magento 2 后台不断在两个地址之间跳转，浏览器最后显示 Too many redirects，先记录每一次 Location 的目标。只有知道循环发生在 HTTP/HTTPS、带不带 www，还是后台登录与仪表板之间，才能判断是哪一层在改写。</p>
<pre><code>BASE_URL='站点地址'
curl -I \"$BASE_URL/admin\"
curl -IL --max-redirs 10 \"$BASE_URL/admin\"</code></pre>
<p>如果 HTTP 跳 HTTPS 后又被 Magento 跳回 HTTP，通常是 Secure Base URL 或代理协议识别问题；如果登录页和 dashboard 互相跳，重点检查 session Cookie 是否保存成功。</p>
<h3>核对 Magento 中真实生效的 URL</h3>
<pre><code>bin/magento config:show web/unsecure/base_url
bin/magento config:show web/secure/base_url
bin/magento config:show web/secure/use_in_frontend
bin/magento config:show web/secure/use_in_adminhtml</code></pre>
<p>Base URL 应包含正确协议、域名和结尾斜杠。配置可能按 scope 覆盖，因此默认值正确并不代表当前网站没有错误值。紧急修复配置前先备份，并确保命令针对正确环境；不要直接批量替换 core_config_data 中所有 URL。</p>
<h3>反向代理后最常见的是 HTTPS 判断错误</h3>
<p>Nginx、负载均衡器或 CDN 在前端接收 HTTPS，回源时可能使用 HTTP。若没有传递并信任原始协议，Magento 会认为当前请求不安全并再次重定向。检查 <code>X-Forwarded-Proto</code>、后端 fastcgi 参数及可信代理设置，同时避免 CDN 页面规则和 Web 服务器规则重复强制不同主域名。</p>
<h3>Cookie 不能跨错误的域和路径</h3>
<p>查看浏览器中 admin session Cookie 的 Domain、Path、Secure 和 SameSite。Cookie Domain 写成旧域名、Path 只覆盖前台，或 Secure Cookie 通过 HTTP 访问，都会使登录提交后下一次请求失去会话。清除旧 Cookie 只能用于验证，最终仍要修正服务器配置。</p>
<p>还有一种情况是后台入口路径被 Web 服务器规则当作前台 URL 重写。确认请求确实进入 Magento 的 <code>index.php</code>，并排除把后台路径重定向到尾斜杠或语言目录的规则。</p>
<p>修复后用无痕窗口完整登录一次，确认登录页只跳到 dashboard 一次；再检查前台 HTTP、HTTPS、www 与非 www 的规范跳转。不要只验证管理员自己的浏览器，因为旧 Cookie 可能掩盖配置问题。</p>]]></description>
      <pubDate>Mon, 05 Aug 2024 02:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户登录后购物车变空是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cart-empty-after-login/</link>
      <description><![CDATA[<p>访客已经把商品加入购物车，登录后数量却变成 0，先确认是 Quote 真的没有合并，还是页面上的 mini cart 没有刷新。直接进入购物车页面并重新加载；如果商品仍在，只是右上角显示 0，问题更可能在 customer-data 缓存和前端组件。</p>
<h3>理解登录时的 Quote 合并</h3>
<p>Magento 会为访客维护 active quote，客户登录后再与该客户原有的 active quote 合并。检查同一客户和商店下的记录：</p>
<pre><code>SELECT entity_id, customer_id, store_id, is_active,
       items_count, items_qty, updated_at
FROM quote
WHERE customer_id = 123
ORDER BY updated_at DESC;</code></pre>
<p>访客 quote 在登录前没有 customer_id，需要通过服务器日志或调试确认 session 中的 quote_id。不要在生产环境随意把旧 quote 改成 active，这可能把历史购物车或已下单数据重新带回。</p>
<p>自定义登录、社交登录和单页结账模块经常绕过标准 customer session 或提前替换 checkout session，导致 merge 没有执行。检查它们是否调用标准登录流程，以及对 <code>checkout_session</code>、QuoteRepository 的 plugin 是否改变了 active quote。</p>
<h3>Cookie 与网站作用域必须一致</h3>
<p>如果加入购物车使用一个域名，登录跳转到另一个子域、HTTP/HTTPS 或不同网站，浏览器可能没有发送原来的 session Cookie。核对 Base URL、Cookie Domain、Cookie Path、Secure 和 SameSite 配置。反向代理终止 HTTPS 时，Magento 还要正确识别原始协议，否则会生成不同安全属性的 Cookie。</p>
<p>多网站环境中，quote 绑定 store。客户跨网站登录后是否应该共享购物车，取决于客户账户共享范围和业务设计，不能简单把所有 store 的 quote 合并。</p>
<h3>页面显示为 0 时检查 private content</h3>
<p>mini cart 使用 <code>customer-data</code> sections。主题或扩展在登录成功后没有失效 cart section，就会显示旧数据。浏览器控制台查看 RequireJS 错误，并检查 localStorage 中相关 section 是否更新。不要把整个 localStorage 每次都清空作为线上解决方案，应修复 section invalidation。</p>
<p>验证时准备三种场景：客户没有旧购物车、客户已有旧购物车、访客与客户购物车包含相同 SKU。分别确认数量合并、可配置选项和优惠券结果，并检查数据库中的 active quote 数量。这样才能发现是会话丢失、合并规则还是仅前端显示的问题。</p>]]></description>
      <pubDate>Fri, 02 Aug 2024 07:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据库 Deadlock found 的常见原因与解决方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-database-deadlock/</link>
      <description><![CDATA[<p>日志出现 <code>SQLSTATE[40001]: Deadlock found when trying to get lock</code>，说明 InnoDB 检测到两个或更多事务互相等待，并主动回滚其中一个。它与普通的 lock wait timeout 不同：死锁不能靠把超时时间调大解决。</p>
<h3>先保存最近一次死锁证据</h3>
<p>问题发生后尽快执行：</p>
<pre><code>SHOW ENGINE INNODB STATUS\G
SHOW FULL PROCESSLIST;</code></pre>
<p>在 LATEST DETECTED DEADLOCK 中关注两个事务分别执行的 SQL、等待的索引、持有的锁以及被回滚的事务。生产环境还可以短期开启 <code>innodb_print_all_deadlocks</code> 将信息写入数据库错误日志，但要注意日志量，定位完成后恢复原设置。</p>
<p>MySQL 8 可进一步查看：</p>
<pre><code>SELECT * FROM performance_schema.data_lock_waits;
SELECT * FROM performance_schema.data_locks;</code></pre>
<p>只看到表名还不够，要结合索引名和 WHERE 条件判断锁的是单条记录、范围还是间隙。</p>
<h3>Magento 中容易出现死锁的几类场景</h3>
<p>高并发下单会同时更新 quote、sales sequence、库存 reservation 和索引变更表；批量商品保存会更新 EAV、URL rewrite 与分类关联；Cron 与手工 reindex 同时执行也可能以不同顺序访问表。第三方 observer 如果在一个大事务中再次保存商品、订单或客户，锁的范围会继续扩大。</p>
<p>检查相关 SQL 是否使用有效索引：</p>
<pre><code>EXPLAIN SELECT ... FROM table_name WHERE ...;</code></pre>
<p>缺少索引会扫描并锁住更多记录，但&ldquo;加索引&rdquo;不是固定答案。必须根据真实查询和写入成本评估，尤其不要在生产高峰直接对大表执行阻塞式 DDL。</p>
<h3>解决重点是统一锁顺序并缩短事务</h3>
<p>如果两个业务都要更新 A、B 两类记录，应确保它们都按同一顺序访问。批处理按主键排序、减少单事务包含的商品或订单数量，也能降低交叉等待。不要在数据库事务内调用外部 API、发送邮件或做长时间计算。</p>
<p>对可安全重试的操作，可以捕获 deadlock 并进行有限次数、带随机退避的重试；但创建订单、扣款、退款等操作必须具备幂等性，不能因为重试生成两笔业务记录。框架的重试能力也不能替代根因修复。</p>
<p>处理后用接近真实的并发重放相同路径，观察死锁日志、事务时长和错误率。只让一笔测试订单成功没有意义；目标是在正常峰值并发下不再出现循环等待，同时保持库存、订单和索引数据一致。</p>]]></description>
      <pubDate>Thu, 01 Aug 2024 01:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 OpenSearch 索引失败：catalogsearch_fulltext 报错排查]]></title>
      <link>https://www.360magento.com/blog/magento-2-opensearch-index-error/</link>
      <description><![CDATA[<p>执行 <code>catalogsearch_fulltext</code> 重建时报错，先保留完整异常，不要只截取最后一句。连接超时、索引只读、字段映射冲突和 bulk 请求过大都会表现为&ldquo;搜索索引失败&rdquo;，处理方式完全不同。</p>
<h3>确认 Magento 实际连接的是哪一个搜索节点</h3>
<p>先查看部署配置和后台搜索引擎设置，确认主机、端口、索引前缀、认证与 HTTPS 是否一致。可从服务器测试健康接口：</p>
<pre><code>SEARCH_ENDPOINT='搜索服务地址'
curl -sS \"$SEARCH_ENDPOINT/_cluster/health?pretty\"
curl -sS \"$SEARCH_ENDPOINT/_cat/indices?v\"</code></pre>
<p>连接被拒绝应检查服务监听、DNS、防火墙和 TLS；401/403 则检查凭据和访问策略。不要为了让索引通过而关闭搜索服务认证。</p>
<h3>黄色不一定失败，红色和只读必须处理</h3>
<p>单节点集群因副本无法分配而显示 yellow，通常仍可读写；red 表示主分片未分配，需要先恢复集群。磁盘达到 flood-stage watermark 时，OpenSearch 会把索引设为只读，Magento 的 bulk 写入随即失败。释放磁盘后还要确认只读标记已经解除，再重新索引。</p>
<pre><code>curl -sS \"$SEARCH_ENDPOINT/_cluster/settings?include_defaults=true&amp;pretty\"
curl -sS \"$SEARCH_ENDPOINT/_cat/allocation?v\"</code></pre>
<p>不要直接删除所有索引来腾空间。先识别过期索引、快照和日志占用，确认索引前缀，避免误删其他应用的数据。</p>
<h3>映射冲突通常来自属性数据</h3>
<p>异常中出现 mapper_parsing_exception、illegal_argument_exception 或某字段类型冲突时，找出对应商品属性。一个属性原来按数字索引，后来写入文本，或第三方模块向同名字段输出不同类型，都可能造成 bulk 中部分文档失败。核对属性 backend type、input type 与历史数据，再修复异常记录。</p>
<p>若错误是请求体过大或超时，可以调整 Magento 搜索索引批次，但批次越小只会降低单次峰值，不会修复坏数据。先单独运行并记录详细输出：</p>
<pre><code>bin/magento indexer:reset catalogsearch_fulltext
bin/magento indexer:reindex catalogsearch_fulltext -vvv</code></pre>
<p><code>reset</code> 只重置状态，不会解决服务端根因。修复后检查 indexer 状态、集群文档数量，并在前台分别搜索名称、SKU 和一个可搜索属性。还要再修改一个商品，确认增量索引可以自动更新，避免只验证了一次全量重建。</p>]]></description>
      <pubDate>Wed, 31 Jul 2024 08:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单已经付款为什么不能创建发货？]]></title>
      <link>https://www.360magento.com/blog/magento-2-paid-order-cannot-ship/</link>
      <description><![CDATA[<p>订单显示已付款，但后台没有&ldquo;发货&rdquo;按钮，不能简单等同于支付异常。Magento 是否允许创建 Shipment，取决于订单中是否仍有可发货的实体商品、订单 state 是否允许，以及模块对 <code>canShip()</code> 的判断。付款只是其中一个条件。</p>
<h3>先看每个订单行的数量</h3>
<p>虚拟商品和下载商品本来就不需要发货。实体商品则要比较 ordered、shipped、refunded 和 canceled 数量。可以在只读数据库连接中检查：</p>
<pre><code>SELECT item_id, sku, product_type,
       qty_ordered, qty_shipped, qty_refunded, qty_canceled,
       is_virtual, parent_item_id
FROM sales_order_item
WHERE order_id = 100001;</code></pre>
<p>可配置商品会同时保存父行和简单商品子行，不能把两行都当成独立可发数量。若所有实体行都已发完、取消或退款，系统不再提供发货入口是正常的。</p>
<h3>状态标签和内部 state 不是一回事</h3>
<p>自定义状态可能显示&ldquo;已付款&rdquo;，但绑定的内部 state 已经是 complete、closed 或 canceled。查询订单的 <code>state</code>、<code>status</code>，并在后台检查状态分配。不要为了显示按钮直接修改 <code>sales_order</code> 表；订单状态、库存和支付记录必须保持一致。</p>
<pre><code>SELECT entity_id, increment_id, state, status,
       total_qty_ordered
FROM sales_order
WHERE increment_id = '000000123';</code></pre>
<p>支付方式采用 Authorize Only 时，订单可以已授权但尚未捕获；采用 Capture 时可能已自动生成发票。能否发货不要求所有场景都先有发票，但支付扩展经常通过插件增加业务限制，因此要同时查看 payment additional information 与支付模块日志。</p>
<h3>启用 MSI 后还要选择正确来源</h3>
<p>Multi-Source Inventory 会在下单时创建 reservation，发货时从 Source 扣减。确认订单销售渠道关联的 Stock 包含可用 Source，来源商品状态启用且有足够数量。可用量异常时可运行官方库存一致性命令做检查，但不要直接手工删除 reservation 记录。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies
bin/magento inventory:reservation:create-compensations</code></pre>
<p>第二条命令会写入补偿预约，执行前应先审阅第一条输出，并在备份和维护窗口内处理。</p>
<p>如果原生订单可以发货，只有特定支付、ERP 或仓储模块的订单不行，就检查它们对 Order 或 Shipment service 的 around/after plugin。修复后用一个实体商品新建订单，完成付款、开票、部分发货和剩余发货，确认可发数量随流程正确减少，而不是仅让按钮重新出现。</p>]]></description>
      <pubDate>Tue, 30 Jul 2024 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品页面价格显示为 0 如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-price-zero/</link>
      <description><![CDATA[<p>后台已经填写价格，前台商品页却显示 0.00，不能只看商品编辑页中的 Price 字段。Magento 最终展示价格还会受到商品类型、网站作用域、客户组、目录价格规则和价格索引影响。第一步是确认问题只发生在一个商品、一个商店视图，还是所有商品都受影响。</p>
<h3>从商品类型开始判断</h3>
<p>简单商品应直接有基础价格；可配置商品的展示价格来自可售子商品的索引结果；Bundle 和 Grouped 商品则由选项或关联商品计算。可配置商品的父商品价格不是唯一依据。如果所有子商品都被禁用、未分配到当前网站或不可售，父商品可能没有有效的最低价。</p>
<p>先检查商品归属网站、状态、子商品关联和价格作用域。多网站使用 Website 级价格时，默认作用域有值并不代表当前网站也有正确值。还要核对特价起止时间，错误的日期和时区可能让最终价格意外落入折扣区间。</p>
<h3>直接检查价格索引，而不是反复保存商品</h3>
<p>找出商品实体 ID 后，可对当前网站和客户组查看索引：</p>
<pre><code>SELECT entity_id, customer_group_id, website_id,
       price, final_price, min_price, max_price
FROM catalog_product_index_price
WHERE entity_id = 123;</code></pre>
<p>如果索引表中已经是 0，问题位于数据、规则或索引过程；如果索引值正确而页面显示 0，重点转向缓存、模板和 JavaScript。检查索引状态并只重建价格索引：</p>
<pre><code>bin/magento indexer:status catalog_product_price
bin/magento indexer:reindex catalog_product_price
bin/magento cache:clean block_html full_page</code></pre>
<p>全量 reindex 能临时恢复但随后再次变成 0，通常说明 Cron 增量索引没有持续运行，或某个保存插件写入了错误作用域的数据。</p>
<h3>规则与主题也会改写最终结果</h3>
<p>目录价格规则可能针对特定网站、客户组或日期生效。先临时复制一个不参加规则的测试商品进行对照，而不是直接删除线上规则。对于主题问题，检查页面生成的 priceConfig 和 price-box。自定义模板若直接读取 <code>getPrice()</code>，可能绕过 FinalPrice 模型；RequireJS 错误也会让可配置商品的价格更新停在初始值。</p>
<p>最终验证应覆盖访客、登录客户、不同客户组和当前网站的商店视图。可配置商品还要逐个选择子项，确认最低价、特价和含税显示一致。数据库索引值、接口返回值和页面价格三者对得上，才算真正解决。</p>]]></description>
      <pubDate>Mon, 29 Jul 2024 07:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台保存分类很慢怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-category-save-slow/</link>
      <description><![CDATA[<p>后台编辑分类时，页面打开很快，但点击&ldquo;保存&rdquo;后要等几十秒甚至超时，问题通常不在浏览器，而在分类保存触发的数据库写入、商品关联更新、索引或第三方事件。先记录一次请求的总耗时和 HTTP 状态，不要一开始就清空所有缓存。</p>
<h3>先判断时间花在 PHP 还是数据库</h3>
<p>在浏览器 Network 中找到分类保存请求，观察 Waiting/TTFB。如果请求很快返回但页面跳转慢，再查代理和静态资源；如果 TTFB 本身很长，同时查看 <code>var/log/system.log</code>、<code>var/log/exception.log</code> 与 PHP-FPM slow log。保存期间可在数据库执行：</p>
<pre><code>SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS\G</code></pre>
<p>如果看到对 <code>catalog_category_entity</code>、<code>catalog_category_product</code> 或索引表的锁等待，应该先找持锁事务。不要直接杀掉所有数据库连接，先确认是否有批量导入、索引或长时间未提交的自定义脚本。</p>
<h3>分类商品越多，保存动作越值得检查</h3>
<p>分类页面提交的商品关联会更新大量 position 数据。若只有商品很多的分类保存慢，检查表单是否提交了异常大的商品集合，以及扩展是否逐个加载完整商品对象。一个常见的低效写法是在分类保存 observer 中循环调用 repository 的 <code>getById()</code>；它会放大 EAV 查询和插件链。更合理的做法是只读取需要的属性，或让资源模型批量处理。</p>
<p>同时检查索引模式：</p>
<pre><code>bin/magento indexer:show-mode
bin/magento indexer:status
bin/magento cron:run --group index</code></pre>
<p>生产站通常使用&ldquo;按计划更新&rdquo;。如果分类商品索引被改为&ldquo;保存时更新&rdquo;，一次后台保存可能同步完成大量索引工作。切换模式前要确认 Cron 正常，否则只是把慢保存变成前台数据长期不更新。</p>
<h3>排除插件时看执行顺序，不要直接删模块</h3>
<p>分类保存会经过 repository、资源模型事件及 URL 重写等链路。开启数据库 profiler 或应用性能监控后，比较原生保存与启用第三方模块时的调用耗时。重点查 <code>catalog_category_save_before</code>、<code>catalog_category_save_after</code>、repository plugin，以及生成 URL Rewrite 的定制逻辑。</p>
<p>修复后分别用空分类、几十个商品的分类和大量商品的分类各保存一次，记录 TTFB、SQL 数量和锁等待。只有三种规模下耗时都稳定，且分类商品、URL 和索引结果正确，才能说明根因已经处理，而不是偶然避开了锁。</p>]]></description>
      <pubDate>Fri, 26 Jul 2024 01:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多语言页面如何设置 hreflang？SEO 配置要点]]></title>
      <link>https://www.360magento.com/blog/magento-2-hreflang-multistore/</link>
      <description><![CDATA[<p>Magento 2 多语言商店常使用不同 Store View，但原生主题并不会自动为所有页面生成完整 hreflang。实现时要先建立&ldquo;同一内容在不同商店视图中的对应关系&rdquo;，不能只替换 URL 中的语言代码。</p>
<p>标签使用标准语言或语言-地区代码，例如 <code>zh-CN</code>、<code>en-US</code>。每个页面应包含自身和其他语言版本，并保持双向引用；英文页指向中文页时，中文页也应指回英文页。</p>
<p>商品未分配到某个网站、分类结构不同或 CMS 页面标识不一致时，不应生成一个会跳首页或返回 404 的替代地址。可以为默认国际版本增加 <code>x-default</code>，但它不是所有网站都必须使用。</p>
<p>hreflang 与 canonical 不能互相打架。每个语言页通常 canonical 到自身，而不是全部指向同一个语言版本。上线后抽查商品、分类、CMS、分页和缺少翻译的页面，确保输出的是可访问的绝对 URL。</p>]]></description>
      <pubDate>Thu, 25 Jul 2024 08:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何批量修改商品属性？后台操作与导入方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-bulk-update-attributes/</link>
      <description><![CDATA[<p>几十个商品需要统一修改品牌、税类或可见性，可以在产品列表筛选并勾选商品，使用 Update Attributes。提交后确认选择的是当前页还是全部筛选结果，避免把未显示的商品一起修改。</p>
<p>上千个 SKU 更适合 CSV 导入。先导出几个同类型商品作为模板，保留 <code>sku</code> 和需要更新的属性列，导入行为选择 Add/Update。不要使用 Replace 处理局部更新。</p>
<p>下拉、多选属性通常需要使用选项标签，并保证目标商店视图存在对应选项。属性按网站或商店视图管理时，还要明确 <code>store_view_code</code>，否则值可能写入错误作用域。</p>
<p>批量操作前用 2 至 3 个 SKU 测试，检查前台值、索引和接口输出。多选属性的分隔方式、空值是否代表清除，都应先在当前版本验证。数据库 UPDATE 虽然快，却会绕过 EAV 处理、事件和索引，不适合作为常规商品管理方法。</p>]]></description>
      <pubDate>Wed, 24 Jul 2024 02:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单无法取消是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-cannot-cancel/</link>
      <description><![CDATA[<p>后台订单没有 Cancel 按钮，通常说明订单对象的 <code>canCancel()</code> 判断为否。已进入 complete、closed、canceled 状态，或全部商品已经开票，订单通常不能再按普通取消流程处理。</p>
<p>支付方式也会参与判断。仅授权的交易在取消订单时可能需要向网关发起 void；如果授权已过期、交易已捕获或支付扩展不支持 void，按钮可能消失或操作失败。</p>
<p>检查订单 state、status、已开票数量、已取消数量和 payment transaction。自定义状态如果错误绑定到 complete，也会让业务上尚未完成的订单失去取消能力。</p>
<p>已经收款的订单通常应走 Credit Memo 退款，而不是强行取消。不要直接修改 sales_order 的 state/status 恢复按钮，这会绕过库存补偿、支付处理和订单历史。应先确定资金与履约实际状态，再选择取消、作废授权或退款。</p>]]></description>
      <pubDate>Tue, 23 Jul 2024 07:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台上传大文件失败，应该检查哪些配置？]]></title>
      <link>https://www.360magento.com/blog/magento-2-large-upload-failed/</link>
      <description><![CDATA[<p>小文件可以上传，大文件进度完成后却返回空白或 413，说明限制通常在 Magento 收到请求之前。Nginx 的 <code>client_max_body_size</code>、Apache 请求限制、CDN 上传上限都可能先拦截。</p>
<p>PHP 层重点比较：</p>
<pre><code>upload_max_filesize
post_max_size
memory_limit
max_execution_time
max_input_time
upload_tmp_dir</code></pre>
<p><code>post_max_size</code> 应大于单文件上限，还要为其他表单字段保留空间。后台页面使用的是 PHP-FPM 配置，不一定与命令行 <code>php -i</code> 相同。</p>
<p>请求进入 Magento 后，再检查模块允许的扩展名、MIME 校验、媒体目录与临时目录权限。导入 CSV 超时与图片上传失败也不是同一种问题：前者可能已上传成功，只是在解析阶段超时。</p>
<p>修改配置后重载对应服务，用略低于和略高于限制的文件分别测试。这样能确认真正生效的上限，而不是只看到某个 php.ini 数字就认为已经修复。</p>]]></description>
      <pubDate>Mon, 22 Jul 2024 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何开启模板路径提示？前端调试方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-template-path-hints/</link>
      <description><![CDATA[<p>修改商品页或结账页时不知道内容来自哪个 PHTML，可以使用 Template Path Hints。它会在页面区块外显示模板路径和 Block 类，适合快速定位主题覆盖关系。</p>
<p>在开发环境的高级开发配置中开启模板路径提示，并按需要显示 Block 名称。多网站环境要确认当前 Store View，配置保存后清理配置与全页缓存。</p>
<p>如果后台开关不可见，先确认应用处于允许开发配置的环境；也可以通过配置命令在指定作用域设置，但不要把调试配置写死到生产部署文件。</p>
<h3>为什么不建议在正式站直接开启</h3>
<p>路径提示会改变页面输出，并暴露模块、主题和服务器目录结构。确需在线排查时，应限制访问 IP、缩短开启时间，并在完成后恢复配置和缓存。</p>
<p>找到模板后还要确认主题继承：优先在自定义主题中覆盖最小文件，不要修改 vendor 内原文件。否则下一次 Composer 更新会覆盖改动。</p>]]></description>
      <pubDate>Fri, 19 Jul 2024 06:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据库连接数过多的常见原因与优化方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-db-too-many-connections/</link>
      <description><![CDATA[<p>网站出现 <code>SQLSTATE: Too many connections</code> 时，临时提高 MySQL 的 <code>max_connections</code> 可能恢复访问，但也可能让数据库在更高并发下耗尽内存。</p>
<pre><code>SHOW STATUS LIKE 'Threads_connected';
SHOW FULL PROCESSLIST;
SHOW VARIABLES LIKE 'max_connections';</code></pre>
<p>先观察连接是大量 Sleep，还是都在执行相同慢查询。PHP-FPM 子进程过多、Cron 重叠、消费者数量失控，会同时放大数据库连接。某个扩展在循环中重复创建资源连接，也会导致连接快速增长。</p>
<p>若连接都被长事务占住，检查未提交事务、锁等待和慢查询。数据库升级参数前，应结合每个连接的内存开销评估服务器容量。</p>
<p>稳定方案通常包含：限制应用进程并发、修复慢 SQL、让长任务拆批、正确配置读写节点，并为数据库保留管理连接。只重启 MySQL 会清掉现场证据，最好先保存 processlist 与监控曲线，再处理故障。</p>]]></description>
      <pubDate>Thu, 18 Jul 2024 03:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账提示 Please specify a shipping method 如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-shipping-method-required/</link>
      <description><![CDATA[<p>结账页面明明选中了运费，却提示 <code>Please specify a shipping method</code>，说明界面状态与服务端 quote 中保存的配送方式不一致。先查看保存配送信息的请求是否成功，以及请求体中的 <code>carrier_code</code>、<code>method_code</code> 是否为空。</p>
<p>地址变化会重新收集运费。国家、邮编或地区更新后，原来选中的方式可能已经不再可用，但自定义一步结账仍保留了旧的单选状态。此时应重新请求费率并让顾客选择有效方式。</p>
<p>虚拟商品不需要配送方式；混合购物车却必须处理实体商品的 shipping assignment。自定义代码如果直接设置展示名称而没有设置 <code>carrier_method</code> 组合，提交订单仍会失败。</p>
<p>切换到原生结账测试同一购物车，可以判断问题来自承运配置还是前端扩展。修复后测试地址修改、免邮门槛变化、多地址以及刷新页面恢复，确保 quote 与界面始终使用同一运费代码。</p>]]></description>
      <pubDate>Wed, 17 Jul 2024 08:09:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么 Magento 2 可销售数量和来源数量不一致？]]></title>
      <link>https://www.360magento.com/blog/magento-2-salable-vs-source-qty/</link>
      <description><![CDATA[<p>MSI 环境中，Source Quantity 表示某个仓库记录的实物数量，Salable Quantity 则是当前网站还能承诺销售的数量，两者本来就不一定相等。</p>
<p>订单提交后会产生负向预留，商品尚未发货时来源数量可能保持不变，可销售数量已经下降。订单取消会写入补偿预留；发货时才正式扣减来源数量。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies</code></pre>
<p>除预留外，还要考虑 Out-of-Stock Threshold。来源合计 100、缺货阈值为 5 时，可销售数量不会简单等于 100。网站绑定的 Stock 只聚合被分配的 Sources，查看错误库存范围也会得到不同数字。</p>
<p>出现负数或长期不一致时，按 SKU 核对来源分配、预留记录和订单状态。不要直接修改库存表或清空 reservation；先确认是否存在订单导入、取消或退款流程绕过库存服务，再针对真实业务记录生成补偿。</p>]]></description>
      <pubDate>Tue, 16 Jul 2024 02:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何设置自定义订单状态？完整配置步骤]]></title>
      <link>https://www.360magento.com/blog/magento-2-custom-order-status/</link>
      <description><![CDATA[<p>Magento 2 可以在后台创建自定义订单状态，但创建完成后还要绑定到正确的订单 State。Status 是显示给管理员和客户的业务名称，State 才决定订单处于 new、processing、complete 等系统阶段。</p>
<p>进入订单状态管理，新增状态代码和标签。状态代码保存后不宜随意修改，因为扩展和接口可能已经按代码判断。随后执行&ldquo;将状态分配给 State&rdquo;，选择对应阶段，并决定是否设为该 State 的默认状态或在前台显示。</p>
<p>例如&ldquo;等待仓库确认&rdquo;通常仍属于 processing，而不是 complete。绑定错误会影响取消、发票、发货和退款按钮是否可用。</p>
<p>支付回调或自定义代码更新状态时，应先确认订单业务动作已经完成，再通过订单服务设置状态并写入历史记录。不要只更新数据库字段，否则状态历史、通知和扩展事件不会同步。配置后分别测试新订单、已付款、已发货和取消流程，确认自定义名称没有改变核心处理能力。</p>]]></description>
      <pubDate>Mon, 15 Jul 2024 07:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台无法删除商品怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-delete-product-error/</link>
      <description><![CDATA[<p>后台勾选商品执行删除后一直转圈，或提示无法删除，先查看浏览器请求和 Magento 异常日志。删除商品会同时清理 EAV 数据、分类关联、媒体关系、URL 重写和索引数据，其中任何插件抛出异常都会让事务回滚。</p>
<p>先确认管理员角色具有删除商品权限，再检查该 SKU 是否被 Bundle、Grouped、可配置商品或第三方组合模块引用。标准 Magento 能处理常规关联，但自定义外键如果没有正确设置级联规则，可能阻止删除。</p>
<h3>不要直接删除 catalog_product_entity</h3>
<p>直接删主表会留下孤立的库存、媒体和重写记录。需要批量删除时，应使用 Repository 或后台标准操作，并控制每批数量，避免一次请求因超时中断。</p>
<p>若单个普通商品能删，特定商品失败，重点比较它的商品类型、关联与扩展属性；所有商品都失败，则查看全局插件、数据库权限和索引器。删除前保留备份，并确认业务是否更适合将商品禁用而不是永久移除。</p>]]></description>
      <pubDate>Fri, 12 Jul 2024 01:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 支付成功但订单状态一直是 Pending]]></title>
      <link>https://www.360magento.com/blog/magento-2-payment-success-order-pending/</link>
      <description><![CDATA[<p>支付平台显示成功，Magento 订单仍是 Pending，最重要的是先避免重复扣款。不要让客户反复支付，也不要仅凭截图手工改为 Complete。</p>
<p>核对网关交易号、订单号和金额，再查看 Magento 是否收到 webhook/IPN。通知 URL 不可访问、HTTPS 证书问题、防火墙拦截、签名密钥错误，都会让支付平台成功而商城没有更新。</p>
<p>浏览器返回成功页不能替代服务端通知。顾客可能关闭页面，返回请求也可能被网络中断；订单状态更新应以经过签名验证的服务器通知或主动查询为依据。</p>
<p>如果交易记录已写入但状态没变，检查支付模块把 authorized、captured 等网关状态映射到哪个 Magento state/status。修复后用同一交易号做幂等处理：重复 webhook 可以安全返回成功，但不能重复开票、发邮件或扣库存。</p>]]></description>
      <pubDate>Thu, 11 Jul 2024 08:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 前台 CSS 和 JS 文件出现 404]]></title>
      <link>https://www.360magento.com/blog/magento-2-static-files-404/</link>
      <description><![CDATA[<p>页面没有样式，网络面板里大量 <code>static/version...</code> 返回 404，先记录一个完整失败 URL。URL 中包含区域语言、主题和文件路径，它已经告诉你 Magento 正在寻找哪套静态资源。</p>
<p>生产模式需要为实际使用的主题与 locale 部署静态内容。只部署 en_US，而商店使用 zh_CN，就会缺少对应目录。部署前后还要保证 <code>pub/static</code> 的发布策略与权限一致。</p>
<pre><code>bin/magento deploy:mode:show
bin/magento setup:static-content:deploy zh_CN en_US</code></pre>
<p>静态签名开启时，Web 服务器必须正确处理 version 路径。Nginx/Apache 配置若没有使用 Magento 提供的规则，真实文件存在也可能返回 404。</p>
<p>开发模式下不要盲目部署所有语言，先检查主题继承和源文件是否存在。单个文件失败偏向路径或模块资源；所有文件失败则优先查 Base Static URL、Web 根目录与重写规则。</p>]]></description>
      <pubDate>Wed, 10 Jul 2024 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cron 大量任务停在 pending 状态]]></title>
      <link>https://www.360magento.com/blog/magento-2-cron-pending-backlog/</link>
      <description><![CDATA[<p><code>cron_schedule</code> 中 pending 越积越多，说明计划能够生成，但没有被及时执行，或者执行速度赶不上生成速度。直接清表只会删掉证据，过一段时间还会再次堆积。</p>
<pre><code>SELECT job_code,status,COUNT(*) qty
FROM cron_schedule
GROUP BY job_code,status
ORDER BY qty DESC;</code></pre>
<p>先确认系统 crontab 按分钟调用 Magento，并且使用正确 PHP 与项目用户。再找出数量最多、执行时间最长的 job code；一个长任务占住进程，会拖累同组其他任务。</p>
<p>检查 running 记录是否长期不结束、进程锁是否残留，以及多节点调度是否按设计配置。消费者停止时，依赖队列的任务也会在业务层表现为&ldquo;Cron 没执行&rdquo;。</p>
<p>处理积压时应先修复执行能力，再根据业务重要性分批消化。邮件、索引、价格规则和第三方同步的容错要求不同，不能把所有旧任务无差别重新跑一遍。</p>]]></description>
      <pubDate>Tue, 09 Jul 2024 07:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 产品列表筛选结果不准确，索引不是唯一原因]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-grid-filter-wrong/</link>
      <description><![CDATA[<p>后台按品牌筛选显示 50 条，实际只有 42 条符合条件，先确认筛选的是默认值还是商店视图覆盖值。EAV 属性在不同作用域可以有多条记录，扩展联表不当会产生重复行。</p>
<p>重置网格筛选和列配置，排除管理员保存的旧视图。自定义属性如果更换过 backend type，旧值可能残留在原 EAV 表；界面显示新值，查询却同时命中历史数据。</p>
<p>开发层面检查 collection 是否重复 join 同一张表，是否缺少 store_id 条件，以及是否用 group by 掩盖重复。随意加 distinct 虽能让数量看起来正常，却可能破坏分页和排序。</p>
<p>目录索引主要服务前台价格、分类和搜索，后台产品网格并非所有筛选都依赖它。先抓取实际 SQL 与总数查询，比较重复的 entity_id，通常比重建全部索引更接近根因。</p>]]></description>
      <pubDate>Mon, 08 Jul 2024 02:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 robots.txt 修改后没有生效]]></title>
      <link>https://www.360magento.com/blog/magento-2-robots-txt-not-updated/</link>
      <description><![CDATA[<p>后台修改 robots 内容后，访问 <code>/robots.txt</code> 仍是旧版本，先确认请求到底由谁响应。Magento 可以按网站配置生成 robots，但站点根目录中的物理文件、Nginx 规则或 CDN 边缘规则可能在它之前直接返回。</p>
<p>用响应头查看缓存状态，并在服务器上检查是否存在真实 robots.txt。多网站共用代码时，不同域名应进入各自的网站作用域；Base URL 和网站代码映射错误，会让两个域名读取同一份配置。</p>
<p>清理配置与全页缓存后仍不变，再刷新 CDN 对该单一 URL 的缓存，不必清空所有静态资源。搜索引擎看到变化还需要重新抓取，浏览器显示新内容不等于站长平台会立即更新。</p>
<p>修改前先明确目标。Disallow 只限制抓取，不保证 URL 从索引消失；需要移除结果时，应使用可抓取的 noindex、正确状态码或访问控制，不能把所有问题都交给 robots.txt。</p>]]></description>
      <pubDate>Fri, 05 Jul 2024 09:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 多商店价格不同步，先分清价格作用域]]></title>
      <link>https://www.360magento.com/blog/magento-2-website-price-scope/</link>
      <description><![CDATA[<p>在中文商店视图修改价格，英文站没有变化，或反过来两个站总是一起变，先确认 Catalog Price Scope。Magento 原生商品价格通常按 Global 或 Website 管理，不是每个 Store View 都有独立价格。</p>
<p>同一 Website 下的多个 Store View 主要用于语言与展示，它们共享网站级价格。若业务需要不同售价，应建立不同 Website，或使用客户组价、目录价格规则等适合的机制。</p>
<p>切换后台作用域时，价格字段旁的&ldquo;使用默认值&rdquo;会显示继承关系。CSV 导入也要提供正确的网站关联；只写 store_view_code 并不能让一个原本网站级的价格变成商店视图级。</p>
<p>保存正确但前台仍不同步时，检查价格索引、客户组、币种换算与税费显示。所谓&ldquo;价格不同步&rdquo;有时只是一个站显示含税，另一个显示不含税，底层基础价格其实相同。</p>]]></description>
      <pubDate>Thu, 04 Jul 2024 03:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 发货后没有物流跟踪信息]]></title>
      <link>https://www.360magento.com/blog/magento-2-shipment-tracking-missing/</link>
      <description><![CDATA[<p>订单已经显示 Shipped，但客户中心没有物流单号，这是因为 Shipment 和 Track 是相关但独立的数据。创建发货只代表商品已出库，不会凭空知道承运人的运单号。</p>
<p>在发货记录中添加 Tracking Number 时，选择正确的 Carrier，并确认保存到了对应 shipment。自定义承运人可以显示名称，但若没有跟踪 URL 逻辑，客户点击后不会自动跳到承运商网站。</p>
<p>仓储系统回传物流时，应通过发货与跟踪服务写入，不能只更新订单状态。接口需以 shipment 或 order 的业务键去重，避免同一运单反复添加。</p>
<p>如果后台能看到单号、邮件里没有，检查发货邮件模板是否包含 tracking 区块，以及发送邮件时记录是否已经存在。先发邮件后补单号，旧邮件不会自动重发。客户中心、发货邮件和接口响应应分别确认，三处可能使用不同展示路径。</p>]]></description>
      <pubDate>Wed, 03 Jul 2024 06:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账成功却跳回购物车，重点看这三处]]></title>
      <link>https://www.360magento.com/blog/magento-2-checkout-returns-to-cart/</link>
      <description><![CDATA[<p>顾客点提交订单后又回到购物车，先别把它统称为&ldquo;支付失败&rdquo;。第一处看订单是否已经创建：后台有订单但页面跳错，和根本没有订单，是两条完全不同的链路。</p>
<p>第二处看 checkout session。域名、Secure Cookie、SameSite、反向代理配置错误，会让支付站返回时原会话丢失。浏览器应保持同一个 quote 与 session，而不是在回跳后新建空会话。</p>
<p>第三处看支付模块的 return、cancel 和 webhook 逻辑。同步返回页面只负责用户体验，最终支付状态通常还要以服务端通知为准。返回参数缺失或签名失败时，不应重复创建订单。</p>
<p>复现时记录提交请求、订单 ID、网关交易号和返回 URL。若订单已成功，页面应该进入 success 流程并清理 quote；若订单未创建，则从 totals 校验、库存、地址和支付异常继续向前找。</p>]]></description>
      <pubDate>Tue, 02 Jul 2024 01:56:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单号不连续，通常不是丢单]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-number-gaps/</link>
      <description><![CDATA[<p>订单号从 100000125 跳到 100000127，很多管理员会怀疑中间订单被删除。实际上 increment ID 是业务展示编号，不是判断数据库完整性的唯一依据。</p>
<p>不同商店视图可以使用不同前缀和序列。结账过程中某些流程会先取得序列号，随后支付失败或保存事务回滚，号码便不会对应一张最终订单。高并发下为了保证唯一性，序列也不承诺完全无间隔。</p>
<p>核对时应查销售订单实体、支付网关交易和失败日志，而不是自行把序列表往回改。强行回退序列可能造成重复订单号，后果比跳号严重。</p>
<p>如果财务要求连续票据编号，应由发票或合规系统按当地规则实现，不能默认把 Magento 订单号当作法定连续凭证。判断是否丢单，要看客户扣款、quote 转换、订单表与网关通知能否对应。</p>]]></description>
      <pubDate>Mon, 01 Jul 2024 08:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Redis 缓存占满内存后的排查思路]]></title>
      <link>https://www.360magento.com/blog/magento-2-redis-memory-full/</link>
      <description><![CDATA[<p>Redis 报 OOM 或 Magento 突然无法写缓存时，第一步不是 <code>FLUSHALL</code>。先确认当前实例承载的是默认缓存、全页缓存还是 session；共享实例上的清空命令可能让所有用户退出或影响其他应用。</p>
<pre><code>redis-cli INFO memory
redis-cli INFO keyspace
redis-cli CONFIG GET maxmemory-policy</code></pre>
<p>缓存实例通常允许合适的淘汰策略，session 则不能随意淘汰活跃会话。检查 Magento 的数据库编号和 key 前缀，确认不同用途没有错误混用。</p>
<p>键数量持续增长时，关注缓存标签失效、第三方模块生成高基数缓存 ID，以及全页缓存中大量带参数 URL。抽样大键比只看总键数更有意义，但生产扫描应控制频率，避免阻塞 Redis。</p>
<p>临时扩容能恢复服务，却不能解释增长来源。记录内存曲线、命中率、淘汰数和发布节点，才能判断是容量不足、过期策略错误，还是某次代码发布制造了无法复用的缓存。</p>]]></description>
      <pubDate>Fri, 28 Jun 2024 02:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 出现 There has been an error processing your request]]></title>
      <link>https://www.360magento.com/blog/magento-2-error-report-page/</link>
      <description><![CDATA[<p>前台只显示 <code>There has been an error processing your request</code>，这是生产模式的通用错误页，不是具体原因。页面如果带 report number，可在 <code>var/report</code> 中找到对应报告；同时查看 <code>var/log/exception.log</code> 和系统日志。</p>
<p>不要在生产站长期切换 Developer 模式把堆栈直接展示给访客，其中可能包含文件路径和配置细节。更安全的方式是在受控环境复现，或从服务器日志读取异常。</p>
<p>刚部署后出现时，常见方向包括生成代码未更新、依赖注入编译失败、文件权限、模块版本不兼容和数据库 schema 未升级。只在某个商品或订单出现，则优先检查该对象的数据与扩展处理。</p>
<p>报告中的第一条业务异常通常比最后的通用框架调用更有价值。记录请求 URL、时间、用户动作和 report number，再对照同一时刻的 PHP-FPM、Web 服务器日志，能避免在大量历史错误中找错记录。</p>]]></description>
      <pubDate>Thu, 27 Jun 2024 07:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 更换域名后商品图片仍指向旧地址]]></title>
      <link>https://www.360magento.com/blog/magento-2-old-domain-image-urls/</link>
      <description><![CDATA[<p>网站 Base URL 已换成新域名，商品图片请求却仍指向旧站，先查看配置中的 Base Media URL。它可以继承 Base URL，也可以单独被网站或商店视图覆盖。</p>
<p>如果配置正确，查看页面源代码：图片地址是 Magento 动态生成，还是商品描述、CMS 块中写死的绝对 URL。数据库搜索旧域名时要先备份，并只修改确认属于内容字段的记录，不能对整个数据库做无差别替换。</p>
<p>全页缓存、CDN 和浏览器缓存可能继续返回旧 HTML。清理对应缓存并刷新 CDN 后，再检查响应。邮件模板和站点地图也可能保留旧地址，它们不一定与商品页使用同一缓存。</p>
<p>采用对象存储或独立媒体域名时，旧域名可能本来就是设计的一部分。判断标准不是&ldquo;所有地址必须一样&rdquo;，而是该媒体域名是否仍可访问、证书是否有效，以及 canonical 和页面主体是否已经统一到新站。</p>]]></description>
      <pubDate>Wed, 26 Jun 2024 01:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 产品列表增加自定义属性列]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-grid-custom-column/</link>
      <description><![CDATA[<p>希望在后台商品列表直接查看品牌、仓库编码等字段，先打开属性配置，确认该属性启用了&ldquo;用于产品列表&rdquo;和&ldquo;可在网格中使用&rdquo;等选项。对常规 EAV 属性，这一步可能已经足够，无需写模块。</p>
<p>保存属性后，重新加载产品网格的列选择器。如果字段可选但筛选很慢，检查属性 backend type 和查询方式；大文本属性不适合直接作为高频网格筛选条件。</p>
<p>需要展示计算值或外部数据时，再通过产品 listing 的 UI Component 添加 column，并让数据源一次性提供字段。不要在每一行的渲染器中重新加载商品或调用接口，这会产生典型的 N+1 查询。</p>
<p>自定义列还要处理排序、筛选和导出。页面能显示不代表 CSV 会自动包含，也不代表数据库能高效排序。设计前先明确该列只是查看，还是必须支持搜索与批量操作。</p>]]></description>
      <pubDate>Tue, 25 Jun 2024 09:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CSV 导入后中文乱码的处理方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-csv-chinese-garbled/</link>
      <description><![CDATA[<p>商品 CSV 在编辑器里正常，导入后中文变成乱码，先确认文件实际编码。文件名写着 UTF-8 不代表内容真是 UTF-8，尤其是经过 Excel 或旧版表格软件重新保存后。</p>
<pre><code>file -bi products.csv
iconv -f GB18030 -t UTF-8 products.csv &gt; products-utf8.csv</code></pre>
<p>转换前要确定原编码，猜错源编码会造成二次损坏。UTF-8 BOM 有时能帮助表格软件识别中文，但某些处理脚本会把 BOM 当成第一列表头的一部分；应根据 Magento 导入器实际读取结果决定是否保留。</p>
<p>还要检查字段分隔符、文本包围符和换行。描述中包含逗号或换行时，必须正确使用双引号包围，字段内部的双引号要转义。不要通过直接替换逗号破坏正文。</p>
<p>先用两条商品记录导入并检查名称、描述、URL Key 和自定义属性，再处理完整文件。原始文件保留只读备份，避免多次打开保存让编码越来越难判断。</p>]]></description>
      <pubDate>Mon, 24 Jun 2024 03:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单地址出现乱码：字符集排查记录]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-address-garbled/</link>
      <description><![CDATA[<p>客户地址簿中的中文正常，新订单地址却变成问号，说明问题可能发生在 quote 转 order 或外部接口回写阶段。先比较 customer_address、quote_address 和 sales_order_address 中同一字段的原始值。</p>
<p>Magento 页面和数据库通常使用 UTF-8。检查数据库、表、字段以及连接字符集是否一致；只改表的默认字符集不会自动修复已有字段，更不会恢复已经变成问号的数据。</p>
<pre><code>SHOW CREATE TABLE sales_order_address;
SHOW VARIABLES LIKE 'character_set%';</code></pre>
<p>若数据库记录正常而 PDF、邮件或后台乱码，继续检查字体和输出层。第三方 ERP 如果使用 GBK，接口转换必须明确源编码与目标编码；对已经是 UTF-8 的文本重复转码也会产生乱码。</p>
<p>选一条包含中文、省市区和特殊符号的测试地址，沿每个数据节点比对。最早出现异常的位置，才是应该修复的边界。</p>]]></description>
      <pubDate>Fri, 21 Jun 2024 06:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 购物车规则突然失效，别只检查优惠券代码]]></title>
      <link>https://www.360magento.com/blog/magento-2-cart-rule-not-working/</link>
      <description><![CDATA[<p>昨天还能使用的促销今天突然不打折，不要只测试优惠券字符串。先确认规则仍启用，并且当前网站、客户组和有效日期都匹配。服务器时区与后台显示时区不同，活动开始或结束的边界最容易出问题。</p>
<p>Conditions 决定购物车是否有资格，Actions 决定哪些商品真正享受折扣。把商品属性条件放错位置，会出现购物车符合活动却没有任何商品被折扣的情况。</p>
<p>再检查 Stop Further Rules Processing 和优先级。另一条高优先级规则可能先命中并阻止后续规则，即使那条规则给出的折扣并不明显。优惠券使用次数也分规则总次数和每位客户次数，登录邮箱变化会影响计数。</p>
<p>复制一份线上购物车时，要保留网站、客户组、商品属性和地址条件。用一个简单商品逐层增加条件，比在复杂订单上反复改优惠券更容易找到失效的那一步。</p>]]></description>
      <pubDate>Thu, 20 Jun 2024 01:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 分类页商品排序不生效，问题可能不在前端]]></title>
      <link>https://www.360magento.com/blog/magento-2-category-sort-not-working/</link>
      <description><![CDATA[<p>在分类中调整商品 Position 后，前台顺序没有变化，先看分类页当前选择的排序方式。如果顾客选的是价格或名称，后台 Position 自然不会成为第一排序条件。</p>
<p>分类的 Available Product Listing Sort By 与 Default Product Listing Sort By 决定可选项和默认值。默认使用 Position 时，才会读取分类商品关联里的位置值。多个商品使用相同位置，数据库返回顺序可能不稳定，最好给重点商品设置明确且不同的数字。</p>
<p>使用搜索引擎驱动分类集合时，分类商品和搜索索引都可能参与。更新分类关联后检查相关索引与 Cron，不要只清浏览器缓存。</p>
<p>若原生主题排序正常，自定义主题异常，查看 toolbar 是否把 order 参数固定为某字段，或扩展是否重写 collection 的排序。排序问题看似是页面展示，根因经常出在查询已经提前指定了另一套顺序。</p>]]></description>
      <pubDate>Wed, 19 Jun 2024 08:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重置密码链接提示已过期]]></title>
      <link>https://www.360magento.com/blog/magento-2-password-reset-link-expired/</link>
      <description><![CDATA[<p>客户刚收到邮件，点击就提示链接已过期，先确认使用的是最新一封邮件。每次重新申请都会生成新令牌，之前邮件里的链接可能立即失效。</p>
<p>后台可以配置恢复链接有效期。服务器时间、数据库时间与 PHP 时区如果相差很大，令牌会被错误判断为超时。建议比较应用日志、数据库当前时间和服务器 UTC 时间，不要只看后台界面显示。</p>
<p>更换域名或 HTTPS 后，邮件模板可能仍生成旧 Base URL。旧域名跳转时若丢失查询参数，reset token 和 customer id 就无法完整传递。复制邮件中的原始地址，检查跳转前后参数是否保留。</p>
<p>某些企业邮箱安全服务会预先打开邮件链接进行扫描。若扩展把第一次 GET 访问就视为已使用，真实客户再点时便失效。标准流程应在成功提交新密码后才完成令牌消费，同时对机器人预取保持兼容。</p>]]></description>
      <pubDate>Tue, 18 Jun 2024 02:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台订单状态和前台显示不一致的原因]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-status-mismatch/</link>
      <description><![CDATA[<p>Magento 订单同时存在 <code>state</code> 与 <code>status</code>。State 代表处理阶段，例如 processing、complete；Status 是展示给管理员和客户的具体标签。一个 state 可以绑定多个 status，所以前后台文字不同不一定代表订单数据冲突。</p>
<p>先读取同一订单的 state、status，再到后台订单状态配置中查看绑定关系。自定义状态如果绑定到错误 state，可能导致后台显示&ldquo;已处理&rdquo;，系统却仍认为订单不能开票或发货。</p>
<p>前台主题和接口不应根据中文标签判断业务阶段。自定义代码应读取状态代码，涉及能否取消、开票、发货时，应使用订单对象提供的能力判断，而不是自己比较字符串。</p>
<p>若数据库值一致但客户中心仍显示旧状态，检查页面缓存、自定义 API 缓存和前端状态映射。支付回调延迟也会造成短暂差异，应结合订单历史中的时间顺序判断，而不是立即手工修改状态。</p>]]></description>
      <pubDate>Mon, 17 Jun 2024 07:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品保存越来越慢：常见瓶颈与定位顺序]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-save-slow/</link>
      <description><![CDATA[<p>商品编辑页打开正常，点&ldquo;保存&rdquo;却等待几十秒，先把问题分成两段：请求提交前慢，还是服务器收到请求后慢。前者常见于属性过多、浏览器脚本和图片上传；后者才需要看 PHP、数据库与扩展代码。</p>
<p>在测试环境记录一次保存请求的总耗时，并对比只改商品名称、价格、分类和图片时的差异。分类数量很多时，分类关联保存可能明显变慢；属性集包含大量不用的属性，也会增加表单和 EAV 写入。</p>
<h3>保存事件最容易被扩展拖慢</h3>
<p>检查针对 product save 的 observer、plugin 和消息发送逻辑。有些扩展会在保存过程中同步调用 ERP、搜索服务或图片接口，只要外部请求变慢，后台就一直等待。外部同步更适合写入队列，再由消费者处理。</p>
<p>索引设为 Save 模式时，保存动作可能同步更新多个索引；商品规模较大时可评估按计划更新。最终要用性能追踪找到具体 SQL 或方法，不要用不断提高 PHP 超时来掩盖瓶颈。</p>]]></description>
      <pubDate>Fri, 14 Jun 2024 01:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品属性值保存后消失如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-attribute-value-not-saved/</link>
      <description><![CDATA[<p>商品属性输入后提示保存成功，刷新却为空，先确认该属性确实分配到商品使用的 Attribute Set。只创建属性但没有加入属性集，编辑表单可能通过自定义 UI 显示，却无法按预期持久化。</p>
<p>查看属性的 Catalog Input Type、Scope 和 backend type。全局属性在默认层级保存；网站或商店视图属性若勾选&ldquo;使用默认值&rdquo;，当前层级的输入会被继承值覆盖。排查时明确当前商店视图，不要只对比两个页面截图。</p>
<p>通过代码创建属性时，错误的 type、backend model 或 source model 会把值写入错误 EAV 表，或在保存前后转换掉。检查商品保存插件、observer 和数据补丁，尤其是对空值执行 unset 的逻辑。</p>
<p>还要排除 <code>max_input_vars</code> 导致表单后半部分字段被截断。用单独 API 请求保存该属性做对照：API 成功而后台失败偏向表单；两者都失败则继续检查属性元数据与保存扩展。</p>]]></description>
      <pubDate>Thu, 13 Jun 2024 08:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 图片缓存无法生成怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-image-cache-generation-failed/</link>
      <description><![CDATA[<p>商品原图存在，但前台缓存尺寸返回 404，先确认源文件在 <code>pub/media/catalog/product</code> 中能被部署用户读取。文件名大小写在 Linux 上敏感，数据库路径与实际文件大小写不一致时，本地开发可能正常、生产却失败。</p>
<p>检查 PHP 的 GD 或 Imagick 扩展、内存限制和 Magento 日志。某一张图片失败时，通常是源文件损坏、颜色空间或尺寸异常；所有图片都失败则更像目录权限、媒体存储或 Base Media URL 配置。</p>
<pre><code>bin/magento catalog:images:resize</code></pre>
<p>批量预生成可以暴露具体失败文件，但大目录应在维护窗口执行。清理图片缓存后，首次请求需要重新生成，不能在高流量时直接删除全部缓存而没有预热。</p>
<p>使用远程存储、CDN 或只读发布目录时，还要确认生成节点能写缓存且其他节点能读取。修复权限时遵循部署用户和 Web 用户的共享策略，不要简单把 media 目录设为 777。</p>]]></description>
      <pubDate>Wed, 12 Jun 2024 02:58:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 搜索结果出现已禁用商品怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-disabled-product-in-search/</link>
      <description><![CDATA[<p>商品已经禁用，站内搜索仍能找到，先确认禁用发生在哪个作用域。默认视图设为禁用，但某个商店视图可能保留启用值；网站分配和可见性也要一起检查。</p>
<p>随后查看 <code>catalogsearch_fulltext</code> 索引状态。Update by Schedule 模式依赖 Cron 消费变更日志，手工保存后短时间延迟可以理解，长期存在则要查 backlog 与失败任务。</p>
<p>使用 Elasticsearch/OpenSearch 时，确认 Magento 当前连接的集群、索引前缀和别名。部署切换过环境却仍查询旧索引，会出现后台数据与搜索结果完全不同步。重建后还要清理应用缓存，但不要直接删除整个共享集群。</p>
<p>如果站内搜索已消失、外部搜索引擎仍有页面，那是抓取与索引更新问题，应通过页面状态、canonical 和站点地图处理。先分清&ldquo;Magento 搜索&rdquo;和&ldquo;搜索引擎结果&rdquo;，排查方向才不会混在一起。</p>]]></description>
      <pubDate>Tue, 11 Jun 2024 06:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Bundle 商品价格显示为 0 如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-bundle-price-zero/</link>
      <description><![CDATA[<p>Bundle 商品列表显示&ldquo;低至 0&rdquo;，先看 Price 是 Dynamic 还是 Fixed。动态价格来自已选择子商品；如果没有必选项，最低组合确实可能是零。Fixed 模式则使用 Bundle 自身价格，子项价格按选项配置参与计算。</p>
<p>检查至少一个必选选项是否有默认选择，关联简单商品是否启用、分配到当前网站且有有效价格。子商品不可售或价格作用域不一致，会让可用组合与后台预期不同。</p>
<p>数据正确但前台仍为零时，重建 <code>catalog_product_price</code> 索引并检查主题是否错误读取 regular price。客户组价、目录规则、含税显示也会改变最终区间。</p>
<p>商品页选择完整组合后再看购物车 totals。如果商品页为零、购物车正确，问题偏向展示组件；两处都为零，则应回到商品配置和价格索引。不要在模板里用&ldquo;如果为零就隐藏&rdquo;的方式掩盖计算错误。</p>]]></description>
      <pubDate>Mon, 10 Jun 2024 01:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户地址保存失败如何排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-customer-address-save-error/</link>
      <description><![CDATA[<p>客户中心点击保存地址没有反应，先查看请求响应。Magento 通常会返回具体校验消息，只是某些主题没有把消息组件正确显示出来。</p>
<p>不同国家对 Region、Postcode 和 Telephone 的要求不同。切换国家后，地区字段可能从下拉框变成文本框；前端传了 region 名称却缺少 region_id，或反过来，都可能被服务端拒绝。</p>
<p>安装客户属性扩展后出现问题，要检查新增属性是否被设为必填、是否分配到 customer_address 实体，以及 REST/GraphQL 请求是否包含允许字段。后台能保存而前台失败，通常指向表单布局或前端 payload；两个入口都失败则更像属性或数据约束。</p>
<p>地址簿数量达到限制、字符串过长、非法字符和 max_input_vars 也值得排除。不要直接往 customer_address_entity 表插数据，标准 repository 保存会负责验证、属性处理与默认账单/配送地址关系。</p>]]></description>
      <pubDate>Fri, 07 Jun 2024 09:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台导出 CSV 文件为空怎么解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-csv-export-empty/</link>
      <description><![CDATA[<p>后台点击 Export CSV 下载到零字节文件，先看浏览器网络请求的状态码与响应头。若响应实际是 HTML 登录页或报错页，问题不是 CSV 编码，而是会话或服务器异常。</p>
<p>清除网格筛选后用少量记录测试。有些网格的&ldquo;全选&rdquo;仍受当前筛选条件约束，条件没有结果时会正常导出空文件。自定义列若在页面能显示，却没有为导出集合提供字段，也可能触发 SQL 错误。</p>
<p>检查 Magento 日志、PHP-FPM 日志和 <code>var/export</code> 权限。数据量大时，PHP 内存、执行时间和反向代理超时都可能中断响应；这类导出更适合异步生成，而不是无限提高 Web 请求超时。</p>
<p>用原生网格与禁用自定义列做对照，能判断问题在核心导出还是扩展。修复后打开 CSV 检查表头、记录数、中文编码和公式字符，避免文件虽然不空却无法安全使用。</p>]]></description>
      <pubDate>Thu, 06 Jun 2024 03:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重新索引时占用内存过高如何优化？]]></title>
      <link>https://www.360magento.com/blog/magento-2-reindex-memory-high/</link>
      <description><![CDATA[<p><code>bin/magento indexer:reindex</code> 被系统杀死时，先单独运行各索引器，找出真正消耗内存的那一个。一次重建全部索引会把问题藏在长输出里。</p>
<pre><code>bin/magento indexer:status
bin/magento indexer:reindex catalog_product_price
/usr/bin/time -v bin/magento indexer:reindex catalogsearch_fulltext</code></pre>
<p>价格索引会随网站、客户组、商品类型和规则数量增长；搜索索引还受属性数量与搜索引擎批量请求影响。检查异常多的网站分配、客户组价、孤立关联和被设为可搜索的大文本属性。</p>
<p>支持批次配置的索引器可在部署配置中调整 batch size。批次太大会产生内存峰值，太小则增加数据库往返，没有一个适合所有商店的固定数字。</p>
<p>CLI memory_limit 可以合理提高，但若服务器开始 swap 或触发 OOM，应先减少批次并修复数据规模问题。记录单个索引器的峰值内存、耗时和处理量，优化才有可比较的依据。</p>]]></description>
      <pubDate>Wed, 05 Jun 2024 07:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 保存分类后商品没有显示怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-category-products-missing/</link>
      <description><![CDATA[<p>后台分类的 Products in Category 已勾选商品，前台却是空的，先确认商品是否分配到该商店对应的网站。分类归属 Root Category，商品归属 Website，两者必须落在同一商店链路中。</p>
<p>商品状态要启用，可见性不能是&ldquo;单独不可见&rdquo;（除非它作为可配置商品子项），库存展示规则也可能隐藏不可售商品。多商店下还要查看商店视图级别是否把状态或名称覆盖。</p>
<p>确认数据正确后检查 <code>catalog_category_product</code> 与相关索引状态，执行针对性的分类商品索引，而不是先 flush 全部缓存。分层导航或搜索引擎异常一般不会改变分类分配本身，但会影响前台集合。</p>
<p>如果保存后勾选立即消失，检查管理员请求是否超过 <code>max_input_vars</code>，以及自定义分类保存插件是否重写关联数据。商品很多的分类更容易暴露这个问题。</p>]]></description>
      <pubDate>Tue, 04 Jun 2024 01:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 新提交的商品评价不显示怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-review-not-showing/</link>
      <description><![CDATA[<p>顾客提交评价后前台看不到，最常见原因是评价仍处于 Pending。进入后台评价列表审核并设为 Approved，同时确认它关联了正确商品与商店视图。</p>
<p>多商店环境中，评价可以只对部分 Store View 可见。管理员在默认视图批准，但没有选择顾客正在浏览的商店时，商品页不会显示。</p>
<p>评价内容与星级汇总是两类数据。内容已出现但平均星级不更新时，检查 rating 是否启用、是否分配到当前网站，以及汇总数据是否正常生成。主题覆盖评价模板或移除布局块，也会让数据存在却没有输出。</p>
<p>如果所有新评价都直接消失，查看表单提交响应、form key、验证码和日志，确认请求确实保存成功。处理后用访客提交一条测试评价，分别观察待审核、批准和前台显示三个阶段，便能定位问题是在保存、审核还是展示。</p>]]></description>
      <pubDate>Mon, 03 Jun 2024 08:13:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台没有退款按钮是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-refund-button-missing/</link>
      <description><![CDATA[<p>Magento 2 的退款通常通过 Credit Memo 完成。订单没有发票时，后台不会按正常已收款流程提供可退款金额；已经全额退款或关闭的订单也不会继续显示入口。</p>
<p>打开对应发票查看是否有 Credit Memo 操作。在线退款要求支付模块保存可退款交易，并且网关仍允许对原交易退款；离线退款只更新 Magento 账务，不会把钱退回支付渠道，两者不能混淆。</p>
<p>部分订单只剩运费、调整金额或某几行可退，系统会根据 invoiced、refunded 和 canceled 数量计算上限。管理员角色还需要销售退款相关权限。</p>
<h3>按钮消失前发生了什么</h3>
<p>若安装支付扩展后才出现，检查它是否改写 <code>canRefund</code>、交易关闭标记或订单 state。不要直接修改订单表恢复按钮。先确认真实收款状态，再修复支付能力判断，否则后台显示了退款入口也可能对网关发出错误请求。</p>]]></description>
      <pubDate>Fri, 31 May 2024 02:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 邮件中的 Logo 不显示怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-email-logo-not-showing/</link>
      <description><![CDATA[<p>订单邮件文字正常但 Logo 是破图，先查看邮件源代码中的图片地址。它应该是收件人可以访问的绝对 HTTPS URL，而不是后台地址、内网域名或本地文件路径。</p>
<p>Magento 的邮件 Logo 可以按网站或商店视图配置。多品牌站常见问题是在默认作用域上传了图片，子商店却覆盖为空，或仍指向旧域名。重新上传后确认文件实际存在于媒体目录，并能在未登录浏览器中直接访问。</p>
<p>部分邮件客户端不支持 SVG，过大的图片也可能被代理压缩或拦截。使用常见 PNG/JPG、合理尺寸，并为图片设置明确的宽高与替代文字。HTTP 图片嵌入 HTTPS 邮件还会触发安全限制。</p>
<p>如果只有外部邮箱不显示，而测试工具能显示，检查 CDN 防盗链、User-Agent 限制和邮件客户端的远程图片策略。不要把图片转成巨大 Base64 塞进每封邮件，这会增加邮件体积并影响投递。</p>]]></description>
      <pubDate>Thu, 30 May 2024 06:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 汇率更新失败如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-currency-rate-update-failed/</link>
      <description><![CDATA[<p>多币种商店价格长期不变，先区分&ldquo;汇率没有导入&rdquo;和&ldquo;前台没有使用新汇率&rdquo;。后台汇率矩阵只有启用的允许货币才会出现，基础货币到显示货币的方向也不能填反。</p>
<p>使用在线导入服务时，查看系统日志中的 HTTP 状态、超时和返回格式。服务器 DNS、代理、防火墙或 CA 证书异常，都可能让浏览器能访问而 PHP 请求失败。第三方服务还可能需要密钥或限制调用频率。</p>
<p>自动更新依赖 Cron。检查计划是否生成、任务是否成功，以及后台选择的频率和开始时间。手工导入成功而自动失败，通常应优先查调度链路。</p>
<p>紧急情况下可手工填写汇率，但要记录来源与生效时间，并核对价格舍入。保存后清理配置相关缓存，再用同一商品比较基础币与显示币。汇率只负责换算，目录价格规则、固定价格和税费配置仍可能让最终金额看起来没有按简单乘法变化。</p>]]></description>
      <pubDate>Wed, 29 May 2024 01:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品税费计算不正确怎么排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-tax-calculation-error/</link>
      <description><![CDATA[<p>同一商品在分类页、购物车和结账页显示不同税额时，不要先改税率数字。Magento 通过商品税类、客户税类、税率和 Tax Rule 的组合决定税费，任何一层不匹配都会让规则不命中。</p>
<p>确认商店税务来源地址，以及计算依据使用配送地址、账单地址还是来源地址。访客尚未填写地址前，系统可能使用默认国家地区估算，填写真实地址后税额变化属于正常行为。</p>
<h3>含税与不含税配置必须成套</h3>
<p>&ldquo;商品价格输入方式&rdquo;&ldquo;目录显示&rdquo;&ldquo;购物车显示&rdquo;是不同设置。后台按含税价格录入，却配置成不含税，会产生重复加税或反算差异。折扣在税前还是税后应用，也会改变结果。</p>
<p>一分钱误差常来自按单价或按行汇总舍入，以及跨境汇率换算。用一个简单商品、明确地址和无折扣订单手算对照，再逐步加入折扣、运费和多数量，能定位差异从哪一步开始。</p>]]></description>
      <pubDate>Tue, 28 May 2024 09:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单无法创建发票如何处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-invoice-unavailable/</link>
      <description><![CDATA[<p>订单详情中没有&ldquo;发票&rdquo;按钮，不一定是后台权限问题。Magento 只有在订单仍可开票、存在未开票数量且状态允许时才显示入口。</p>
<p>先看订单是否已全部开票、取消或关闭。对虚拟商品、部分发货和部分退款订单，要逐行比较 ordered、invoiced、canceled、refunded 数量。支付方式的 Payment Action 也会影响流程：Authorize Only 通常需要后台捕获，Authorize and Capture 可能在下单时已生成发票。</p>
<p>网关授权过期、交易被拒绝或扩展把订单标记为不可捕获时，在线开票会失败。查看 payment additional information 和网关日志，但不要把完整敏感响应展示给客服。</p>
<p>如果自定义订单状态绑定到错误的 state，界面也可能误判业务阶段。不要通过直接改销售表强行生成发票，应修正状态映射或支付逻辑，再使用 Magento 的发票服务创建记录，确保库存、交易与通知保持一致。</p>]]></description>
      <pubDate>Mon, 27 May 2024 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 一直显示维护模式如何恢复？]]></title>
      <link>https://www.360magento.com/blog/magento-2-maintenance-mode-stuck/</link>
      <description><![CDATA[<p>部署完成后前台一直是 503 维护页，先用 Magento 命令查看真实状态：</p>
<pre><code>bin/magento maintenance:status
bin/magento maintenance:disable</code></pre>
<p>维护模式由 <code>var/.maintenance.flag</code> 控制。命令显示关闭但文件仍存在时，通常是部署用户与 Web 用户权限不一致；不要长期依赖手工删除而忽略权限根因。</p>
<p>如果某些 IP 能访问、其他用户仍看到维护页，检查维护模式的 IP 允许列表。命令已经关闭但浏览器仍显示同一页面，则查看 CDN、反向代理或全页缓存是否缓存了 503 响应。503 不应被长时间缓存。</p>
<p>还要确认页面真的是 Magento 维护页。有些负载均衡器在后端健康检查失败时也返回自定义 503，此时关闭 Magento 维护模式不会生效。</p>
<p>自动部署脚本应使用失败捕获，确保编译或静态部署出错后也能明确报告并按策略退出维护状态。恢复访问后再检查部署是否完整，避免只去掉维护页却留下半套代码。</p>]]></description>
      <pubDate>Fri, 24 May 2024 07:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Composer 安装提示内存不足如何处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-composer-memory-error/</link>
      <description><![CDATA[<p>运行 Composer 时出现 <code>Allowed memory size exhausted</code>，先确认报错来自 PHP 限制还是操作系统终止进程。命令行使用的 php.ini 可能与网站完全不同：</p>
<pre><code>php --ini
php -r 'echo ini_get("memory_limit"), PHP_EOL;'
free -m</code></pre>
<p>临时提高 CLI memory_limit 只能解决上限过低，不会增加服务器真实内存。若进程被 OOM Killer 终止，应减少并发、增加可用内存或在构建机完成依赖安装。</p>
<p>生产部署优先使用已有 <code>composer.lock</code> 执行 install；随意运行 update 会重新求解整个依赖图，耗时和内存都更高。扩展的版本约束过宽或彼此冲突，也会让求解器反复尝试。</p>
<pre><code>composer validate
composer why-not vendor/package 1.2.3</code></pre>
<p>不要删除 lock 文件来碰运气。先确认 PHP 版本、Composer 版本和 Magento 版本的兼容范围，再解决具体冲突，构建结果才可重复。</p>]]></description>
      <pubDate>Thu, 23 May 2024 01:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 sitemap.xml 无法生成是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-sitemap-generation-failed/</link>
      <description><![CDATA[<p>后台点击生成 Sitemap 后没有文件，或定时生成长期不更新，先看配置记录中的文件名与路径。路径应位于可写的公开目录内，Web 用户与 Cron 用户都要有正确权限。</p>
<p>手动生成失败时查看 exception 与系统日志；定时任务失败则同时检查 <code>cron_schedule</code> 中 sitemap 相关任务。常见情况是命令行 PHP 与 Web PHP 使用不同用户，后台测试可写，Cron 却没有权限。</p>
<p>多商店要为各商店视图创建对应 Sitemap，并确认 Base URL、商品和分类 URL 使用正确域名。商品量很大时，应使用系统的文件大小和 URL 数量拆分，不要生成一个超大 XML 后再手工切割。</p>
<p>文件生成后还要直接请求它，确认返回 200、内容是 XML 而不是登录页或 404。站点地图只负责列出规范 URL；被 noindex、重定向或 canonical 到其他页面的地址不应继续混在其中。</p>]]></description>
      <pubDate>Wed, 22 May 2024 08:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 可配置商品切换选项后价格不变怎么解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-configurable-price-not-updating/</link>
      <description><![CDATA[<p>可配置商品选择颜色、尺码后价格不变化，先确认关联简单商品是否真的有不同最终价格。Magento 2 的展示价格来自价格索引和页面中的配置数据，并不是每次切换都重新请求商品对象。</p>
<p>检查父商品与子商品的网站归属、状态、客户组价格、特价日期和价格作用域，然后重建 <code>catalog_product_price</code> 索引。若后台和接口中的最终价格正确，问题多半在主题层。</p>
<h3>查看页面中的价格配置</h3>
<p>原生 swatch/configurable 组件会根据 JSON 配置更新 price-box。主题覆盖模板、合并旧版 JavaScript，或重复初始化组件，都可能使选项变化却没有触发价格更新。浏览器控制台若出现 RequireJS 或 mixin 错误，应先解决最早的那一条。</p>
<p>切换到原生主题做对照，能快速区分数据与前端问题。修复后测试普通价格、特价、客户组价格和含税显示，因为它们走的最终价格组合并不完全相同。</p>]]></description>
      <pubDate>Tue, 21 May 2024 02:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页不显示配送方式怎么排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-shipping-methods-missing/</link>
      <description><![CDATA[<p>地址填写完成后没有配送方式，先判断是 Magento 没返回可用费率，还是前端没有渲染。查看 shipping-information 和 estimate-shipping-methods 请求的响应，比反复清缓存更快。</p>
<p>固定运费与免运费要核对启用状态、网站作用域、适用国家、最低订单金额和错误提示。表格费率还与目的国家、地区、邮编、商品重量以及导入的条件类型有关；CSV 里的国家代码必须与系统使用的代码一致。</p>
<p>只有某些商品失败时，检查重量是否为零、是否为虚拟商品，以及购物车是否混合了不可配送的商品。第三方承运人则要查看接口日志、凭据、沙盒/正式模式和超时。</p>
<h3>前端扩展也可能截断结果</h3>
<p>一步结账或地址自动补全模块可能没有触发 totals 重新计算。可在原生主题中用相同地址对照。最终应覆盖不同国家、邮编、重量和金额，确认规则边界，而不是只让一个测试地址出现运费。</p>]]></description>
      <pubDate>Mon, 20 May 2024 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台总是自动退出如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-auto-logout/</link>
      <description><![CDATA[<p>后台操作几分钟就回到登录页，先不要只把 Session Lifetime 调得很大。这个现象可能是会话过期，也可能是浏览器根本没有持续发送同一个 Cookie。</p>
<p>先在浏览器网络面板观察 admin Cookie 是否频繁变化，再检查后台安全配置中的会话时长。多域名、HTTP 与 HTTPS 混用、Cookie Domain 配错，都会让浏览器把管理端请求当成另一套会话。经过 CDN 或负载均衡时，还要确保 Magento 能识别原始 HTTPS。</p>
<h3>Redis 会话也要看过期策略</h3>
<p>使用 Redis 保存 session 时，检查连接是否稳定、内存淘汰策略是否误删会话，以及多节点是否共用同一配置。PHP 的 session 回收时间不能比后台期望时长更短。</p>
<p>如果只有某一位管理员出现，清理该站点 Cookie 后重新登录，并排除浏览器隐私插件。所有管理员都在固定时间退出，则重点比较 Magento 会话时长、PHP/Redis TTL 和代理层超时，找到最短的那一层。</p>]]></description>
      <pubDate>Fri, 17 May 2024 01:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台批量操作一直卡在处理中？]]></title>
      <link>https://www.360magento.com/blog/magento-2-mass-action-stuck/</link>
      <description><![CDATA[<p>批量操作一直显示处理中时，先不要重复点击，否则同一批对象可能被多次处理。打开网络面板确认请求是否发出、状态码和响应异常。</p>
<p>少量成功、选择全部失败时，关注 <code>selected</code> 与 <code>excluded</code>。Magento 的&ldquo;选择全部&rdquo;表示当前筛选结果，自定义控制器若错误展开整个集合，容易耗尽内存。检查 PHP-FPM、Web 服务器与 Magento 日志中的超时和内存错误。</p>
<p>大任务应拆批或交给消息队列，并提供可追踪状态。请求成功但数据不变时，查看消费者、队列积压和失败消息；扩展对 collection 或 repository 的插件也可能让每个实体执行昂贵查询。</p>
<p>用同一条件测试单条、当前页与全部结果，并确认目标数量、失败项和重复提交保护都正确。后台不转圈只是表面，数据完整性才是完成标准。</p>]]></description>
      <pubDate>Thu, 16 May 2024 08:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 页面出现 Invalid Form Key 如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-invalid-form-key/</link>
      <description><![CDATA[<p><code>Invalid Form Key</code> 表示表单令牌与当前会话不一致，或提交数据里没有收到该字段。反复刷新只能掩盖问题。</p>
<p>先观察 Cookie 是否在请求间不断变化。Base URL、Cookie Domain、Cookie Path、HTTP/HTTPS 混用都可能让浏览器不发送原会话。负载均衡环境应共享正确的会话存储与加密配置，代理也要让 Magento 识别原始 HTTPS。</p>
<p>若只在保存大商品时出现，检查 <code>post_max_size</code>、<code>max_input_vars</code> 与服务器请求体限制。请求被截断后，位于后面的 form_key 可能丢失。</p>
<pre><code>php -i | grep -E "post_max_size|max_input_vars|upload_max_filesize"</code></pre>
<p>自定义表单必须输出 Magento 提供的 form key。不要关闭验证来&ldquo;修复&rdquo;，应记录请求大小、会话 ID 变化与代理头，找出令牌为什么没有匹配。</p>]]></description>
      <pubDate>Thu, 16 May 2024 02:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何处理大量无效搜索词？]]></title>
      <link>https://www.360magento.com/blog/magento-2-search-terms-cleanup/</link>
      <description><![CDATA[<p>热门搜索词中出现乱码、网址和药品词，通常来自机器人批量请求。它不仅污染运营数据，还可能制造大量动态搜索 URL。</p>
<p>先分清搜索词统计、商品搜索索引和外部搜索引擎收录，这是三件事。清理搜索词表不会改善商品索引，也不会让已收录 URL 自动消失。</p>
<p>按条件清理前先备份并统计时间来源，结合访问日志识别高频 IP、User-Agent 与请求模式，在 CDN、WAF 或 Web 服务器限速，比让请求进入 Magento 更省资源。搜索结果页通常不适合作为外部搜索落地页，应确认 robots meta 与站点地图策略。</p>
<p>真实用户的错别字、旧型号和俗称不要一起删除，它们可用于同义词、重定向与商品属性优化。垃圾请求负责限制清理，真实零结果词用于改进搜索体验，数据才有运营价值。</p>]]></description>
      <pubDate>Wed, 15 May 2024 07:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 客户注册邮件收不到怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-registration-email-missing/</link>
      <description><![CDATA[<p>注册邮件问题应沿&ldquo;生成&mdash;发送&mdash;服务商接收&mdash;收件箱投递&rdquo;逐段检查。先确认客户配置是否要求邮箱确认：开启时发送确认模板，关闭时使用欢迎模板。再核对当前商店视图的发件人、模板和语言。</p>
<p>查看系统、异常及 SMTP 日志。若使用异步邮件，确认队列消费者与 Cron 正常。服务器上的 PHP mail 测试成功，也不能证明 Magento 当前发件人和传输插件正确。</p>
<p>服务商接受后仍可能因 SPF、DKIM、DMARC、域名信誉或退信抑制不投递，应按收件人和时间查服务商状态。只有某个商店失败时，比较发件身份、模板与 Base URL；模板变量异常也会导致渲染失败。</p>
<p>修复后分别测试新注册、需要确认、重发确认和忘记密码。这些流程的模板与触发条件并不完全相同。</p>]]></description>
      <pubDate>Wed, 15 May 2024 01:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何添加自定义系统配置项？]]></title>
      <link>https://www.360magento.com/blog/magento-2-system-config-field/</link>
      <description><![CDATA[<p>模块参数应放在 <code>etc/adminhtml/system.xml</code>，而不是写死。字段需要 section、group、field 层级，并用 <code>showInDefault</code>、<code>showInWebsite</code>、<code>showInStore</code> 明确作用域。</p>
<pre><code>&lt;field id="batch_size" type="text" sortOrder="10"
 showInDefault="1" showInWebsite="1" showInStore="0"&gt;
 &lt;label&gt;Batch Size&lt;/label&gt;
 &lt;validate&gt;validate-number validate-greater-than-zero&lt;/validate&gt;
&lt;/field&gt;</code></pre>
<p>在 <code>etc/acl.xml</code> 添加对应的 <code>Alwayly_Sync::config</code> 权限，否则普通管理员可能看不到或无法保存。默认值可放在 etc/config.xml。</p>
<p>业务代码通过 <code>ScopeConfigInterface</code> 读取，并明确网站或商店范围。API 密钥应使用 obscure 类型和加密后端模型，日志中不要输出解密值。添加后运行模块升级、清配置缓存，再用不同角色和网站作用域测试继承行为。</p>]]></description>
      <pubDate>Tue, 14 May 2024 09:01:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品 URL Key 重复怎么解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-duplicate-url-key/</link>
      <description><![CDATA[<p>保存商品提示 URL key 已存在，冲突的常是同一商店下最终 <code>request_path</code> 已被商品、分类或自定义重写占用。</p>
<pre><code>SELECT url_rewrite_id,entity_type,entity_id,request_path,store_id
FROM url_rewrite
WHERE request_path='example-product.html';</code></pre>
<p>查询时要带正确 store_id 与 URL 后缀。记录属于正常商品或分类时，应为新商品换 URL Key；若是历史 301，要先判断旧地址是否仍有 SEO 价值。只有确认孤立错误后，才做受控数据修复。</p>
<p>批量导入时，多商品同名且未提供唯一 URL Key 很容易冲突，可按 SKU 生成稳定短路径。不要删除整张 url_rewrite 再重建，那会丢失自定义跳转。</p>
<p>修复后访问新旧 URL、所属分类和不同商店视图，确认响应与 canonical 一致。目标不仅是保存成功，还要让已公开地址保持可预期。</p>]]></description>
      <pubDate>Tue, 14 May 2024 03:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何限制特定国家下单？]]></title>
      <link>https://www.360magento.com/blog/magento-2-restrict-order-countries/</link>
      <description><![CDATA[<p>商店只面向部分国家时，可在通用国家选项中配置允许国家。但它主要影响地址选项，真实业务还要同步检查配送和支付方式的适用国家。</p>
<p>多网站应在正确网站作用域设置，不能把限制写死在主题。前端隐藏国家只改变界面，REST、GraphQL 或客户地址簿仍可能提交其他国家。</p>
<p>通用国家、配送和支付三处不一致时，顾客可能能填写地址，却在下一步找不到配送或支付方式。需要&ldquo;允许浏览，但某类商品不能寄往某国&rdquo;这类细规则，应在服务端报价或下单校验中实现，并返回清楚提示；只用 JavaScript 禁用按钮可以被接口绕过。</p>
<p>修改后测试新地址、旧地址、访客结账、移动端接口和后台代客下单。限制国家本质是订单资格规则，前端下拉框只是其中一种展示。</p>]]></description>
      <pubDate>Mon, 13 May 2024 06:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页无法加载支付方式如何排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-payment-methods-missing/</link>
      <description><![CDATA[<p>结账页提示没有可用支付方式时，先判断服务端没有返回，还是浏览器收到后未渲染。查看网络请求与控制台错误，再检查当前网站作用域中的支付开关、允许国家、币种、最小最大金额和客户组。</p>
<p>用同一商品分别测试访客与登录客户、不同国家地址、无折扣与大额折扣。若填写地址后才消失，优先看国家、币种和总额条件，而不是重装模块。</p>
<p>后端有方法但前端不显示时，检查 renderer 的 RequireJS 映射、布局处理器与 Knockout 模板。自定义一步结账可能覆盖原生布局，可临时切换干净主题对照。</p>
<p>清理配置与静态资源缓存后仍异常，再查支付模块和 exception 日志。生产环境不要把完整网关响应输出到页面。最终应以多种地址、币种和金额组合验证规则，而不是只让一个测试购物车显示出来。</p>]]></description>
      <pubDate>Mon, 13 May 2024 01:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何安全清理 generated 和 var 目录？]]></title>
      <link>https://www.360magento.com/blog/magento-2-clean-generated-var/</link>
      <description><![CDATA[<p>&ldquo;权限异常就把 var 全删掉&rdquo;风险很高。<code>var</code> 不只有缓存，还可能包含日志、导出、报告与文件会话。清理前要确认 Magento 模式和目录用途。</p>
<pre><code>bin/magento maintenance:enable
bin/magento cache:clean
bin/magento setup:di:compile
bin/magento maintenance:disable</code></pre>
<p><code>cache:clean</code> 只清 Magento 使用的类型；<code>cache:flush</code> 会清整个缓存存储，共享 Redis 时影响更大。generated/code 与 generated/metadata 可在重新编译前清理，但不要让前台流量访问半生成状态。</p>
<p>var/cache、var/page_cache 可按需处理；var/log 应走轮转；var/session 不能随意删，否则顾客和管理员会退出。绝不要把 pub/media、app/etc/env.php 或 Magento 根目录放入通配删除命令。自动部署应写明确目录，并在编译完成后做健康检查。</p>]]></description>
      <pubDate>Fri, 10 May 2024 08:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 管理员保存配置后没有生效？]]></title>
      <link>https://www.360magento.com/blog/magento-2-config-not-applied/</link>
      <description><![CDATA[<p>后台提示保存成功，只代表请求完成，不代表当前页面读取的就是这个作用域的值。先记录配置路径，再确认默认、网站和商店视图层级。</p>
<pre><code>bin/magento config:show web/secure/base_url
bin/magento cache:clean config</code></pre>
<p>若子作用域取消了&ldquo;使用系统值&rdquo;，它会覆盖默认配置。通过部署命令锁定的值还可能进入 <code>app/etc/config.php</code> 或 <code>env.php</code>，此时数据库值会被文件覆盖，应在部署流程修改。</p>
<p>自定义模块也可能读取错路径或 scope。代码应使用 <code>ScopeConfigInterface</code>，并传入正确网站或商店上下文。长驻消费者与全页缓存也可能保留旧状态，需要按架构处理相应进程。</p>
<p>按&ldquo;配置路径&mdash;当前 scope&mdash;最终值&mdash;代码读取位置&rdquo;的顺序检查，能快速区分值没有保存，还是保存后读取了另一份值。</p>]]></description>
      <pubDate>Fri, 10 May 2024 02:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Cron 任务重复执行是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cron-runs-twice/</link>
      <description><![CDATA[<p>同一封邮件发两次，不等于 <code>cron_schedule</code> 必然有两条记录。先按 job code 查询计划时间、执行与完成时间，还原发生过程。</p>
<pre><code>SELECT schedule_id,job_code,status,scheduled_at,executed_at
FROM cron_schedule
WHERE job_code='alwayly_sync_pending'
ORDER BY schedule_id DESC LIMIT 20;</code></pre>
<p>相同计划时间有多条时，检查部署用户、控制面板和 <code>crontab -l</code>，常见情况是安装命令已有一套，运维又手工添加。多 Web 节点共用数据库时，也要确认只有规划好的节点负责调度。</p>
<p>记录只有一条而业务做了两次，通常是任务被终止后重跑，外部动作已成功但状态未写回。应以业务唯一键去重。若一次执行时间超过调度间隔，增加锁、缩小批次或独立 cron group。清空 cron_schedule 只会删除诊断证据，不能解决重复执行。</p>]]></description>
      <pubDate>Thu, 09 May 2024 07:34:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何创建自定义 Cron 任务？]]></title>
      <link>https://www.360magento.com/blog/magento-2-custom-cron-job/</link>
      <description><![CDATA[<p>自定义任务由模块的 <code>etc/crontab.xml</code> 声明：</p>
<pre><code>&lt;group id="default"&gt;
  &lt;job name="alwayly_sync_pending"
   instance="Alwayly\Sync\Cron\ProcessPending" method="execute"&gt;
    &lt;schedule&gt;*/15 * * * *&lt;/schedule&gt;
  &lt;/job&gt;
&lt;/group&gt;</code></pre>
<p>执行类应通过构造函数注入业务服务，不要直接使用 Object Manager。一次只处理有限批次，例如 <code>$this-&gt;processor-&gt;processBatch(100);</code>。</p>
<p>Cron 可能超时重跑，也可能在多节点同时触发。处理订单、库存或外部接口时，应以状态字段、唯一键或锁保证幂等。部署后确认系统 crontab 已调用 Magento，再查看 <code>cron_schedule</code> 中该 job code 的 pending、running、success 和 error。</p>
<p>开发环境连续运行两次 <code>bin/magento cron:run --group=default</code>，通常第一次生成计划，后续运行执行到期任务。上线前可人为制造一次失败，确认日志能定位批次，且重跑不会重复处理成功数据。</p>]]></description>
      <pubDate>Thu, 09 May 2024 01:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 canonical 标签错误怎么排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-canonical-url-error/</link>
      <description><![CDATA[<p>页面出现两个 canonical，或仍指向旧域名时，先查看最终 HTML 源码。商品与分类有各自的 canonical 配置，商品是否使用分类路径也会改变最终地址；应先确定网站希望保留的永久 URL。</p>
<h3>常见来源</h3>
<ol>
<li>Base URL 或代理协议识别错误，HTTP 与 HTTPS 混用。</li>
<li>主题布局重复添加标签。</li>
<li>SEO 扩展与原生功能同时开启。</li>
<li>多商店域名、尾斜杠规则不一致。</li>
</ol>
<p>可在自定义代码中搜索：<code>grep -R "canonical" app/code app/design/frontend</code>。分页、排序和筛选参数也不应一律 canonical 到首页，主版本应能代表实际内容集合。</p>
<p>修复后抽查商品多分类、分页、分层导航、多商店与 HTTP 跳转。每个页面应只有一个绝对地址的 canonical，而且该地址返回 200。</p>]]></description>
      <pubDate>Wed, 08 May 2024 09:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 测试域名被搜索引擎收录如何处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-test-domain-indexed/</link>
      <description><![CDATA[<p>测试域名进入搜索结果后，只写 <code>Disallow: /</code> 并不能保证消失。robots.txt 只是阻止继续抓取，已索引 URL 仍可能保留，而且爬虫也无法看到页面里的 noindex。</p>
<p>仍在使用的测试环境应优先加 HTTP 身份验证或限制 IP。无法封闭时输出 <code>noindex, nofollow</code>，并确认正式站没有链接或站点地图指向测试域名。</p>
<p>同时检查 Base URL、媒体地址和 canonical 是否残留测试域名。若测试站已停用，有明确正式页面的 URL 可逐条 301；没有对应内容则返回 404 或 410，不要把所有地址都跳到首页。</p>
<p>处理后抽查首页、分类、商品、搜索页，确保正式站未误带 noindex。以后创建测试环境时，应把访问控制作为部署步骤，而不是上线前才补的 SEO 设置。</p>]]></description>
      <pubDate>Wed, 08 May 2024 03:05:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何隐藏缺货商品？]]></title>
      <link>https://www.360magento.com/blog/magento-2-hide-out-of-stock-products/</link>
      <description><![CDATA[<p>在库存配置中把&ldquo;显示缺货商品&rdquo;设为否，可让不可售商品退出分类和搜索结果。但开关只决定展示策略，商品是否缺货仍由库存系统判断。</p>
<p>多网站先确认作用域，再检查库存与搜索索引：<code>bin/magento indexer:reindex inventory catalogsearch_fulltext</code>。数量为零仍可售时，查看是否允许延期交货、缺货阈值是否为负数、商品是否关闭库存管理。MSI 环境还要看网站绑定的 Stock 与 Salable Quantity，不能只看某个 Source。</p>
<p>可配置商品应从子商品判断：只要仍有可售选项，父商品继续显示是合理的；所有子项缺货后，父商品索引也需及时更新。</p>
<p>长期下架商品是否隐藏，还应结合补货周期与 SEO 决定。保留页面并推荐替代品，有时比让 URL 突然消失更合适。库存开关解决列表展示，不替代商品生命周期管理。</p>]]></description>
      <pubDate>Tue, 07 May 2024 06:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台搜索订单很慢如何优化？]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-grid-search-slow/</link>
      <description><![CDATA[<p>订单列表打开正常，一输入邮箱或状态就很慢，问题通常集中在网格查询。Magento 主要读取 <code>sales_order_grid</code>，但扩展添加的列可能把查询联回订单、地址或支付表。</p>
<p>在测试环境复现同一筛选条件，用慢查询日志找到最终 SQL，再看 <code>EXPLAIN</code> 是否全表扫描、临时表或文件排序。像 <code>LIKE '%example%'</code> 这样的前置模糊搜索难以使用普通索引；业务允许时可改成精确或前缀匹配。</p>
<p>关闭某个扩展后若明显变快，检查它是否重复 join，或每一行又加载一次订单对象。常用筛选值更适合同步到网格表，再按真实查询方式设计索引。不要给所有字段盲目加索引，冗余索引会拖慢下单与网格写入。</p>
<p>优化前后应比较同一 SQL 的执行时间与扫描行数，而不是只凭页面感觉。</p>]]></description>
      <pubDate>Tue, 07 May 2024 01:39:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何设置订单最小金额？]]></title>
      <link>https://www.360magento.com/blog/magento-2-minimum-order-amount/</link>
      <description><![CDATA[<p>Magento 2 已内置 Minimum Order Amount。进入商店配置的销售设置，先切到正确网站作用域，再启用并填写金额与提示文字。</p>
<p>真正需要确认的是系统拿哪个金额比较。优惠券把小计降到门槛以下时，顾客可能突然无法结账；税费是否参与显示与计算，也要结合网站价格配置测试。启用多地址配送后，还有&ldquo;每个地址分别满足&rdquo;或&ldquo;整张订单满足&rdquo;的差别。</p>
<p>保存后可清理配置缓存：<code>bin/magento cache:clean config full_page</code>。前台没有提示时，检查子作用域是否覆盖默认值，主题是否隐藏购物车消息。GraphQL、移动端和一步结账也必须展示服务端返回的校验错误，不能只在浏览器判断。</p>
<p>上线前覆盖刚好等于门槛、折扣后低于门槛、含税显示和多地址四种情况。设置的不只是一个数字，而是一条在不同结账入口都应一致的销售规则。</p>]]></description>
      <pubDate>Mon, 06 May 2024 08:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 下单后库存没有扣减是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-stock-not-deducted/</link>
      <description><![CDATA[<p>启用 MSI 后，订单提交时通常先产生库存预留，来源的实际 Quantity 在创建发货时扣减。因此只看 Sources 页面，很容易误判&ldquo;没扣库存&rdquo;。</p>
<p>正确的观察对象是 Salable Quantity：下单后它应下降；发货后来源数量下降，并通过补偿预留保持账面一致；取消订单则写入相反方向的补偿记录。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies</code></pre>
<p>若出现不一致，先核对订单是否经历导入、取消、退款或扩展改写状态。确认业务事实后再执行补偿，不要直接删除 <code>inventory_reservation</code>。</p>
<p>订单成功但可销售数量也没变化时，检查 SKU 是否分配到当前网站使用的 Stock、商品是否关闭&ldquo;管理库存&rdquo;，以及自定义下单代码是否绕过服务契约直接写销售表。选一笔新订单记录下单前后来源数量、可销售数量和预留，再创建发货观察变化，便能区分正常时点差异与库存链路故障。</p>]]></description>
      <pubDate>Mon, 06 May 2024 02:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何批量更新商品价格和库存？]]></title>
      <link>https://www.360magento.com/blog/magento-2-bulk-update-price-stock/</link>
      <description><![CDATA[<p>商品多时，最稳妥的方法是先从同一网站导出少量样本，保留 Magento 的列名，再制作更新文件。选择&ldquo;添加/更新&rdquo;，不要用&ldquo;替换&rdquo;；替换会重新处理整条商品数据，缺少的列可能造成意外结果。</p>
<pre><code>sku,store_view_code,price
SKU-1001,,129.00
SKU-1002,,88.50</code></pre>
<p>价格文件至少保留 SKU 和 price，多网站环境还要确认商店视图与网站归属。库存则要先区分环境：传统库存常用 qty、is_in_stock；MSI 的数量属于 source item，应按 <code>source_code + sku</code> 更新，不能把多个来源粗暴合并。</p>
<p>数量大于零仍可能缺货，因为可销售数量还受预留量、缺货阈值和来源分配影响。导入后查看报告，再检查库存索引：<code>bin/magento indexer:status</code>。建议先用 2 至 3 个 SKU 预演，确认网站价格、特价和可销售数量正确后再导入完整文件。直接改数据库会绕过事件与索引，不适合作为批量更新方案。</p>]]></description>
      <pubDate>Fri, 03 May 2024 07:46:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 上传商品图片提示 Disallowed file type 如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-image-file-type-error/</link>
      <description><![CDATA[<p>后台上传 JPG、PNG 时出现 <code>Disallowed file type</code>，先不要修改核心文件的白名单。Magento 不只看文件名，还会读取真实 MIME；不少所谓 JPG 实际是 WebP，或只是改了后缀。</p>
<h3>先确认文件与请求</h3>
<pre><code>file --mime-type product-image.jpg
identify product-image.jpg</code></pre>
<p>若识别结果与后缀不同，重新导出图片。还要排除双扩展名、零字节文件，并检查 PHP 的 <code>upload_max_filesize</code> 与 <code>post_max_size</code>。请求被截断时，Magento 收到的文件也会异常。</p>
<h3>只有自定义字段报错</h3>
<p>系统图库可上传而自定义字段失败，通常是 uploader 配置。自定义模块应通过依赖注入设置允许扩展名，同时保留内容校验：<code>$uploader-&gt;setAllowedExtensions(['jpg','jpeg','png','gif']);</code>。需要 WebP 时，还应确认 Magento 版本、主题和图片处理库都支持；只改前端 accept 属性无效。</p>
<p>修复后分别测试标准 JPG、PNG 和故意改错后缀的文件。前两者成功、错误文件仍被拒绝，才说明功能与安全检查都正常。</p>]]></description>
      <pubDate>Fri, 03 May 2024 01:24:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 站内搜索结果不准确如何优化？]]></title>
      <link>https://www.360magento.com/blog/magento-2-search-quality/</link>
      <description><![CDATA[<p>搜索服务状态正常、索引也没有报错，但用户搜&ldquo;红色连衣裙&rdquo;却先看到配件，或者搜索 SKU 找不到准确商品，这属于搜索质量问题，不是简单的连接故障。</p>
<h2>先收集真实搜索词</h2>
<p>不要只让运营人员凭感觉测试。整理站内搜索记录中的高频词、无结果词和搜索后立即退出的词，并为每个词写出理想的前 5 个结果。没有基准集，就无法判断调整是否真的变好。</p>
<h2>属性是否应该参与搜索</h2>
<p>商品名称、SKU、品牌、颜色和关键描述字段可以设为可搜索，但不是字段越多越好。把长描述、内部备注和大量无关属性全部加入全文索引，会稀释相关性。</p>
<p>为重要属性设置更高 Search Weight，例如名称和 SKU 高于普通描述。修改属性后重新构建搜索索引。</p>
<h2>SKU 与自然语言不是同一种查询</h2>
<p>SKU 通常需要精确或前缀匹配；中文自然语言依赖分词和分析器。一个配置很难同时完美处理两者。测试时把 SKU、品牌词、品类词和描述性长词分开评估。</p>
<h2>同义词要解决用户用词差异</h2>
<p>用户可能搜索&ldquo;手机壳&rdquo;&ldquo;保护壳&rdquo;或英文品牌别名。使用同义词把真实等价词关联起来，但不要把上下位概念随意设成完全同义，否则结果会变得更宽泛。</p>
<h2>无结果不一定是搜索引擎问题</h2>
<p>商品没有分配当前网站、状态禁用、Visibility 不包含 Search、库存策略隐藏缺货商品，都会让它不出现在结果中。先检查商品资格，再调整相关性。</p>
<h2>排序还会受到业务规则影响</h2>
<p>第三方搜索模块可能增加置顶、降权、库存、销量或利润规则。业务排序过强时，文本相关性高的商品反而被压到后面。每次只调整一个因素，并保留修改前后的结果对比。</p>
<p>一套可持续的做法是每周查看无结果词，每月抽测核心关键词，并关注&ldquo;搜索后加购率&rdquo;，而不是只看是否返回了几十个结果。好的站内搜索不是结果越多，而是用户更快找到真正想买的商品。</p>]]></description>
      <pubDate>Thu, 02 May 2024 07:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品页 Meta Title 不生效如何排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-meta-title/</link>
      <description><![CDATA[<p>商品后台已经填写 Meta Title，但浏览器标签和页面源码仍显示商品名称，先确认查看的到底是 HTML 的 <code>&lt;title&gt;</code>，还是页面正文中的 H1。两者是不同字段，修改 Meta Title 不会自动改变商品标题。</p>
<h2>从页面源码确认结果</h2>
<p>不要只看浏览器标签缓存。打开页面源代码，查找第一个 <code>&lt;title&gt;</code>。如果源码已经更新，问题可能只是浏览器或搜索引擎缓存；如果源码仍旧，继续检查 Magento 渲染过程。</p>
<h2>Store View 范围最容易忽略</h2>
<p>商品 Meta Title 可以按 Store View 保存。默认范围填了新标题，但当前中文 Store View 可能仍保留旧值。切换到实际 Store View，检查&ldquo;使用默认值&rdquo;是否勾选。</p>
<h2>主题或 SEO 扩展可能覆盖</h2>
<p>自定义主题可以通过布局 XML 或 Block 重新设置页面标题，SEO 扩展也可能按模板生成标题。搜索代码中的 <code>pageConfig-&gt;getTitle()-&gt;set()</code>，并检查商品详情布局更新。</p>
<p>如果多个模块都设置标题，最终执行顺序决定结果。不要同时在模板、Observer 和 Plugin 中重复处理。</p>
<h2>缓存层</h2>
<pre><code>bin/magento cache:clean full_page layout block_html</code></pre>
<p>源站已经更新但公开域名没有变化时，再检查 Varnish 或 CDN。商品页面应通过商品缓存标签精准失效，不需要每次修改 Meta Title 都清空全部缓存。</p>
<h2>搜索引擎为什么还显示旧标题</h2>
<p>页面源码更新后，搜索结果不会立刻改变。搜索引擎需要重新抓取，而且可能根据查询和页面内容重写标题。保证 canonical、H1、Meta Title 和页面主题一致，比频繁修改标题更重要。</p>
<p>实际处理时同时检查默认范围和目标 Store View，再暂时停用一个可能覆盖标题的 SEO 模板做对照。只要页面源码稳定输出正确标题，Magento 端就已经完成修复。</p>]]></description>
      <pubDate>Thu, 02 May 2024 01:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何添加自定义后台菜单？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-menu/</link>
      <description><![CDATA[<p>Magento 2 后台菜单不是只写一个 <code>menu.xml</code> 就结束。菜单项、ACL 资源、adminhtml 路由和控制器必须使用同一组标识，否则会出现菜单不显示、点击 404 或 Access Denied。</p>
<h2>声明后台路由</h2>
<p>文件：<code>app/code/Alwayly/Reports/etc/adminhtml/routes.xml</code></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
  &lt;router id="admin"&gt;
    &lt;route id="alwayly_reports" frontName="alwayly_reports"&gt;
      &lt;module name="Alwayly_Reports"/&gt;
    &lt;/route&gt;
  &lt;/router&gt;
&lt;/config&gt;</code></pre>
<h2>添加菜单项</h2>
<p>文件：<code>etc/adminhtml/menu.xml</code></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"&gt;
  &lt;menu&gt;
    &lt;add id="Alwayly_Reports::root" title="Alwayly Reports" module="Alwayly_Reports" sortOrder="80" resource="Alwayly_Reports::root"/&gt;
    &lt;add id="Alwayly_Reports::orders" title="Order Report" module="Alwayly_Reports" sortOrder="10" parent="Alwayly_Reports::root" action="alwayly_reports/order/index" resource="Alwayly_Reports::orders"/&gt;
  &lt;/menu&gt;
&lt;/config&gt;</code></pre>
<h2>配置 ACL</h2>
<p>文件：<code>etc/acl.xml</code></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd"&gt;
  &lt;acl&gt;&lt;resources&gt;&lt;resource id="Magento_Backend::admin"&gt;
    &lt;resource id="Alwayly_Reports::root" title="Alwayly Reports"&gt;
      &lt;resource id="Alwayly_Reports::orders" title="Order Report"/&gt;
    &lt;/resource&gt;
  &lt;/resource&gt;&lt;/resources&gt;&lt;/acl&gt;
&lt;/config&gt;</code></pre>
<p>控制器的 <code>ADMIN_RESOURCE</code> 应与叶子 ACL 一致：</p>
<pre><code>public const ADMIN_RESOURCE = 'Alwayly_Reports::orders';</code></pre>
<p>最后执行 <code>bin/magento setup:upgrade</code> 并清理配置缓存。已有管理员角色需要重新保存权限，菜单才可能出现。若菜单可见但点击 404，优先核对 frontName、action 和控制器目录，而不是修改 ACL。</p>]]></description>
      <pubDate>Wed, 01 May 2024 09:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 为什么会出现重复订单？如何避免？]]></title>
      <link>https://www.360magento.com/blog/magento-2-duplicate-orders/</link>
      <description><![CDATA[<p>Magento 2 出现两笔内容相同、时间相近的订单，不能简单归因于用户点了两次。正常下单流程会对 Quote 状态做控制，但第三方支付、自定义 API、网络重试和错误的异常处理仍可能绕过保护。</p>
<h2>先比较两笔订单</h2>
<p>记录订单创建时间、quote_id、客户、商品、金额、支付方式和外部交易号。如果两笔订单来自不同 quote_id，可能是前端或接口创建了两个购物车；如果关联同一业务请求，则更像重复提交或并发。</p>
<h2>前端按钮只能改善体验</h2>
<p>点击 Place Order 后禁用按钮可以减少用户重复点击，但不能作为唯一防线。网络超时后浏览器、App 或网关都可能重试，服务端必须具备幂等能力。</p>
<h2>支付回调会重复到达</h2>
<p>支付服务商通常采用&ldquo;至少一次&rdquo;投递。你的回调接口返回超时或 500 时，同一通知会再次发送。处理前应使用支付交易号或事件 ID 检查是否已经完成。</p>
<pre><code>if ($this-&gt;paymentEventRepository-&gt;exists($eventId)) {
    return;
}
$this-&gt;transaction-&gt;addObject($eventRecord);
$this-&gt;paymentProcessor-&gt;process($payload);
$this-&gt;transaction-&gt;save();</code></pre>
<p>幂等键必须有数据库唯一约束，不能只先查再写，否则两个并发请求仍可能同时通过检查。</p>
<h2>自定义下单接口</h2>
<p>为每次业务下单请求生成稳定的 request_id。客户端重试时继续使用同一个 ID，服务端返回已创建订单，而不是再次调用 CartManagement 创建新订单。</p>
<h2>错误处理造成的假失败</h2>
<p>订单已经写入数据库，但响应在邮件发送或外部同步阶段抛出异常，客户端会认为下单失败并再次提交。非关键后续任务应异步处理，不能让它们改变订单创建的最终响应。</p>
<p>修复前不要删除重复订单来掩盖问题。保留两笔订单和日志，按 quote_id、request_id、交易号重建时间线。找到重复发生在哪个边界，才能决定是前端防抖、回调幂等还是事务拆分。</p>]]></description>
      <pubDate>Wed, 01 May 2024 03:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 磁盘空间不足，如何快速找到占用目录？]]></title>
      <link>https://www.360magento.com/blog/magento-2-disk-usage/</link>
      <description><![CDATA[<p>Magento 2 服务器磁盘接近 100% 时，后台保存、Session、索引和数据库都可能开始报错。处理目标不是&ldquo;随便删点东西&rdquo;，而是先找到增长来源，再清理明确可恢复或可归档的数据。</p>
<h2>从文件系统开始</h2>
<pre><code>df -h
df -i</code></pre>
<p><code>df -h</code> 看容量，<code>df -i</code> 看 inode。大量小 Session 或缓存文件可能耗尽 inode，即使容量还有剩余也无法创建新文件。</p>
<h2>定位 Magento 项目中的大目录</h2>
<pre><code>du -xhd1 /var/www/magento | sort -h
du -xhd1 /var/www/magento/var | sort -h
du -xhd1 /var/www/magento/pub/media | sort -h</code></pre>
<p>把路径替换成实际项目目录。<code>-x</code> 避免跨越其他挂载点。不要在不确认当前路径时执行递归删除。</p>
<h2>最常见的五类占用</h2>
<ol>
<li><strong>var/log：</strong>重复异常或调试日志持续增长。</li>
<li><strong>var/report：</strong>大量错误报告长期未归档。</li>
<li><strong>var/cache 与 page_cache：</strong>文件缓存未正确清理。</li>
<li><strong>pub/media：</strong>商品原图、缓存图、导入文件和重复媒体。</li>
<li><strong>备份与导出：</strong>数据库 dump、订单 CSV 或迁移包留在项目目录。</li>
</ol>
<h2>文件删了，空间为什么没回来</h2>
<p>进程仍持有已删除文件句柄时，目录中看不到文件，但磁盘仍被占用。可以使用：</p>
<pre><code>lsof +L1</code></pre>
<p>找到对应进程后，按服务流程重新打开日志或平滑重载，不要直接杀死未知数据库进程。</p>
<h2>数据库不一定在项目目录</h2>
<p>如果项目目录并不大，检查 MySQL 数据目录、binlog、OpenSearch 数据和容器存储。数据库文件不能通过文件系统手工删除，应使用各服务自己的保留和清理策略。</p>
<p>紧急释放空间后，给日志、备份和导出文件设置保留周期，并监控目录增长速度。磁盘告警的价值在于提前处理，等到 100% 再清理，往往已经伴随索引或数据库异常。</p>]]></description>
      <pubDate>Tue, 30 Apr 2024 06:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 CMS 页面修改后前台不更新如何处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cms-cache/</link>
      <description><![CDATA[<p>CMS 页面保存成功，后台预览也能看到新内容，但公开页面还是旧版本。此时先不要重做页面，通常只是查看范围或缓存层与编辑时不同。</p>
<h2>第一件事：确认编辑的是当前 Store View</h2>
<p>CMS 页面可以分配到多个 Store View。两个页面也可能使用相同标题、不同 identifier。打开前台 URL 后，确认域名对应的网站和 Store View，再回到后台核对页面分配。</p>
<h2>页面内容里是否引用了静态块</h2>
<p>很多 CMS 页面本身只包含布局或 Widget，真正内容来自 Static Block。修改页面正文不会改变被引用的 Block；反过来，修改了错误 Store View 的 Block，前台也不会更新。</p>
<h2>精准清理缓存</h2>
<pre><code>bin/magento cache:clean full_page block_html layout</code></pre>
<p>先使用 clean，不要习惯性 flush 整个 Redis。启用 Varnish 或 CDN 时，还要确认 CMS 页面保存产生的缓存标签能正确触发失效。</p>
<h2>HTML 新了，样式还是旧的</h2>
<p>这种情况不是 CMS 内容缓存，而是 CSS、JavaScript 或浏览器缓存。检查页面源代码和 Network，确认 HTML 中已经出现新内容，再处理静态资源版本。不要为一个 CSS 问题反复保存 CMS 页面。</p>
<h2>Page Builder 内容</h2>
<p>使用 Page Builder 时，后台编辑器可能自动处理 HTML 结构和媒体 URL。复制外部 HTML 后如果出现内容丢失，应检查不受支持的标签、内联脚本和内容安全策略，而不是直接关闭过滤。</p>
<h2>CDN 仍返回旧页面</h2>
<p>直接访问源站或通过内部 Host 测试。如果源站是新内容、公开域名是旧内容，按目标 URL 清理 CDN，并检查缓存 TTL 和 purge 配置。</p>
<p>一个简单判断顺序是：先核对 Store View，再看 CMS 页面与静态块，接着比较源站和公开域名。沿着这条链路处理，比一上来清空所有缓存更安全。</p>]]></description>
      <pubDate>Tue, 30 Apr 2024 01:17:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 购物车商品自动消失是什么原因？]]></title>
      <link>https://www.360magento.com/blog/magento-2-cart-missing/</link>
      <description><![CDATA[<p>用户把商品加入购物车，刷新页面后购物车变空；或者登录以后，游客购物车里的商品少了一部分。表面上都是&ldquo;购物车消失&rdquo;，实际可能是 Session 换了，也可能是 Quote 合并时商品被重新校验后移除。</p>
<h2>先判断整个购物车丢了，还是只有商品被移除</h2>
<p>如果购物车 ID 和 Session 同时变化，优先看 Cookie、Redis Session 和负载均衡。如果 Quote 仍存在，只少了某几个商品，则检查商品是否在当前网站可售。</p>
<h2>常见的 Session 问题</h2>
<ul>
<li>Cookie 域与当前域名不匹配。</li>
<li>HTTP 与 HTTPS 跳转导致 Secure Cookie 行为异常。</li>
<li>多个 Web 节点没有共享 Session。</li>
<li>Redis 内存淘汰了仍在使用的 Session。</li>
<li>前端和结账使用了不同二级域名，但 Cookie 范围不正确。</li>
</ul>
<p>在浏览器 Network 中观察加入购物车前后的 Session Cookie，不要记录或传播完整 Cookie 值。</p>
<h2>登录时 Quote 会合并</h2>
<p>游客登录后，Magento 会把游客 Quote 与客户现有 Quote 合并。重复 SKU、不同自定义选项、最小购买量或失效商品都可能改变合并结果。测试时要先确认客户账户中是否已经有旧购物车。</p>
<h2>商品重新校验失败</h2>
<p>刷新购物车或进入结账时，系统会再次检查商品状态、网站分配、库存、必填选项和购买数量。商品刚被禁用、子商品缺货或自定义选项被删除时，可能从可购买状态变为错误状态。</p>
<h2>自定义插件不要在 collectTotals 中删除项目</h2>
<p>一些促销或库存扩展会在 totals 计算时调用 <code>removeItem()</code>。Totals 可能在一个请求中执行多次，这种写法容易造成难以复现的丢商品。业务限制应返回明确错误，让用户知道为什么不能购买。</p>
<p>排查时给一次请求记录 quote_id、customer_id、store_id 和被移除的 item_id，不记录支付或认证信息。用同一浏览器分别测试游客刷新、登录合并、切换 Store View 和进入结账，通常能很快确定商品在哪一步消失。</p>]]></description>
      <pubDate>Mon, 29 Apr 2024 08:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何正确配置 OpenSearch？]]></title>
      <link>https://www.360magento.com/blog/magento-2-opensearch/</link>
      <description><![CDATA[<p>Magento 2.4 系列依赖外部搜索服务处理目录搜索。OpenSearch 服务能访问，并不代表 Magento 一定配置正确；版本兼容、认证、索引前缀和网络路径都需要一起确认。</p>
<h2>安装前先确认兼容版本</h2>
<p>不同 Magento 2.4 补丁版本支持的 OpenSearch 版本不同。不要直接安装仓库中的最新主版本，应根据当前 Magento 版本的系统要求选择。升级搜索服务前，也要先在预发布环境测试索引和查询。</p>
<h2>从 Magento 运行环境测试连接</h2>
<pre><code>curl -sS opensearch:9200/
curl -sS opensearch:9200/_cluster/health</code></pre>
<p>命令必须从运行 Magento 的容器或服务器执行。开发机能连接，不代表 PHP-FPM 所在网络也能访问。启用 HTTPS 或认证时，不要把密码直接写进公开脚本和日志。</p>
<h2>配置搜索引擎</h2>
<p>可以在后台的目录搜索配置中填写，也可以使用 CLI。下面只展示常见字段，实际命令选项以当前版本的 <code>setup:config:set --help</code> 为准：</p>
<pre><code>bin/magento setup:config:set \n  --search-engine=opensearch \n  --opensearch-host=opensearch \n  --opensearch-port=9200 \n  --opensearch-index-prefix=alwayly_store</code></pre>
<p>同一个 OpenSearch 集群承载多个 Magento 环境时，每个环境必须使用不同索引前缀，避免测试站覆盖生产索引。</p>
<h2>连接测试通过以后</h2>
<pre><code>bin/magento indexer:reindex catalogsearch_fulltext
bin/magento indexer:status catalogsearch_fulltext
bin/magento cache:clean config full_page</code></pre>
<p>全量索引失败时查看 Magento 日志和 OpenSearch 日志。集群磁盘达到高水位后，索引可能进入只读状态；继续重试不会自行恢复。</p>
<h2>生产环境需要监控什么</h2>
<ul>
<li>集群健康与未分配分片。</li>
<li>磁盘水位和 JVM 内存。</li>
<li>索引耗时、查询延迟和拒绝请求。</li>
<li>Magento 增量索引是否持续更新。</li>
</ul>
<p>最后不要只搜索一个商品名称。用 SKU、中文分词、部分词、同义词和无结果词分别测试，才能确认&ldquo;服务连接成功&rdquo;之外的搜索质量也正常。</p>]]></description>
      <pubDate>Mon, 29 Apr 2024 02:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品价格显示不一致，应该检查哪些地方？]]></title>
      <link>https://www.360magento.com/blog/magento-2-price-mismatch/</link>
      <description><![CDATA[<p>同一个商品在分类页显示 99 元，详情页变成 109 元，加入购物车又是另一个价格。这类问题不能只看商品后台的 Price 字段，因为 Magento 最终价格会受到客户组、特价、阶梯价、商品价格规则、税率和币种转换共同影响。</p>
<h2>先记录四个上下文</h2>
<p>排查前写下 Store View、客户组、显示币种和商品类型。游客看到的价格与登录会员不同可能是正常配置；可配置商品列表页显示最低子商品价格，也不一定等于默认选项价格。</p>
<h2>详情页正确、分类页错误</h2>
<p>这种组合通常优先检查价格索引和 Full Page Cache：</p>
<pre><code>bin/magento indexer:status catalog_product_price
bin/magento indexer:reindex catalog_product_price
bin/magento cache:clean full_page block_html</code></pre>
<p>如果手动重建后暂时正常，下一次改价又出错，应继续修复 Cron 或增量索引，而不是每天定时全量 reindex。</p>
<h2>购物车价格与前台不同</h2>
<p>购物车会重新计算 Catalog Rule、Cart Rule、Tier Price、税额和汇率。检查商品是否存在 Special Price 日期、客户组价格或数量阶梯；再查看购物车是否应用了优惠券。</p>
<h2>含税与不含税</h2>
<p>分类页、详情页和购物车可以分别配置价格显示方式。如果商品税类、客户税类或配送地区变化，结账页的含税价格可能不同。重点检查 Tax Calculation Based On 和各页面的 Display Product Prices 配置。</p>
<h2>多币种</h2>
<p>目录价格可能以基础货币保存，前台按汇率转换。汇率更新时间、四舍五入和固定商品税会带来小额差异。不要在模板中再次自行转换已经格式化的价格。</p>
<h2>主题与扩展</h2>
<p>自定义主题如果直接输出 <code>getPrice()</code>，可能绕过最终价格模型。正确做法是使用 Magento 的价格渲染组件。第三方促销扩展也可能只修改详情页或只影响 totals。</p>
<p>选一个具体 SKU，用游客和目标客户组分别记录索引价、详情页价、购物车单价和订单单价。把差异定位到具体阶段后，通常很快能判断是索引、促销还是税务配置。</p>]]></description>
      <pubDate>Fri, 26 Apr 2024 07:52:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台登录验证码不显示如何解决？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-captcha/</link>
      <description><![CDATA[<p>Magento 2 后台登录页已经出现验证码输入框，但图片是空白或破图，通常不是管理员账号问题。验证码图片由服务端动态生成，并依赖 Session；图片请求被缓存、Cookie 丢失或 PHP 图像环境异常，都可能导致无法显示。</p>
<h2>先打开验证码图片请求</h2>
<p>在浏览器开发者工具的 Network 中刷新验证码，找到对应图片请求。重点看状态码和响应类型：</p>
<ul>
<li>404：后台路径、路由或 Web 服务器 rewrite 可能有问题。</li>
<li>500：查看同一时间的 Magento、PHP-FPM 错误日志。</li>
<li>200 但不是图片：请求可能被登录跳转或错误页面替代。</li>
<li>图片正常返回但页面不显示：检查主题样式和 Content Security Policy。</li>
</ul>
<h2>确认配置范围</h2>
<p>后台 CAPTCHA 配置可能按默认范围或网站范围保存。确认管理员登录验证码已启用，并检查&ldquo;显示时机&rdquo;是始终显示，还是达到失败次数后才显示。修改后清理配置缓存：</p>
<pre><code>bin/magento cache:clean config</code></pre>
<h2>Session 不一致会让验证码失效</h2>
<p>如果图片可以看到，但每次输入都提示错误，比较验证码图片请求和登录请求的 Cookie。多节点环境必须共享 Session，或正确配置粘性会话。使用 Redis 时还要检查 Session 数据库是否被缓存清理误删。</p>
<h2>图像扩展与字体</h2>
<p>验证码生成依赖 PHP 图像能力和字体文件。先确认 CLI 与 PHP-FPM 使用的 PHP 版本和扩展一致：</p>
<pre><code>php -m | grep -Ei 'gd|imagick'
php -i | grep 'Loaded Configuration File'</code></pre>
<p>CLI 有 GD 不代表 PHP-FPM 也已加载。字体文件缺失、部署权限不正确时，错误通常会出现在 PHP 或 Magento 日志中。</p>
<h2>不要缓存验证码响应</h2>
<p>CDN、Varnish 或 Nginx 如果缓存动态验证码图片，不同用户可能拿到同一张旧图。验证码路由应绕过公共缓存，同时保留正确的 Session Cookie。</p>
<p>修复后先用无痕窗口测试一次后台登录，再连续刷新验证码，确认图片和 Session 都会更新。不要为了绕过问题长期关闭后台验证码；如果问题发生在生产后台，应同时检查是否存在大量异常登录请求。</p>]]></description>
      <pubDate>Fri, 26 Apr 2024 01:38:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Sitemap 生成失败或内容为空如何处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-sitemap-generation-failed-empty/</link>
      <description><![CDATA[<p>Magento 2 后台可以创建 Sitemap 记录，但“记录存在”不代表 XML 文件已经成功生成。常见问题包括保存路径不可写、文件写到了错误节点、目标 Store View 没有可收录内容，或 Cron 从未执行。</p><h2>后台显示成功，服务器却找不到文件</h2><p>Sitemap 的 Path 是相对于 Magento 可写目录的路径。多节点环境中，如果后台请求写入 A 节点本地磁盘，而公开流量访问 B 节点，就会出现后台成功、前台 404。Sitemap 应放在所有 Web 节点都能读取的位置，或通过部署流程同步。</p><p>检查文件位置和权限时，不要使用 777。生成 Sitemap 的 PHP/CLI 用户需要写入权限，Web 用户需要读取权限。</p><h2>文件存在但内容很少</h2><p>Magento 只会输出当前 Store View 中符合条件的商品、分类和 CMS 页面。商品未分配网站、状态禁用、可见性不合适，分类未启用，CMS 页面没有分配到当前 Store，都可能让内容缺失。</p><p>多语言站点应为不同 Store View 生成对应 Sitemap，而不是把所有语言 URL 混进同一个文件。</p><h2>手动生成正常，自动生成失败</h2><p>这种情况优先检查 Cron。查看 <code>cron_schedule</code> 中与 sitemap 相关的 job code、状态和 messages：</p><pre><code>SELECT job_code, status, messages, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE job_code LIKE '%sitemap%'
ORDER BY schedule_id DESC
LIMIT 20;</code></pre><p>如果没有调度记录，检查系统 crontab 和 Magento Cron 配置；如果状态为 error，按 messages 对应到同一时间的 Magento 日志。</p><h2>大量 URL 时的文件拆分</h2><p>大型目录会生成 Sitemap 索引和多个分片文件。确认所有分片都可以访问，不能只检查主索引。反向代理或 CDN 也不要把旧 Sitemap 长期缓存。</p><h2>提交给搜索引擎之前</h2><p>直接打开 Sitemap URL，确认返回 200、XML 格式正确、域名和协议属于当前站点。抽查几个商品、分类和 CMS URL，不能包含后台、客户账户、搜索结果或测试 Store 的地址。</p><p>Sitemap 修复后不需要每天手工点生成。让 Cron 按内容更新频率自动生成，并监控文件更新时间和访问状态，更适合长期维护。</p>]]></description>
      <pubDate>Thu, 25 Apr 2024 07:43:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[一次 Magento 2 首页变慢的排查：最终问题不是缓存]]></title>
      <link>https://www.360magento.com/blog/magento-2-homepage-slow-troubleshooting-case/</link>
      <description><![CDATA[<p>问题最初看起来很像缓存：Magento 2 首页首字节从不到 300ms 变成 6 秒，执行 <code>cache:flush</code> 后第一次更慢，随后几次又恢复。半小时后问题重新出现。</p>
<p>如果只看&ldquo;清缓存后好了一会儿&rdquo;，很容易得出错误结论。我们先保留缓存，分别测了首页、分类页和一个简单 CMS 页面。分类和 CMS 都稳定，只有首页周期性变慢，范围因此缩小到首页布局和 Block。</p>
<h2>第一步：确认是不是 Full Page Cache 未命中</h2>
<p>响应头显示慢请求确实没有命中 FPC，但这只能解释请求进入了 PHP，不能解释 PHP 为什么需要 6 秒。接下来在测试环境记录首页各 Block 的渲染时间。</p>
<p>一个&ldquo;猜你喜欢&rdquo;Block 每次缓存失效后需要 5 秒以上。继续向下看，Block 并没有从本地集合读取商品，而是同步请求一个外部推荐接口。接口正常时 200ms，异常时要等到默认超时结束。</p>
<h2>为什么看起来像缓存问题</h2>
<p>Full Page Cache 命中时，慢 Block 根本不会执行，所以首页很快；缓存过期或被商品更新清理后，第一个用户请求触发外部接口，页面就变慢。清缓存不是修复，反而主动制造了更多慢请求。</p>
<h2>修改方式</h2>
<p>我们没有把接口超时从 5 秒改成 30 秒，而是做了三件事：</p>
<ul>
<li>把推荐结果写入独立缓存，TTL 与整页缓存分开。</li>
<li>把接口连接和读取超时限制在可接受范围。</li>
<li>接口失败时返回本地热销商品，不阻塞首页。</li>
</ul>
<pre><code>try {
    $items = $this-&gt;recommendationClient-&gt;fetch($customerContext);
    $this-&gt;cache-&gt;save($items, $cacheKey, 900);
} catch (\Throwable $e) {
    $this-&gt;logger-&gt;warning('Recommendation service unavailable', [
        'exception_class' =&gt; $e::class
    ]);
    $items = $this-&gt;fallbackProducts-&gt;getItems(8);
}</code></pre>
<p>日志只记录异常类型和关联信息，没有写入客户画像或接口凭据。</p>
<h2>这次排查留下的经验</h2>
<p>页面慢和缓存未命中可以同时发生，但未命中只是触发条件。真正要优化的是未缓存请求的执行时间。遇到类似问题，先比较不同页面，再缩小到布局和 Block，最后检查 SQL 与外部依赖。这样比一遍遍清缓存更接近根因。</p>]]></description>
      <pubDate>Thu, 25 Apr 2024 01:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何给指定客户组设置专属价格？]]></title>
      <link>https://www.360magento.com/blog/magento-2-customer-group-special-price-setup/</link>
      <description><![CDATA[<p>给 VIP、批发客户或经销商显示不同价格，Magento 2 有三种常见做法：商品 Advanced Pricing、Tier Price 和 Catalog Price Rule。选择哪一种，取决于商品数量、折扣方式以及是否需要按购买数量分级。</p>
<h2>少量商品：直接设置 Advanced Pricing</h2>
<p>打开商品编辑页，在价格区域进入 Advanced Pricing。可以为指定 Website、客户组和数量设置价格。若最低数量为 1，这个价格就可以作为该客户组的基础专属价。</p>
<p>这种方式最直观，适合商品数量少、每个商品价格都不同的情况。缺点是批量维护成本高。</p>
<h2>数量越多越便宜：使用 Tier Price</h2>
<p>例如普通会员买 1 件为 100 元，批发组买 10 件为 85 元、50 件为 75 元，就适合阶梯价格。前台会根据当前客户组和购物车数量选择可用价格。</p>
<p>测试时不要只看商品详情页的提示，还要实际加入不同数量，检查购物车中的单价变化。</p>
<h2>整个分类统一折扣：商品价格规则更合适</h2>
<p>如果批发组购买某个分类统一九折，为每个 SKU 单独录入 Group Price 很难维护。创建 Catalog Price Rule，选择目标网站和客户组，再用分类或商品属性作为条件即可。</p>
<h2>价格冲突时谁生效</h2>
<p>Special Price、Tier Price、Group Price 和 Catalog Price Rule 可能同时存在。Magento 会根据价格模型计算最终价，不是简单按后台填写顺序叠加。上线活动前要挑选同时具有特价和阶梯价的商品做测试。</p>
<h2>客户组切换后的缓存</h2>
<p>公开页面缓存必须按客户组隔离价格内容。客户登录或切换组后，如果仍看到旧价格，检查 Full Page Cache、private content 和自定义主题是否把客户组相关价格做成了公共缓存。</p>
<h2>批量维护</h2>
<p>大量商品可使用官方导入字段或经过验证的管理工具。导入前先导出少量商品作为格式样例，尤其注意 Website、客户组名称、数量和价格字段。</p>
<p>最终应分别用游客、普通会员和目标客户组登录，检查分类页、详情页、搜索、小购物车、结账和订单价格。专属价只有在整个购买链路一致时才算配置完成。</p>]]></description>
      <pubDate>Wed, 24 Apr 2024 08:12:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台订单列表导出超时的优化思路]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-order-grid-export-timeout-optimization/</link>
      <description><![CDATA[<p>订单只有几千条时，后台直接导出 CSV 很方便；数据增长到几十万条后，同一个操作可能占满 PHP 内存、触发网关超时，甚至拖慢后台其他请求。把执行时间从 30 秒改成 30 分钟，往往只是把问题推迟。</p>
<h2>导出前先看列表本身</h2>
<p>如果订单 Grid 打开就慢，导出只会更慢。检查筛选条件是否命中索引，第三方模块是否向 Grid 追加多张表 JOIN，以及自定义列是否为每行再次加载订单对象。</p>
<pre><code>EXPLAIN SELECT entity_id, increment_id, created_at, grand_total
FROM sales_order_grid
WHERE created_at &gt;= '2024-04-01 00:00:00'
  AND created_at &lt; '2024-05-01 00:00:00';</code></pre>
<p>示例用于说明思路，实际应从慢查询日志或分析工具获取真实 SQL，不能凭空为每个筛选字段增加索引。</p>
<h2>把一次大导出改成明确范围</h2>
<p>按月份、Store、订单状态分批导出，比&ldquo;全部订单&rdquo;更容易恢复和核对。先在 Grid 中应用筛选，再导出当前集合。业务需要年度数据时，可以在离线环境合并文件。</p>
<h2>Grid 数据是否同步</h2>
<p><code>sales_order_grid</code> 是为列表查询准备的扁平表。若第三方代码绕过正常保存流程，Grid 可能缺字段或不同步。应修复写入流程，不要在每次导出时 JOIN 全部 EAV 或业务表补救。</p>
<h2>插件是隐藏成本</h2>
<p>导出会遍历集合。针对列值的 Plugin、Renderer 或数据提供器如果逐行调用 Repository，就会形成 N+1 查询。100 行列表看不明显，导出 10 万行时会放大为灾难。</p>
<h2>真正的大数据导出应该异步</h2>
<p>把导出请求写入队列，由 CLI 或消费者分批读取，生成文件后在后台提供下载。这样可以控制批次大小、记录进度、失败重试，并避免 Web 请求长期占用 PHP-FPM。</p>
<p>异步文件应放在受保护的位置，设置过期时间和下载权限。订单 CSV 包含客户信息，不能直接放到公开的 <code>pub/media</code> 路径。</p>
<p>短期处理可以用日期筛选和分批导出；长期方案应把大数据导出从同步后台请求中移走。单纯提高 memory_limit 和超时时间，无法解决数据库和并发压力。</p>]]></description>
      <pubDate>Wed, 24 Apr 2024 02:51:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 邮件模板变量不显示，问题通常出在哪里？]]></title>
      <link>https://www.360magento.com/blog/magento-2-email-template-variables-not-rendering/</link>
      <description><![CDATA[<p>邮件已经发送成功，但模板里的订单号、客户名称或自定义内容是空白，这类问题通常与 SMTP 无关。传输链路已经工作，接下来要看模板写了什么变量，以及发送代码实际传入了什么。</p>
<h2>先确认变量名称</h2>
<p>模板中写 <code>{{var order.increment_id}}</code>，前提是发送时确实存在名为 <code>order</code> 的对象，并且模板系统允许访问对应数据。变量名大小写或层级不一致，通常不会报明显异常，只会渲染为空。</p>
<p>后台邮件模板页面会显示可用变量信息，但自定义模块新增的变量仍需在代码和模板之间保持一致。</p>
<h2>自定义邮件的传值示例</h2>
<pre><code>$transport = $this-&gt;transportBuilder
    -&gt;setTemplateIdentifier($templateId)
    -&gt;setTemplateOptions([
        'area' =&gt; \Magento\Framework\App\Area::AREA_FRONTEND,
        'store' =&gt; $storeId,
    ])
    -&gt;setTemplateVars([
        'customer_name' =&gt; $customerName,
        'order_number' =&gt; $order-&gt;getIncrementId(),
        'support_note' =&gt; $supportNote,
    ])
    -&gt;setFromByScope('general', $storeId)
    -&gt;addTo($recipient)
    -&gt;getTransport();
$transport-&gt;sendMessage();</code></pre>
<p>对应模板应使用 <code>{{var customer_name}}</code>、<code>{{var order_number}}</code> 和 <code>{{var support_note}}</code>，而不是继续按订单对象的写法读取。</p>
<h2>对象、数组和标量不要混用</h2>
<p>如果代码把 <code>order_number</code> 作为字符串传入，模板就不能写成 <code>order_number.increment_id</code>。反过来，传入对象时也要确认模板安全规则允许访问目标字段。最稳妥的方式是只传模板真正需要的标量值，减少对象暴露。</p>
<h2>Store View 也会让测试产生误判</h2>
<p>邮件模板可按 Store View 配置。你修改了中文模板，但测试订单属于英文 Store View，收到的仍可能是另一份模板。记录订单的 <code>store_id</code>，并检查发送代码中的 template options。</p>
<h2>一个实用的调试方法</h2>
<p>在测试环境记录变量键名和非敏感值类型，例如字符串、整数或对象类名，不要把客户地址、Token 或完整订单内容写进日志。确认键名到达 TransportBuilder 后，再回头检查模板。</p>
<p>邮件变量问题修好后，用游客订单、注册客户订单和不同 Store View 各发一封。三封邮件的模板和变量都正确，才说明不是偶然命中了默认范围。</p>]]></description>
      <pubDate>Tue, 23 Apr 2024 06:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何禁止搜索引擎收录筛选参数页面？]]></title>
      <link>https://www.360magento.com/blog/magento-2-prevent-indexing-filter-parameter-pages/</link>
      <description><![CDATA[<p>Magento 2 分类页启用分层导航后，一个分类可能产生颜色、尺码、价格、排序和分页的多种 URL 组合。全部开放收录会造成重复内容和抓取浪费，但简单在 robots.txt 中屏蔽所有带问号的 URL，也可能影响搜索引擎理解页面。</p>
<h2>先决定哪些筛选页值得保留</h2>
<p>并不是所有筛选页都没有价值。&ldquo;女士黑色连衣裙&rdquo;如果有独立搜索需求、稳定商品集合和可编辑内容，可以做成落地页；临时排序、每页数量、价格滑块通常不值得收录。先按业务价值分组，再制定规则。</p>
<h2>canonical 是主要信号</h2>
<p>普通筛选参数页通常应把 canonical 指向无参数的分类规范 URL。检查主题或 SEO 扩展生成的标签，不能让 canonical 指向当前参数页，也不要所有分类都指向首页。</p>
<p>如果某个筛选组合被做成正式落地页，它应有自己的稳定 URL、标题和 canonical，而不是继续依赖多个参数顺序。</p>
<h2>robots 的作用不同</h2>
<p><code>noindex,follow</code> 用于告诉搜索引擎不收录当前页面但可继续发现链接；robots.txt 的 Disallow 阻止抓取，搜索引擎可能无法看到页面里的 noindex 和 canonical。两者不是可以随意互换的开关。</p>
<p>Magento 原生对复杂分层导航的 SEO 控制有限，很多项目会通过主题布局或专门模块按参数类型输出 robots。实现时要避免把正常分类、搜索结果或分页误伤。</p>
<h2>内部链接和 Sitemap</h2>
<ul>
<li>导航中的参数链接不要无限组合。</li>
<li>排序和每页数量链接无需加入 Sitemap。</li>
<li>XML Sitemap 只保留希望收录的规范分类和落地页。</li>
<li>站内推荐链接统一使用规范 URL。</li>
</ul>
<h2>上线前抽样</h2>
<p>选择一个分类，测试无参数、单一颜色、颜色加价格、排序和分页五种 URL。查看状态码、robots、canonical 和页面内容，再检查爬虫日志是否仍在大量访问无价值组合。</p>
<p>参数治理不是一次性封禁。分类属性和 SEO 策略变化后，应定期重新看搜索引擎抓取报告，防止新的属性参数重新制造 URL 膨胀。</p>]]></description>
      <pubDate>Tue, 23 Apr 2024 01:44:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么 Magento 2 库存有货却显示缺货？]]></title>
      <link>https://www.360magento.com/blog/magento-2-in-stock-but-shows-out-of-stock/</link>
      <description><![CDATA[<p>后台看到 Quantity 大于 0，并不代表商品一定可销售。启用 Multi-Source Inventory 后，前台判断使用的是 Salable Quantity，它会综合 Source 数量、Stock 与销售渠道关系、缺货阈值和未结算预留。</p>
<h2>先回答一个问题：你看到的是哪种数量？</h2>
<p><strong>Quantity</strong> 是来源中的实际数量；<strong>Salable Quantity</strong> 是当前 Stock 还能承诺销售的数量。订单创建后会产生 reservation，抵扣可售数量，但来源数量通常在发货环节才扣减。因此两者短时间不一致是设计行为。</p>
<h2>商品只有一个来源也要检查 MSI</h2>
<p>确认商品已分配到启用的 Source，Source 状态为启用，数量大于阈值。然后检查该 Source 是否属于正确的 Stock，以及 Stock 是否分配给当前 Website。</p>
<pre><code>bin/magento inventory:reservation:list-inconsistencies</code></pre>
<p>这个命令用于列出预留不一致，不会自动修复。先阅读输出并核对订单状态，再考虑补偿操作，避免人为制造新的库存偏差。</p>
<h2>缺货阈值会改变结果</h2>
<p>如果 Out-of-Stock Threshold 设为 5，而数量只有 3，即使后台显示正数，商品也可能不可售。允许延期交货时，阈值还可能使用负数。不要只查看商品级配置，还要看它是否继承全局库存设置。</p>
<h2>可配置商品需要看子商品</h2>
<p>父商品没有可售子项时会显示缺货。检查每个子商品的状态、网站分配、Source、可售数量以及可配置属性组合。只给父商品增加数量不会解决子商品不可售的问题。</p>
<h2>索引和消费者</h2>
<pre><code>bin/magento indexer:status inventory
bin/magento indexer:reindex inventory
bin/magento cache:clean full_page</code></pre>
<p>实际索引器名称以 <code>bin/magento indexer:info</code> 输出为准。手动重建后如果下一次库存变化又不同步，继续检查 Cron 和消息消费者，而不是把 reindex 设为人工日常操作。</p>
<p>处理这类问题时，最好选一个具体 SKU，记录 Source Quantity、Salable Quantity、Stock、Website 和 reservations。把这五项放在一起看，通常比反复切换&ldquo;有货/缺货&rdquo;状态更快找到原因。</p>]]></description>
      <pubDate>Mon, 22 Apr 2024 08:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 产品导入失败：常见 CSV 错误一次说清]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-import-csv-errors/</link>
      <description><![CDATA[<p>产品 CSV 导入失败，经常不是&ldquo;文件格式不对&rdquo;这么简单。同一份文件可能通过文件检查，却在真正导入时因为属性选项、图片路径或关联商品数据失败。处理时最好保留 Magento 导出的样例文件，不要完全靠手工猜表头。</p>
<h2>看到这些提示时，先查什么</h2>
<p><strong>Column names have duplicates</strong><br />表头存在重复列，或不可见字符让两个字段看起来相同。用纯文本编辑器检查第一行，并确认文件编码为 UTF-8。</p>
<p><strong>Invalid value for Attribute Set</strong><br />CSV 中的 <code>attribute_set_code</code> 必须与后台属性集名称匹配。多余空格和大小写差异也可能造成失败。</p>
<p><strong>Value for option does not exist</strong><br />下拉、多选、颜色等属性的选项不存在。先在后台创建选项，或确认导入功能是否允许自动创建。多语言 Store View 的选项标签不要与默认范围混用。</p>
<h2>图片列是另一个高发点</h2>
<p>导入图片前，把文件放到配置允许的导入目录，并在 CSV 中填写正确的相对路径。Linux 区分大小写，<code>Image.jpg</code> 和 <code>image.jpg</code> 是两个文件。</p>
<p>常用图片列包括 <code>base_image</code>、<code>small_image</code>、<code>thumbnail_image</code> 和 <code>additional_images</code>。图片文件损坏或 PHP 缺少图像扩展，也会在处理阶段报错。</p>
<h2>新增、更新和替换不要选错</h2>
<ul>
<li>新增/更新：适合日常维护，已存在 SKU 会更新。</li>
<li>替换：可能用导入数据替换现有实体，风险更高。</li>
<li>删除：按 SKU 删除商品，不适合用来&ldquo;清理失败数据&rdquo;。</li>
</ul>
<p>第一次导入应先用 5&ndash;10 个商品在预发布环境测试。把简单商品跑通后，再处理可配置商品与子商品关联。</p>
<h2>多选字段与分隔符</h2>
<p>CSV 自身使用逗号分列，而多选属性和附加图片又需要内部多值分隔符。后台导入页面设置的 Multiple Value Separator 必须与文件一致，否则一串值会被当成一个不存在的选项。</p>
<h2>导入成功以后</h2>
<p>不要马上把文件扩大到几万行。先检查商品网站分配、状态、可见性、价格、库存和图片，再观察索引与 Cron 是否正常。若大文件超时，优先分批导入并检查 PHP、Web 服务器的上传与执行限制，而不是不断提高到无限值。</p>]]></description>
      <pubDate>Mon, 22 Apr 2024 02:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何修改订单号前缀？先了解 Sequence 表]]></title>
      <link>https://www.360magento.com/blog/magento-2-change-order-number-prefix-sequence-table/</link>
      <description><![CDATA[<p>Magento 2 的订单号不是简单地把 <code>sales_order.entity_id</code> 显示出来。订单、发票、发货和退款单分别使用销售序列生成编号，因此修改订单号前缀之前，要先确认目标 Store 和实体类型。</p>
<h2>订单号是怎样生成的</h2>
<p><code>sales_sequence_meta</code> 记录实体类型、Store ID 与具体序列表的关系；<code>sales_sequence_profile</code> 保存前缀、后缀、起始值和步长。真正递增的数字位于对应的 <code>sequence_order_*</code> 表。</p>
<pre><code>SELECT meta.meta_id, meta.entity_type, meta.store_id, meta.sequence_table,
       profile.prefix, profile.suffix, profile.start_value, profile.step
FROM sales_sequence_meta AS meta
JOIN sales_sequence_profile AS profile ON profile.meta_id = meta.meta_id
WHERE meta.entity_type = 'order'
ORDER BY meta.store_id;</code></pre>
<p>先执行查询，确认目标 Store ID。多商店项目最常见的错误，是修改了默认商店的 profile，却在另一个 Store 下测试。</p>
<h2>修改前缀</h2>
<p>假设已确认目标 profile ID，可以在维护窗口内更新前缀：</p>
<pre><code>UPDATE sales_sequence_profile
SET prefix = 'CN-'
WHERE profile_id = 3;</code></pre>
<p>示例中的 ID 只是说明，不能直接复制到生产库。操作前应备份数据库，并保留原值。前缀长度还要符合数据库字段和外部 ERP、支付、物流系统的订单号格式限制。</p>
<h2>不要用这种方式重置历史订单</h2>
<p>Sequence 只负责生成新编号。修改 profile 不会重写已有订单，也不应该批量修改 <code>increment_id</code>。订单号可能被支付记录、发票、邮件和外部系统引用，重写历史数据会破坏关联。</p>
<h2>关于起始数字</h2>
<p>若业务要求从新的数字区间开始，应先理解对应序列表和 <code>start_value</code> 的计算方式，并在没有下单并发的维护窗口实施。直接修改 AUTO_INCREMENT 可能与已有编号冲突。</p>
<p>完成后创建一笔测试订单，并同时检查订单、发票和发货编号。通常只需要改变订单前缀时，不要顺手修改其他实体的序列。把本次 Store ID、profile ID、修改前后值记录到发布单中，后续排查会容易很多。</p>]]></description>
      <pubDate>Fri, 19 Apr 2024 07:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 出现 503 Service Unavailable 如何排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-503-service-unavailable-troubleshooting/</link>
      <description><![CDATA[<p>Magento 2 返回 503 时，最容易做错的事情是反复清缓存。503 表示当前服务暂时不能处理请求，真正原因可能发生在 Magento 启动之前。先观察页面长什么样：如果是 Magento 自带的维护提示，和 Nginx、CDN 或负载均衡器生成的 503，处理方向完全不同。</p>
<h2>先看是不是维护模式</h2>
<pre><code>bin/magento maintenance:status
ls -la var/.maintenance.flag</code></pre>
<p>发布中断后，维护标记可能没有被关闭。确认部署已经完成、数据库升级和静态文件都正常后，再执行：</p>
<pre><code>bin/magento maintenance:disable</code></pre>
<p>不要只删除标记文件就立即开放流量。如果编译或数据库升级只完成了一半，前台恢复后会出现更难定位的错误。</p>
<h2>如果 503 不是 Magento 页面</h2>
<p>查看响应头和服务器错误日志。Nginx 常见记录包括 upstream timed out、connection refused 和 no live upstreams。它们分别指向 PHP 执行超时、PHP-FPM 未监听、或上游节点全部不可用。</p>
<pre><code>systemctl status php-fpm
ss -lntp | grep php
tail -n 100 /var/log/nginx/error.log</code></pre>
<p>实际服务名称与日志路径取决于系统版本，不要照抄后直接重启未知服务。</p>
<h2>一次资源耗尽导致的 503</h2>
<p>如果故障只在活动高峰出现，要同时查看 CPU、内存、磁盘和 PHP-FPM 队列。磁盘空间或 inode 用尽时，Session、缓存和日志都可能无法写入。</p>
<pre><code>uptime
free -m
df -h
df -i</code></pre>
<p>PHP-FPM 的 <code>pm.max_children</code> 太小会让请求排队，设置过大又可能耗尽内存。调整前先根据单个 PHP 进程内存和机器容量估算，而不是盲目加倍。</p>
<h2>有 CDN 或负载均衡时</h2>
<p>源站正常但公开域名仍 503，检查健康检查路径、超时时间和节点状态。健康检查不应依赖结账、搜索等重接口，也不能被维护规则错误拦截。</p>
<p>恢复服务后，保留故障时段的 Nginx、PHP-FPM、Magento 和系统指标。503 已消失不代表问题解决；如果根因是进程数、慢接口或磁盘持续增长，它还会再次出现。</p>]]></description>
      <pubDate>Fri, 19 Apr 2024 01:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何设置商品价格规则？完整操作步骤]]></title>
      <link>https://www.360magento.com/blog/magento-2-configure-catalog-price-rule/</link>
      <description><![CDATA[<p>商品价格规则适合在商品进入购物车前直接显示促销价格，例如某个分类九折、会员专属价或指定品牌活动。它与购物车价格规则不同：前者影响商品展示价格，后者在购物车和结账阶段计算优惠。</p>
<h2>1. 新建规则</h2>
<p>进入商品价格规则，新建规则并填写名称、说明、启用状态、网站、客户组、开始日期和结束日期。日期应结合商店时区确认，避免活动提前或延后生效。</p>
<h2>2. 设置商品条件</h2>
<p>Conditions 可以按分类、SKU、属性集或允许用于促销规则的商品属性筛选。自定义属性如果没有出现在条件列表中，需要检查该属性是否启用了促销规则条件。</p>
<p>组合条件时注意 ALL 和 ANY：</p>
<ul>
<li>ALL：所有子条件都满足。</li>
<li>ANY：满足任意一个子条件。</li>
</ul>
<h2>3. 设置折扣动作</h2>
<p>常见动作包括：</p>
<ul>
<li>按原价百分比折扣，例如减 10%。</li>
<li>按固定金额折扣，例如减 50 元。</li>
<li>设置为原价的百分比。</li>
<li>设置为固定价格。</li>
</ul>
<p>要分清&ldquo;减去 20%&rdquo;与&ldquo;设置为原价的 20%&rdquo;，配置错误可能导致价格远低于预期。</p>
<h2>4. 优先级和后续规则</h2>
<p>多个商品价格规则同时匹配时，Priority 决定处理顺序。设置是否停止后续规则处理，避免多个折扣意外叠加。促销规则要有统一的优先级规划，不能所有规则都使用相同值。</p>
<h2>5. 保存并应用</h2>
<p>保存规则后按后台提示应用规则，并确保相关索引和 Cron 正常：</p>
<pre><code>bin/magento indexer:status catalogrule_rule catalogrule_product
bin/magento indexer:reindex catalogrule_rule catalogrule_product
bin/magento cache:clean full_page block_html</code></pre>
<p>索引器名称会因版本和模块状态略有差异，执行前可使用 <code>bin/magento indexer:info</code> 查看当前实例。</p>
<h2>6. 特价和规则价的关系</h2>
<p>商品 Special Price、Tier Price、Group Price 与 Catalog Price Rule 可能同时存在。Magento 会根据价格模型选择最终价格，不应只看后台规则折扣值。测试时要包含已有特价商品。</p>
<h2>验证清单</h2>
<ol>
<li>目标和非目标商品的列表页价格。</li>
<li>商品详情页、搜索页和小购物车价格。</li>
<li>不同客户组和网站。</li>
<li>活动开始与结束日期。</li>
<li>含特价、阶梯价和可配置商品。</li>
<li>加入购物车后的单价与前台显示一致。</li>
</ol>
<p>规则上线后还应抽查实际订单，确认展示价格、购物车价格和订单价格完全一致。</p>]]></description>
      <pubDate>Thu, 18 Apr 2024 07:27:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何解决 Magento 2 客户登录后跳回登录页的问题？]]></title>
      <link>https://www.360magento.com/blog/solve-magento-2-customer-login-redirects-back-login/</link>
      <description><![CDATA[<p>Magento 2 客户登录后又回到登录页，通常说明认证请求完成了，但浏览器没有保存有效 Session，或者下一次请求无法读取同一个 Session。应从浏览器 Cookie、Base URL 和 Session 存储开始排查。</p>
<h2>1. 观察登录请求</h2>
<p>打开浏览器 Network，提交登录表单，检查响应状态、跳转地址和 <code>Set-Cookie</code>。如果返回 302 后又立刻跳回登录页，比较登录前后的 Session Cookie 是否发生变化。</p>
<p>不要把完整 Cookie 值复制到日志或工单，它属于敏感认证数据。</p>
<h2>2. 检查 Base URL 和 HTTPS</h2>
<pre><code>bin/magento config:show web/unsecure/base_url
bin/magento config:show web/secure/base_url
bin/magento config:show web/secure/use_in_frontend
bin/magento config:show web/cookie/cookie_domain
bin/magento config:show web/cookie/cookie_path</code></pre>
<p>Cookie 域必须与实际访问域名匹配。代理层终止 HTTPS 时，还要保证 Magento 能正确识别原始协议，否则 Secure Cookie 可能无法按预期工作。</p>
<h2>3. 清理浏览器旧 Cookie</h2>
<p>修改域名、HTTPS 或 Cookie 设置后，旧 Cookie 可能仍然干扰登录。使用无痕窗口做对照，再删除该站点旧 Cookie。不要让用户先清理全部浏览器数据。</p>
<h2>4. 检查 Session 存储</h2>
<p>如果 Session 使用 Redis，检查连接、数据库编号、内存淘汰和多节点配置。负载均衡环境中的所有 Web 节点必须访问同一 Session 存储，或者正确配置粘性会话。</p>
<pre><code>bin/magento cache:status
redis-cli -h redis INFO clients
redis-cli -h redis INFO memory</code></pre>
<h2>5. 自定义登录逻辑</h2>
<p>登录 Plugin、Observer、验证码、社交登录和客户审批扩展都可能改变跳转或 Session。检查最近上线的模块，并在测试环境做禁用对照。自定义跳转 URL 必须属于允许域名，不能形成循环。</p>
<h2>6. Session 生命周期</h2>
<p>服务器时间不一致、Session 生命周期过短、Redis 提前淘汰或 PHP 配置冲突都会让会话立即失效。对比 Web 节点时间、Magento Session 配置和 Redis 中键的 TTL。</p>
<h2>验证场景</h2>
<ul>
<li>游客登录普通客户账号。</li>
<li>不同浏览器和移动端。</li>
<li>HTTP 自动跳 HTTPS。</li>
<li>带 www 与不带 www 的域名。</li>
<li>多 Store View 切换。</li>
<li>登录后进入账户页、购物车和结账页。</li>
</ul>
<p>修复后要确认 Session 在多个连续请求中保持稳定，而不仅是登录页面出现一次成功提示。</p>]]></description>
      <pubDate>Thu, 18 Apr 2024 01:49:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何开启生产模式？部署前后检查步骤]]></title>
      <link>https://www.360magento.com/blog/magento-2-enable-production-mode-deployment-checklist/</link>
      <description><![CDATA[<p>Magento 2 生产模式会关闭按需生成部分代码和静态资源，适合正式站点，但切换过程会触发编译和部署。不能在未准备静态文件和回滚方案时直接执行。</p>
<h2>部署前检查</h2>
<pre><code>bin/magento deploy:mode:show
bin/magento module:status
bin/magento setup:db:status
df -h</code></pre>
<p>确认代码版本、Composer 依赖、数据库状态、磁盘空间和 PHP CLI 版本。备份 <code>app/etc/env.php</code>、<code>config.php</code> 与数据库，并记录当前可回滚版本。</p>
<h2>进入维护模式</h2>
<pre><code>bin/magento maintenance:enable</code></pre>
<p>有负载均衡时，要确保所有节点使用一致的维护和发布策略。仅在一个节点执行、其他节点继续提供旧代码，可能造成版本混用。</p>
<h2>执行数据库升级和编译</h2>
<pre><code>bin/magento setup:upgrade --keep-generated
bin/magento setup:di:compile</code></pre>
<p>编译失败时从第一个异常处理，常见原因是构造函数依赖错误、生成代理冲突或扩展与 PHP 版本不兼容。不要删除错误信息后继续上线。</p>
<h2>部署静态内容</h2>
<pre><code>bin/magento setup:static-content:deploy zh_Hans_CN en_US</code></pre>
<p>参数应包含实际启用的 area、主题和 locale。多节点站点要保证每个节点读取相同版本的静态资源。</p>
<h2>切换生产模式</h2>
<pre><code>bin/magento deploy:mode:set production --skip-compilation
bin/magento cache:clean
bin/magento maintenance:disable</code></pre>
<p>因为前面已经完成编译，所以可跳过重复编译。不同版本的命令参数可能有差异，执行前先查看 <code>--help</code>。</p>
<h2>权限检查</h2>
<p>部署用户、Web 用户和 Cron 用户应按项目策略共享必要用户组。不要使用 777。确认 <code>var</code>、<code>generated</code>、<code>pub/static</code> 和 <code>pub/media</code> 的读写边界正确。</p>
<h2>上线后验证</h2>
<ul>
<li>首页、分类、商品、搜索和结账正常。</li>
<li>后台可以登录并保存配置。</li>
<li>静态文件和媒体没有 404。</li>
<li>Cron、消费者和索引器正常运行。</li>
<li>PHP、Magento、Web 服务器日志没有新异常。</li>
<li>缓存能够命中，页面响应时间恢复稳定。</li>
</ul>
<p>生产模式切换成功只是部署的一部分。只有业务页面、后台任务和监控全部正常，发布才算完成。</p>]]></description>
      <pubDate>Wed, 17 Apr 2024 09:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 分类页面不收录如何优化？]]></title>
      <link>https://www.360magento.com/blog/magento-2-category-page-not-indexed-seo-optimization/</link>
      <description><![CDATA[<p>Magento 2 分类页面长期不被搜索引擎收录，原因可能是页面不可抓取、canonical 指向错误、内容重复、站点地图缺失或页面质量不足。先检查技术信号，再考虑内容优化。</p>
<h2>确认页面返回 200</h2>
<p>使用未登录状态访问分类 URL，检查最终状态码和跳转链。页面如果返回软 404、循环重定向或需要 Cookie 才能访问，搜索引擎很难稳定收录。</p>
<h2>检查 robots 设置</h2>
<p>后台的默认 Robots 配置应符合当前环境。生产站点误保留 <code>NOINDEX,NOFOLLOW</code> 是常见问题。还要检查主题布局或 SEO 扩展是否为单个分类输出了额外 robots 标签。</p>
<p>robots.txt 不应屏蔽分类页面需要的 CSS 和 JavaScript，也不要简单屏蔽所有带查询参数的 URL，而应先分析筛选导航策略。</p>
<h2>检查 canonical</h2>
<p>分类页面 canonical 应指向希望收录的规范 URL。如果所有分类都错误指向首页，搜索引擎会把分类视为重复页面。多 Store View 还要确认域名、Store Code 和语言版本的 canonical 不串站。</p>
<h2>站点地图</h2>
<p>在后台生成并提交 XML Sitemap，确认目标分类 URL 实际存在于 Sitemap 中，且 URL 可公开访问。Sitemap 只用于发现，不会保证收录。</p>
<h2>筛选和分页</h2>
<p>分层导航可能生成大量颜色、价格和排序参数组合。需要确定哪些组合值得收录，其他组合通过 canonical、robots 或路由策略控制。不能一概把所有参数页开放，也不能把所有分页都指向第一页而忽略内容差异。</p>
<h2>分类页面内容</h2>
<ul>
<li>使用独立、清晰的分类名称和 Meta Title。</li>
<li>添加对用户有帮助的分类说明，不堆砌关键词。</li>
<li>保证分类中有可购买商品，不长期显示空列表。</li>
<li>优化加载速度和移动端体验。</li>
<li>从首页、导航和相关内容页提供内部链接。</li>
</ul>
<h2>Magento 配置检查</h2>
<pre><code>bin/magento config:show design/search_engine_robots/default_robots
bin/magento cache:clean config full_page</code></pre>
<p>配置路径和取值可能受 Store View 范围覆盖，CLI 检查后仍需在后台对应范围核对。</p>
<h2>验证</h2>
<ol>
<li>查看页面源码中的 title、robots 和 canonical。</li>
<li>确认状态码为 200，且没有多余跳转。</li>
<li>确认 Sitemap 和站内链接都使用规范 URL。</li>
<li>抽查带筛选和排序参数的页面。</li>
<li>修改后等待搜索引擎重新抓取，观察覆盖率与日志。</li>
</ol>]]></description>
      <pubDate>Wed, 17 Apr 2024 03:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 优惠券无法使用的常见原因与解决方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-coupon-code-not-working-reasons-solutions/</link>
      <description><![CDATA[<p>Magento 2 输入优惠券后提示无效，通常不是代码故障，而是购物车价格规则的某个范围或条件没有满足。排查时应使用具体购物车复现，不要只看规则名称和优惠码。</p>
<h2>规则是否真正可用</h2>
<ul>
<li>状态为启用。</li>
<li>当前日期位于生效和结束日期之间。</li>
<li>选择了当前网站。</li>
<li>包含当前客户组；游客属于 NOT LOGGED IN。</li>
<li>Coupon 选项与实际使用方式一致。</li>
<li>优惠码没有多余空格，大小写按当前系统行为测试。</li>
</ul>
<h2>检查使用次数</h2>
<p>规则可能设置每张优惠券使用次数、每位客户使用次数和规则总次数。订单取消是否返还次数取决于业务流程和扩展实现，不能假设取消后一定立即恢复。</p>
<p>可在后台查看优惠券报告或规则数据。不要直接修改计数表来&ldquo;恢复&rdquo;优惠券，否则可能造成审计和并发问题。</p>
<h2>条件没有匹配</h2>
<p>常见条件包括小计、商品属性、分类、SKU、配送国家和付款方式。需要注意：</p>
<ul>
<li>商品属于子分类不一定自动满足父分类条件。</li>
<li>可配置商品条件可能匹配父商品或子商品，取决于属性位置。</li>
<li>小计可能是折扣前、折扣后、含税或不含税口径。</li>
<li>条件组合中的 ALL 与 ANY 会改变匹配逻辑。</li>
</ul>
<h2>规则优先级和停止处理</h2>
<p>更高优先级的规则如果启用了&ldquo;停止后续规则处理&rdquo;，后面的优惠券可能不会执行。给相关规则设置清晰的 Priority，并测试多个规则同时存在的情况。</p>
<h2>前端提示不等于后端没有应用</h2>
<p>自定义主题或结账扩展可能没有刷新 totals，导致页面仍显示原金额。打开浏览器 Network，检查 coupon API 和 totals 响应；最终以后端 totals segment 为准。</p>
<h2>缓存处理</h2>
<pre><code>bin/magento cache:clean config full_page</code></pre>
<p>保存规则后如仍不生效，先重新加载一个全新的购物车，避免旧 Session 中保存的地址、客户组或报价状态影响测试。</p>
<h2>验证清单</h2>
<ol>
<li>创建低金额和达标金额两个购物车。</li>
<li>分别测试游客与目标客户组。</li>
<li>测试规则单独启用和与其他规则共同启用。</li>
<li>检查购物车、结账页、订单和邮件中的折扣金额。</li>
<li>达到使用次数后确认优惠券按预期失效。</li>
</ol>]]></description>
      <pubDate>Tue, 16 Apr 2024 06:55:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 满额包邮如何设置？购物车规则配置方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-free-shipping-over-amount-cart-rule/</link>
      <description><![CDATA[<p>Magento 2 的满额包邮可以通过购物车价格规则实现。配置重点不只是输入金额，还要明确使用折扣前还是折扣后小计、哪些商品参与、适用的配送方式和客户组。</p>
<h2>1. 创建购物车价格规则</h2>
<p>在后台进入购物车价格规则，新建规则并填写名称、启用状态、网站、客户组和生效日期。如果所有符合条件的购物车都自动包邮，优惠券选项选择&ldquo;不使用优惠券&rdquo;。</p>
<h2>2. 设置金额条件</h2>
<p>在 Conditions 中选择购物车属性，例如 Subtotal 大于等于指定金额。若商店含税、折扣或多币种配置复杂，应先确认后台条件使用的金额口径，避免用户看到的合计已经达标但规则没有触发。</p>
<h2>3. 设置免运费动作</h2>
<p>在 Actions 中将 Free Shipping 设置为适当范围：</p>
<ul>
<li>For shipment with matching items：只要符合条件的商品在配送中，即可影响该配送。</li>
<li>For matching items only：仅匹配商品享受免运费，适合部分商品活动。</li>
</ul>
<p>不同版本后台文字可能略有差异，应以当前系统字段说明为准。</p>
<h2>4. 配送方式也要支持</h2>
<p>购物车规则标记免运费后，还要确保 Free Shipping 配送方式已在当前网站范围启用，或当前承运方式能正确处理 free shipping 标记。检查最低订单金额、适用国家和错误提示。</p>
<h2>5. 控制规则叠加</h2>
<p>如果站点还有优惠券或会员折扣，设置规则优先级，并决定是否停止后续规则处理。两个规则同时修改运费时，顺序不明确容易造成前台显示和订单金额不一致。</p>
<h2>6. 缓存和索引</h2>
<pre><code>bin/magento cache:clean config full_page</code></pre>
<p>购物车价格规则保存后通常不需要全量重建所有索引。若规则未生效，先检查网站、客户组、日期和条件，不要先执行全部 reindex。</p>
<h2>测试场景</h2>
<ul>
<li>金额刚好低于、等于和高于门槛。</li>
<li>登录客户与游客。</li>
<li>含税和不含税显示。</li>
<li>使用优惠券前后。</li>
<li>多地址结账。</li>
<li>不同国家、配送方式和币种。</li>
<li>购物车中包含不参与活动的商品。</li>
</ul>
<p>测试时以最终订单的 shipping amount 为准，同时确认购物车、结账页、订单邮件和后台订单金额一致。</p>]]></description>
      <pubDate>Tue, 16 Apr 2024 01:37:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何创建多语言商店？详细配置步骤]]></title>
      <link>https://www.360magento.com/blog/magento-2-create-multi-language-store-step-by-step/</link>
      <description><![CDATA[<p>Magento 2 多语言通常通过 Store View 实现。同一个 Website 和 Store 下创建多个 Store View，可以共享商品与库存，同时分别维护商品名称、CMS 内容、Locale 和界面翻译。</p>
<h2>1. 规划层级</h2>
<ul>
<li>Website：价格、客户账户和结账范围的重要边界。</li>
<li>Store：通常对应根分类。</li>
<li>Store View：最适合语言和展示差异。</li>
</ul>
<p>如果只是中文和英文版本，不需要为了语言新建两个 Website。错误的层级会增加价格、库存和客户数据维护成本。</p>
<h2>2. 创建 Store View</h2>
<p>在后台进入商店管理，选择现有 Store，新建中文或英文 Store View，设置唯一 Code、名称、排序和启用状态。上线前可保持禁用，内容准备完成后再开启。</p>
<h2>3. 设置 Locale</h2>
<p>切换配置范围到目标 Store View，在常规区域设置 Locale、时区、重量单位和周起始日。取消&ldquo;使用网站&rdquo;继承后再保存。</p>
<pre><code>bin/magento config:show general/locale/code
bin/magento cache:clean config translate</code></pre>
<p>CLI 默认输出可能是默认范围值，核验时应同时在后台确认具体 Store View 范围。</p>
<h2>4. 安装语言包</h2>
<p>语言包必须与 Magento 版本和目标 Locale 匹配。安装后执行依赖安装和静态内容部署：</p>
<pre><code>bin/magento setup:static-content:deploy -f zh_Hans_CN en_US
bin/magento cache:clean translate full_page</code></pre>
<p>生产模式应通过正式发布流程执行，不能在访问高峰随意清理静态目录。</p>
<h2>5. 配置 URL</h2>
<p>可通过 URL 中的 Store Code 区分语言，也可以给每个 Store View 配置独立域名。选择后要保持一致，并正确设置 Base URL、Cookie 域和 HTTPS。避免同一内容同时通过多个可索引 URL 访问。</p>
<h2>6. 翻译内容</h2>
<p>商品名称、描述、分类名称和 CMS 页面要切换到对应 Store View 后填写。先取消继承，再保存翻译值。URL Key、Meta Title 和 Meta Description 也应按语言单独优化。</p>
<h2>7. 验证</h2>
<ol>
<li>切换语言后页面和 URL 正确。</li>
<li>购物车在语言切换后按预期保留。</li>
<li>货币、价格和税额没有被语言设置意外改变。</li>
<li>邮件模板使用订单所属 Store View 的语言。</li>
<li>搜索、Sitemap 和 canonical 指向正确语言版本。</li>
</ol>
<p>多语言上线前应逐个 Store View 检查首页、分类、商品、结账、客户账户和邮件，不能只验证首页翻译。</p>]]></description>
      <pubDate>Mon, 15 Apr 2024 08:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 日志文件太大如何自动清理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-log-files-too-large-auto-clean/</link>
      <description><![CDATA[<p>Magento 2 的 <code>var/log</code>、PHP-FPM 日志和 Web 服务器日志如果持续增长，可能最终占满磁盘。直接删除文件只能暂时释放空间，首先要确认是哪条错误在高频重复。</p>
<h2>找出增长最快的文件</h2>
<pre><code>du -h var/log/* | sort -h
tail -n 200 var/log/system.log
tail -n 200 var/log/exception.log</code></pre>
<p>观察同一异常是否每秒重复出现，并按时间与 Cron、消费者或外部接口任务对应。日志爆增常见原因包括失败任务无限重试、第三方 API 超时、索引异常和自定义代码在循环中记录 info。</p>
<h2>先修复日志源头</h2>
<p>不要简单关闭全部日志。应让重复任务设置退避和最大重试次数，避免在商品循环中为每条成功记录写日志，并为异常增加业务 ID 和关联 ID，而不是输出完整敏感数据。</p>
<h2>配置 logrotate</h2>
<p>可在服务器的 logrotate 配置中加入项目日志规则，具体路径和运行用户按部署环境调整：</p>
<pre><code>/var/www/magento/var/log/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}</code></pre>
<p><code>copytruncate</code> 适用于进程持续持有文件句柄、又无法主动重新打开日志的情况，但轮转瞬间可能有少量竞争。更可靠的方式是让日志进程收到信号后重新打开文件，需结合 PHP-FPM 和日志系统配置决定。</p>
<h2>先测试配置</h2>
<pre><code>logrotate -d /etc/logrotate.d/magento
logrotate -f /etc/logrotate.d/magento</code></pre>
<p>调试模式只检查计划；强制执行会真实轮转，应在确认路径和权限后使用。轮转后的文件所有者必须允许 Magento 继续写入。</p>
<h2>数据库和第三方日志</h2>
<p>有些 SMTP、导入或审计扩展把日志写入数据库。应查看扩展是否提供保留天数和 Cron 清理功能，不要在不了解关联关系时直接删除表记录。</p>
<h2>磁盘已经接近满时</h2>
<p>先确认占用来源，再压缩或移动明确可归档的旧日志。不要在生产服务器执行针对宽泛目录的递归删除命令。磁盘恢复后还要检查 MySQL、Redis 和搜索服务是否因空间不足进入只读或异常状态。</p>
<h2>验证</h2>
<ol>
<li>确认日志按天轮转并保留 14 份。</li>
<li>新日志文件的用户和权限正确。</li>
<li>压缩文件能够正常读取。</li>
<li>监控磁盘使用率和日志增长速度。</li>
<li>确认原始高频异常已经消失。</li>
</ol>]]></description>
      <pubDate>Mon, 15 Apr 2024 02:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何添加自定义商品属性？]]></title>
      <link>https://www.360magento.com/blog/magento-2-add-custom-product-attribute/</link>
      <description><![CDATA[<p>Magento 2 可以在后台创建商品属性，也可以通过模块 Data Patch 管理。需要在多个环境稳定部署时，推荐把属性定义写进代码，避免测试、预发布和生产环境配置不一致。</p>
<h2>创建 Data Patch</h2>
<p>文件：<code>app/code/Alwayly/CatalogSetup/Setup/Patch/Data/AddMaterialAttribute.php</code></p>
<pre><code>&lt;?php
declare(strict_types=1);
namespace Alwayly\CatalogSetup\Setup\Patch\Data;

use Magento\Catalog\Model\Product;
use Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

final class AddMaterialAttribute implements DataPatchInterface
{
    public function __construct(
        private readonly ModuleDataSetupInterface $moduleDataSetup,
        private readonly EavSetupFactory $eavSetupFactory
    ) {}

    public function apply(): self
    {
        $this-&gt;moduleDataSetup-&gt;getConnection()-&gt;startSetup();
        $eavSetup = $this-&gt;eavSetupFactory-&gt;create(['setup' =&gt; $this-&gt;moduleDataSetup]);
        $eavSetup-&gt;addAttribute(Product::ENTITY, 'alwayly_material', [
            'type' =&gt; 'varchar',
            'label' =&gt; 'Material',
            'input' =&gt; 'text',
            'required' =&gt; false,
            'sort_order' =&gt; 120,
            'global' =&gt; ScopedAttributeInterface::SCOPE_STORE,
            'visible' =&gt; true,
            'user_defined' =&gt; true,
            'searchable' =&gt; true,
            'filterable' =&gt; false,
            'comparable' =&gt; true,
            'visible_on_front' =&gt; true,
            'used_in_product_listing' =&gt; true
        ]);
        $this-&gt;moduleDataSetup-&gt;getConnection()-&gt;endSetup();
        return $this;
    }

    public static function getDependencies(): array { return []; }
    public function getAliases(): array { return []; }
}</code></pre>
<h2>选择正确的后端类型</h2>
<p>短文本通常使用 <code>varchar</code>，长文本使用 <code>text</code>，整数和选项值常用 <code>int</code>。类型一旦上线并产生数据，不应随意修改，否则可能造成数据迁移问题。</p>
<h2>属性作用范围</h2>
<ul>
<li>Global：所有网站和商店共用。</li>
<li>Website：同一网站下共用。</li>
<li>Store View：每个商店视图可单独设置。</li>
</ul>
<p>示例使用 Store View 范围，适合多语言材质名称。若只是内部编码，应使用 Global，避免重复维护。</p>
<h2>执行和检查</h2>
<pre><code>bin/magento setup:upgrade
bin/magento cache:clean config eav
bin/magento indexer:reindex catalog_product_attribute catalogsearch_fulltext</code></pre>
<p>运行后在后台打开属性集，确认新属性位于预期分组。部分项目需要在 Patch 中显式把属性加入指定属性集和属性组，不能假设所有自定义属性集都会自动出现。</p>
<h2>前台读取</h2>
<pre><code>$attribute = $product-&gt;getCustomAttribute('alwayly_material');
$value = $attribute ? (string)$attribute-&gt;getValue() : '';</code></pre>
<p>如果是下拉选项，前台通常需要读取选项文本，而不是直接输出 option ID。模板中还要进行正确的 HTML 转义。</p>
<h2>验证清单</h2>
<ol>
<li>简单、可配置和虚拟商品都能保存属性。</li>
<li>不同 store view 的值符合作用范围。</li>
<li>搜索与商品列表索引能读取新属性。</li>
<li>API 返回值符合预期。</li>
<li>重复执行 <code>setup:upgrade</code> 不会重复创建。</li>
</ol>]]></description>
      <pubDate>Fri, 12 Apr 2024 07:36:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何解决 Magento 2 Redis 连接失败问题？]]></title>
      <link>https://www.360magento.com/blog/solve-magento-2-redis-connection-failed/</link>
      <description><![CDATA[<p>Magento 2 使用 Redis 保存缓存或 Session 后，如果出现 <code>Connection refused</code>、<code>read error on connection</code>、页面 503 或后台频繁退出，应先确定故障发生在网络、认证还是 Redis 资源层，不要直接删除全部 Redis 数据。</p>
<h2>1. 确认 Redis 服务和端口</h2>
<pre><code>redis-cli -h 127.0.0.1 -p 6379 ping
ss -lntp | grep 6379
systemctl status redis</code></pre>
<p>正常情况下 <code>ping</code> 返回 <code>PONG</code>。如果 Magento 和 Redis 位于不同容器或服务器，<code>127.0.0.1</code> 指向的是当前容器，不一定是 Redis 主机。应使用部署环境提供的服务名称或内网地址。</p>
<h2>2. 检查 Magento 实际配置</h2>
<p>Redis 连接信息通常位于 <code>app/etc/env.php</code> 的 cache、page_cache 或 session 节点。三个用途可以使用不同数据库编号，避免清理缓存时误删 Session。</p>
<pre><code>'session' =&gt; [
    'save' =&gt; 'redis',
    'redis' =&gt; [
        'host' =&gt; 'redis',
        'port' =&gt; '6379',
        'database' =&gt; '2',
        'timeout' =&gt; '2.5'
    ]
]</code></pre>
<p>修改前先备份 <code>env.php</code>，并确认代码部署不会覆盖环境配置。密码、哨兵和 TLS 参数必须以当前 Magento 版本与基础设施的实际配置为准。</p>
<h2>3. 验证认证和数据库编号</h2>
<pre><code>redis-cli -h redis -p 6379 --user app ping
redis-cli -h redis -p 6379 INFO keyspace</code></pre>
<p>不要把真实密码直接写进命令历史。可以通过受保护的配置文件或安全的环境变量传递认证信息。若使用 Redis ACL，应确认用户允许访问所需命令和数据库。</p>
<h2>4. 检查内存与连接数</h2>
<pre><code>redis-cli -h redis INFO memory
redis-cli -h redis INFO clients
redis-cli -h redis INFO stats</code></pre>
<p>重点观察 <code>used_memory</code>、<code>maxmemory</code>、<code>connected_clients</code>、<code>blocked_clients</code> 和拒绝连接数量。Redis 达到内存上限后，不同淘汰策略会产生完全不同的表现；Session 数据不应使用可能随机淘汰关键会话的策略。</p>
<h2>5. 区分短暂故障和持续故障</h2>
<p>偶发 read error 可能来自网络抖动、Redis 重启、连接空闲超时或主从切换。持续 Connection refused 通常表示地址、端口、防火墙或服务状态错误。应按时间把 Magento 日志、Redis 日志和基础设施事件对应起来。</p>
<h2>修复后的验证</h2>
<ol>
<li>执行 <code>bin/magento cache:status</code>，确认 CLI 能连接。</li>
<li>连续访问前台和后台，确认 Session 不丢失。</li>
<li>清理一个 Magento 缓存类型，确认没有影响登录会话。</li>
<li>观察 Redis 内存、连接数和错误日志至少一个业务高峰。</li>
</ol>
<p>不要把重启 Redis 当作最终修复。只有找出连接失败的具体层级，并确认缓存和 Session 都稳定，问题才算解决。</p>]]></description>
      <pubDate>Fri, 12 Apr 2024 01:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 前台页面突然变成 404 怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-frontend-page-suddenly-404/</link>
      <description><![CDATA[<p>Magento 2 页面突然 404，第一步是判断 404 由 Web 服务器返回，还是请求已经进入 Magento 后由路由返回。两者页面样式、响应头和日志位置通常不同。</p>
<h2>确认影响范围</h2>
<ul>
<li>只有一个商品或分类 404：优先检查实体和 URL 重写。</li>
<li>所有前台页面 404，但静态文件正常：检查入口文件与 rewrite 规则。</li>
<li>只有某个 store view 404：检查 Base URL、store code 和网站绑定。</li>
<li>后台正常、前台全站异常：检查部署、维护模式和前端路由。</li>
</ul>
<h2>检查实体状态</h2>
<p>商品必须启用、分配到当前网站，并具有适合的可见性。分类需要启用且位于当前网站使用的根分类下。CMS 页面要启用，并分配到当前 store view。</p>
<h2>检查 URL 重写</h2>
<pre><code>SELECT url_rewrite_id, entity_type, entity_id, request_path,
       target_path, redirect_type, store_id
FROM url_rewrite
WHERE request_path = 'example-path.html';</code></pre>
<p>查询时使用不带域名和开头斜线的实际 request path，并匹配当前 store ID。如果没有记录，先检查实体 URL Key 和网站范围，不要手工插入一条未经验证的 target_path。</p>
<h2>Web 服务器规则</h2>
<p>Nginx 或 Apache 必须把不存在的物理路径交给 Magento 的入口处理。发布新配置后，可先做语法检查再 reload：</p>
<pre><code>nginx -t
# 通过后再由有权限的运维流程 reload</code></pre>
<p>不要直接复制其他项目的 Nginx 配置覆盖当前站点，尤其要保留媒体、静态文件、安全目录和 PHP 入口规则。</p>
<h2>检查 Base URL 与 Store</h2>
<pre><code>bin/magento config:show web/unsecure/base_url
bin/magento config:show web/secure/base_url
bin/magento config:show web/url/use_store</code></pre>
<p>代理层终止 HTTPS 时，还要确认转发协议头配置正确，否则可能产生错误跳转，看起来像 404。</p>
<h2>缓存不是第一原因</h2>
<p>路由或 URL 重写修复后，可精准清理配置和 Full Page Cache：</p>
<pre><code>bin/magento cache:clean config full_page</code></pre>
<p>单纯反复 flush 不会创建缺失的 URL 重写，也不能修复错误的 Web 服务器规则。</p>
<h2>验证</h2>
<ol>
<li>直接访问目标 URL，记录状态码和最终跳转地址。</li>
<li>确认同一页面在各 store view 的表现。</li>
<li>检查旧 URL 是否按预期 301，新 URL 是否返回 200。</li>
<li>抽查首页、分类、商品、CMS、静态文件和媒体文件。</li>
<li>再次保存测试实体，确认 URL 重写能自动维护。</li>
</ol>]]></description>
      <pubDate>Thu, 11 Apr 2024 07:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 URL 重写记录越来越多怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-url-rewrite-records-growing/</link>
      <description><![CDATA[<p><code>url_rewrite</code> 表记录商品、分类、CMS 和自定义路由。记录很多不一定是故障：多网站、多 store view、分类路径和历史重定向都会增加数量。应先找增长来源，再决定是否处理。</p>
<h2>先统计，不要直接清表</h2>
<pre><code>SELECT entity_type, store_id, redirect_type, COUNT(*) AS total
FROM url_rewrite
GROUP BY entity_type, store_id, redirect_type
ORDER BY total DESC;

SELECT DATE_FORMAT(created_at, '%Y-%m-%d') AS day, COUNT(*) AS total
FROM url_rewrite
GROUP BY day
ORDER BY day DESC
LIMIT 30;</code></pre>
<p>某些版本的表可能没有 <code>created_at</code>，执行前先使用 <code>DESCRIBE url_rewrite</code> 核对结构。</p>
<h2>检查重复模式</h2>
<pre><code>SELECT store_id, request_path, COUNT(*) AS total
FROM url_rewrite
GROUP BY store_id, request_path
HAVING COUNT(*) &gt; 1
ORDER BY total DESC;</code></pre>
<p>正常结构通常要求同一 store 下 request_path 唯一。若出现重复，应先确认索引和约束状态，再查第三方导入脚本是否绕过 Repository 直接写表。</p>
<h2>为什么会持续增长</h2>
<ul>
<li>商品 URL Key 经常变化，并开启创建永久重定向。</li>
<li>商品分配到大量分类，且配置生成分类路径。</li>
<li>导入任务每次都生成新的 URL Key。</li>
<li>第三方扩展重复创建自定义重写。</li>
<li>多语言 store view 为同一实体生成独立路径。</li>
</ul>
<h2>不要盲目删除 301</h2>
<p>历史重定向可能承接搜索引擎和外部链接。批量删除会造成 404 和 SEO 流量损失。应先导出候选记录，确认目标路径仍有效，并与站点日志中的访问情况对照。</p>
<h2>修复生成来源</h2>
<p>如果增长来自导入程序，确保只有 URL Key 实际变化时才保存商品，并避免循环保存同一实体。自定义 URL 重写应使用稳定的唯一标识和 request_path，写入前检查现有记录。</p>
<pre><code>// 伪代码：只有新旧 URL key 不同时才提交变更
if ($oldUrlKey !== $newUrlKey) {
    $product-&gt;setUrlKey($newUrlKey);
    $productRepository-&gt;save($product);
}</code></pre>
<h2>处理前后的验证</h2>
<ol>
<li>备份数据库并记录各类重写数量。</li>
<li>在预发布环境复现清理方案。</li>
<li>检查主要商品、分类和 CMS URL。</li>
<li>抽查旧 URL 是否仍正确 301 到新地址。</li>
<li>运行一轮商品导入，确认记录不再异常增长。</li>
</ol>
<p>真正的解决方案是停止重复生成，而不是定期把 <code>url_rewrite</code> 清空。</p>]]></description>
      <pubDate>Thu, 11 Apr 2024 01:41:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 结账页面一直转圈怎么排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-checkout-loading-forever/</link>
      <description><![CDATA[<p>结账页面一直转圈时，最有效的入口不是清缓存，而是浏览器 Console 和 Network。加载动画只是结果，真正错误通常发生在静态资源、checkout 配置、购物车 totals、配送地址或支付接口。</p>
<h2>先看第一个失败请求</h2>
<p>打开无痕窗口进入结账页，在 Network 中筛选 4xx、5xx 和长时间 pending 的请求。常见目标包括 totals-information、shipping-information、payment-information 以及客户地址相关接口。</p>
<p>点击失败请求，记录 URL、状态码和响应中的错误类型。不要把客户姓名、地址、Token 或支付数据复制到公共工单。</p>
<h2>检查 Console</h2>
<p>常见前端原因包括 Knockout binding 错误、mixin 返回值不正确、RequireJS 模块路径错误，以及第三方支付组件初始化异常。开启开发者模式只适合测试环境：</p>
<pre><code>bin/magento deploy:mode:show
bin/magento cache:clean config layout block_html full_page</code></pre>
<p>不要为了调试直接在生产环境切换开发模式。</p>
<h2>检查静态文件是否完整</h2>
<p>如果 Console 出现模块加载失败或静态文件 404，先检查部署版本、主题和 locale。结账页依赖大量 JavaScript，一个关键模块缺失就可能让 UI 永远停在 loading 状态。</p>
<h2>排查配送和支付方法</h2>
<p>暂时在测试环境禁用最近新增的配送或支付扩展做对照。服务端插件必须在无可用方法时返回合法空结果，而不是抛出未处理异常。外部接口应设置明确超时，不能让 PHP 请求无限等待。</p>
<h2>Totals 是否循环更新</h2>
<p>自定义费用、优惠券或地址监听代码如果在每次 totals 返回后再次触发 totals 请求，会形成循环。可在 Network 中观察相同请求是否连续出现。</p>
<pre><code>// 错误思路：每次 totals 更新后无条件再次 estimateTotals
// 正确做法：仅在真实输入变化且值不同的情况下触发，并增加防抖与进行中状态判断。</code></pre>
<h2>服务器端日志</h2>
<pre><code>tail -f var/log/system.log var/log/exception.log
# 同时查看 PHP-FPM 与 Web 服务器错误日志</code></pre>
<p>如果接口返回 500，应按请求时间和关联 ID 找到对应异常。不要只处理前端的通用错误提示。</p>
<h2>验证矩阵</h2>
<ul>
<li>游客与登录客户。</li>
<li>虚拟商品与实体商品。</li>
<li>一个地址和新建地址。</li>
<li>不同配送与支付方法。</li>
<li>有无优惠券、不同币种和 store view。</li>
<li>桌面与移动浏览器。</li>
</ul>
<p>修复后应确认请求数量恢复正常、没有重复 totals 调用，并实际完成一笔测试订单。</p>]]></description>
      <pubDate>Wed, 10 Apr 2024 09:16:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 管理员账号被锁定如何解锁？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-user-locked-unlock/</link>
      <description><![CDATA[<p>Magento 2 后台连续登录失败后，管理员账号可能进入锁定状态。不要直接修改数据库密码字段，也不要关闭后台安全策略。优先使用 Magento 提供的 CLI 解锁命令。</p>
<h2>使用 CLI 解锁</h2>
<pre><code>bin/magento admin:user:unlock admin_username</code></pre>
<p>命令中的 <code>admin_username</code> 是后台用户名，不是邮箱。CLI 应由 Magento 文件所属的部署用户运行，并使用项目对应的 PHP 版本。</p>
<h2>确认账号确实存在</h2>
<p>如果命令提示找不到用户，先核对用户名和当前项目环境。不要在聊天、工单或日志里记录管理员密码。确实需要创建新的应急管理员时，可使用官方用户创建命令，并在恢复后按权限策略处理临时账号。</p>
<pre><code>bin/magento admin:user:create \n  --admin-user=emergency_admin \n  --admin-email=admin@example.invalid \n  --admin-firstname=Emergency \n  --admin-lastname=Admin</code></pre>
<p>执行时命令会要求符合策略的密码。不要把真实密码写进 shell 历史或自动化日志。</p>
<h2>解锁后仍然无法登录</h2>
<ul>
<li>浏览器保存了错误密码，持续自动提交。</li>
<li>反向代理或 WAF 改变了客户端 IP 判断。</li>
<li>管理员账号被禁用或角色权限异常。</li>
<li>服务器时间不正确，影响会话或双因素认证。</li>
<li>Redis session、Cookie 域名或后台 URL 配置异常。</li>
</ul>
<p>查看 <code>var/log</code>、Web 服务器访问日志和安全设备记录，确认失败来源。不要把完整 Cookie、会话 ID 或认证信息复制到公开日志。</p>
<h2>检查安全配置</h2>
<p>后台路径应避免使用默认值，并启用 HTTPS、合理的锁定阈值和最小权限角色。若短时间出现大量不同用户名的失败请求，应按安全事件处理，而不是反复解锁。</p>
<h2>验证步骤</h2>
<ol>
<li>运行解锁命令并确认返回成功。</li>
<li>清除浏览器中该后台域名的旧登录状态。</li>
<li>只尝试一次正确登录。</li>
<li>确认角色权限正常，没有意外新增管理员。</li>
<li>检查失败登录来源是否停止。</li>
</ol>
<p>账号解锁只是恢复访问，真正的结束条件是找出账号为什么被锁定，并确认没有持续的恶意尝试。</p>]]></description>
      <pubDate>Wed, 10 Apr 2024 03:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 执行 static-content:deploy 报错怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-static-content-deploy-error/</link>
      <description><![CDATA[<p><code>setup:static-content:deploy</code> 报错后，终端最后一行不一定是真正原因。应保存完整输出，从第一个异常开始看。常见根因包括主题继承错误、LESS 文件语法、缺失语言包、权限、PHP 内存和并行部署进程。</p>
<h2>先确认部署模式</h2>
<pre><code>bin/magento deploy:mode:show
php -v
php -m</code></pre>
<p>开发模式通常按需生成静态文件；生产模式需要在发布流程中部署。<code>-f</code> 只是允许在非生产模式强制执行，不会修复代码错误。</p>
<h2>缩小部署范围</h2>
<pre><code>bin/magento setup:static-content:deploy -f zh_Hans_CN \n  --theme Alwayly/storefront \n  --area frontend \n  -j 1</code></pre>
<p>先用单一语言、主题、area 和单进程复现，日志更容易阅读。问题解决后再恢复并行和全部 locale。</p>
<h2>检查主题与模块文件</h2>
<ul>
<li><code>theme.xml</code> 中父主题是否存在。</li>
<li>LESS 或 CSS 引用的文件路径与大小写是否一致。</li>
<li>模块的 <code>view/frontend</code> 和 <code>view/adminhtml</code> 是否放错。</li>
<li>语言包 locale 是否与命令参数一致。</li>
<li>自定义 requirejs-config 是否存在语法错误。</li>
</ul>
<h2>权限与磁盘</h2>
<pre><code>df -h
df -i
find pub/static var/view_preprocessed generated -maxdepth 1 -not -user "$(id -un)" -print</code></pre>
<p>CLI 用户与 Web 用户权限不一致时，生成的文件可能无法覆盖或读取。不要用 777 解决；应统一部署用户和用户组。磁盘 inode 用尽也会表现为无法创建文件。</p>
<h2>安全清理构建产物</h2>
<p>在维护窗口、确认当前目录正确后，只清理可重新生成的静态构建产物。保留 <code>pub/static/.htaccess</code>。不要把删除整个项目目录写进部署脚本。</p>
<pre><code>bin/magento maintenance:enable
# 按项目发布脚本清理 pub/static 与 var/view_preprocessed 的可生成内容
bin/magento setup:static-content:deploy zh_Hans_CN en_US
bin/magento cache:clean config layout block_html full_page
bin/magento maintenance:disable</code></pre>
<h2>内存和并行度</h2>
<p>出现 allowed memory size 时，先定位是主题导致异常膨胀还是 CLI 内存确实不足。并行度过高会同时放大内存和 IO；用 <code>-j 1</code> 成功后再逐步增加。</p>
<h2>验证</h2>
<p>部署成功后检查首页、分类页、结账页和后台登录页的 CSS、JavaScript 是否返回 200，并确认响应的静态版本路径已更新。只有命令成功但页面大量 404，仍属于部署失败。</p>]]></description>
      <pubDate>Tue, 09 Apr 2024 06:21:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 新商品在前台搜索不到怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-new-product-not-found-in-search/</link>
      <description><![CDATA[<p>新商品搜索不到时，不要马上全量重建所有索引。先确认商品是否满足当前网站、store view 和搜索引擎的收录条件，再检查 <code>catalogsearch_fulltext</code> 是否更新。</p>
<h2>先核对商品本身</h2>
<ul>
<li>商品状态为启用。</li>
<li>已分配到当前网站。</li>
<li>Visibility 包含 Search，而不是仅 Catalog 或 Not Visible Individually。</li>
<li>库存状态允许前台展示；使用 MSI 时检查销售渠道和 source assignment。</li>
<li>商品名称、SKU 或目标属性在当前 store view 有正确值。</li>
</ul>
<p>可配置商品的简单子商品通常设置为单独不可见，用户应搜索到父商品，这属于正常行为。</p>
<h2>检查索引状态</h2>
<pre><code>bin/magento indexer:status catalogsearch_fulltext
bin/magento indexer:show-mode catalogsearch_fulltext
bin/magento indexer:reindex catalogsearch_fulltext</code></pre>
<p>手动 reindex 成功只能说明全量重建可运行。若索引器使用按计划更新，还必须确认后续修改能由 Cron 自动消费。</p>
<pre><code>SELECT view_id, mode, status, updated
FROM mview_state
WHERE view_id LIKE '%catalogsearch%';

SELECT job_code, status, messages, scheduled_at
FROM cron_schedule
WHERE job_code LIKE '%index%'
ORDER BY schedule_id DESC
LIMIT 20;</code></pre>
<h2>检查搜索属性</h2>
<p>自定义属性需要开启&ldquo;用于搜索&rdquo;，修改属性配置后通常要重新索引。文本太短、分词方式、同义词和语言分析器也会影响结果。先使用 SKU 或完整商品名称做精确对照，再判断是否是分词问题。</p>
<h2>检查搜索服务</h2>
<pre><code>bin/magento config:show catalog/search/engine
bin/magento config:show catalog/search/opensearch_server_hostname
bin/magento config:show catalog/search/opensearch_server_port</code></pre>
<p>确认 Magento 使用的搜索引擎与服务版本匹配，并查看集群健康、磁盘水位和索引是否只读。不要在未知影响范围时直接删除搜索索引。</p>
<h2>多商店问题</h2>
<p>同一商品可能在默认范围启用，但在某个 store view 被禁用或名称为空。测试时记录网站 ID、store ID 和请求域名，避免在错误范围内验证。</p>
<h2>修复后的验证</h2>
<ol>
<li>搜索 SKU、完整名称和一个普通关键词。</li>
<li>修改商品名称中的测试词，等待计划索引自动处理。</li>
<li>确认旧关键词消失、新关键词出现。</li>
<li>检查分类页和搜索页的价格、库存是否一致。</li>
</ol>
<p>最终目标是恢复增量索引链路，而不是每次新增商品都手动执行全量 reindex。</p>]]></description>
      <pubDate>Tue, 09 Apr 2024 01:53:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 商品图片上传成功但前台不显示怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-image-uploaded-not-showing/</link>
      <description><![CDATA[<p>商品图片上传成功但前台不显示，常见现象包括占位图、图片 URL 404、后台有图但列表页无图，或者只有某个 store view 异常。排查时先复制前台实际图片 URL，不要只看后台缩略图。</p>
<h2>检查图片角色和商店范围</h2>
<p>确认图片已分配到 Base、Small、Thumbnail 等需要的角色，并且没有在当前 store view 使用&ldquo;无图片&rdquo;覆盖。可配置商品还要确认前台展示的是父商品图片还是子商品图片。</p>
<h2>确认原始文件存在</h2>
<p>商品原图通常位于 <code>pub/media/catalog/product</code>。从数据库记录的相对路径定位文件：</p>
<pre><code>SELECT cpe.sku, cpev.value AS image_path
FROM catalog_product_entity_varchar cpev
JOIN catalog_product_entity cpe ON cpe.entity_id = cpev.entity_id
JOIN eav_attribute ea ON ea.attribute_id = cpev.attribute_id
WHERE ea.attribute_code = 'image'
  AND cpe.sku = 'TEST-SKU';</code></pre>
<p>不同 Magento 版本的实体关联字段可能不同，执行前先核对表结构。文件不存在时，应检查上传目录、共享存储挂载和部署流程，不要伪造数据库路径。</p>
<h2>重新生成图片缓存</h2>
<pre><code>bin/magento catalog:images:resize
bin/magento cache:clean block_html full_page</code></pre>
<p>大量图片重新生成会消耗 CPU 和磁盘 IO，生产环境应在低峰执行并监控空间。若命令报错，重点检查原图格式、损坏文件和 PHP 图像扩展。</p>
<h2>检查权限和 Web 路由</h2>
<pre><code>find pub/media/catalog/product -type d ! -perm -u+rwx -print
find pub/media/catalog/product -type f ! -perm -u+r -print</code></pre>
<p>不要为了省事把目录改成 777。正确做法是让部署用户、CLI 用户和 Web 用户使用一致的用户组，并按项目部署策略设置目录与文件权限。</p>
<h2>远程存储和 CDN</h2>
<p>如果使用对象存储或 CDN，确认原图已同步、缓存 URL 指向正确的媒体域名，并检查大小写差异。Linux 文件系统区分大小写，本地开发环境正常不代表生产环境正常。</p>
<h2>验证</h2>
<ol>
<li>直接访问原图 URL，确认不是 404 或 403。</li>
<li>访问生成后的缓存图片 URL。</li>
<li>分别检查商品详情页、分类页和搜索结果页。</li>
<li>切换 store view，确认图片角色没有被范围配置覆盖。</li>
<li>更新一张测试图片，确认后续上传流程能够自动生效。</li>
</ol>]]></description>
      <pubDate>Mon, 08 Apr 2024 08:32:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 订单邮件一直不发送怎么排查？]]></title>
      <link>https://www.360magento.com/blog/magento-2-order-email-not-sending/</link>
      <description><![CDATA[<p>订单邮件不发送时，先确认是&ldquo;Magento 没有生成邮件&rdquo;，还是&ldquo;邮件已经交给传输服务但没有送达&rdquo;。这两类问题的处理方向完全不同。</p>
<h2>确认后台配置</h2>
<p>检查商店配置中的销售邮件是否启用、发件人身份是否存在，以及订单邮件模板是否属于当前 store view。还要确认是否开启了异步发送。</p>
<pre><code>bin/magento config:show sales_email/order/enabled
bin/magento config:show sales_email/general/async_sending</code></pre>
<p>配置值可能受网站或商店范围覆盖。CLI 默认值看起来正确时，还需要在后台切换到实际 store view 检查。</p>
<h2>检查订单邮件标记</h2>
<pre><code>SELECT entity_id, increment_id, store_id,
       send_email, email_sent, created_at
FROM sales_order
ORDER BY entity_id DESC
LIMIT 20;</code></pre>
<ul>
<li><code>send_email=1</code> 且 <code>email_sent</code> 为空：邮件仍可能在等待处理或发送失败。</li>
<li><code>email_sent=1</code>：只代表 Magento 认为发送流程成功，不保证收件服务器最终投递。</li>
<li><code>send_email=0</code>：检查下单流程或第三方支付扩展是否改变了发送标记。</li>
</ul>
<p>不要直接批量修改这些字段后就结束排查，否则可能重复发送历史订单邮件。</p>
<h2>检查 Cron</h2>
<pre><code>bin/magento cron:run --group=default
SELECT job_code, status, messages, scheduled_at, executed_at, finished_at
FROM cron_schedule
WHERE job_code LIKE '%email%'
ORDER BY schedule_id DESC
LIMIT 30;</code></pre>
<p>如果异步发送开启但 Cron 长期不工作，订单邮件会持续积压。修复后应观察新订单是否自动发送，而不是只手动运行一次 Cron。</p>
<h2>查看应用和邮件传输日志</h2>
<pre><code>tail -f var/log/system.log var/log/exception.log</code></pre>
<p>使用 SMTP 扩展时，还要查看扩展自己的日志和队列状态。常见问题包括认证失败、端口或加密方式不匹配、发件域名未授权、连接超时和服务商限流。</p>
<h2>模板也可能让发送失败</h2>
<p>自定义模板中的变量、布局句柄或附件插件可能抛出异常。先切回对应版本的默认模板做对照，再逐步恢复自定义内容。不要把真实客户信息写进调试日志。</p>
<h2>完整验证</h2>
<ol>
<li>在测试环境创建一笔新订单，并记录订单号和 store ID。</li>
<li>确认订单邮件标记发生预期变化。</li>
<li>确认 Cron 记录为 success，日志无传输异常。</li>
<li>查看邮件服务商的接受记录、退信和垃圾邮件判定。</li>
<li>分别测试纯文本收件箱和常用邮箱服务。</li>
</ol>
<p>只有从 Magento 队列到收件服务器的整条链路都确认正常，才能判断问题已经解决。</p>]]></description>
      <pubDate>Mon, 08 Apr 2024 02:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 清了缓存还是显示旧页面怎么处理？]]></title>
      <link>https://www.360magento.com/blog/magento-2-old-page-after-cache-clean/</link>
      <description><![CDATA[<p>Magento 2 清缓存后页面没有变化，并不代表缓存命令无效。一个页面可能同时经过 Magento Full Page Cache、Varnish、CDN、浏览器缓存和静态文件缓存。先判断旧的是 HTML 还是 CSS、JavaScript、图片，再处理对应层。</p>
<h2>先区分 clean 和 flush</h2>
<pre><code>bin/magento cache:status
bin/magento cache:clean full_page block_html layout
bin/magento cache:flush</code></pre>
<p><code>cache:clean</code> 清理 Magento 对应缓存类型的记录；<code>cache:flush</code> 会清空当前缓存存储，可能影响共享同一 Redis 实例的其他应用。生产环境应优先精准 clean，不要把 flush 当成固定发布步骤。</p>
<h2>判断旧的是 HTML 还是静态文件</h2>
<ul>
<li>页面文字和价格旧：检查 Full Page Cache、Varnish 和 CDN。</li>
<li>HTML 已更新但样式旧：检查静态资源 URL、部署版本和浏览器缓存。</li>
<li>商品图片旧：检查媒体缓存目录及 CDN 图片缓存。</li>
<li>只有登录用户正常或异常：检查 private content 与客户段缓存。</li>
</ul>
<p>可用浏览器 Network 查看 HTML 响应和 CSS 文件的实际内容，并比较无痕窗口。不要只按 Ctrl+F5 后就认定服务器缓存正常。</p>
<h2>检查 Varnish 和反向代理</h2>
<p>使用 Varnish 时，Magento 清理缓存需要正确的后端主机配置和 purge 通路。如果应用缓存已清理，但反向代理仍返回旧 HTML，应检查响应头、Varnish 日志以及缓存失效请求是否到达。</p>
<pre><code>bin/magento config:show system/full_page_cache/caching_application
bin/magento config:show system/full_page_cache/varnish/access_list</code></pre>
<p>不要直接在文章或业务代码中写死清空全部 Varnish 的命令。应通过缓存标签让单个商品、分类或 CMS 页面精准失效。</p>
<h2>CSS 和 JavaScript 还是旧版本</h2>
<pre><code>bin/magento deploy:mode:show
bin/magento setup:static-content:deploy -f zh_Hans_CN en_US
bin/magento cache:clean config full_page</code></pre>
<p>生产模式发布静态文件前，应先进入维护窗口并按站点实际 locale 与主题部署。不要在访问高峰删除整个 <code>pub/static</code>。保留 <code>.htaccess</code>，并确认 Web 用户能读取新文件。</p>
<h2>CDN 与浏览器缓存</h2>
<p>如果源站已经返回新内容，但 CDN 节点仍旧，按具体 URL 或缓存标签刷新 CDN。若只有某台电脑异常，检查 Service Worker、浏览器磁盘缓存和本地代理。</p>
<h2>验证方法</h2>
<ol>
<li>给目标模板加入一个临时版本标识。</li>
<li>分别访问源站、Varnish 和公开域名。</li>
<li>核对 HTML 与静态文件请求的响应内容和缓存头。</li>
<li>删除临时标识，再做一次精准失效。</li>
</ol>
<p>正确的修复结果是相关页面更新、不相关页面仍保持缓存命中，而不是每次修改都清空全站缓存。</p>]]></description>
      <pubDate>Fri, 05 Apr 2024 07:47:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 后台保存商品很慢怎么办？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-save-product-slow/</link>
      <description><![CDATA[<p>后台保存一个商品需要几十秒，问题通常不在商品表本身，而在保存后触发的索引、库存、URL 重写、图片处理或第三方扩展。不要一开始就执行全站缓存清理，它既不能找出慢点，还会增加前台压力。</p>
<h2>先确认慢在哪一步</h2>
<p>打开浏览器开发者工具的 Network，观察保存请求本身是否很慢。如果请求很快但页面跳转慢，应继续检查后台页面资源；如果保存请求耗时很长，再查看同一时间的 PHP、Web 服务器和 Magento 日志。</p>
<pre><code>tail -f var/log/system.log var/log/exception.log
bin/magento indexer:status
bin/magento indexer:show-mode</code></pre>
<h2>检查索引模式</h2>
<p>生产环境通常更适合让可调度的索引器使用&ldquo;按计划更新&rdquo;。如果多个重量级索引器处于&ldquo;保存时更新&rdquo;，每次商品保存都会同步执行相关计算。</p>
<pre><code>bin/magento indexer:set-mode schedule catalog_product_price catalogsearch_fulltext
bin/magento indexer:status
bin/magento cron:run --group=index</code></pre>
<p>修改模式后必须确认 Cron 正常运行，否则只是把&ldquo;保存很慢&rdquo;变成&ldquo;前台数据一直不更新&rdquo;。</p>
<h2>查数据库锁，不要只看慢查询</h2>
<pre><code>SHOW FULL PROCESSLIST;
SELECT * FROM performance_schema.data_lock_waits;</code></pre>
<p>第二条查询是否可用取决于 MySQL 版本和权限。重点看保存时是否在等待库存、价格、URL 重写或自定义表的事务。若长期存在锁等待，应找到持锁事务的业务来源，不要直接终止未知生产事务。</p>
<h2>排查 Plugin 和 Observer</h2>
<p>商品保存会经过 Repository、资源模型和多个事件。第三方扩展如果在保存过程中同步调用外部 API、遍历全部商品或重复保存当前商品，会明显拖慢请求。</p>
<pre><code>bin/magento dev:di:info Magento\Catalog\Api\ProductRepositoryInterface</code></pre>
<p>可在测试环境临时禁用可疑模块做对照，但不要在生产站点随意切换模块。自定义逻辑应记录每个阶段的耗时：</p>
<pre><code>$startedAt = microtime(true);
$this-&gt;processor-&gt;execute($product);
$this-&gt;logger-&gt;info('Product post-save processor', [
    'sku' =&gt; $product-&gt;getSku(),
    'seconds' =&gt; round(microtime(true) - $startedAt, 3)
]);</code></pre>
<h2>几个容易忽略的原因</h2>
<ul>
<li>商品分配到大量网站或分类，导致关联数据和 URL 重写工作量增大。</li>
<li>可配置商品包含大量子商品，扩展又在保存时逐个加载完整模型。</li>
<li>远程媒体存储、搜索服务或 ERP 接口响应慢。</li>
<li>消费者未运行，导致本应异步的任务回落或积压。</li>
<li>PHP-FPM 工作进程不足，后台请求实际在排队。</li>
</ul>
<h2>修复后怎么验证</h2>
<p>使用同一个商品连续保存三次，分别记录请求时间、SQL 等待和索引积压。还要再修改一次价格或库存，确认前台能自动更新。只有保存速度和数据一致性同时恢复，才算真正解决。</p>]]></description>
      <pubDate>Fri, 05 Apr 2024 01:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 缓存标签与精准失效：避免全站 flush 的实现方法]]></title>
      <link>https://www.360magento.com/blog/magento-2-cache-tags-identity-precise-invalidation/</link>
      <description><![CDATA[<p>频繁执行 <code>cache:flush</code> 会清空共享缓存存储中的大量数据，造成缓存雪崩和首屏延迟。Magento 2 的正确做法是让缓存内容携带实体标签，在实体更新时只清理相关记录。</p>
<h2>实体身份标签</h2>
<p>自定义实体可实现 <code>IdentityInterface</code>：</p>
<pre><code>&lt;?php
declare(strict_types=1);
namespace Alwayly\News\Model;

use Magento\Framework\DataObject\IdentityInterface;

final class Article extends \Magento\Framework\Model\AbstractModel implements IdentityInterface
{
    public const CACHE_TAG = 'alwayly_article';
    protected $_cacheTag = self::CACHE_TAG;
    protected $_eventPrefix = self::CACHE_TAG;

    public function getIdentities(): array
    {
        $id = (int)$this-&gt;getId();
        return $id ? [self::CACHE_TAG . '_' . $id] : [self::CACHE_TAG];
    }
}</code></pre>
<p>集合页如果展示多篇文章，应包含每个可见实体的标签以及列表级标签。只返回通用标签会让一次更新清理全部文章缓存；只返回实体标签又可能漏掉新增文章对列表页的影响。</p>
<h2>Block 缓存键</h2>
<pre><code>public function getCacheKeyInfo(): array
{
    return [
        'ALWAYLY_ARTICLE',
        (int)$this-&gt;getStoreId(),
        (int)$this-&gt;getRequest()-&gt;getParam('id'),
        (string)$this-&gt;getData('template'),
    ];
}

public function getIdentities(): array
{
    return $this-&gt;article ? $this-&gt;article-&gt;getIdentities() : [];
}</code></pre>
<p>缓存键描述&ldquo;哪些上下文会产生不同内容&rdquo;，标签描述&ldquo;哪个实体变化时需要清理&rdquo;。二者不能互相替代。若内容与客户组、币种或 store view 有关，必须加入对应键；包含私有客户数据的 Block 不应进入公共 FPC。</p>
<h2>手动精准清理</h2>
<pre><code>$this-&gt;cache-&gt;clean(
    [\Alwayly\News\Model\Article::CACHE_TAG . '_' . $articleId]
);</code></pre>
<p>优先让实体保存流程触发标准清理。只有在数据通过外部流程更新、未经过模型生命周期时，才考虑显式清理，并记录清理原因。</p>
<h2>常见错误</h2>
<ul>
<li>更新一个实体就调用 <code>cache:flush</code>。</li>
<li>缓存键遗漏 store、客户组或查询参数，导致内容串用。</li>
<li>标签包含随机值，导致永远无法命中失效。</li>
<li>页面由多个 Block 组成，却只有父 Block 提供不完整标签。</li>
<li>把 session 相关内容直接缓存进公共页面。</li>
</ul>
<h2>验证方法</h2>
<ol>
<li>连续请求同一页面，确认第二次命中缓存。</li>
<li>修改单个实体，确认相关详情页和列表页更新。</li>
<li>确认不相关页面仍保持缓存命中。</li>
<li>在 Varnish 场景检查响应标签与 purge 行为。</li>
<li>分别验证不同 store view、客户组和币种。</li>
</ol>
<p>精准缓存失效的目标是同时保证一致性和命中率。出现陈旧数据时，应先检查缓存键与身份标签，而不是把全站 flush 固化到业务代码。</p>]]></description>
      <pubDate>Fri, 29 Mar 2024 08:28:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento如何将附件添加到邮件中]]></title>
      <link>https://www.360magento.com/blog/add-attachments-to-magento-email/</link>
      <description><![CDATA[<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">在 Magento 中，增强沟通策略可以显著提高客户满意度和参与度。其中一种有效的方法就是在电子邮件中添加附件，为客户提供详细的信息，并改善整体用户体验。&nbsp;</p>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">在这篇博文中，我们将指导您完成创建 Magento 模块的过程，以将发票自动附加到您的电子邮件中，从而增强整体用户体验。</p>
<h2 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Why_adding_attachments_to_Magento_email_is_a_valuable_enhancement" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>为什么向Magento 电子邮件添加附件是一项有价值的增强功能<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h2>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">事实证明，将文件附加到 Magento 电子邮件对企业和客户都有利。</p>
<h3 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="With_businesses" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>与企业<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h3>
<h4 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Efficiency_and_Time_Savings" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>提高效率并节省时间<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h4>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">通过预先自动准备发票附件，企业可以节省时间和精力。发件人可以轻松点击&ldquo;发送&rdquo;，简化沟通过程。</p>
<h4 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Professional_Brand_Image" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>专业的品牌形象<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h4>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">将精心设计的附件包含在内有助于公司树立专业形象。这反映了对组织有序和详细沟通的承诺，提升了业务的整体感知。</p>
<h3 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="With_customers" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">与客户</span><br /><span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h3>
<h4 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Comprehensive_Order_Details" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">全面的订单详情</span><br /><span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h4>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">附件提供给客户详细的订单信息，例如发票、收据和运输详情，直接在电子邮件中。这消除了客户需要在外部平台导航的必要，确保他们全面了解自己的购买。</p>
<h4 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Simplified_Communication" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">简化沟通</span><br /><span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h4>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">附件采用了易于理解的格式，减少了客户阅读冗长电子邮件的必要性。重要信息被清晰、简洁地呈现，从而提升了整体用户体验。</p>
<h2 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Step-by-step_Instructions_to_Add_an_Invoice_Attachment_to_Magento_Email" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">在Magento电子邮件中添加发票附件的步骤说明</span><br /><span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h2>
<h3 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="1_Create_Module_Files" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">1. 创建模块文件</span><br /><span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h3>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">首先，您需要使用以下文件设置模块的基本结构：</p>
<p data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce" data-immersive-translate-paragraph="1">文件 di.xml</span></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
 
 
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"&gt;
   &lt;preference for="Magento\Framework\Mail\Template\TransportBuilder"
           	type="Alwayly\SendPdf\Mail\Template\TransportBuilder"/&gt;
   &lt;type name="Magento\Sales\Model\Order\Email\SenderBuilder"&gt;
   	&lt;plugin name="add.attachment.email" type="Alwayly\SendPdf\Plugin\SenderBuilder"/&gt;
   &lt;/type&gt;
&lt;/config&gt;</code></pre>
<p data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">文件 module.xml</span></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
   &lt;module name="Alwayly_SendPdf" /&gt;
&lt;/config&gt;</code></pre>
<p data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce" data-immersive-translate-paragraph="1">文件 registration.php</span></p>
<pre class="wp-block-code"><code>&lt;?php
/*
* @author  Alwayly Solutions &lt;info@Alwayly.com&gt;
* @copyright Copyright (c) 2023 Alwayly Solutions &lt;https://www.alwayly.com&gt;. All rights reserved.
* @license  Open Software License (&ldquo;OSL&rdquo;) v. 3.0
*/
 
use Magento\Framework\Component\ComponentRegistrar;
 
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Alwayly_SendPdf', __DIR__);</code></pre>
<h3 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="2_Override_TransportBuilder" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>2.&nbsp;重写TransportBuilder&nbsp;<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h3>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">然后，我们需要覆盖Magento 中Alwayly\SendPdf\Mail\Template目录中的TransportBuilder文件以包含附件功能。</p>
<pre class="wp-block-code"><code>&lt;?php
 
declare (strict_types=1);
 
namespace Alwayly\SendPdf\Mail\Template;
 
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Mail\AddressConverter;
use Magento\Framework\Mail\EmailMessageInterfaceFactory;
use Magento\Framework\Mail\MessageInterface;
use Magento\Framework\Mail\MessageInterfaceFactory;
use Magento\Framework\Mail\MimeMessageInterfaceFactory;
use Magento\Framework\Mail\MimePartInterfaceFactory;
use Magento\Framework\Mail\Template\FactoryInterface;
use Magento\Framework\Mail\Template\SenderResolverInterface;
use Magento\Framework\Mail\TransportInterfaceFactory;
use Magento\Framework\ObjectManagerInterface;
use Laminas\Mime\Mime;
use Laminas\Mime\Message;
use Laminas\Mime\PartFactory;
 
/**
* Class TransportBuilder
* @package Alwayly\SendPdf\Mail\Template
*/
class TransportBuilder extends \Magento\Framework\Mail\Template\TransportBuilder
{
   /**
	* @var Message
	*/
   protected $messageMime;
 
   /**
	* @var
	*/
   protected $message;
 
   /**
	* @var array
	*/
   protected $attachments = [];
 
   /**
	* @var PartFactory|mixed
	*/
   protected $partFactory;
 
   /**
	* @param Message $messageMime
	* @param PartFactory $partFactory
	* @param FactoryInterface $templateFactory
	* @param MessageInterface $message
	* @param SenderResolverInterface $senderResolver
	* @param ObjectManagerInterface $objectManager
	* @param TransportInterfaceFactory $mailTransportFactory
	* @param MessageInterfaceFactory|null $messageFactory
	* @param EmailMessageInterfaceFactory|null $emailMessageInterfaceFactory
	* @param MimeMessageInterfaceFactory|null $mimeMessageInterfaceFactory
	* @param MimePartInterfaceFactory|null $mimePartInterfaceFactory
	* @param AddressConverter|null $addressConverter
	*/
   public function __construct(
   	Message $messageMime,
   	PartFactory $partFactory,
   	FactoryInterface $templateFactory,
   	MessageInterface $message,
   	SenderResolverInterface $senderResolver,
   	ObjectManagerInterface $objectManager,
   	TransportInterfaceFactory $mailTransportFactory,
   	MessageInterfaceFactory $messageFactory = null,
   	EmailMessageInterfaceFactory $emailMessageInterfaceFactory = null,
   	MimeMessageInterfaceFactory $mimeMessageInterfaceFactory = null,
   	MimePartInterfaceFactory $mimePartInterfaceFactory = null,
   	AddressConverter $addressConverter = null
   ) {
   	$this-&gt;templateFactory = $templateFactory;
   	$this-&gt;partFactory = $partFactory;
   	$this-&gt;messageMime = $messageMime;
   	parent::__construct(
       	$templateFactory,
       	$message,
       	$senderResolver,
       	$objectManager,
       	$mailTransportFactory,
       	$messageFactory,
       	$emailMessageInterfaceFactory,
       	$mimeMessageInterfaceFactory,
       	$mimePartInterfaceFactory,
       	$addressConverter
   	);
   }
 
   /**
	* @return $this|TransportBuilder
	* @throws LocalizedException
	*/
 protected function prepareMessage()
   {
   	$result = parent::prepareMessage();
   	if (!empty($this-&gt;attachments)) {
       	foreach ($this-&gt;attachments as $attachment) {
           	$body = $this-&gt;message-&gt;getBody();
           	if (!$body) {
               	$body = $this-&gt;messageMime;
           	}
           	$body-&gt;addPart($attachment);
           	$this-&gt;message-&gt;setBody($body);
       	}
       	$this-&gt;attachments = [];
   	}
   	return $result;
   }
 
   /**
	* @param $content
	* @param $fileName
	* @param $fileType
	* @return $this
	*/
   public function addAttachment($content, $fileName, $fileType)
   {
   	$attachmentPart = $this-&gt;partFactory-&gt;create();
   	$attachmentPart-&gt;setContent($content)
       	-&gt;setType($fileType)
       	-&gt;setFileName($fileName)
       	-&gt;setDisposition(Mime::DISPOSITION_ATTACHMENT)
       	-&gt;setEncoding(Mime::ENCODING_BASE64);
   	$this-&gt;attachments[] = $attachmentPart;
 
   	return $this;
   }
}</code></pre>
<h3 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="3_Plugin_for_SenderBuilder" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>3. SenderBuilder插件<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h3>
<pre class="wp-block-code"><code>&lt;?php
 
namespace Alwayly\SendPdf\Plugin;
 
use Laminas\Validator\Date;
use Alwayly\SendPdf\Mail\Template\TransportBuilder;
use Magento\Sales\Model\Order\Email\Container\Template;
use Magento\Sales\Model\Order\Pdf\Invoice;
use Magento\Framework\Stdlib\DateTime\DateTime;
 
class SenderBuilder
{
   private TransportBuilder $transportBuilder;
 
   private Template $templateContainer;
 
   private Invoice $renderInvoice;
 
   private DateTime $dateTime;
 
   public function __construct(
   	DateTime $dateTime,
   	Invoice $renderInvoice,
   	Template $templateContainer,
   	TransportBuilder $transportBuilder
   ) {
   	$this-&gt;transportBuilder = $transportBuilder;
   	$this-&gt;templateContainer = $templateContainer;
   	$this-&gt;renderInvoice = $renderInvoice;
   	$this-&gt;dateTime = $dateTime;
   }
 
   public function beforeSend(\Magento\Sales\Model\Order\Email\SenderBuilder $subject)
   {
   	$dataInvoice = $this-&gt;_getDataTemplate();
   	try {
       	if(!empty($dataInvoice)){
           	$pdfContent = $this-&gt;renderInvoice-&gt;getPdf($dataInvoice)-&gt;render();
           	$date = $this-&gt;dateTime-&gt;date('Y-m-d_H-i-s');
           	$this-&gt;transportBuilder-&gt;addAttachment($pdfContent, 'invoice' . $date . '.pdf', 'application/pdf');
       	}
   	} catch (\Exception $e) {
       	return;
   	}
   }
 
   private function _getDataTemplate()
   {
   	$data = $this-&gt;templateContainer-&gt;getTemplateVars();
   	if (array_key_exists('invoice_id', $data)) {
       	return [$data['invoice']];
   	}
   	if (isset($data['order']) &amp;&amp; $data['order']-&gt;hasInvoices()) {
       	return $data['order']-&gt;getInvoiceCollection()-&gt;getItems();
   	}
   	return [$data['invoice']] ?? '';
   }</code></pre>
<h2 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Result" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>结果<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h2>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">当发出发票或订单的电子邮件时，会自动地在邮件中添加发票附件。</p>
<p><img alt="Magento 邮件附件" src="https://www.360magento.com/media/wysiwyg/blog_815/pasted_image_0.png" title="Magento 邮件附件" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce" /></p>
<h2 class="wp-block-heading" data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"><span class="ez-toc-section" id="Conclusion" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span>总结<span class="ez-toc-section-end" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce"></span></h2>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">总之，按照这些步骤，您可以轻松地将发票附件添加到Magento的电子邮件中。这样做可以增强您的沟通策略，为客户提供详细信息，从而促进积极的购物体验。</p>
<p data-immersive-translate-paragraph="1" data-immersive-translate-walked="92b8b840-8be6-4601-9621-63d1461f18ce">根据您的具体需求对该模块进行定制，从而在竞争激烈的电子商务市场中提高客户参与度。如果需要，欢迎联系我们，我们为您提供更多的Magento平台定制服务。</p>]]></description>
      <pubDate>Wed, 27 Mar 2024 05:29:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示/删除 CMS 页面的面包屑导航]]></title>
      <link>https://www.360magento.com/blog/how-to-show-breadcrumbs-to-cms-pages-magento/</link>
      <description><![CDATA[<h2 class="wp-block-heading" id="670915065-a6159s">实践中常见的 3 种面包屑类型</h2>
<p>面包屑主要分为三种类型。每个都有其自己的目的和不同的用途。以下是您在网站上有效实施面包屑的 3 种方法。</p>
<p>总之，强烈建议您在 Magento 商店中添加面包屑，尽管它不是网站的强制组件。</p>
<h3 class="wp-block-heading" id="-1290161138-1zu3iu">基于层次结构的面包屑</h3>
<p>这被认为是使用最广泛和最常见的面包屑类型。本质上，基于层次结构的面包屑告诉网络访问者他们在网站结构中的位置。每个文本链接所指向的页面比其右侧的页面高一级。</p>
<p>我们以亚马逊为例。当打开亚马逊上的任何产品页面时，您可以轻松地在页面的左上角看到类似这样的面包屑痕迹。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/R4df8yk.jpg" /></p>
<p><span>例如：</span>电子产品 &gt; 计算机及配件 &gt; 计算机配件及外围设备。</p>
<p>显然，这种类型的面包屑可以帮助用户轻松查看他们在网站架构中的位置。当您可以与面包屑路径的每个部分进行交互时，导航到较低或较高级别的页面也变得更加方便。</p>
<h3 class="wp-block-heading" id="-740246070-2y1vhf">基于历史的面包屑</h3>
<p>与基于层次结构的面包屑不同，基于历史（或基于路径）的面包屑具有与浏览器后退按钮相同的功能。它允许用户快速返回到他们访问过的先前页面，并且所有选择都完好无损。</p>
<p>当访问者在类别页面上应用多个过滤器后只想快速跳回到上一页时，这种类型的面包屑链接非常有用。它关注的是实际的点击路径而不是位置。</p>
<h3 class="wp-block-heading" id="-1757321817-l7587y">基于属性的面包屑</h3>
<p>除了第一种面包屑类型之外，基于属性的面包屑是电子商务网站上使用最广泛的两种面包屑类型。</p>
<p>顾名思义，这种面包屑类型包含产品属性，这些属性向客户显示他们点击了哪些属性。</p>
<p>基于属性的面包屑与基于层次结构的面包屑最显着的区别在于，它不仅列出您的路径，还表示您在产品上选择的过滤器（价格、质量、颜色等）。您还可以直接在面包屑路径上取消选择产品过滤器。</p>
<h2 class="wp-block-heading" id="2051462103-xoj5vm">为什么面包屑对电子商务商店很重要？</h2>
<p>对于电子商务企业来说，面包屑在帮助用户有效地浏览整个网站和页面之间发挥着至关重要的作用。</p>
<p>然而，面包屑不仅仅局限于改善用户的浏览体验，它在很多方面都更有益。</p>
<h3 class="wp-block-heading" id="519656927-o68zfl">提升用户体验</h3>
<p>不用说，面包屑使网络访问者可以更轻松地系统地浏览整个在线商店。当顾客在您的商店里闲逛时迷路时，您只需要面包屑路径即可为他们指明出路。</p>
<p>通过正确实施面包屑类型，您可以帮助用户眨眼间移动到他们想要的页面。</p>
<p>尽管面包屑只是一种常见的界面元素，但它有助于减少摩擦并为客户带来便利。</p>
<h3 class="wp-block-heading" id="1814997951-hrfpbs">降低跳出率</h3>
<p>面包屑本身的另一个好处是能够降低跳出率。如前所述，面包屑可以作为一种方便的指南：</p>
<ul>
<li>向用户准确显示他们在您网站上的位置</li>
<li>只需单击一下即可根据客户的偏好向后或向前导航</li>
</ul>
<p>换句话说，您为网络访问者提供了一种使用面包屑导航轻松浏览您的网站的便捷方式。</p>
<p>因此，面包屑的应用提高了可用性、价值、网站的可信度以及整体用户体验。</p>
<h3 class="wp-block-heading" id="-381822069-uxi31r">有助于网站的 SEO 性能</h3>
<p>面包屑不仅有利于用户体验，而且对 Google 排名也有重大影响。对于那些不知道的人，Google 使用面包屑对内容进行分类和上下文关联。</p>
<p>换句话说，面包屑向搜索引擎显示该网站的结构。这对于 SEO 来说是双赢，因为面包屑会直接影响：</p>
<ul>
<li>用户如何在您的网站上查找信息，从而提高网络可用性</li>
<li>搜索引擎如何对您的网站编制索引并确定您的网站在 Google 上的排名</li>
</ul>
<p>从SEO优化的角度来看，面包屑无疑是一个多功能工具。</p>
<h2 class="wp-block-heading" id="-1578893068-bbia9a">如何在 Magento 2 中向 CMS 页面显示面包屑</h2>
<ol>
<li>在 Magento 2 管理面板上，单击<span>商店</span>。在<span>设置</span>部分中，选择<span>配置</span>。</li>
<li>在左侧面板的&ldquo;常规&rdquo;下，选择&ldquo;Web&rdquo;</li>
<li>打开<span>默认页面</span>部分。</li>
<li><span>将CMS 页面的显示面包屑</span>更改为 *Yes</li>
<li>完成后，单击<span>&ldquo;保存配置&rdquo;</span>。<br /><img src="https://www.360magento.com/media/wysiwyg/2v19oJC.jpg" /></li>
</ol>]]></description>
      <pubDate>Wed, 28 Feb 2024 07:38:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何获取浏览量最高的产品]]></title>
      <link>https://www.360magento.com/blog/get-most-viewed-product-collection-magento/</link>
      <description><![CDATA[<p>展示浏览次数最多的产品通常用于吸引客户使用该产品，也可以作为对他们的推荐。这个浏览次数最多的产品系列对于对商店中销售的产品不太了解的首次访问用户特别有帮助。它可以帮助他们更轻松地选择最好的商品。</p>
<p><span>浏览次数最多的产品</span>在帮助您的商店提高销量方面发挥着重要作用。这是因为在您的网站上展示这些产品可以引导客户收集最有趣的产品，而不是让他们毫无方向地闲逛。但是，要显示浏览次数最多的产品，您需要获取浏览次数最多的产品集合。因此，在今天的文章中，我将指导您如何在 Magento 2 中<span>获得浏览次数最多的产品集合</span>。</p>
<p><span>获取浏览次数最多的产品系列的 3 个步骤</span></p>
<ul>
<li>第 1 步：创建 MostViewedProducts 块</li>
<li>第 2 步：插入phtml文件</li>
<li>第 3 步：刷新缓存和测试结果</li>
</ul>
<h2 class="wp-block-heading" id="1808567723-oyrfsm">第 1 步：创建 MostViewedProducts 块</h2>
<p>要获得浏览次数最多的产品集合，首先，您需要创建一个<code>MostViewedProducts</code>块。为此，请按照路径<code>Example/Productslider/Block/MostViewedProducts.php</code>添加以下代码：</p>
<pre class="wp-block-code"><code>&lt;?php

namespace Example\Productslider\Block;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Mageplaza\Productslider\Helper\Data;
use Example\Productslider\Model\ResourceModel\Report\Product\CollectionFactory as MostViewedCollectionFactory;
/**
 * Class MostViewedProducts
 * @package Mageplaza\Productslider\Block
 */
class MostViewedProducts extends AbstractSlider
{
    /**
     * @var MostViewedCollectionFactory
     */
    protected $_mostViewedProductsFactory;
    /**
     * MostViewedProducts constructor.
     * @param Context $context
     * @param CollectionFactory $productCollectionFactory
     * @param Visibility $catalogProductVisibility
     * @param DateTime $dateTime
     * @param Data $helperData
     * @param HttpContext $httpContext
     * @param MostViewedCollectionFactory $mostViewedProductsFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        CollectionFactory $productCollectionFactory,
        Visibility $catalogProductVisibility,
        DateTime $dateTime,
        Data $helperData,
        HttpContext $httpContext,
        MostViewedCollectionFactory $mostViewedProductsFactory,
        array $data = []
    ) {
        $this-&gt;_mostViewedProductsFactory = $mostViewedProductsFactory;
        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);
    }
    /**
     * Get Product Collection of MostViewed Products
     * @return mixed
     */
    public function getProductCollection()
    {
        $collection = $this-&gt;_mostViewedProductsFactory-&gt;create()
            -&gt;addAttributeToSelect('*')
            -&gt;setStoreId($this-&gt;getStoreId())-&gt;addViewsCount()
            -&gt;addStoreFilter($this-&gt;getStoreId())
            -&gt;setPageSize($this-&gt;getProductsCount());
        return $collection;
    }
}
</code></pre>
<h2 class="wp-block-heading" id="541800160-dw3lip">第 2 步：插入phtml文件</h2>
<p>在块中拥有集合后，现在您可以按照此代码片段从块中获取产品集合<code>Example/HelloWorld/view/frontend/templates/list.phtml</code>。</p>
<p>接下来，请在phtml文件中插入以下代码</p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<h2 class="wp-block-heading" id="-964542453-qy5wef">第 3 步：刷新缓存和测试结果</h2>
<p>最后，让我们刷新缓存并测试结果。</p>]]></description>
      <pubDate>Thu, 22 Feb 2024 07:13:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用Magento 2 API获取所有产品、订单和类别的指南]]></title>
      <link>https://www.360magento.com/blog/get-all-products-orders-categories-magento2/</link>
      <description><![CDATA[<p>Magento是一款功能强大的电子商务平台，提供了强大的API来与其进行集成。通过Magento 2 API，您可以轻松地获取产品、订单和类别等信息，从而实现各种自动化和定制化的功能。本文将介绍如何使用Magento 2 API来获取所有产品、订单和类别的方法。</p>
<h3>1. 准备工作</h3>
<p>首先，您需要确保您有一个Magento 2的实例，并且已经配置了API访问权限。在Magento 2的后台管理界面中，您可以通过以下步骤配置API访问权限：</p>
<ul>
<li>登录Magento 2后台管理界面。</li>
<li>转到&ldquo;系统&rdquo; -&gt; &ldquo;集成API&rdquo;。</li>
<li>确保已启用API，并创建一个新的集成。</li>
</ul>
<p>创建集成后，您将获得一个访问令牌，用于通过API进行身份验证。</p>
<h3>2. 使用API获取产品信息</h3>
<p>要获取所有产品的信息，您可以使用Magento 2的<code>catalogProductRepositoryV1</code>端点。您可以发送一个GET请求到以下端点：</p>
<div class="dark bg-gray-950 rounded-md">
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-bash">http://yourmagento2domain.com/rest/V1/products</code></div>
</div>
<p>确保在请求头中包含正确的身份验证信息，使用您的访问令牌进行身份验证。这将返回包含所有产品信息的JSON响应。</p>
<h3>3. 使用API获取订单信息</h3>
<p>要获取所有订单的信息，您可以使用Magento 2的<code>salesOrderRepositoryV1</code>端点。发送GET请求到以下端点：</p>
<div class="dark bg-gray-950 rounded-md">
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-bash">http://yourmagento2domain.com/rest/V1/orders</code></div>
</div>
<p>同样，请确保在请求头中包含正确的身份验证信息。响应将包含所有订单的详细信息。</p>
<h3>4. 使用API获取类别信息</h3>
<p>要获取所有类别的信息，您可以使用Magento 2的<code>catalogCategoryManagementV1</code>端点。发送GET请求到以下端点：</p>
<div class="dark bg-gray-950 rounded-md">
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-bash">http://yourmagento2domain.com/rest/V1/categories</code><br /><span></span></div>
</div>
<p>同样，不要忘记在请求头中包含身份验证信息。响应将包含所有类别的详细信息。</p>
<h3>5. 示例代码</h3>
<p>以下是一个简单的Python示例代码，演示如何使用<code>requests</code>库来通过Magento 2 API获取产品、订单和类别信息：</p>
<div class="dark bg-gray-950 rounded-md">
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>python</span></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span></span><code class="!whitespace-pre hljs language-python"><span class="hljs-keyword">import</span> requests <span class="hljs-comment"># 设置Magento 2的API端点和访问令牌</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">base_url = <span class="hljs-string">"http://yourmagento2domain.com/rest/V1/"</span></code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python"> token = <span class="hljs-string">"your_access_token"</span> <span class="hljs-comment"># 获取所有产品信息</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">product_url = base_url + <span class="hljs-string">"products"</span> product_response = requests.get(product_url, headers={<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">"Bearer "</span> + token})</code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python"> products = product_response.json() <span class="hljs-built_in">print</span>(<span class="hljs-string">"Products:"</span>, products) <span class="hljs-comment"># 获取所有订单信息</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">order_url = base_url + <span class="hljs-string">"orders"</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">order_response = requests.get(order_url, headers={<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">"Bearer "</span> + token}) </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">orders = order_response.json() <span class="hljs-built_in">print</span>(<span class="hljs-string">"Orders:"</span>, orders) <span class="hljs-comment"># 获取所有类别信息</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">category_url = base_url + <span class="hljs-string">"categories"</span> </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">category_response = requests.get(category_url, headers={<span class="hljs-string">"Authorization"</span>: <span class="hljs-string">"Bearer "</span> + token}) </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python">categories = category_response.json() </code></div>
<div class="flex items-center relative text-token-text-secondary bg-token-main-surface-secondary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-python"><span class="hljs-built_in">print</span>(<span class="hljs-string">"Categories:"</span>, categories)</code></div>
</div>]]></description>
      <pubDate>Mon, 19 Feb 2024 07:02:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改 Favicon]]></title>
      <link>https://www.360magento.com/blog/how-upload-favicon-magento/</link>
      <description><![CDATA[<p>在Magento 2中更改站点的favicon是一个相对简单的过程，您可以通过以下步骤完成。在这篇博文中，我将指导您如何更改Magento 2站点的favicon。</p>
<h3>步骤 1：准备favicon图标</h3>
<p>首先，您需要准备好要用作favicon的图标。通常，这是一个ICO格式的图标文件，建议大小为16x16像素或32x32像素。您可以使用图标制作工具或在线图标生成器来创建favicon。</p>
<h3>步骤 2：上传favicon图标到Magento 2</h3>
<ol>
<li>
<p>将favicon图标上传到Magento 2的您的主题目录中。您的主题目录通常位于<code>app/design/frontend/Your_Vendor/Your_Theme</code>。</p>
</li>
<li>
<p>将favicon图标放置在您的主题目录的<code>web</code>子目录中。如果<code>web</code>子目录不存在，请创建它。</p>
</li>
</ol>
<h3>步骤 3：更新Magento 2配置</h3>
<ol>
<li>
<p>登录到Magento 2后台管理面板。</p>
</li>
<li>
<p>转到&ldquo;内容(Content)&rdquo; &gt; &ldquo;配置(Configuration)&rdquo; &gt; &ldquo;设计(Design)&rdquo;。</p>
</li>
<li>
<p>在&ldquo;HTML头部(HTML Head)&rdquo;部分，找到&ldquo;Favicon图标(Favicon Icon)&rdquo;字段。</p>
</li>
<li>
<p>在&ldquo;Favicon图标(Favicon Icon)&rdquo;字段中输入您的favicon图标的URL。例如，如果您的主题目录是<code>app/design/frontend/Your_Vendor/Your_Theme</code>，而您的favicon图标名为<code>favicon.ico</code>，则输入<code>Your_Vendor/Your_Theme/favicon.ico</code>。</p>
</li>
<li>
<p>保存配置更改。</p>
</li>
</ol>
<h3>步骤 4：清除缓存并刷新页面</h3>
<p>在Magento 2中更新任何配置后，都应该清除缓存以确保更改生效。完成后，刷新您的Magento 2网站页面，您应该能够看到新的favicon图标已经生效了。</p>]]></description>
      <pubDate>Sun, 18 Feb 2024 07:52:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加新的 CMS 块]]></title>
      <link>https://www.360magento.com/blog/how-to-add-new-cms-blocks-magento/</link>
      <description><![CDATA[<p>Magento 2的CMS块（Content Management System Blocks）是一种方便的方式，可以在网站的不同位置添加自定义内容，而无需深度的编码知识。以下是在Magento 2中添加新的CMS块的详细步骤：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>通过浏览器访问Magento 2后台，输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入CMS块管理页面</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Content&rdquo;（内容），然后选择&ldquo;Elements&rdquo;（元素）下的&ldquo;Blocks&rdquo;（块）。</p>
<p><span>步骤 3：创建新CMS块</span></p>
<p>在&ldquo;Blocks&rdquo;页面上，点击右上角的&ldquo;Add New Block&rdquo;（添加新块）按钮。</p>
<p><span>步骤 4：填写CMS块信息</span></p>
<p>在&ldquo;Block Information&rdquo;（块信息）页面上，填写以下信息：</p>
<ul>
<li><span>Block Title（块标题）：</span> 输入CMS块的标题。</li>
<li><span>Identifier（标识符）：</span> 输入唯一的标识符，通常是小写字母和下划线的组合，用于在代码中引用CMS块。</li>
<li><span>Store View（商店视图）：</span> 选择CMS块要适用的商店视图。</li>
<li><span>Content（内容）：</span> 在文本编辑器中输入CMS块的内容，您可以使用HTML标记自定义格式。</li>
</ul>
<p><span>步骤 5：设置CMS块的显示与隐藏</span></p>
<p>在&ldquo;Block Information&rdquo;页面的右上角，您可以选择CMS块的状态：</p>
<ul>
<li><span>Enable Block（启用块）：</span> 将其设置为&ldquo;Yes&rdquo;（是）以启用CMS块。</li>
<li><span>Hide from Navigation (在导航中隐藏)：</span> 将其设置为&ldquo;Yes&rdquo;（是）以在导航中隐藏CMS块。</li>
</ul>
<p><span>步骤 6：保存CMS块</span></p>
<p>点击页面右上角的&ldquo;Save Block&rdquo;（保存块）按钮，以保存新创建的CMS块。</p>
<p><span>步骤 7：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>步骤 8：在页面或布局中调用CMS块</span></p>
<p>在您希望显示CMS块的页面或布局文件中，您可以使用以下代码调用CMS块：</p>
<div class="dark bg-black rounded-md">
<div class="flex items-center relative text-token-text-secondary bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span></span><code class="!whitespace-pre hljs language-xml"></code></div>
</div>
<p>将<code>your_block_identifier</code>替换为您在第4步中设置的标识符。</p>]]></description>
      <pubDate>Mon, 12 Feb 2024 07:28:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加、删除、管理客户评论和评级？]]></title>
      <link>https://www.360magento.com/blog/how-manage-review-rating-magento/</link>
      <description><![CDATA[<p><span>步骤 1：登录Magento后台</span></p>
<p>通过浏览器访问Magento 2后台，输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：添加客户评论和评级</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Marketing&rdquo;（营销），然后选择&ldquo;User Content&rdquo;（用户内容）下的&ldquo;Reviews and Ratings&rdquo;（评论和评级）。</p>
<ul>
<li><span>添加新评论：</span>
<ul>
<li>点击&ldquo;Customer Reviews&rdquo;（客户评论）。</li>
<li>点击右上角的&ldquo;Add New Review&rdquo;（添加新评论）按钮。</li>
<li>选择要评价的产品，填写评分和评论信息。</li>
<li>点击&ldquo;Save Review&rdquo;（保存评论）。</li>
</ul>
</li>
</ul>
<p><span>步骤 3：管理评论和评级</span></p>
<ul>
<li><span>查看和编辑评论：</span>
<ul>
<li>在&ldquo;Customer Reviews&rdquo;页面，您可以查看所有评论和评级。</li>
<li>点击要编辑的评论，进行相应的修改。</li>
<li>点击&ldquo;Save Review&rdquo;（保存评论）以保存更改。</li>
</ul>
</li>
</ul>
<p><span>步骤 4：删除评论和评级</span></p>
<ul>
<li><span>删除评论：</span>
<ul>
<li>在&ldquo;Customer Reviews&rdquo;页面，找到要删除的评论。</li>
<li>选择评论并点击右上角的&ldquo;Delete&rdquo;（删除）按钮。</li>
<li>确认删除。</li>
</ul>
</li>
</ul>
<p><span>步骤 5：管理评级选项</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店），然后选择&ldquo;Configuration&rdquo;（配置）。在&ldquo;Catalog&rdquo;（目录）下的&ldquo;Product Reviews&rdquo;（产品评论）中，您可以配置有关评论和评级的各种选项。</p>
<ul>
<li>
<p><span>启用/禁用评论：</span></p>
<ul>
<li>在&ldquo;Product Reviews&rdquo;页面，找到&ldquo;General Settings&rdquo;（常规设置）部分。</li>
<li>将&ldquo;Enabled&rdquo;（启用）设置为&ldquo;Yes&rdquo;（是）以启用评论功能，设置为&ldquo;No&rdquo;（否）以禁用。</li>
</ul>
</li>
<li>
<p><span>审核评论：</span></p>
<ul>
<li>在&ldquo;Product Reviews&rdquo;页面，找到&ldquo;Product Review Approval&rdquo;（产品评论批准）部分。</li>
<li>将&ldquo;New Reviews&rdquo;（新评论）设置为&ldquo;Approved&rdquo;（批准）或&ldquo;Pending&rdquo;（待定）。</li>
</ul>
</li>
</ul>
<p><span>步骤 6：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>注意事项：</span></p>
<ol>
<li>
<p><span>审慎删除评论：</span> 在删除评论之前，请确保您真的需要删除它们，并且了解删除评论可能对客户信任和购买决策产生的影响。</p>
</li>
<li>
<p><span>定期审核：</span> 定期审核和回复评论，以维护积极的在线社区和客户关系。</p>
</li>
</ol>]]></description>
      <pubDate>Sun, 11 Feb 2024 08:25:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中更改商店电子邮件地址的详细步骤]]></title>
      <link>https://www.360magento.com/blog/how-change-store-email-addresses-magento/</link>
      <description><![CDATA[<p>通过浏览器访问Magento 2后台，输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入系统配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店），然后选择&ldquo;Configuration&rdquo;（配置）。</p>
<p><span>步骤 3：配置Store Email Addresses</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，展开&ldquo;General&rdquo;（常规）并选择&ldquo;Store Email Addresses&rdquo;（商店电子邮件地址）。</p>
<p><span>步骤 4：更新General Contact（一般联系）地址</span></p>
<p>在&ldquo;Store Email Addresses&rdquo;页面上，您将看到&ldquo;General Contact&rdquo;（一般联系）部分。在这里，您可以更改与一般店铺联系相关的电子邮件地址。</p>
<ul>
<li><span>Sender Name：</span> 输入显示为邮件发送者的名称。</li>
<li><span>Sender Email：</span> 输入商店的一般联系电子邮件地址。</li>
</ul>
<p><span>步骤 5：更新Sales Representative（销售代表）地址（可选）</span></p>
<p>如果您的商店需要与销售相关的电子邮件通知，您可以在&ldquo;Sales Representative&rdquo;（销售代表）部分更新相关信息。</p>
<ul>
<li><span>Sender Name：</span> 输入显示为邮件发送者的名称。</li>
<li><span>Sender Email：</span> 输入销售代表的电子邮件地址。</li>
</ul>
<p><span>步骤 6：更新Customer Support（客户支持）地址（可选）</span></p>
<p>如果您的商店提供客户支持，您可以在&ldquo;Customer Support&rdquo;（客户支持）部分更新相关信息。</p>
<ul>
<li><span>Sender Name：</span> 输入显示为邮件发送者的名称。</li>
<li><span>Sender Email：</span> 输入客户支持的电子邮件地址。</li>
</ul>
<p><span>步骤 7：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对商店电子邮件地址的更改。</p>
<p><span>步骤 8：清理缓存</span></p>]]></description>
      <pubDate>Sat, 10 Feb 2024 07:15:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改 Favicon]]></title>
      <link>https://www.360magento.com/blog/how-upload-favicon-magento-2/</link>
      <description><![CDATA[<p>Favicon是显示在浏览器标签页和书签上的小图标，对于网站来说是一个重要的视觉元素。在Magento 2中，更改Favicon是一项简单的任务，以下是详细的步骤：</p>
<p><span>步骤 1：准备Favicon图标</span></p>
<p>首先，准备一个正方形的图标，通常推荐大小为16x16像素或32x32像素。确保图标的文件格式为.ico（Windows图标格式）或.png。</p>
<p><span>步骤 2：上传Favicon图标</span></p>
<p>将准备好的Favicon图标上传到Magento 2的媒体文件夹。您可以使用FTP或Magento后台的媒体库来完成此操作。推荐将图标命名为<code>favicon.ico</code>以确保兼容性。</p>
<p><span>步骤 3：登录Magento后台</span></p>
<p>通过浏览器访问Magento 2后台，输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 4：进入主题配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Content&rdquo;（内容），然后选择&ldquo;Configuration&rdquo;（配置）。</p>
<p><span>步骤 5：选择当前主题</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，找到您当前使用的主题。在&ldquo;Themes&rdquo;部分，展开当前主题的选项。</p>
<p><span>步骤 6：配置Favicon设置</span></p>
<p>在当前主题的选项下，找到&ldquo;Favicon&rdquo;部分。在&ldquo;Favicon Icon&rdquo;字段中，输入您上传的Favicon图标的路径。例如，如果您上传的图标在<code>/media/favicon.ico</code>，则在该字段中输入<code>/media/favicon.ico</code>。</p>
<p><span>步骤 7：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对Favicon的更改。</p>
<p><span>步骤 8：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>步骤 9：刷新浏览器缓存</span></p>
<p>刷新您的浏览器缓存，或者在浏览器中打开一个新的标签页，以查看更改后的Favicon。</p>]]></description>
      <pubDate>Fri, 09 Feb 2024 07:12:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中将小部件插入侧边栏的详细步骤]]></title>
      <link>https://www.360magento.com/blog/how-to-insert-a-widget-into-sidebar-magento/</link>
      <description><![CDATA[<p>在Magento 2中，使用小部件（Widget）是一种方便的方法，可以在网站的侧边栏中添加各种自定义内容，例如广告、促销信息或其他相关信息。以下是在Magento 2中将小部件插入侧边栏的步骤：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>在您的Magento 2安装目录中，通过浏览器访问Magento后台。输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：创建小部件</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Content&rdquo;（内容），然后选择&ldquo;Widgets&rdquo;（小部件）。</p>
<p>在&ldquo;Widgets&rdquo;页面上，点击右上角的&ldquo;Add Widget&rdquo;（添加小部件）按钮。</p>
<p><span>步骤 3：选择小部件类型</span></p>
<p>在&ldquo;Type&rdquo;（类型）下拉菜单中，选择要插入侧边栏的小部件类型。通常，您可以选择&ldquo;CMS Static Block&rdquo;（CMS静态块）或其他适合您需求的小部件类型。</p>
<p><span>步骤 4：配置小部件参数</span></p>
<p>根据所选小部件类型，您将看到不同的配置选项。例如，如果选择&ldquo;CMS Static Block&rdquo;（CMS静态块），您需要选择要显示的静态块。</p>
<p>填写所需的配置信息，确保选择正确的Store View（商店视图），然后点击&ldquo;Save and Continue Edit&rdquo;（保存并继续编辑）。</p>
<p><span>步骤 5：指定布局更新</span></p>
<p>在左侧导航栏中，选择&ldquo;Layout Updates&rdquo;（布局更新）。然后，点击&ldquo;Add Layout Update&rdquo;（添加布局更新）按钮。</p>
<p>在&ldquo;Display On&rdquo;（显示在）下拉菜单中，选择&ldquo;Specified Page&rdquo;（指定页面），并选择您希望小部件显示的页面。</p>
<p><span>步骤 6：保存小部件配置</span></p>
<p>点击页面右上角的&ldquo;Save&rdquo;（保存）按钮，以保存小部件的配置。</p>
<p><span>步骤 7：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>步骤 8：刷新前端页面</span></p>
<p>刷新您的网站前端页面，您将看到已添加的小部件显示在指定的侧边栏位置上。</p>]]></description>
      <pubDate>Thu, 08 Feb 2024 07:11:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中启用模板路径提示的详细步骤]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-template-path-hints-magento/</link>
      <description><![CDATA[<p>Magento 2提供了一种方便的开发工具，即模板路径提示，它可以在前端页面上显示每个块的模板路径。以下是在Magento 2中启用和使用模板路径提示的步骤：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>在您的Magento 2安装目录中，通过浏览器访问Magento后台。输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入系统配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店）下的&ldquo;Configuration&rdquo;（配置）选项。</p>
<p><span>步骤 3：配置Developer模式</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，左侧导航栏中展开&ldquo;Advanced&rdquo;（高级）并选择&ldquo;Developer&rdquo;（开发者）。</p>
<ul>
<li>在&ldquo;Debug&rdquo;（调试）部分，将&ldquo;Enabled Template Path Hints for Storefront&rdquo;（在商店前端启用模板路径提示）设置为&ldquo;Yes&rdquo;（是）。</li>
<li>将&ldquo;Enabled Template Path Hints for Admin&rdquo;（在管理后台启用模板路径提示）设置为&ldquo;Yes&rdquo;（是）。</li>
</ul>
<p><span>步骤 4：配置Developer Client Restrictions（可选）</span></p>
<p>在&ldquo;Developer&rdquo;页面上，继续滚动到&ldquo;Developer Client Restrictions&rdquo;部分。</p>
<ul>
<li>如果您想仅在特定IP地址上显示模板路径提示，将&ldquo;Allowed IPs (comma-separated)&rdquo;（允许的IP地址，用逗号分隔）设置为相应的IP地址。</li>
</ul>
<p><span>步骤 5：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对系统配置的更改。</p>
<p><span>步骤 6：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>步骤 7：刷新前端页面</span></p>
<p>在前端页面上，刷新浏览器，您将看到每个块的模板路径提示。</p>]]></description>
      <pubDate>Wed, 07 Feb 2024 08:03:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中启用CSS和JavaScript文件合并的步骤]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-merge-css-javascript-magento/</link>
      <description><![CDATA[<p>Magento 2允许您通过合并CSS和JavaScript文件来减少HTTP请求，从而提高页面加载速度。以下是在Magento 2中启用此功能的步骤：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>在您的Magento 2安装目录中，通过浏览器访问Magento后台。输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入系统配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店）下的&ldquo;Configuration&rdquo;（配置）选项。</p>
<p><span>步骤 3：配置CSS合并</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，左侧导航栏中展开&ldquo;Advanced&rdquo;（高级）并选择&ldquo;Developer&rdquo;（开发者）下的&ldquo;CSS Settings&rdquo;（CSS设置）。</p>
<ul>
<li>将&ldquo;Merge CSS Files&rdquo;（合并CSS文件）设置为&ldquo;Yes&rdquo;（是）。</li>
<li>将&ldquo;Minify CSS Files&rdquo;（压缩CSS文件）设置为&ldquo;Yes&rdquo;（是）（可选）。</li>
<li>将&ldquo;Generate Source Maps&rdquo;（生成源映射）设置为&ldquo;Yes&rdquo;（是）（可选）。</li>
</ul>
<p><span>步骤 4：配置JavaScript合并</span></p>
<p>在&ldquo;Developer&rdquo;页面上，继续滚动到&ldquo;JavaScript Settings&rdquo;（JavaScript设置）部分。</p>
<ul>
<li>将&ldquo;Enable JavaScript Bundling&rdquo;（启用JavaScript捆绑）设置为&ldquo;Yes&rdquo;（是）。</li>
<li>将&ldquo;Minify JavaScript Files&rdquo;（压缩JavaScript文件）设置为&ldquo;Yes&rdquo;（是）（可选）。</li>
<li>将&ldquo;Enable JavaScript Source Maps&rdquo;（启用JavaScript源映射）设置为&ldquo;Yes&rdquo;（是）（可选）。</li>
</ul>
<p><span>步骤 5：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对系统配置的更改。</p>
<p><span>步骤 6：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>]]></description>
      <pubDate>Tue, 06 Feb 2024 03:59:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用客户登录/注册验证码]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-customer-login-register-captcha-magento/</link>
      <description><![CDATA[<p>启用验证码是一项有效的安全措施，可以防止自动化攻击和恶意注册。在Magento 2中，您可以通过以下步骤启用客户登录和注册时的验证码：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>在您的Magento 2安装目录中，通过浏览器访问Magento后台。输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入系统配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店）下的&ldquo;Configuration&rdquo;（配置）选项。</p>
<p><span>步骤 3：配置验证码设置</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，左侧导航栏中展开&ldquo;Customers&rdquo;（客户）并选择&ldquo;Customer Configuration&rdquo;（客户配置）。</p>
<ul>
<li>在&ldquo;Create New Account Options&rdquo;（创建新帐户选项）下，将&ldquo;Enable CAPTCHA on Storefront&rdquo;（在商店前端启用验证码）设置为&ldquo;Yes&rdquo;（是）。</li>
<li>在&ldquo;Login Options&rdquo;（登录选项）下，将&ldquo;Enable CAPTCHA in Admin&rdquo;（在管理后台启用验证码）设置为&ldquo;Yes&rdquo;（是）（可选）。</li>
</ul>
<p><span>步骤 4：选择验证码类型</span></p>
<p>在&ldquo;Customer Configuration&rdquo;页面上，继续滚动到&ldquo;CAPTCHA&rdquo;部分。</p>
<ul>
<li>在&ldquo;Forms&rdquo;（表单）下，选择要启用验证码的表单，例如&ldquo;Create User&rdquo;（创建用户）和&ldquo;Login&rdquo;（登录）。</li>
<li>在&ldquo;Displaying Mode&rdquo;（显示模式）下，选择&ldquo;Always&rdquo;（始终）或&ldquo;After Number of Attempts to Login&rdquo;（登录尝试次数后）。</li>
</ul>
<p><span>步骤 5：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对系统配置的更改。</p>
<p><span>步骤 6：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>]]></description>
      <pubDate>Mon, 05 Feb 2024 07:00:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中启用单一商店模式的步骤和注意事项]]></title>
      <link>https://www.360magento.com/blog/how-enable-single-store-mode-magento-2/</link>
      <description><![CDATA[<p>Magento 2 默认以多商店模式运行，这意味着您可以在一个Magento实例中管理多个商店。但在某些情况下，可能需要将系统配置为单一商店模式，特别是在只需要一个商店的情况下。以下是在Magento 2中启用单一商店模式的步骤：</p>
<p><span>步骤 1：登录Magento后台</span></p>
<p>在您的Magento 2安装目录中，通过浏览器访问Magento后台。输入管理员用户名和密码，登录到Magento管理面板。</p>
<p><span>步骤 2：进入系统配置</span></p>
<p>在Magento管理面板的左侧导航栏中，找到并点击&ldquo;Stores&rdquo;（商店）下的&ldquo;Configuration&rdquo;（配置）选项。</p>
<p><span>步骤 3：选择单一商店模式</span></p>
<p>在&ldquo;Configuration&rdquo;页面上，左侧导航栏中展开&ldquo;General&rdquo;（常规）并选择&ldquo;General&rdquo;下的&ldquo;Single-Store Mode&rdquo;（单一商店模式）。</p>
<p><span>步骤 4：启用单一商店模式</span></p>
<p>在&ldquo;Single-Store Mode&rdquo;选项中，将&ldquo;Enable Single-Store Mode&rdquo;（启用单一商店模式）设置为&ldquo;Yes&rdquo;（是）。</p>
<p><span>步骤 5：保存配置更改</span></p>
<p>点击页面右上角的&ldquo;Save Config&rdquo;（保存配置）按钮，以保存对系统配置的更改。</p>
<p><span>步骤 6：清理缓存</span></p>
<p>在Magento 2中，配置更改后通常需要清理缓存。在Magento管理面板的左侧导航栏中，选择&ldquo;System&rdquo;（系统）下的&ldquo;Cache Management&rdquo;（缓存管理）。然后，点击&ldquo;Flush Magento Cache&rdquo;（清除Magento缓存）以确保新的配置生效。</p>
<p><span>注意事项：</span></p>
<ol>
<li>
<p><span>备份数据库和文件：</span> 在进行系统配置更改之前，请务必备份Magento数据库和文件。这样可以在发生意外情况时恢复系统状态。</p>
</li>
<li>
<p><span>检查扩展和主题兼容性：</span> 一些Magento扩展和主题可能依赖于多商店模式，因此在切换到单一商店模式之前，请确保您使用的扩展和主题与该模式兼容。</p>
</li>
<li>
<p><span>审查网站链接：</span> 在单一商店模式下，网站链接的结构可能会发生变化。确保在更改模式后，您的网站链接仍然正常工作，以避免SEO和用户体验方面的问题。</p>
</li>
<li>
<p><span>测试功能和购物流程：</span> 在切换到单一商店模式后，仔细测试您的网站功能和购物流程，确保一切正常运作。</p>
</li>
</ol>]]></description>
      <pubDate>Sun, 04 Feb 2024 08:55:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[创建新的 Magento 2 管理员用户]]></title>
      <link>https://www.360magento.com/blog/how-to-create-new-admin-user-magento-2/</link>
      <description><![CDATA[<h2 class="wp-block-heading" id="604957466-0euw2p">通过命令行创建 Magento 2 管理员帐户</h2>
<p>创建管理员帐户/用户的另一种方法是，我们可以通过命令行（cli）创建新的管理员用户。以下是具体操作方法。</p>
<p>转到 Magento 2 根文件夹，运行创建一个新的管理员用户命令行：</p>
<pre class="wp-block-code"><code>php bin/magento admin:user:create
</code></pre>
<p>它会询问您：用户名、密码、电子邮件、名字和姓氏。</p>
<p>这是我们填写的内容：</p>
<pre class="wp-block-code"><code>Admin user: YourName
Admin password: YourPassword
Admin email: YourName@email.com
Admin first name: YourName
Admin last name: Team
</code></pre>
<p>并得到结果：</p>
<pre class="wp-block-code"><code>Created Magento administrator user named YourName</code></pre>]]></description>
      <pubDate>Sat, 03 Feb 2024 07:51:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 缓存管理：12 种缓存类型]]></title>
      <link>https://www.360magento.com/blog/10-cache-types-how-manage-cache-magento-2/</link>
      <description><![CDATA[<h2 class="wp-block-heading" id="1085759115-1jpjjf"><br class="Apple-interchange-newline" />12 Magento 2 缓存类型</h2>
<p>具体来说，<span>Cache</span>的不同类别是：</p>
<ul>
<li><code>Configuration (config)</code>：调整配置文件后，需要刷新它们，包括配置并存储特定设置</li>
<li><code>Layouts (layout)</code>：调整布局文件后，需要刷新它们，包括所有组件中编译后的页面布局</li>
<li><code>Blocks HTML output (block_html)</code>：调整视图层后，需要刷新它们，包括每个块的页面片段</li>
<li><code>Collections Data (collections)</code>：通过Magento，它可以自动刷新数据库查询。但是，自定义模块可能会写入导致 Magento 无法自行清理的条目，以防 Magento 无法清理，因此我们需要清理缓存</li>
<li><code>Reflection Data (reflection)</code>：API接口反射数据将被刷新</li>
<li><code>Database DDL operations (db_ddl)</code>：它可以由Magento自动刷新，但第3方可以在对 进行自定义更改后添加更多数据，<code>database schema</code>这可以清理缓存</li>
<li><code>EAV types and attributes (eav)</code>：将有关实体属性的元数据放入缓存中，一般情况下不应该刷新缓存</li>
<li><code>Integrations Configuration (config_integration)</code>：在您的商店中缓存已编译的集成。添加新的或更改现有的集成后进行清理</li>
<li><code>Integrations API Configuration (config_integration_api)</code>：商店集成的编译集成API配置</li>
<li><code>Page Cache (full_page)</code>：此缓存链接 HTML 页面，因此有必要定期清理此类缓存</li>
<li><code>Translations (translate)</code>：合并所有模块的翻译后，合并缓存将被清除</li>
<li><code>Web Services Configuration (config_webservice)</code>: 缓存<code>Web API Structure</code></li>
</ul>]]></description>
      <pubDate>Fri, 02 Feb 2024 07:48:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento开发中的10个小技巧，让您的项目更高效]]></title>
      <link>https://www.360magento.com/blog/magento-dev-totips/</link>
      <description><![CDATA[<ol>
<li>
<p><span>使用代码段（Snippets）提高效率：</span> 利用您的IDE（集成开发环境）或编辑器中的代码段功能，预定义一些常用的Magento代码片段，如创建新模块、添加布局文件等。这样可以加快编码速度，减少重复性劳动。</p>
</li>
<li>
<p><span>使用Magento命令行工具：</span> Magento命令行工具（CLI）提供了许多有用的命令，如清理缓存、重建索引、安装模块等。熟练使用这些命令可以在开发过程中省时省力。</p>
</li>
<li>
<p><span>启用开发者模式：</span> 在开发环境中启用Magento的开发者模式，这可以提供更详细的错误报告和调试信息。在<code>app/bootstrap.php</code>文件中设置<code>MAGENTO_MODE</code>为<code>developer</code>即可。</p>
</li>
</ol><ol start="4">
<li>
<p><span>使用Xdebug进行调试：</span> 集成Xdebug来进行代码调试，这样可以更轻松地识别和解决问题。配置您的IDE以与Xdebug一起使用，并设置断点进行逐步调试。</p>
</li>
<li>
<p><span>定期清理日志和临时文件：</span> 定期清理Magento的日志文件和临时文件，以保持系统性能。您可以设置定时任务或使用Magento命令行工具来自动执行这些清理操作。</p>
</li>
<li>
<p><span>了解Magento事件（Events）：</span> 使用Magento的事件体系，它允许您在系统的不同部分插入自定义代码。这是扩展Magento功能的强大方式，同时保持模块的松耦合性。</p>
</li>
<li>
<p><span>优化数据库查询：</span> 编写高效的数据库查询是关键之一。使用Magento的数据库抽象层和索引，避免使用直接SQL查询，以确保查询的效率和可维护性。</p>
</li>
<li>
<p><span>使用布局和块缓存：</span> 利用Magento的布局和块缓存，减少页面加载时间。了解何时使用缓存，以及如何在需要时清除缓存，有助于提高网站性能。</p>
</li>
<li>
<p><span>合理使用Magento UI组件：</span> Magento的UI组件提供了丰富的前端功能。了解如何正确使用这些组件，以及如何根据项目需要进行自定义，可以使您的前端开发更加灵活。</p>
</li>
<li>
<p><span>版本控制和部署策略：</span> 使用版本控制系统（如Git）来管理您的Magento项目。定义清晰的部署策略，包括配置文件、数据库迁移等，以确保在不同环境中的一致性。</p>
</li>
</ol>
<p><span>结论：</span> 这些小技巧可能看似微不足道，但在Magento开发过程中，它们可以累积成为提高效率和代码质量的关键因素。通过灵活运用这些技巧，您将更轻松地应对各种开发挑战，提升Magento项目的成功实施。</p>]]></description>
      <pubDate>Thu, 01 Feb 2024 07:36:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2的最新技术趋势]]></title>
      <link>https://www.360magento.com/blog/magento-new-technology-trends/</link>
      <description><![CDATA[<p>尊敬的Magento2开发者们，</p>
<p>欢迎回到我们的博客！今天，我们将深入探讨Magento2的一些最新技术趋势，帮助您更好地了解如何提升您的开发效率和用户体验。让我们一起来看看吧！</p>
<p><span>1. Magento PWA Studio的崭新体验</span></p>
<p>随着移动设备在电商中的重要性不断增加，Magento PWA Studio成为开发者们的热门选择。采用渐进式Web应用程序（PWA）的理念，Magento PWA Studio能够提供更快速、流畅的用户体验，并在各种设备上保持一致性。我们建议您深入研究并考虑在您的项目中采用PWA技术，以提高网站性能和用户满意度。</p>
<p><span>2. Magento Cloud的便捷部署与扩展性</span></p>
<p>随着云计算的普及，Magento Cloud提供了一种简化部署和扩展性的解决方案。借助云服务，您可以轻松部署、管理和扩展您的Magento2实例，同时受益于高级安全性和性能优化。我们建议您考虑将您的Magento2项目迁移到云平台，以获得更灵活的扩展和更好的性能。</p>
<p><span>3. GraphQL的数据查询灵活性</span></p>
<p>Magento2引入了GraphQL，这是一种强大的数据查询语言，能够帮助您更精准地获取所需的数据，减少不必要的负载。通过合理利用GraphQL，您可以提高数据查询的效率，并为客户提供更快速的响应时间。在您的开发过程中，尝试使用GraphQL来优化数据获取流程，提升网站性能。</p>
<p><span>4. Magento2.4.x的安全更新</span></p>
<p>安全始终是我们开发者关注的焦点。确保您的Magento2实例始终更新到最新版本，以获取最新的安全补丁和功能改进。Magento2.4.x系列引入了一系列安全性增强措施，包括CSRF攻击防护和更强大的身份验证机制。保持更新，是确保您的网站安全的关键步骤。</p>]]></description>
      <pubDate>Thu, 18 Jan 2024 08:44:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2 中 ngnix 配置多站点]]></title>
      <link>https://www.360magento.com/blog/magento2-ngnix-config/</link>
      <description><![CDATA[<p>在 Magento 2 中，配置多站点（Multi-Store）需要特殊的 Nginx 配置，因为 Magento 2 支持在同一个安装中运行多个站点。以下是一个简单的示例，假设您有两个站点，分别是 site1.com 和 site2.com：</p>
<div class="bg-black rounded-md">
<pre>server {
    listen 80;
    server_name site1.com www.site1.com;

    set $MAGE_ROOT /path/to/magento2;
    set $MAGE_MODE production;

    include /path/to/magento2/nginx.conf.sample;
}
 
server {
    listen 80;
    server_name site2.com www.site2.com;

    set $MAGE_ROOT /path/to/magento2;
    set $MAGE_MODE production;

    include /path/to/magento2/nginx.conf.sample;
}
</pre>
</div>
<p>在这个配置中，每个 <code>server</code> 块对应一个站点，通过 <code>server_name</code> 指定了该 server 块所处理的域名。</p>
<p>请将 <code>/path/to/magento2</code> 替换为您 Magento 2 安装的实际路径。并确保 Nginx 配置文件 <code>/path/to/magento2/nginx.conf.sample</code> 存在并包含 Magento 2 的相关配置。</p>
<p>Magento 2 通常附带一个名为 <code>nginx.conf.sample</code> 的示例配置文件，您可以在 Magento 安装目录的 <code>pub</code> 子目录下找到它。确保配置文件中的 <code>fastcgi_pass</code> 和其他相关设置正确指向您的 Magento 2 安装。</p>
<p>最后，确保每个域名的 DNS 记录正确指向您的服务器 IP 地址。配置完成后，重新加载或重启 Nginx 使配置生效。</p>]]></description>
      <pubDate>Wed, 17 Jan 2024 08:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 中ngnix 和Apache 配置 ]]></title>
      <link>https://www.360magento.com/blog/magento2-web-ngnix-apach/</link>
      <description><![CDATA[<p>在 Magento 2 中，您可以选择使用 Nginx 或 Apache 作为 web 服务器。以下是简单的示例配置，分别适用于 Nginx 和 Apache。</p>
<h3>Nginx 配置示例：<br /><br /></h3>
<pre>server {
    listen 80;
    server_name your_domain.com www.your_domain.com;

    set $MAGE_ROOT /path/to/your/magento2;
    set $MAGE_MODE production;

    include /path/to/your/magento2/nginx.conf.sample;
}
</pre>
<p>请将 <code>/path/to/your/magento2</code> 替换为您 Magento 2 安装的实际路径。确保 Nginx 配置文件 <code>/path/to/your/magento2/nginx.conf.sample</code> 存在并包含 Magento 2 的相关配置。</p>
<h3>Apache 配置示例：</h3>
<p>&lt;VirtualHost *:80&gt;<br /> ServerAdmin webmaster@your_domain.com<br /> DocumentRoot "/path/to/your/magento2"<br /> ServerName your_domain.com<br /> ServerAlias www.your_domain.com</p>
<p>&lt;Directory "/path/to/your/magento2"&gt;<br /> Options Indexes FollowSymLinks<br /> AllowOverride All<br /> Require all granted<br /> &lt;/Directory&gt;</p>
<p>ErrorLog "/var/log/apache2/your_domain_error.log"<br /> CustomLog "/var/log/apache2/your_domain_access.log" combined<br />&lt;/VirtualHost&gt;</p>
<p>同样，请将 <code>/path/to/your/magento2</code> 替换为您 Magento 2 安装的实际路径。确保 Apache 的虚拟主机配置文件包含了必要的设置，如 <code>AllowOverride All</code> 以启用 <code>.htaccess</code> 文件。</p>
<p>在上述配置中，您需要确保 Nginx 或 Apache 的配置正确指向 Magento 2 的安装目录，并且相关的访问和错误日志路径是正确的。</p>
<p>此外，如果您有多个站点（Multi-Store）需要配置，请根据具体情况修改上述配置文件，并确保 Magento 2 的配置文件（如 <code>nginx.conf.sample</code>）中也正确设置了站点信息。</p>
<p>配置完成后，请重新加载或重启相应的 web 服务器，以使配置生效。</p>
<pre><span style="white-space: normal;">
</span></pre>
<div id="gtx-trans" style="position: absolute; left: -51px; top: 28px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 16 Jan 2024 03:22:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 未来趋势]]></title>
      <link>https://www.360magento.com/blog/magento-future-trends/</link>
      <description><![CDATA[<p>Magento作为一流的电商平台，一直在不断演进以适应市场和技术的变化。在这篇文章中，我们将深入研究Magento未来的趋势，以及在下一代电商体验中将会迎来的创新和变革。</p>
<h3>1. <span>头脑购物体验</span></h3>
<p>未来的Magento电商平台将更加注重提供头脑购物（Mindful Shopping）体验。这包括通过人工智能和个性化推荐系统，更深入地了解用户需求，提供更符合其兴趣和偏好的产品。</p>
<h3>2. <span>增强现实（AR）和虚拟现实（VR）整合</span></h3>
<p>Magento将更多地整合增强现实和虚拟现实技术，为用户提供更丰富的购物体验。通过AR，用户可以在实际环境中预览产品，而VR则为他们提供沉浸式的虚拟商店体验。</p>
<h3>3. <span>社交购物整合</span></h3>
<p>未来的Magento将更深度地整合社交媒体和购物体验。用户可以直接在社交平台上发现产品并完成购买，同时商家可以通过社交媒体建立更紧密的客户关系。</p>
<h3>4. <span>可持续和负责任的电商</span></h3>
<p>Magento未来将更加关注可持续和负责任的电商实践。这包括推动供应链的可追溯性、提供环保选项以及支持社会责任项目。这样的做法将有助于塑造品牌形象，吸引越来越注重可持续性的消费者。</p>
<h3>5. <span>无缝跨渠道体验</span></h3>
<p>Magento未来版本将进一步提升跨渠道购物的无缝体验。无论用户是通过电脑、平板还是手机，他们都能够享受一致的购物体验，从而提高用户忠诚度和购物转化率。</p>
<h3>6. <span>智能物流和快速交付</span></h3>
<p>未来Magento将更加注重智能物流系统，通过实时数据和智能算法提高物流效率。同时，支持更快速和可靠的配送方式，以满足用户对于即时交付的需求。</p>
<div id="gtx-trans" style="position: absolute; left: -123px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 15 Jan 2024 08:36:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2的购物车体验]]></title>
      <link>https://www.360magento.com/blog/magento2-engaging-shopping-cart/</link>
      <description><![CDATA[<h3>1. 显示清晰的购物车总览</h3>
<p>确保购物车页面显示清晰而详细的购物车总览信息，包括产品名称、数量、价格和小计。这有助于用户一目了然地了解其购物车内的商品。</p>
<h3>2. 提供即时更新</h3>
<p>通过使用Ajax技术，实现购物车页面的即时更新。当用户更改产品数量或删除产品时，购物车总览应立即反映这些变化，而无需刷新整个页面。</p>
<h3>3. 强调优惠和促销信息</h3>
<p>如果有适用的优惠券或促销活动，确保这些信息在购物车页面中得到明显的展示。这可以激励用户继续购物，并提高购物车价值。</p>
<h3>4. 提供购物车内商品推荐</h3>
<p>在购物车页面底部或侧边，显示购物车内商品的相关推荐。这有助于引导用户发现其他可能感兴趣的产品，增加交叉销售机会。</p>
<h3>5. 实现购物车内编辑功能</h3>
<p>允许用户在购物车内直接编辑产品的数量、修改选项或移除商品。提供清晰的编辑界面，确保用户能够轻松进行调整。</p>
<h3>6. 购物车响应式设计</h3>
<p>确保购物车页面在各种设备上都能够呈现出色。购物车的响应式设计应适应不同屏幕尺寸，提供一致的用户体验。</p>
<h3>7. 引导用户进入结算流程</h3>
<p>在购物车页面明确显示结算按钮，引导用户进入结算流程。提供简化的结算过程，减少步骤，提高用户的购物完成率。</p>
<h3>8. 显示购物车内产品库存状态</h3>
<p>在购物车页面显示产品的实时库存状态，以避免用户在结算时遇到缺货情况。这可以帮助用户做出明智的购物决策。</p>
<h3>9. 提供购物车内产品搜索</h3>
<p>如果购物车中有大量产品，提供购物车内产品搜索功能。这使用户可以快速找到特定的商品，提高购物车内产品的可管理性。</p>
<h3>10. 优化加载速度</h3>
<p>确保购物车页面的加载速度迅速。优化页面元素和资源，减少不必要的HTTP请求，以确保购物车页面在各种网络条件下都能够快速加载。</p>]]></description>
      <pubDate>Sun, 14 Jan 2024 07:07:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何提高Magento2结账流程]]></title>
      <link>https://www.360magento.com/blog/magento2-checkout-optimization/</link>
      <description><![CDATA[<p>结账流程是电子商务网站上最关键的一环之一，直接关系到用户是否最终完成购买。在这篇博客文章中，我们将深入探讨如何在Magento 2主题开发中优化结账流程，以提高转化率并提供无缝的购物体验。</p>
<h3>1. 简化结账步骤</h3>
<p>减少结账流程的步骤数量，将多个步骤合并为一个页面或模态框。用户在短时间内完成结账流程，减少因过长流程而放弃购物车的可能性。</p>
<h3>2. 清晰的结账进度指示</h3>
<p>提供清晰的结账进度指示，让用户了解他们在结账流程中的位置。这可以减轻用户焦虑感，增加完成结账的信心。</p>
<h3>3. 提供多种支付选项</h3>
<p>确保结账页面提供多种支付选项，包括信用卡、PayPal、银行转账等。给予用户灵活性，选择他们偏好的支付方式。</p>
<h3>4. 支持快速注册和访客结账</h3>
<p>允许用户使用访客结账或快速注册选项，减少注册流程中的障碍。提供社交媒体登录选项，简化新用户的注册过程。</p>
<h3>5. 自动填充地址和支付信息</h3>
<p>通过使用自动填充技术，预填充用户已保存的地址和支付信息，减少用户在结账过程中输入的工作。这有助于加速结账速度。</p>
<h3>6. 引导用户解决错误</h3>
<p>如果用户在结账过程中遇到错误或遗漏信息，提供明确的错误消息和引导，帮助用户快速解决问题。避免用户因错误而中断结账流程。</p>
<h3>7. 透明的运费和税费信息</h3>
<p>在结账页面清晰显示运费和税费信息，以避免用户在最后一步才发现额外费用。透明的价格信息有助于建立用户的信任感。</p>
<h3>8. 提供订单总览</h3>
<p>在结账页面提供订单总览，包括产品列表、价格明细和总金额。用户应该在确认订单前清晰地了解他们的购买详情。</p>
<h3>9. 实现订单跟踪和通知</h3>
<p>让用户在结账后能够跟踪他们的订单，并通过电子邮件或短信接收订单更新通知。这有助于提供良好的客户服务体验。</p>
<h3>10. 移动设备友好</h3>
<p>确保结账流程在移动设备上能够流畅运行。通过响应式设计和移动优化来提供在小屏幕上的良好用户体验。</p>
<div id="gtx-trans" style="position: absolute; left: -42px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 14 Jan 2024 03:09:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 主题开发：集成社交媒体分享功能]]></title>
      <link>https://www.360magento.com/blog/magento2-social-media-sharing/</link>
      <description><![CDATA[<h3>1. 选择社交媒体平台</h3>
<p>在开始之前，确定您想要在网站上集成哪些社交媒体平台的分享功能。常见的选择包括Facebook、Twitter、LinkedIn、Pinterest等。确保选择的平台与您的目标受众和业务目标相匹配。</p>
<h3>2. 获取社交媒体分享按钮代码</h3>
<p>每个社交媒体平台都提供用于在网站上添加分享按钮的官方代码。访问相应的社交媒体开发者页面，获取分享按钮的代码片段。</p>
<h3>3. 创建一个专用的社交媒体分享区域</h3>
<p>在Magento 2主题中，创建一个专用的区域，用于容纳社交媒体分享按钮。通常，这可以在您网站的页脚、顶部导航栏或文章页面的侧边栏中实现。</p>
<h3>4. 将分享按钮代码嵌入主题</h3>
<p>在Magento 2主题的相应文件中，将获取的社交媒体分享按钮代码嵌入到您创建的社交媒体分享区域。这通常涉及到在HTML文件或布局文件中添加相应的代码片段。</p>
<h3>5. 优化分享按钮样式</h3>
<p>确保社交媒体分享按钮与您的网站主题一致，并符合品牌风格。您可以使用CSS样式表对这些按钮进行进一步的样式调整，以使它们看起来更加吸引人。</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"><span class="hljs-comment">/* 示例CSS样式表 */</span> <span class="hljs-selector-class">.social-share-button</span> { <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> <span class="hljs-number">10px</span>; <span class="hljs-attribute">font-size</span>: <span class="hljs-number">20px</span>; <span class="hljs-attribute">color</span>: <span class="hljs-number">#333</span>; <span class="hljs-attribute">transition</span>: color <span class="hljs-number">0.3s</span> ease-in-out; }</code></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"> <span class="hljs-selector-class">.social-share-button</span><span class="hljs-selector-pseudo">:hover</span> { <span class="hljs-attribute">color</span>: <span class="hljs-number">#007bff</span>; } </code></div>
</div>
<h3>6. 测试社交媒体分享功能</h3>
<p>在完成集成后，通过测试确保社交媒体分享功能在不同浏览器和设备上正常工作。确保分享的内容（例如页面标题、描述）是准确的且可自定义的。</p>
<h3>7. 考虑使用社交媒体插件</h3>
<p>一些社交媒体平台提供插件或API，可以更深度地集成分享功能。考虑使用这些插件，以获得更多定制选项和用户交互功能。</p>]]></description>
      <pubDate>Sat, 13 Jan 2024 07:05:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 快速搜索功能]]></title>
      <link>https://www.360magento.com/blog/magento2-quick-search-enhancement/</link>
      <description><![CDATA[<h3>1. 集成Magento 2的内置搜索功能</h3>
<p>Magento 2已经内置了强大的搜索功能，包括全文搜索和自动完成。确保在主题中启用这些功能，并在Magento 2后台配置中进行相应的设置。</p>
<h3>2. 优化搜索建议</h3>
<p>通过在搜索建议中显示产品图像、价格和简短描述等信息，提高用户对搜索结果的了解。这可以通过调整主题的HTML和CSS来实现。</p>
<h3>3. 支持自定义搜索过滤器</h3>
<p>考虑支持自定义搜索过滤器，以便用户可以根据特定条件快速缩小搜索范围。这可以包括按类别、品牌或价格范围过滤搜索结果。</p>
<h3>4. 实施Ajax搜索</h3>
<p>使用Ajax技术实现即时搜索结果的加载，无需刷新整个页面。这样可以提高搜索速度，使用户在输入关键词时立即看到相关结果。</p>
<h3>5. 智能搜索建议</h3>
<p>利用智能搜索建议，根据用户输入的关键词提供相关而准确的建议。可以使用机器学习算法或预测性搜索技术来实现。</p>
<h3>6. 移动设备适配</h3>
<p>确保您的快速搜索功能在移动设备上同样友好。优化搜索建议的显示方式，确保在小屏幕上也能提供良好的用户体验。</p>
<h3>7. 提供搜索历史和热门搜索</h3>
<p>为用户提供搜索历史记录和热门搜索建议，帮助他们更快速地找到他们之前或其他用户常搜索的内容。</p>
<h3>8. 结合自动完成</h3>
<p>将自动完成功能与快速搜索相结合，确保用户在输入过程中能够快速找到他们需要的信息。</p>
<h3>9. 实时搜索反馈</h3>
<p>在进行搜索时，通过实时反馈告知用户搜索的进行状态。这可以包括加载指示器或其他提示，使用户知道系统正在工作。</p>]]></description>
      <pubDate>Sat, 13 Jan 2024 03:06:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 创建自定义商品详情页模板]]></title>
      <link>https://www.360magento.com/blog/magento2-custom-product-details-template/</link>
      <description><![CDATA[<p>Magento 2 提供了强大的商品管理系统，但通过创建自定义商品详情页模板，您可以进一步定制和优化商品展示。在这篇博客文章中，我们将深入探讨如何在Magento 2主题开发中创建自定义商品详情页模板，以满足您网站的独特需求。</p>
<h3>1. 了解Magento 2商品详情页结构</h3>
<p>在开始之前，深入了解Magento 2商品详情页的结构是至关重要的。商品详情页通常包括商品图像、价格、描述、属性、加入购物车按钮等元素。了解这些元素的布局和结构是创建自定义模板的第一步。</p>
<h3>2. 创建自定义主题</h3>
<p>确保您已经创建了自定义Magento 2主题。如果没有，请按照Magento 2主题开发的标准流程创建一个新主题，并将其设置为当前主题。</p>
<h3>3. 复制默认商品详情页模板</h3>
<p>在Magento 2主题文件夹中，找到默认商品详情页模板文件，通常位于：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-bash">vendor/magento/module-catalog/view/frontend/templates/product/view/details.phtml </code></div>
</div>
<p>将该文件复制到您的主题文件夹中，路径可能是：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/Magento_Catalog/templates/product/view/details.phtml </code></div>
</div>
<h3>4. 修改自定义模板</h3>
<p>在您复制的<code>details.phtml</code>文件中，您可以根据需要进行修改和定制。您可以添加、删除或调整各个商品详情页元素的排列和样式。</p>
<h3>5. 更新主题布局文件</h3>
<p>在Magento 2主题布局文件中，确保正确引用和加载您创建的自定义商品详情页模板。这通常可以在 <code>catalog_product_view.xml</code> 文件中完成。</p>
<h3>6. 添加自定义样式和脚本</h3>
<p>如果需要添加自定义样式或JavaScript脚本以增强商品详情页的外观和交互性，确保将它们添加到您的主题中的相应文件夹，如：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/web/css/custom-styles.css app/design/frontend/{Vendor}/{Theme}/web/js/custom-scripts.js </code></div>
</div>
<h3>7. 测试和优化</h3>
<p>通过在Magento 2商店中查看商品详情页，测试您的自定义模板。确保它在不同设备和浏览器上都能正常运行，并根据需要进行优化。</p>
<div id="gtx-trans" style="position: absolute; left: -26px; top: 527.969px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 12 Jan 2024 07:04:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 引入字体和图标]]></title>
      <link>https://www.360magento.com/blog/magento2-custom-fonts-icons/</link>
      <description><![CDATA[<p>在Magento 2主题开发中，引入定制字体和图标是提高网站独特性和品牌形象的重要步骤。在这篇博客文章中，我们将深入讨论如何在Magento 2主题中引入和使用定制字体和图标，以打造独特而吸引人的网站设计。</p>
<h3>1. 选择合适的字体</h3>
<p>在选择定制字体之前，考虑您网站的品牌风格和目标受众。您可以选择从Google Fonts、Adobe Fonts等提供商中挑选合适的字体，或者使用自定义字体文件。</p>
<h3>2. 下载和集成字体文件</h3>
<p>一旦选择了字体，下载相应的字体文件（通常包括woff、woff2、ttf等格式）。将这些字体文件添加到Magento 2主题的合适位置，通常是：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/web/fonts/ </code></div>
</div>
<h3>3. 创建字体样式表</h3>
<p>在Magento 2主题中创建一个新的CSS文件，用于定义您引入的字体样式。确保在样式表中正确设置字体路径：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"><span class="hljs-comment">/* 示例字体样式表 */</span> <span class="hljs-keyword">@font-face</span> { <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'YourCustomFont'</span>; <span class="hljs-attribute">src</span>: <span class="hljs-built_in">url</span>(<span class="hljs-string">'../fonts/your-custom-font.woff2'</span>) <span class="hljs-built_in">format</span>(<span class="hljs-string">'woff2'</span>), <span class="hljs-built_in">url</span>(<span class="hljs-string">'../fonts/your-custom-font.woff'</span>) <span class="hljs-built_in">format</span>(<span class="hljs-string">'woff'</span>); <span class="hljs-attribute">font-weight</span>: normal; <span class="hljs-attribute">font-style</span>: normal; } <span class="hljs-selector-tag">body</span> { <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'YourCustomFont'</span>, sans-serif; } </code></div>
</div>
<h3>4. 引入图标库</h3>
<p>除了字体，图标也是网站设计中的关键元素。您可以选择使用矢量图标库，如Font Awesome或Material Icons。引入图标库的步骤通常包括将样式表和字体文件引入主题中。</p>
<h3>5. 使用CSS样式设置图标</h3>
<p>在Magento 2主题中，通过CSS样式表设置图标的方式类似于字体。创建一个新的CSS文件，定义图标的样式：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"><span class="hljs-comment">/* 示例图标样式表 */</span> <span class="hljs-selector-class">.icon</span> { <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Font Awesome'</span>; <span class="hljs-comment">/* 或其他图标库的名称 */</span> <span class="hljs-attribute">font-weight</span>: normal; <span class="hljs-attribute">font-style</span>: normal; } <span class="hljs-comment">/* 使用图标 */</span> <span class="hljs-selector-class">.custom-icon</span><span class="hljs-selector-pseudo">::before</span> { <span class="hljs-attribute">content</span>: <span class="hljs-string">'\f123'</span>; <span class="hljs-comment">/* 替换为您所选择图标的Unicode字符 */</span> } </code></div>
</div>
<h3>6. 更新主题布局</h3>
<p>在Magento 2主题布局文件中，确保正确引用和加载您创建的字体和图标样式表。通常，这可以在 <code>default_head_blocks.xml</code> 文件中完成。</p>
<h3>7. 测试和调整</h3>
<p>在引入定制字体和图标后，通过测试确保它们在不同设备和浏览器上正常显示。根据需要进行调整，以确保字体和图标在整个网站中一致使用。</p>
<div id="gtx-trans" style="position: absolute; left: -38px; top: 451.391px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 12 Jan 2024 03:45:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 响应式]]></title>
      <link>https://www.360magento.com/blog/magento2-responsive-design/</link>
      <description><![CDATA[<p>随着移动设备的广泛使用，响应式设计在Magento 2主题开发中变得愈发重要。在这篇博客文章中，我们将深入探讨如何在Magento 2主题中实践响应式设计，以确保您的电子商务网站在各种设备上都能提供出色的用户体验。</p>
<h3>1. 了解响应式设计原理</h3>
<p>在开始之前，让我们回顾一下响应式设计的基本原理。响应式设计的目标是使网站布局和内容能够适应不同屏幕尺寸和分辨率，包括桌面、平板和移动设备。</p>
<h3>2. 使用媒体查询（Media Queries）</h3>
<p>Magento 2主题中使用媒体查询是实现响应式设计的关键。通过在CSS中嵌入媒体查询，您可以根据屏幕宽度应用不同的样式，以适应不同设备。</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"><span class="hljs-comment">/* 示例媒体查询 */</span> <span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width</span>: <span class="hljs-number">768px</span>) { <span class="hljs-comment">/* 在这里添加移动设备的样式 */</span> } <span class="hljs-keyword">@media</span> <span class="hljs-keyword">only</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width</span>: <span class="hljs-number">769px</span>) <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width</span>: <span class="hljs-number">1024px</span>) { <span class="hljs-comment">/* 在这里添加平板设备的样式 */</span> } </code></div>
</div>
<h3>3. 弹性网格布局（Flexible Grid Layout）</h3>
<p>使用弹性网格布局是实现响应式设计的另一个关键因素。确保您的主题使用相对单位（如百分比）而不是固定单位（如像素）来定义网格和元素的宽度，以适应不同屏幕尺寸。</p>
<h3>4. 图像和多媒体的处理</h3>
<p>通过使用<code>max-width</code>属性和<code>height: auto</code>，确保图像在小屏幕上不会溢出。同时，选择适当的图像格式和压缩以提高加载速度。</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span>&nbsp;</span></div>
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-css"><span class="hljs-comment">/* 图像响应式样式 */</span> <span class="hljs-selector-tag">img</span> { <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">height</span>: auto; } </code></div>
</div>
<h3>5. 移动导航（Mobile Navigation）</h3>
<p>为移动设备设计简洁的导航菜单。您可以考虑使用折叠式菜单、滑动菜单或下拉菜单，以确保在小屏幕上提供更好的导航体验。</p>
<h3>6. 测试在不同设备上</h3>
<p>在开发过程中，定期测试您的Magento 2主题在不同设备上的表现。使用浏览器开发者工具或实际设备进行测试，确保网站在各种情况下都能正常运行。</p>
<div id="gtx-trans" style="position: absolute; left: -54px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 11 Jan 2024 07:05:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 主题优化]]></title>
      <link>https://www.360magento.com/blog/magento2-themes-optimization/</link>
      <description><![CDATA[<h3>1. 图片优化</h3>
<p>优化网站图片是提高性能的首要任务。使用压缩工具来减小图片文件大小，同时确保图片质量不受影响。考虑使用WebP格式，以进一步提高加载速度。</p>
<h3>2. 启用Magento 2 缓存</h3>
<p>Magento 2提供了丰富的缓存功能，包括布局缓存、块缓存和页面缓存。确保这些缓存功能都被启用，以减少服务器响应时间并提高整体性能。</p>
<h3>3. 使用CDN（内容分发网络）</h3>
<p>集成内容分发网络（CDN）以加速静态资源的加载速度。CDN会将网站内容分发到全球多个服务器，使用户从最近的服务器获取资源，从而减少加载时间。</p>
<h3>4. Lazy Loading</h3>
<p>实施图片和其他媒体资源的Lazy Loading，以确保仅在用户滚动到可见区域时加载这些资源，而不是一次性加载所有内容。</p>
<h3>5. 压缩CSS和JavaScript</h3>
<p>使用CSS和JavaScript压缩工具来减小文件大小。这有助于减少页面加载时间，尤其是在较慢的网络连接下。</p>
<h3>6. 移除不必要的扩展和模块</h3>
<p>检查并移除不必要的Magento 2扩展和模块，因为它们可能会增加网站的负载时间。只保留对网站功能至关重要的扩展。</p>
<h3>7. 优化数据库</h3>
<p>定期清理Magento 2数据库，删除不需要的数据和日志。您可以使用Magento 2提供的数据库优化工具或使用第三方工具进行优化。</p>
<h3>8. 使用合适的主题</h3>
<p>选择一个轻量且优化良好的Magento 2主题。避免使用过于复杂或过度设计的主题，以确保页面加载速度得到最大程度的优化。</p>]]></description>
      <pubDate>Thu, 11 Jan 2024 03:25:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2主题开发 ：创建自定义页面模板]]></title>
      <link>https://www.360magento.com/blog/magento2-custom-page-development/</link>
      <description><![CDATA[<h3>1. 了解Magento 2页面结构</h3>
<p>在开始之前，让我们先了解Magento 2的页面结构。每个页面通常由多个块（blocks）组成，而这些块又由布局（layouts）控制。了解页面的块和布局结构是创建自定义页面的关键。</p>
<h3>2. 创建自定义主题</h3>
<p>首先，确保您已经创建了自定义Magento 2主题。如果没有，请按照Magento 2主题开发的标准流程创建一个新主题，并将其设置为当前主题。</p>
<h3>3. 创建自定义页面布局</h3>
<p>在主题文件夹中，创建一个新的布局文件，用于定义自定义页面的结构。通常，这个文件可以命名为 <code>cms_custom_page.xml</code>，放置在以下路径：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span></span><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/Magento_Theme/layout/</code></div>
</div>
<p>在这个文件中，您可以使用布局标记定义块和容器，以构建您页面的基本结构。</p>
<h3>4. 创建自定义块</h3>
<p>在主题文件夹中，创建一个新的块文件，用于处理页面的业务逻辑和渲染。这个文件可以命名为 <code>CustomPage.php</code>，放置在以下路径：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span></span><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/Magento_Theme/Block/</code></div>
</div>
<p>在块文件中，您可以编写PHP代码来处理数据和业务逻辑，并为页面渲染准备必要的信息。</p>
<h3>5. 创建自定义页面模板</h3>
<p>最后，在主题文件夹中，创建一个新的模板文件，用于定义页面的HTML结构。这个文件可以命名为 <code>custom_page.phtml</code>，放置在以下路径：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><span></span><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/Magento_Theme/templates/</code></div>
</div>
<p>在模板文件中，您可以使用HTML和Magento的块标记（如 <code>&lt;?= $block-&gt;getChildHtml('custom.block') ?&gt;</code>）来渲染页面的内容。</p>
<h3>6. 集成到Magento 2系统</h3>
<p>最后一步是将您的自定义页面集成到Magento 2系统中。您可以通过创建一个CMS页面或自定义布局来调用您创建的页面模板。</p>]]></description>
      <pubDate>Wed, 10 Jan 2024 06:55:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 定制产品列表页]]></title>
      <link>https://www.360magento.com/blog/magento2-custom-product-list-page/</link>
      <description><![CDATA[<p>1. 了解Magento 2产品列表结构<br />在开始之前，我们需要了解Magento 2产品列表页的结构。产品列表页通常由多个块（blocks）组成，包括产品列表、分页、排序和过滤器等。深入理解这些组件是定制产品列表的关键。</p>
<p>2. 创建自定义主题<br />确保您已经创建了自定义Magento 2主题。如果没有，请按照Magento 2主题开发的标准流程创建一个新主题，并将其设置为当前主题。</p>
<p>3. 定制产品列表布局<br />在主题文件夹中，创建一个新的布局文件，用于定义产品列表页的结构。此文件通常命名为 catalog_product_view.xml，放置在以下路径：</p>
<p>app/design/frontend/{Vendor}/{Theme}/Magento_Catalog/layout/<br />在这个文件中，您可以使用Magento的布局标记定义产品列表块、分页和其他相关组件。</p>
<p>4. 创建自定义块和模板<br />在主题文件夹中，创建一个新的块文件和模板文件，用于处理产品列表的业务逻辑和渲染。块文件通常命名为 ProductList.php，放置在以下路径：</p>
<p><br />app/design/frontend/{Vendor}/{Theme}/Magento_Catalog/Block/Product/<br />模板文件通常命名为 product_list.phtml，放置在以下路径：</p>
<p><br />app/design/frontend/{Vendor}/{Theme}/Magento_Catalog/templates/product/<br />在这两个文件中，您可以编写PHP代码和HTML代码，以自定义产品列表的外观和功能。</p>
<p>5. 集成到Magento 2系统<br />最后一步是将您的自定义产品列表集成到Magento 2系统中。您可以通过在CMS页面或自定义布局中调用您创建的产品列表块来实现。</p>
<p>6. 添加自定义样式和交互效果<br />通过使用Less或Sass等CSS预处理器，以及Magento提供的JavaScript库，为您的产品列表添加自定义样式和交互效果。确保您的样式与整体网站设计一致。</p>
<div id="gtx-trans" style="position: absolute; left: -48px; top: 168.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 10 Jan 2024 03:35:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 主题开发]]></title>
      <link>https://www.360magento.com/blog/magento2-frontend-development/</link>
      <description><![CDATA[<p>Magento 2 是一款强大而灵活的电子商务平台，提供了丰富的功能和扩展性。在这篇博客文章中，我们将深入了解Magento 2前端开发，着重介绍如何构建一个响应式主题，以确保您的电子商务网站在各种设备上都能提供出色的用户体验。</p>
<h3>1. 了解Magento 2主题结构</h3>
<p>在开始之前，让我们首先了解Magento 2主题的基本结构。Magento 2主题通常包含以下几个关键文件夹：</p>
<ul>
<li><code>app/design/frontend/{Vendor}/{Theme}/</code>：主题文件夹</li>
<li><code>web/</code>：包含CSS、JavaScript和图像等资源</li>
<li><code>Magento_Theme</code>：主题配置文件夹</li>
</ul>
<h3>2. 创建自定义主题</h3>
<p>要创建自定义主题，您需要在Magento 2的主题文件夹中新建一个文件夹，其中包括主题的名称和供应商名称。例如：</p>
<div class="bg-black rounded-md">
<div class="flex items-center relative text-gray-200 bg-gray-800 dark:bg-token-surface-primary px-4 py-2 text-xs font-sans justify-between rounded-t-md"><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/</code></div>
</div>
<h3>3. 设定主题的基本配置</h3>
<p>在主题文件夹中，您需要创建一个 <code>theme.xml</code> 文件以配置主题的基本信息，如名称、父主题等。此文件通常位于：</p>
<div class="bg-black rounded-md">
<div class="p-4 overflow-y-auto"><code class="!whitespace-pre hljs language-bash">app/design/frontend/{Vendor}/{Theme}/Magento_Theme/ </code></div>
</div>
<h3>4. 创建响应式布局</h3>
<p>Magento 2鼓励使用CSS框架和技术来实现响应式设计。您可以使用Less或Sass等预处理器，确保您的CSS代码更加模块化和易于维护。同时，了解Magento 2提供的媒体查询和布局工具，以确保您的主题在各种屏幕尺寸上都能正常显示。</p>
<h3>5. 优化图片和字体</h3>
<p>在响应式主题中，图片和字体的优化至关重要。使用适当的图片压缩工具，并确保字体在不同设备上显示良好。考虑使用WebP格式的图片以提高性能。</p>
<h3>6. 集成JavaScript和Ajax</h3>
<p>Magento 2支持JavaScript的模块化开发，您可以使用RequireJS来管理JavaScript文件的依赖关系。利用Magento提供的Ajax功能，提高网站的交互性和用户体验。</p>]]></description>
      <pubDate>Tue, 09 Jan 2024 07:54:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2 PHTML小技巧]]></title>
      <link>https://www.360magento.com/blog/magento-phtml-tips/</link>
      <description><![CDATA[<h2><span>可翻译的文本</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?= __('String to translate'); ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#call-static-block-id-in-phtml--template-if-existenablednot-empty" id="user-content-call-static-block-id-in-phtml--template-if-existenablednot-empty" tabindex="-1"></a><span>在.phtml模板中调用静态块ID（如果存在/启用/不为空）</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?php if($this-&gt;getLayout()-&gt;createBlock('Magento\Cms\Block\Block')-&gt;setBlockId('BLOCK_ID')-&gt;toHtml() != ''): ?&gt;
    &lt;div class="static-block"&gt;
        &lt;?php echo $this-&gt;getLayout()-&gt;createBlock('Magento\Cms\Block\Block')-&gt;setBlockId('BLOCK_ID')-&gt;toHtml(); ?&gt;
    &lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#call-widget-in-phtml-template" id="user-content-call-widget-in-phtml-template" tabindex="-1"></a><span>在.phtml模板中调用小部件</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?= $this-&gt;getLayout()-&gt;createBlock("Magento\Catalog\Block\Product\Widget\NewWidget")
            -&gt;setDisplayType("all_products")
            -&gt;setShowPager(1)
            -&gt;setProductsPerPage(5)
            -&gt;setProductsCount(10)
            -&gt;setPageVarName("pwkvbl")
            -&gt;setTemplate("product/widget/new/content/new_grid.phtml")
            -&gt;toHtml(); ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#call-method-from-module-helper" id="user-content-call-method-from-module-helper" tabindex="-1"></a><span>从模块助手调用方法</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?php $helper = $this-&gt;helper('Vendor\Module\Helper\Data'); ?&gt;
&lt;?php $helper-&gt;callMethodName(); ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#get-var-value-from-etcviewxml-in-phtml" id="user-content-get-var-value-from-etcviewxml-in-phtml" tabindex="-1"></a><span>从phtml中的/etc/view.xml获取VAR值</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?= $block-&gt;getVar("gallery/width", 'Magento_Catalog'); ?&gt;
&lt;?= $block-&gt;getVar("breakpoints/mobile/conditions/max-width", 'Magento_Catalog'); ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#useful-block-functions" id="user-content-useful-block-functions" tabindex="-1"></a><span>有用的块功能</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>$block-&gt;getViewFileUrl('images/loader-1.gif'); - from web/images directory
$block-&gt;getViewFileUrl('Magento_Catalog::images/filename.jpg'); - from e.g Magento_Catalog/web/images directory

$block-&gt;getUrl('checkout/cart/index');
$block-&gt;getUrl('', array('_direct'=&gt;'hairproducts.html'));
$block-&gt;getUrl('', array('_direct'=&gt;'hairproducts.html', '_query'=&gt;'manufacturer=412'));

$block-&gt;getBaseUrl();
$block-&gt;getMediaDirectory();
$block-&gt;getChildBlock('block.name');
$block-&gt;getChildHtml('block.name');
$block-&gt;getChildChildHtml('block.name');
$block-&gt;getBlockHtml('block.name');
$block-&gt;escapeHtml();
$block-&gt;escapeUrl();
$block-&gt;stripTags(); // removes HTML tags

$block-&gt;escapeHtml('value', $allowedTags);
$block-&gt;escapeHtmlAttr('value', $escapeSingleQuote);
$block-&gt;escapeJs('value');
$block-&gt;escapeUrl($url);
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#example-operations-on-product-attribute" id="user-content-example-operations-on-product-attribute" tabindex="-1"></a><span>产品属性操作示例</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?php if($_product-&gt;getTypeId() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE): ?&gt;
        &lt;?php
        $deliveryTime = $_product-&gt;getResource()-&gt;getAttribute('delivery_time');
        $minDeliveryTime = $deliveryTime-&gt;getFrontend()-&gt;getValue($_product);
        ?&gt;
        &lt;div class="delivery-time"&gt;
            &lt;?php echo __('Delivery time: %1', $minDeliveryTime); ?&gt;
        &lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>$product-&gt;getAttributeText('color'); - value as 'text' label
$product-&gt;getResource()-&gt;getAttribute('color')-&gt;getFrontend()-&gt;getValue($product); - value as 'text' label
$product-&gt;getData('color'); - value as 'id attribute number'
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#execute-javascript-code-after-swatches-are-displayed-in-category-view" id="user-content-execute-javascript-code-after-swatches-are-displayed-in-category-view" tabindex="-1"></a><span>在类别视图中显示样本后执行 JavaScript 代码</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;script&gt;
    require(['jquery', 'Magento_Swatches/js/swatch-renderer'], function ($, swatch) {
        $(document).on('swatch.initialized', function() {
            // Here make some layout changes
        });
    });
&lt;/script&gt;  
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#can-be-used-to-get-the-list-of-handles-while-debugging" id="user-content-can-be-used-to-get-the-list-of-handles-while-debugging" tabindex="-1"></a><span>可用于在调试时获取句柄列表</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>$this-&gt;getLayout()-&gt;getUpdate()-&gt;getHandles();
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#get-backend-config-option-enebleddisabled" id="user-content-get-backend-config-option-enebleddisabled" tabindex="-1"></a><span>获取后端配置选项启用/禁用</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?php $config = $block-&gt;getLayout()-&gt;createBlock(\Magento\Config\Block\System\Config\Form::class);?&gt;
&lt;?php if($config-&gt;getConfigValue('dev/translate_inline/active')): ?&gt;
  // do something
&lt;?php endif; ?&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#media-queries-in-javascript" id="user-content-media-queries-in-javascript" tabindex="-1"></a><span>JavaScript 中的媒体查询</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;script type="text/javascript"&gt;
        require(['jquery', 'matchMedia'], function ($, mediaCheck) {
            mediaCheck({
                media: '(min-width: 768px)',
                // Switch to Desktop Version
                entry: function () {
                   alert('desktop');
                },
                // Switch to Mobile Version
                exit: function () {
                    alert('mobile');
                }
            });
        });
    &lt;/script&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#2-ways-to-call-fotorama-gallery-script" id="user-content-2-ways-to-call-fotorama-gallery-script" tabindex="-1"></a><span>调用 Fotorama 图库脚本的 2 种方法</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;script type="text/x-magento-init"&gt;
    {
        "[data-gallery-role=gallery-placeholder]": {
            "mage/gallery/gallery": {
                "mixins":["magnifier/magnify"],
                "magnifierOpts": &lt;?= $block-&gt;getMagnifier() ?&gt;,
                "data": &lt;?= $block-&gt;getGalleryImagesJson() ?&gt;,
                "options": &lt;?= $block-&gt;getGalleryOptions()-&gt;getOptionsJson() ?&gt;,
                "fullscreen": &lt;?= $block-&gt;getGalleryOptions()-&gt;getFSOptionsJson() ?&gt;,
                "breakpoints": &lt;?= $block-&gt;getBreakpoints() ?&gt;
            }
        }
    }
&lt;/script&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;script&gt;
    require(['jquery', 'mage/gallery/gallery'], function ($, gallery) {
        $(function () {
            $('[data-gallery-role="gallery-placeholder"]').each(function(index, element) {
                gallery({
                    "mixins":["magnifier/magnify"],
                    "magnifierOpts": &lt;?= $block-&gt;getMagnifier() ?&gt;,
                    "data": &lt;?= $block-&gt;getGalleryImagesJson() ?&gt;,
                    "options": &lt;?= $block-&gt;getGalleryOptions()-&gt;getOptionsJson() ?&gt;,
                    "fullscreen": &lt;?= $block-&gt;getGalleryOptions()-&gt;getFSOptionsJson() ?&gt;,
                    "breakpoints": &lt;?= $block-&gt;getBreakpoints() ?&gt;
                }, element);
             });
        });
    });
&lt;/script&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/phtml.md#script-initialization" id="user-content-script-initialization" tabindex="-1"></a><span>脚本初始化</span></h2>
<p><span>标准</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;div class="swiper-container header-slider" data-mage-init='{"Swissup_Swiper/js/swiper": {"loop":true,"centeredSlides":true,"autoplay": {"delay": 10000}, "navigation":{"nextEl":".swiper-button-next","prevEl":".swiper-button-prev"}}}'&gt;
    &lt;div class="swiper-wrapper"&gt;
        &lt;div class="swiper-slide"&gt;1&lt;/div&gt;
        &lt;div class="swiper-slide"&gt;2&lt;/div&gt;
        &lt;div class="swiper-slide"&gt;3&lt;/div&gt;
   &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>或更好：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;script type="text/lazy"&gt;
    require(['jquery', 'Swissup_Swiper/js/swiper'], function ($, swiper) {
        $(function() {
            $('.header-slider').each(function(index, element) {
                swiper({"loop":true,"centeredSlides":true,"autoplay": {"delay": 10000}, "navigation":{"nextEl":".swiper-button-next","prevEl":".swiper-button-prev"}}, element);
             });
        });
    });
&lt;/script&gt;</code></pre>
</div>]]></description>
      <pubDate>Mon, 08 Jan 2024 16:02:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 常用变量]]></title>
      <link>https://www.360magento.com/blog/magento-curly-braces-variable/</link>
      <description><![CDATA[<h2><span>自定义变量</span></h2>
<p><code></code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#store-url" id="user-content-store-url" tabindex="-1"></a><span>商店网址</span></h2>
<p><code>https://www.360magento.com/customer/account/</code><span>- 末尾有斜线</span></p>
<p><code>https://www.360magento.com/contact-us</code><span>- 末尾没有斜杠</span></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#media-url" id="user-content-media-url" tabindex="-1"></a><span>媒体网址</span></h2>
<p><code>https://www.360magento.com/media/wysiwyg/your-image.jpg</code>&nbsp;<code>{{view url='images/logo.svg'}}</code>&nbsp;<code>{{view url='Magento_Theme::images/logo.svg'}}</code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#block-id" id="user-content-block-id" tabindex="-1"></a><span>区块ID</span></h2>
<p><code></code></p>
<p><code></code></p>
<p><code></code></p>
<p><code></code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#widget" id="user-content-widget" tabindex="-1"></a><span>小部件</span></h2>
<p><code></code></p>
<p><code><div class="widget widget-new-products">
    <div class="widget-title">
        <h2>新产品</h2>
    </div>
    <div class="widget-products">
                                <ul class="products-grid">
                    <li class="item first">
                <a href="https://www.360magento.com/anli030" title="LsyBeauty假发在线商城" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/0/1/01_01_1.jpg" width="85" height="85" alt="LsyBeauty假发在线商城" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli030" title="LsyBeauty假发在线商城)">LsyBeauty假发在线商城</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-30-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/30/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/30/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                                    <li class="item">
                <a href="https://www.360magento.com/anli025" title="豆皮小程序电商平台" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/s/m/small_01.jpg" width="85" height="85" alt="豆皮小程序电商平台" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli025" title="豆皮小程序电商平台)">豆皮小程序电商平台</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-25-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/25/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/25/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                                    <li class="item">
                <a href="https://www.360magento.com/anli023" title="代盟海外代购服务平台" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/0/1/01_1_14.jpg" width="85" height="85" alt="代盟海外代购服务平台" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli023" title="代盟海外代购服务平台)">代盟海外代购服务平台</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-23-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/23/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/23/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                                    <li class="item">
                <a href="https://www.360magento.com/anli019" title="Eurofitca线上交易平台" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/0/1/01_1_11.jpg" width="85" height="85" alt="Eurofitca线上交易平台" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli019" title="Eurofitca线上交易平台)">Eurofitca线上交易平台</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-19-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/19/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/19/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                                    <li class="item last">
                <a href="https://www.360magento.com/anli024" title="两端国际跨境电商" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/0/1/01-1.jpg" width="85" height="85" alt="两端国际跨境电商" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli024" title="两端国际跨境电商)">两端国际跨境电商</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-24-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/24/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/24/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                </ul>
                                <ul class="products-grid">
                    <li class="item first">
                <a href="https://www.360magento.com/anli020" title="Fiberoutlets光通信产品批发交易平台" class="product-image"><img src="https://www.360magento.com/media/catalog/product/cache/1/small_image/85x/9df78eab33525d08d6e5fb8d27136e95/0/1/01_1_12.jpg" width="85" height="85" alt="Fiberoutlets光通信产品批发交易平台" /></a>
                <h3 class="product-name"><a href="https://www.360magento.com/anli020" title="Fiberoutlets光通信产品批发交易平台)">Fiberoutlets光通信产品批发交易平台</a></h3>
                                

                        
    <div class="price-box">
                                                                <span class="regular-price" id="product-price-20-widget-new-grid">
                                            <span class="price">￥ 0.00</span>                                    </span>
                        
        </div>

                <div class="actions">
                                            <button type="button" title="加入购物车" class="button btn-cart" onclick="setLocation('https://www.360magento.com/checkout/cart/add/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/product/20/form_key/2CTCG1CiYwbVQJ4D/')"><span><span>加入购物车</span></span></button>
                                        <ul class="add-to-links">
                                                                            <li><span class="separator">|</span> <a href="https://www.360magento.com/catalog/product_compare/add/product/20/uenc/aHR0cHM6Ly93d3cuMzYwbWFnZW50by5jb20vYmxvZy9yc3MvaW5kZXgvc3RvcmVfaWQvMS8,/form_key/2CTCG1CiYwbVQJ4D/" class="link-compare">添加并比较</a></li>
                                            </ul>
                </div>
            </li>
                </ul>
                    </div>
</div>
</code></p>
<p><code></code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#store-contact-information-variables" id="user-content-store-contact-information-variables" tabindex="-1"></a><span>存储联系信息变量</span></h2>
<p><span>基本安全 URL&nbsp;</span><code>https://www.360magento.com/</code></p>
<p><span>一般联系电子邮件&nbsp;</span><code>sales@360magento.com</code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#new-account-template-variables" id="user-content-new-account-template-variables" tabindex="-1"></a><span>新帐户模板变量</span></h2>
<p><span>客户帐户网址</span><code>{{var this.getUrl($store, &lsquo;customer/account/&rsquo;)}}</code></p>
<p><span>客户邮箱</span><code>{{var customer.email}}</code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#new-order-template-variables" id="user-content-new-order-template-variables" tabindex="-1"></a><span>新订单模板变量</span></h2>
<p><span>订单号</span><code>{{var order.increment_id}}</code></p>
<p><span>付款详情</span><code>{{var payment_html|raw}}</code></p>
<p><span>运输说明</span><code>{{var order.getShippingDescription()}}</code></p>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/curly-braces-variable.md#email-template-variables" id="user-content-email-template-variables" tabindex="-1"></a><span>电子邮件模板变量</span></h2>
<p><span>电子邮件徽标图像 URL</span><code>{{var logo_url}}</code></p>
<p><span>电子邮件徽标图像宽度</span><code>{{var logo_width}}</code></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&ndash; For registration:
{{var customer}}

{{var customer.ID}}

{{var customer.email}}

{{var customer.firstname}}

{{var customer.lastname}}

{{var customer.name}}

{{var customer.password}}

{{var customer.created_in}} Store Name

{{var customer.dob}} Date of Birth

{{var customer.password_hash}}

{{var customer.prefix}}

{{var customer.middlename}} Initial

{{var customer.suffix}}

{{var customer.group_id}}

{{var customer.taxvat}}

{{var customer.store.name}}

{{var customer.store.group.name}}

&ndash; To subscribe/unsubscribe newsletter:

{{var subscriber.getConfirmationLink()}}

{{var subscriber.getUnsubscriptionLink()}}

{{var subscriber.email}}

&ndash; Send to a friend:

{{var product_image}}

{{var name}} Recipient&rsquo;s Name

{{var email}} Recipient&rsquo;s Email

{{var product_name}} Product Name

{{var product_url}} Product Url

{{var message}} Message Text

{{var sender_name}} Sender&rsquo;s Name

{{var sender_email}} Sender&rsquo;s Email

{{var product_image}} Product Image

&ndash; Depend Condition

{{depend order.getIsNotVirtual()}}

{{/depend}}

{{depend salable}}

{{/depend}}

&ndash; If Condition

{{if order.getIsNotVirtual()}}

{{else}}

{{/if}}

(else is optional)


&ndash; New order : Shipping Address

{{var order.getShippingAddress().format(&lsquo;html&rsquo;)}}

Items of the shipping address :

{{var order.getShippingAddress().getName()}} Get the first and last name

{{var order.getShippingAddress().getPrefix()}}

{{var order.getShippingAddress().getFirstName()}}

{{var order.getShippingAddress().getMiddleName()}}

{{var order.getShippingAddress().getLastName()}}

{{var order.getShippingAddress().getSuffix()}}

{{var order.getShippingAddress().getStreet1()}}

{{var order.getShippingAddress().getStreet2()}}

{{var order.getShippingAddress().getCity()}}

{{var order.getShippingAddress().getRegion()}}

{{var order.getShippingAddress().getPostcode()}}

{{var order.getShippingAddress().getCountry()}} Get the country&rsquo;s ID

{{var order.getShippingAddress().getCountryModel().getName()}} Get the country&rsquo;s full name

{{var order.getShippingAddress().getRegion()}}

{{var order.getShippingAddress().getTelephone()}}

&ndash; Other

{{var addAllLink}}

{{var alertGrid}}

{{var billingAddress.format(&lsquo;html&rsquo;)}}

{{var checkoutType}}

{{var comment}}

{{var creditmemo.id}}

{{var creditmemo.increment_id}}

{{var data.comment}}

{{var data.email}}

{{var data.name}}

{{var data.telephone}}

{{var dateAndTime}}

{{var invoice.id}}

{{var invoice.increment_id}}

{{var invoice.created_at}}

{{var items}}

{{var items_html}}

{{var message}}

{{var name}}

{{var order.customer_email}}

{{var order.getBillingAddress().format(&lsquo;html&rsquo;)}}

{{var order.getBillingAddress().getName()}}

{{var order.getCreatedAtFormated(&lsquo;long&rsquo;)}}

{{var order.getCustomerName()}}

{{var order.getCustomerFirstname()}}

{{var order.getCustomerLastname()}}

{{var order.getEmailCustomerNote()}} Currently unknwon how to test this variable for being set/empty

{{var order.getShippingDescription()}}

{{var order.getStatusLabel()}}

{{var order.getStoreGroupName()}}

{{var order.id}}

{{var order.increment_id}}

{{var password}}

{{var payment_html}}

{{var paymentMethod}}

{{var product_name}}

{{var product_url}}

{{var reason}} Reason for payment failure

{{var shipment.increment_id}}

{{var shippingAddress.format(&lsquo;html&rsquo;)}}

{{var shippingMethod}}

{{var total}}

{{var user.name}}

{{var viewOnSiteLink}}

{{var warnings}}

{{var billing.name}}</code></pre>
</div>]]></description>
      <pubDate>Mon, 08 Jan 2024 07:58:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[有用的 Magento 2 CLI 命令]]></title>
      <link>https://www.360magento.com/blog/magento2-CLI-commands/</link>
      <description><![CDATA[<h1><span>有用的 Magento 2 CLI 命令</span></h1>
<p><span>部署模式功能：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento deploy:mode:show
php bin/magento deploy:mode:set developer ( default | production | developer )
php bin/magento deploy:mode:set production --skip-compilation

php bin/magento maintenance:disable
php bin/magento maintenance:enable
php bin/magento maintenance:enable --ip=192.0.0.1 --ip=192.0.0.2 (for all clients except this IPs)
php bin/magento maintenance:enable --ip=none (to clear the list of IPs)
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>用于开发的 CSS 和 JS 配置</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento config:set dev/js/enable_js_bundling 0
php bin/magento config:set dev/js/merge_files 0
php bin/magento config:set dev/js/minify_files 0
php bin/magento config:set dev/css/merge_css_files 0
php bin/magento config:set dev/css/minify_files 0
php bin/magento config:set dev/static/sign 0

php bin/magento config:set --scope="stores" --scope-code="default" dev/js/minify_files 0
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>缓存操作：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento cache:status
php bin/magento c:f ( cache:flush }
php bin/magento c:c ( cache:clean }
php bin/magento cache:disable full_page layout block_html translate
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>默认缓存类型：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code> config
 layout
 block_html
 collections
 reflection
 db_ddl
 compiled_config
 eav
 customer_notification
 config_integration
 config_integration_api
 full_page
 config_webservice
 translate
 vertex
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>模块操作（检查当前状态/禁用模块/启用模块）：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento module:status
php bin/magento module:disable VENDOR_MODULENAME
php bin/magento module:enable VENDOR_MODULENAME
php bin/magento module:uninstall VENDOR_MODULENAME (if installed by Composer)
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>设置升级/设置编译/静态内容部署：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php -d memory_limit=2048M bin/magento setup:upgrade
php -d memory_limit=2048M bin/magento setup:di:compile
php -d memory_limit=2048M bin/magento setup:static-content:deploy
php bin/magento setup:static-content:deploy pl_PL -f
php bin/magento setup:static-content:deploy pl_PL --theme Vendor/theme --no-html-minify -f
php bin/magento setup:static-content:deploy pl_PL en_US en_GB --jobs 20

</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>设置配置：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento setup:store-config:set --base-url="http://project.dev/"
php bin/magento setup:store-config:set --base-url-secure="https://project.dev/"

php bin/magento config:set admin/security/session_lifetime 604800 ( 86400 = 1 day / 604800 = 7 days / 31536000 = 1 year / etc )
php bin/magento config:set admin/security/password_is_forced 0
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>索引器（重新索引|重置）：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento indexer:reset
php -d memory_limit=2048M bin/magento indexer:reindex

php bin/magento indexer:status
php bin/magento indexer:reset cataloginventory_stock
php bin/magento indexer:reindex cataloginventory_stock
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>为特定模块生成翻译包</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento i18n:collect-phrases -o app/code/Module/Vendor/i18n/pl_PL.csv app/code/Module/Vendor/
php bin/magento i18n:collect-phrases --output="app/design/frontend//Module/Vendor/i18n/pl_PL.csv" --magento (This option adds themes or modules to each line in the dictionary.)
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>目录图像调整大小：</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento catalog:image:resize
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>对于管理员</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento admin:user:create
php bin/magento info:adminuri
php bin/magento admin:user:unlock USERNAME
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<p><span>获取所有可用命令的列表</span></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>php bin/magento list
php bin/magento help</code></pre>
</div>
<div id="gtx-trans" style="position: absolute; left: 375px; top: -7.92188px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 08 Jan 2024 03:56:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 XML中的属性说明]]></title>
      <link>https://www.360magento.com/blog/magento2-handy-snippets/</link>
      <description><![CDATA[<h2><span>带模板的自定义块</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;block class="Magento\Framework\View\Element\Template" name="my_block" template="Vendor_Module::my-template.phtml" /&gt; ( after="-" or before="-" )
&lt;block class="Magento\Framework\View\Element\Template" name="footer_logo_brands" template="Magento_Theme::html/brand-logos.phtml" after="footer_links"/&gt; 
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#block-with-configuration-condition" id="user-content-block-with-configuration-condition" tabindex="-1"></a><span>具有配置条件的块</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;block class="Magento\Newsletter\Block\Subscribe" name="form.subscribe" as="subscribe" before="-" template="Magento_Newsletter::subscribe.phtml" ifconfig="newsletter/general/active"/&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#block-inside-container" id="user-content-block-inside-container" tabindex="-1"></a><span>容器内的块</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;container name="some.block.wrapper" htmlTag="div" htmlClass="container"&gt;
      // block here
&lt;/container&gt;</code></pre>
<h2><span>从 XML 调用静态块</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;referenceContainer name="footer-container"&gt;
            &lt;block class="Magento\Cms\Block\Block" name="promo" before="-"&gt;
                &lt;arguments&gt;
                    &lt;argument name="block_id" xsi:type="string"&gt;promo&lt;/argument&gt;
                &lt;/arguments&gt;
            &lt;/block&gt;
&lt;/referenceContainer&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#two-ways-set-template-in-xml" id="user-content-two-ways-set-template-in-xml" tabindex="-1"></a><span>在xml中设置模板的两种方法</span></h2>
<ol>
<li></li>
</ol>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;referenceBlock name="page.main.title" template="Vendor_Module::path/to/template.phtml"/&gt;`
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<ol start="2">
<li></li>
</ol>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;referenceBlock name="page.main.title"&gt;
	&lt;arguments&gt;
		&lt;argument name="template" xsi:type="string"&gt;Vendor_Module::path/to/template.phtml&lt;/argument&gt;
	&lt;/arguments&gt;
&lt;/referenceBlock&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#set-template-layout-in-xml-eg-2columns-left-in-catalog_category_viewxml" id="user-content-set-template-layout-in-xml-eg-2columns-left-in-catalog_category_viewxml" tabindex="-1"></a><span>在xml中设置模板布局（例如catalog_category_view.xml中的&ldquo;2columns-left&rdquo;）</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        ...
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#add-custom-link-to-toplinks-customer-dropdown" id="user-content-add-custom-link-to-toplinks-customer-dropdown" tabindex="-1"></a><span>将自定义链接添加到top.links（客户下拉列表）</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;referenceBlock name="top.links"&gt;
    &lt;block class="Magento\Framework\View\Element\Html\Link" name="acount-create-link"&gt;
        &lt;arguments&gt;
            &lt;argument name="label" xsi:type="string" translate="true"&gt;Create an Account&lt;/argument&gt;
            &lt;argument name="path" xsi:type="string"&gt;customer/account/create&lt;/argument&gt;
            &lt;argument name="sortOrder" xsi:type="number"&gt;100&lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/block&gt;
&lt;/referenceBlock&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#include-static-resources-javascript-css-fonts" id="user-content-include-static-resources-javascript-css-fonts" tabindex="-1"></a><span>包括静态资源（JavaScript、CSS、字体）</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;head&gt;
    &lt;!-- Add local styles resources --&gt;
    &lt;css src="css/my-styles.css" /&gt;
    &lt;css src="&lt;Namespace&gt;_&lt;Module&gt;::css/custom-styles.css" /&gt;

    &lt;!-- The following two ways to add local JavaScript files are equal --&gt;
    &lt;script src="Magento_Catalog::js/sample1.js" /&gt;
    &lt;script src="Magento_Catalog/js/sample1.js" /&gt;

    &lt;!-- Magento support async or defer attribute in script tag --&gt;
    &lt;script async="" src="Magento_Catalog::js/sample1.js" /&gt;
    &lt;script defer="" src="Magento_Catalog::js/sample1.js" /&gt;

    &lt;link src="js/sample.js" /&gt;
    &lt;link src="sample.js" /&gt;

    &lt;!-- Add external resources --&gt;
    &lt;css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" src_type="url" /&gt;
    &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" src_type="url" /&gt;
    &lt;link rel="stylesheet" type="text/css" src="http://fonts.googleapis.com/css?family=Montserrat" src_type="url" /&gt;
  &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#remove-static-resources-javascript-css-fonts" id="user-content-remove-static-resources-javascript-css-fonts" tabindex="-1"></a><span>删除静态资源（JavaScript、CSS、字体）</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;head&gt;
    &lt;!-- Remove local styles resources --&gt;
    &lt;remove src="css/styles-m.css" /&gt;
    &lt;remove src="&lt;Namespace&gt;_&lt;ModuleName&gt;::css/styles.css" /&gt;

    &lt;!-- Remove js resources --&gt;
    &lt;remove src="my-js.js" /&gt;
    &lt;remove src="Magento_Catalog::js/sample1.js" /&gt;

    &lt;!-- Remove external resources --&gt;
    &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" /&gt;
    &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" /&gt;
    &lt;remove src="http://fonts.googleapis.com/css?family=Montserrat" /&gt;
   &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#add-meta-tags-to-the-head-block" id="user-content-add-meta-tags-to-the-head-block" tabindex="-1"></a><span>将元标记添加到头块</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;head&gt;
    &lt;!-- This will create a tag like '&lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&gt;' --&gt;
    &lt;meta name="x_ua_compatible" content="IE=edge,chrome=1"/&gt;
    &lt;!-- This will create a tag like '&lt;meta property="og:type" content="article"/&gt;'' --&gt;
    &lt;meta name="og:type" content="article"/&gt;
    &lt;!-- This will create a tag like '&lt;meta charset="UTF-8"&gt;' --&gt;
    &lt;meta name="charset" content="UTF-8"/&gt;
    &lt;!-- This will create a tag like '&lt;meta http-equiv="Content-Type" content="content-type-value"/&gt;' --&gt;
    &lt;meta name="content_type" content="content-type-value"/&gt;
    &lt;!-- This tag will not render (see \Magento\Framework\View\Page\Config\Renderer for details) --&gt;
    &lt;meta name="media_type" content="any-value"/&gt;
    &lt;!-- This will create a tag like '&lt;meta name="my_custom_type" content="my_custom_value"/&gt;' --&gt;
    &lt;meta name="my_custom_type" content="my_custom_value"/&gt;
   &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#set-body-attributes" id="user-content-set-body-attributes" tabindex="-1"></a><span>设置身体属性</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;body&gt;
     &lt;attribute name="class" value="my-new-body-class"/&gt;
&lt;/body&gt;
</code></pre>
<div class="zeroclipboard-container"></div>
</div>
<h2><a class="anchor" href="https://github.com/dev-jq/magento2-handy-snippets/blob/master/xml.md#set-custom-page-title" id="user-content-set-custom-page-title" tabindex="-1"></a><span>设置自定义页面标题</span></h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto">
<pre class="notranslate"><code>&lt;referenceBlock name="page.main.title"&gt;
     &lt;action method="setPageTitle"&gt;
          &lt;argument translate="true" name="title" xsi:type="string"&gt;My title&lt;/argument&gt;
     &lt;/action&gt;
&lt;/referenceBlock&gt;</code></pre>
</div>
</div>]]></description>
      <pubDate>Sun, 07 Jan 2024 07:49:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento网站管理步骤]]></title>
      <link>https://www.360magento.com/blog/magento-website-management/</link>
      <description><![CDATA[<p>Magento是一款功能强大的电子商务平台，为在线商家提供了一个完整的解决方案。然而，要确保您的Magento网站能够取得成功并实现预期的业绩，良好的网站管理是至关重要的。本文将介绍一些关键的Magento网站管理步骤，以帮助您优化网站性能、提升用户体验并实现业务目标。</p>
<ol>
<li>
<p>定期备份和恢复：<br />每个Magento网站都应该定期备份其数据库和文件，以防止数据丢失或网站故障。您可以使用Magento的内置备份工具或第三方插件来执行自动备份，并确保备份文件的安全存储。在需要时，您可以使用这些备份文件来快速恢复网站。</p>
</li>
<li>
<p>更新和维护Magento版本：<br />Magento定期发布更新和修复程序，以解决安全漏洞和错误。确保您的Magento网站始终运行最新版本是至关重要的，这将有助于保护您的网站免受潜在的安全威胁，并提供更好的性能和功能。在进行任何升级前，务必在测试环境中进行充分的测试和验证。</p>
</li>
<li>
<p>密码和访问控制：<br />确保您的Magento网站具有强大的管理员密码，并将其保持机密。此外，限制对Magento后台的访问，并为每个管理员分配适当的权限。这样可以减少潜在的安全风险，并防止未经授权的访问和操作。</p>
</li>
<li>
<p>监控和性能优化：<br />使用监控工具来实时监测您的Magento网站的性能和可用性。这些工具可以提供关键指标，如网站的加载时间、访问量和服务器资源使用情况。通过定期监控，您可以及时发现并解决潜在的性能问题，并确保您的网站始终处于最佳状态。</p>
</li>
<li>
<p>安全和防护措施：<br />采取适当的安全措施来保护您的Magento网站免受潜在的攻击和恶意行为。这包括安装SSL证书，以确保安全的数据传输，以及配置防火墙和入侵检测系统来阻止恶意流量和未经授权的访问。</p>
</li>
<li>
<p>更新和优化内容：<br />定期更新您的Magento网站上的内容，并进行关键字优化，以提高搜索引擎排名和流量。确保您的商品信息、价格、促销和页面内容都是准确、清晰和吸引人的。此外，确保您的网站页面加载速度快，并具有良好的用户导航和响应式设计。</p>
</li>
<li>
<p>用户支持和反馈：<br />提供优质的用户支持，并鼓励用户提供反馈和建议。确保您的Magento网站上有易于找到的联系方式，并及时回复用户的问题和需求。用户反馈是改进您的网站和提供更好用户体验的重要来源。</p>
</li>
</ol>]]></description>
      <pubDate>Sun, 07 Jan 2024 03:46:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2的性能优化]]></title>
      <link>https://www.360magento.com/blog/Magento2-asa-srapageppasa/</link>
      <description><![CDATA[<p><span>Magento 2是一款功能强大的电子商务平台，但在处理大量产品和访问量较高的情况下，性能可能受到影响。本文将介绍一些Magento 2性能优化的关键方面和最佳实践，帮助您加速您的电子商务网站。</span></p>
<ol>
<li>
<p>了解Magento 2的性能挑战：</p>
<ul>
<li>Magento 2的复杂性和资源需求</li>
<li>响应时间和页面加载速度的重要性</li>
<li>常见的性能瓶颈和挑战</li>
</ul>
</li>
<li>
<p>优化Magento 2的服务器环境：</p>
<ul>
<li>选择适当的服务器规格和配置</li>
<li>配置服务器缓存和加速器</li>
<li>优化数据库性能和查询</li>
</ul>
</li>
<li>
<p>Magento 2缓存管理和优化：</p>
<ul>
<li>启用和配置Magento 2的缓存</li>
<li>优化缓存存储和清除策略</li>
<li>利用Varnish和Redis等外部缓存解决方案</li>
</ul>
</li>
<li>
<p>图像和静态资源优化：</p>
<ul>
<li>优化图像大小和格式</li>
<li>使用图像CDN加速图像加载</li>
<li>压缩和合并CSS和JavaScript文件</li>
</ul>
</li>
<li>
<p>代码和数据库优化：</p>
<ul>
<li>优化Magento 2的代码和扩展</li>
<li>避免不必要的重写和扩展</li>
<li>优化数据库查询和索引</li>
</ul>
</li>
<li>
<p>性能监测和测试：</p>
<ul>
<li>使用Magento 2的性能工具和插件</li>
<li>进行负载测试和压力测试</li>
<li>分析和监控网站性能</li>
</ul>
</li>
<li>
<p>高可用性和容错性：</p>
<ul>
<li>设置Magento 2的备份和恢复策略</li>
<li>实施负载均衡和故障转移机制</li>
<li>备份和优化Magento 2的数据</li>
</ul>
</li>
</ol>]]></description>
      <pubDate>Sat, 06 Jan 2024 07:43:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2的主题定制]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-customization/</link>
      <description><![CDATA[<p>Magento 2是一款强大的电子商务平台，提供了丰富的主题定制功能，使您能够创建独特而引人注目的在线商店外观。本文将介绍Magento 2主题定制的基本概念和步骤，以及如何利用它来实现个性化的品牌形象。</p>
<ol>
<li>
<p>Magento 2主题定制的基础知识：</p>
<ul>
<li>Magento 2的主题结构和层次</li>
<li>主题文件和目录的作用</li>
<li>主题继承和覆盖机制</li>
</ul>
</li>
<li>
<p>创建自定义Magento 2主题：</p>
<ul>
<li>创建主题文件和目录结构</li>
<li>定义主题的基本配置</li>
<li>创建和修改布局文件</li>
<li>自定义样式和CSS</li>
<li>添加和修改静态资源（图像、字体等）</li>
</ul>
</li>
<li>
<p>主题定制的最佳实践：</p>
<ul>
<li>使用子主题进行定制</li>
<li>利用Magento 2的主题继承机制</li>
<li>重写和扩展Magento 2的模板文件</li>
<li>利用Magento 2的UI组件进行布局定制</li>
</ul>
</li>
<li>
<p>主题定制的高级技巧和扩展：</p>
<ul>
<li>利用Magento 2的LESS和RequireJS进行高级样式和脚本定制</li>
<li>创建自定义模块和主题集成</li>
<li>主题本地化和多语言支持</li>
</ul>
</li>
<li>
<p>主题定制的测试和部署：</p>
<ul>
<li>使用Magento 2的开发者工具进行主题定制的调试和测试</li>
<li>主题定制的部署和发布流程</li>
<li>主题定制的性能优化和缓存管理</li>
</ul>
</li>
</ol>]]></description>
      <pubDate>Sat, 06 Jan 2024 03:41:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[了解Magento 2：功能强大的电子商务平台]]></title>
      <link>https://www.360magento.com/blog/introduction-to-magento2/</link>
      <description><![CDATA[<p>Magento 2是一款开源的电子商务平台，具有丰富的功能和灵活的可扩展性。本文将介绍Magento 2的主要特点和功能，以及为什么它是构建强大在线商店的理想选择。</p>
<ol>
<li>
<p>Magento 2的特点和优势：</p>
<ul>
<li>现代化的架构和技术栈</li>
<li>强大的扩展性和定制性</li>
<li>多店铺和多语言支持</li>
<li>响应式设计和移动优化</li>
<li>内置的SEO功能和营销工具</li>
</ul>
</li>
<li>
<p>Magento 2的核心功能：</p>
<ul>
<li>产品和目录管理</li>
<li>订单和支付处理</li>
<li>客户管理和个性化体验</li>
<li>营销和促销工具</li>
<li>物流和库存管理</li>
</ul>
</li>
<li>
<p>Magento 2的模块和扩展市场：</p>
<ul>
<li>Magento Marketplace的扩展和主题</li>
<li>自定义模块和主题开发</li>
<li>第三方集成和API支持</li>
</ul>
</li>
<li>
<p>Magento 2的性能和安全性：</p>
<ul>
<li>缓存和索引优化</li>
<li>代码和数据的安全性</li>
<li>支持HTTPS和PCI DSS合规性</li>
</ul>
</li>
<li>
<p>Magento 2的社区和支持：</p>
<ul>
<li>Magento开发者社区和论坛</li>
<li>官方文档和教程资源</li>
<li>Magento认证和培训机会</li>
</ul>
</li>
</ol>
<p>结论：Magento 2是一款功能强大的电子商务平台，它提供了丰富的功能和灵活的可扩展性，让您能够构建和管理强大的在线商店。无论是小型企业还是大型企业，Magento 2都是一个值得考虑的选择。</p>]]></description>
      <pubDate>Fri, 05 Jan 2024 08:39:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的API来获取产品信息]]></title>
      <link>https://www.360magento.com/blog/magento2-api-get-products/</link>
      <description><![CDATA[<pre>
$host = 'http://your-magento-site.com';
$apiUser = 'your_api_username';
$apiKey = 'your_api_key';

$productId = 123; // 产品ID

$client = new SoapClient($host . '/api/soap/?wsdl');

// 登录到API
$session = $client-&gt;login($apiUser, $apiKey);

// 获取产品信息
$productInfo = $client-&gt;call($session, 'catalog_product.info', $productId);

// 打印产品信息
echo '产品名称：' . $productInfo['name'] . "\n";
echo '产品价格：' . $productInfo['price'] . "\n";
echo '产品描述：' . $productInfo['description'] . "\n";

// 注销API会话
$client-&gt;endSession($session);
</pre>
<pre><br /><br /></pre>
<p>在上述示例代码中，您需要替换以下变量：</p>
<ul>
<li><code>$host</code>：您的Magento站点的URL。</li>
<li><code>$apiUser</code>：您在Magento中创建的API用户名。</li>
<li><code>$apiKey</code>：与API用户关联的API密钥。</li>
<li><code>$productId</code>：您要获取信息的产品ID。</li>
</ul>
<p>上述代码首先创建了一个SOAP客户端，并使用提供的URL进行登录。然后，通过调用<code>catalog_product.info</code>方法并传递产品ID，从API中获取产品信息。最后，通过打印结果来显示产品的名称、价格和描述等信息。</p>
<p>请确保您的Magento站点已启用并配置了SOAP API，并且您已经具有正确的API访问凭据。</p>]]></description>
      <pubDate>Thu, 04 Jan 2024 16:33:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何配置 Magento 2 管理操作日志]]></title>
      <link>https://www.360magento.com/blog/system_config_edit/</link>
      <description><![CDATA[<p>Magento 2是一款强大的电商平台，为了确保系统的安全性和稳定性，配置管理操作日志是至关重要的。管理操作日志记录了后台用户的活动，帮助你跟踪变更、排除问题，并提高系统监控水平。</p>
<p>以下是配置Magento 2管理操作日志的步骤：</p>
<h3>步骤1：登录Magento 2后台</h3>
<p>首先，使用管理员凭证登录Magento 2后台。</p>
<h3>步骤2：打开配置设置</h3>
<ol>
<li>在左侧导航栏中，选择&ldquo;系统&rdquo;。</li>
<li>在下拉菜单中，选择&ldquo;配置&rdquo;。</li>
</ol>
<h3>步骤3：选择管理操作日志设置</h3>
<p>在配置页面，选择&ldquo;高级&rdquo;部分。在这里，你可以看到&ldquo;系统&rdquo;下的&ldquo;管理操作日志&rdquo;。</p>
<h3>步骤4：启用管理操作日志</h3>
<ol>
<li>将&ldquo;启用管理操作日志&rdquo;选项切换为&ldquo;是&rdquo;。</li>
<li>根据需要，你还可以调整&ldquo;最长日志保留期限&rdquo;以限制日志保存的时间。</li>
</ol>
<h3>步骤5：保存配置</h3>
<p>确保在更改设置后，点击页面右上角的&ldquo;保存配置&rdquo;按钮。</p>
<h3>步骤6：检查日志</h3>
<p>现在，Magento 2将开始记录管理操作日志。你可以在系统的/var/log目录中找到日志文件。</p>
<div id="gtx-trans" style="position: absolute; left: -132px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 04 Jan 2024 06:52:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中重写控制器]]></title>
      <link>https://www.360magento.com/blog/magento-review-Controller/</link>
      <description><![CDATA[<h2>1. <span>了解Magento的控制器结构</span></h2>
<p>在开始重写控制器之前，首先需要了解Magento的控制器结构。Magento的控制器通常位于<code>app/code/{Vendor}/{Module}/Controller/{Path}</code>目录下。了解控制器的路径结构以及它们是如何组织的，对于成功地进行重写是至关重要的。</p>
<h2>2. <span>选择重写的控制器</span></h2>
<p>确定你想要重写的控制器。在Magento中，你可以通过查看模块的<code>routes.xml</code>文件来了解控制器的路由和名称。选择与你定制需求相关的控制器进行重写。</p>
<h2>3. <span>创建一个新的模块</span></h2>
<p>在开始重写之前，创建一个新的Magento模块。这可以通过创建一个<code>registration.php</code>文件和一个<code>module.xml</code>文件来实现。确保在<code>module.xml</code>文件中指定正确的依赖关系和顺序。</p>
<h2>4. <span>创建新的控制器类</span></h2>
<p>在新的模块中创建一个新的控制器类，该类将用于替代原始控制器。确保这个类继承自原始控制器，并重写你需要修改的方法。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/QQ20240102-151524_2x.png" /></p>
<h2>5. <span>配置重写</span></h2>
<p>在新的模块目录下，创建一个<code>di.xml</code>文件，用于配置控制器的重写。在文件中添加以下内容：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/QQ20240102-151535_2x.png" /></p>
<p>确保替换大括号内的占位符为你实际的供应商、模块和控制器路径。</p>
<h2>6. <span>清除缓存</span></h2>
<p>在完成上述步骤后，清除Magento缓存以确保新的控制器类得到正确加载。</p>]]></description>
      <pubDate>Wed, 03 Jan 2024 07:14:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento JS异步加载优化]]></title>
      <link>https://www.360magento.com/blog/magento-js-custom/</link>
      <description><![CDATA[<p>JavaScript异步加载是提高Magento网站性能的一项重要策略。通过在加载JavaScript时优化异步加载，你可以确保页面在等待文件下载和执行时仍能够迅速呈现。以下是一些建议，帮助你优化Magento JS异步加载。</p>
<h2>1. 合理使用异步标记</h2>
<p>在Magento中，你可以使用<code>async</code>标记来异步加载JavaScript文件。确保仅将此标记应用于不影响关键用户交互和页面渲染的文件。对于必需的JS文件，考虑使用延迟加载，以确保它们在页面准备好时加载。</p>
<p>&lt;script src="your-script.js" async&gt;&lt;/script&gt;</p>
<h2>2. 考虑使用延迟加载</h2>
<p>延迟加载允许JavaScript文件在页面加载完毕后再加载，而不会阻塞页面的初始渲染。这对于非关键脚本和跟踪代码非常有用，但要小心不要延迟加载对页面关键功能和用户体验有影响的文件。<br /><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"your-script.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></p>
<h2>3. 优化加载顺序</h2>
<p>确保按照正确的顺序加载JavaScript文件，特别是对于依赖关系较强的文件。这可以防止潜在的错误和确保文件按照正确的顺序执行。</p>
<h2>4. 使用外部库和CDN</h2>
<p>考虑将常用的JavaScript库，如jQuery等，从外部引入并托管在内容分发网络（CDN）上。这可以提高文件加载速度，并利用CDN的缓存效果。</p>
<h2>5. 定期检查和测试</h2>
<p>在Magento后台启用JS合并和缓存时，定期检查并测试你的网站性能。确保这些优化措施仍然有效，并根据需要进行调整。</p>]]></description>
      <pubDate>Wed, 03 Jan 2024 03:11:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento布局]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-custom/</link>
      <description><![CDATA[<p>Magento是一款强大而灵活的电子商务平台，而布局设计是打造成功在线商店的关键因素之一。在这篇博客中，我们将深入探讨Magento布局的相关概念，帮助你优化你的网站设计，提升用户体验。</p>
<h2>1. Magento布局基础</h2>
<p>Magento采用XML文件定义布局，将页面划分为块（blocks）、容器（containers）和其他元素。了解布局基础是优化和定制你的商店外观的第一步。</p>
<h2>2. 主题和布局</h2>
<p>Magento主题是布局的核心组成部分之一。通过选择或创建适合你品牌的主题，你可以轻松改变整个商店的外观。了解如何在Magento中使用主题以及如何自定义主题布局是成功设计商店的关键。</p>
<h2>3. 响应式设计</h2>
<p>随着移动设备的普及，响应式设计变得至关重要。确保你的Magento布局能够适应不同屏幕大小和设备类型，提供无缝的用户体验。</p>
<h2>4. 布局调试和优化</h2>
<p>在实际设计中，布局可能会遇到一些挑战。学会使用Magento提供的调试工具，如Layout Handles和Template Path Hints，可以帮助你更轻松地识别和解决布局问题。</p>
<h2>5. 自定义布局元素</h2>
<p>除了使用Magento提供的默认布局元素外，你还可以通过自定义块和容器来进一步个性化你的商店。掌握如何添加自定义布局元素将帮助你实现更精确的设计目标。</p>]]></description>
      <pubDate>Tue, 02 Jan 2024 07:19:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2集成支付]]></title>
      <link>https://www.360magento.com/blog/integrating-payment-gateways-magento-2/</link>
      <description><![CDATA[<p>在电商网站中，集成支付网关是一个关键的任务，而Magento 2提供了强大的功能来实现与各种支付网关的集成。本篇博客将为您介绍Magento 2集成支付网关的步骤和注意事项，帮助您顺利实现安全、可靠的在线支付功能。</p>
<p>首先，我们将讨论Magento 2支付网关集成的准备工作。这包括了解您选择的支付网关的要求和接口文档，获取必要的API密钥和凭证，以及确保您的Magento 2网站具备HTTPS支持和SSL证书等安全要求。</p>
<p>接下来，我们将深入探讨Magento 2支付网关集成的实际步骤。我们将介绍如何使用Magento 2的扩展机制来安装和配置支付网关模块。您将学习如何设置支付网关的参数、回调URL和通知机制，以确保支付交易的正常处理和状态更新。</p>
<p>我们还将讨论Magento 2中的支付流程和订单管理。您将了解如何处理支付请求、生成订单、更新订单状态和发送支付确认邮件给客户。</p>
<p>除了基本的支付网关集成，我们还将介绍一些高级功能和注意事项。这包括处理退款和取消订单、处理异常情况和错误处理、以及实施额外的安全性措施，如双因素身份验证和反欺诈策略等。</p>
<p>最后，我们将分享一些Magento 2支付网关集成的最佳实践。这些实践包括进行充分的测试和模拟交易，定期监测支付交易日志和报告，以及保持与支付网关提供商的沟通和升级。</p>]]></description>
      <pubDate>Mon, 01 Jan 2024 07:08:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento主题开发]]></title>
      <link>https://www.360magento.com/blog/magento-theme-development/</link>
      <description><![CDATA[<p>在电商网站设计中，主题起着至关重要的作用，决定了网站的外观和用户体验。Magento作为一款流行的电商平台，提供了强大而灵活的主题开发功能，使网站开发人员能够根据特定需求定制化网站设计。本文将详细介绍Magento主题开发的关键步骤，帮助您创建独特且符合品牌形象的电商网站。</p>
<ol>
<li>理解Magento主题结构</li>
</ol>
<p>首先，我们将介绍Magento主题的基本结构。您将了解到Magento主题的目录结构，包括主题文件夹、布局文件、模板文件、静态资源文件等。我们将解释每个文件夹和文件的作用，以及它们在主题开发中的重要性。</p>
<ol start="2">
<li>创建自定义主题</li>
</ol>
<p>接下来，我们将讨论如何创建自定义主题。您将学习如何在Magento中创建新的主题文件夹，并设置主题的层次结构。我们还将介绍如何创建主题的配置文件，并设置主题的父主题（如果有）。此外，我们将探讨如何在Magento后台中启用和配置自定义主题。</p>
<ol start="3">
<li>定义主题布局</li>
</ol>
<p>在本节中，我们将重点介绍如何定义主题的布局。您将学习如何创建主题的布局文件，并使用Magento的布局指令来定义页面的结构和内容。我们将讨论如何定义主页、分类页面、产品页面等的布局，并展示如何使用块和容器来组织页面的不同部分。</p>
<ol start="4">
<li>定制主题样式</li>
</ol>
<p>在此部分，我们将讨论如何定制主题的样式。您将了解如何使用CSS和LESS来修改主题的样式表，并实现自定义的外观效果。我们将介绍如何使用Magento的样式继承机制和样式覆盖规则，以确保样式修改的正确应用。</p>
<ol start="5">
<li>集成JavaScript和定制功能</li>
</ol>
<p>最后，我们将讨论如何集成JavaScript和定制功能到主题中。您将学习如何添加自定义JavaScript文件，并进行必要的初始化和事件处理。我们还将介绍如何使用Magento的模块开发功能，添加自定义功能和扩展到主题中，以满足特定需求。</p>]]></description>
      <pubDate>Sun, 31 Dec 2023 16:22:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2主题开发]]></title>
      <link>https://www.360magento.com/blog/magento-2-theme-development/</link>
      <description><![CDATA[<p>Magento 2作为一款功能强大的电商平台，提供了丰富的主题定制化选项，使您能够个性化您的电商网站外观。在本篇博客中，我们将深入探讨Magento 2主题开发，帮助您定制化网站外观，以满足品牌需求和提供卓越的用户体验。</p>
<p>首先，我们将介绍Magento 2主题的基本结构和文件组成。了解主题的目录结构、模板文件和布局文件的关系，是进行主题开发的关键。</p>
<p>接下来，我们将讨论Magento 2主题开发中的样式定制。您将学习如何使用CSS和LESS来修改和定制网站的样式，包括颜色、字体、布局等。我们还将介绍如何使用Magento 2的样式覆盖机制和模块化CSS来避免样式冲突。</p>
<p>我们还将深入研究Magento 2主题的模板定制。通过修改和定制Magento 2的模板文件，您可以调整网站的布局、块级元素和内容显示。我们将演示如何使用Magento 2的块和容器来构建自定义页面和部分，以及如何使用UI组件来实现交互功能。</p>
<p>此外，我们将讨论Magento 2主题开发中的响应式设计。了解如何创建响应式的主题，以适应不同设备和屏幕尺寸，将为您的电商网站提供无缝的跨平台体验。</p>
<p>最后，我们将分享一些Magento 2主题开发的最佳实践和调试技巧。这些实践包括代码规范、调试工具和跨浏览器测试，以确保您开发的主题在各种环境下工作正常。</p>
<p>通过本篇博客，您将掌握Magento 2主题开发的关键技巧，能够定制化您的电商网站外观，提升品牌形象和用户体验。</p>]]></description>
      <pubDate>Sun, 31 Dec 2023 08:07:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento布局开发]]></title>
      <link>https://www.360magento.com/blog/magento-layout-insights/</link>
      <description><![CDATA[<p>在电商网站的设计和开发过程中，布局起着至关重要的作用。Magento作为一款流行的电商平台，提供了灵活而强大的布局系统，使网站设计人员能够创建具有吸引力和功能性的页面。本文将深入探讨Magento布局的重要性以及如何优化布局以提升电商网站的设计和用户体验。</p>
<ol>
<li>了解Magento布局体系结构</li>
</ol>
<p>首先，我们将介绍Magento布局体系结构的基本概念。您将了解到Magento布局的层次结构，包括布局文件、块（Blocks）和容器（Containers）的概念。我们将探讨布局文件的作用和结构，并介绍常用的布局文件类型，如XML布局文件和主题布局文件。</p>
<ol start="2">
<li>使用布局文件自定义页面结构</li>
</ol>
<p>接下来，我们将讨论如何使用Magento的布局文件来自定义页面结构。您将了解如何创建自定义布局文件，并使用布局指令来定义页面上的块和容器。我们将介绍如何在布局文件中引用模板文件和块类，并向您展示如何使用布局文件来组织页面的不同部分和内容。</p>
<ol start="3">
<li>利用布局文件进行页面排版和设计</li>
</ol>
<p>在本节中，我们将探讨如何使用Magento的布局文件进行页面排版和设计。您将学习如何使用布局指令来定义页面的列和行，以及如何配置块和容器的位置和大小。我们还将介绍如何使用Magento的栅格系统来创建响应式布局，以适应不同的设备和屏幕尺寸。</p>
<ol start="4">
<li>优化布局以提升用户体验</li>
</ol>
<p>最后，我们将分享一些优化布局的最佳实践，以提升电商网站的用户体验。您将学习如何合理使用布局文件和块来优化页面加载速度，以及如何通过合理的布局设计来提升页面的可用性和易用性。我们还将介绍如何使用Magento的布局更新（Layout Updates）功能来实现页面的动态变化和个性化。</p>]]></description>
      <pubDate>Sun, 31 Dec 2023 03:21:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2缓存优化]]></title>
      <link>https://www.360magento.com/blog/optimizing-magento-2-performance/</link>
      <description><![CDATA[<p>作为一款功能强大的电商平台，Magento 2的性能优化对于提供良好的用户体验至关重要。在本篇博客中，我们将分享一些优化Magento 2性能的关键技巧，帮助您加速网站加载速度、提高响应性能，并提升整体用户体验。</p>
<p>首先，我们将介绍Magento 2的缓存系统。了解如何正确配置和管理Magento 2的缓存设置，包括页面缓存、块级缓存和对象缓存，可以显著减少页面加载时间和数据库负载。</p>
<p>接着，我们将探讨优化Magento 2的数据库性能。通过优化数据库查询、索引和表结构，您可以提高数据访问速度和响应性能。我们还将介绍工具和技术，如数据库分片和读写分离，用于处理高负载情况下的数据库压力。</p>
<p>我们还将讨论优化Magento 2前端性能的关键技巧。这包括合并和压缩CSS和JavaScript文件、使用图像优化技术、启用HTTP/2和CDN等，以加快网页加载速度并减少网络请求。</p>
<p>此外，我们将分享一些针对Magento 2的服务器配置和优化建议。通过正确配置服务器环境、调整PHP和数据库参数，以及使用高性能缓存和反向代理等技术，您可以提升Magento 2的整体性能表现。</p>
<p>最后，我们将提供一些监测和测试Magento 2性能的工具和方法。通过定期监测和测试，您可以识别瓶颈和性能问题，并采取相应的优化措施。</p>
<p>通过本篇博客，您将了解到一些关键的技巧和最佳实践，帮助您优化Magento 2的性能，提升网站速度和用户体验。</p>]]></description>
      <pubDate>Sat, 30 Dec 2023 08:06:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2安全性指南]]></title>
      <link>https://www.360magento.com/blog/magento-2-security-guide/</link>
      <description><![CDATA[<p>首先，我们将介绍Magento 2的安全功能和设置。这包括使用安全证书（SSL）来加密网站的通信，启用两步验证（2FA）以增强管理员和用户的身份验证，以及配置强密码策略和登录尝试限制来防止恶意登录。</p>
<p>接着，我们将深入研究Magento 2安全性的主要方面。您将了解到如何保护Magento 2的后台管理页面，包括限制IP访问、使用安全的管理员用户名和密码，以及监控和审计管理员活动。我们还将讨论如何保护Magento 2的数据库，包括加密敏感数据、定期备份和监控数据库的安全性。</p>
<p>我们还将探讨Magento 2插件和主题的安全性。您将学习如何选择可靠的插件和主题供应商，审查插件和主题的代码质量和安全性，以及定期更新和升级插件和主题以修复安全漏洞。</p>
<p>此外，我们将介绍一些Magento 2安全性的最佳实践和建议。这些实践包括定期更新Magento 2的核心代码和扩展，使用安全的托管环境和防火墙，定期进行安全性扫描和漏洞评估，以及培训员工和用户有关安全性最佳实践和保护隐私的意识。</p>
<p>最后，我们将分享一些Magento 2安全性资源和社区支持。您将了解到可以获取安全性文档、漏洞报告和安全更新的官方资源，以及参与Magento 2安全性社区和论坛的机会。</p>]]></description>
      <pubDate>Sat, 30 Dec 2023 03:16:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento数据库优化]]></title>
      <link>https://www.360magento.com/blog/magento-database-optimization/</link>
      <description><![CDATA[<p>数据库是Magento系统关键组成部分,优化它对提升整体性能影响重大。主要优化方面包括:</p>
<ol>
<li>索引优化</li>
</ol>
<p>根据查询条件添加合理索引,如商品名、分类等字段。</p>
<ol start="2">
<li>表结构优化</li>
</ol>
<p>调整表字段类型、去除没用字段、合并小表等操作。</p>
<ol start="3">
<li>查询优化</li>
</ol>
<p>避免表关联深度过多,使用explain分析查询效率。</p>
<ol start="4">
<li>缓存查询结果</li>
</ol>
<p>对常用数据如商品信息等进行缓存,降低查询次数。</p>
<ol start="5">
<li>分表设计</li>
</ol>
<p>对数据量大的表 like order_item 分割表。</p>
<ol start="6">
<li>数据库参数调优</li>
</ol>
<p>优化MySQL参数如查询缓存大小、连接数等。</p>
<ol start="7">
<li>数据归档</li>
</ol>
<p>定期归档老数据到其他数据库或表,降低活跃表数据量。</p>
<p>通过系统地进行这些优化,可以显著提升Magento数据库访问效率,对整体系统性能提升很重要。</p>]]></description>
      <pubDate>Fri, 29 Dec 2023 07:05:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 SEO优化]]></title>
      <link>https://www.360magento.com/blog/magento-2-seo-optimization/</link>
      <description><![CDATA[<p>在竞争激烈的电商市场中，优化您的网站以提升搜索排名是至关重要的。Magento 2作为一款流行的电商平台，提供了各种功能和工具来帮助您进行SEO（搜索引擎优化）。在本篇博客中，我们将深入探讨Magento 2的SEO优化策略和技巧，帮助您提升电商网站在搜索引擎中的可见性和排名。</p>
<p>首先，我们将介绍Magento 2中的基本SEO设置和配置。您将学习如何优化网站的标题（Title）、描述（Meta Description）和关键词（Meta Keywords），以及如何生成友好的URL结构。我们还将讨论如何设置网站地图（Sitemap）和Robots.txt文件，以便搜索引擎能够正确地抓取和索引您的网页。</p>
<p>接下来，我们将深入探讨Magento 2网页优化的关键因素。这包括优化网页内容、使用关键词和标签、以及创建高质量的产品和类别页面。我们还将介绍如何优化网页的加载速度和性能，以提供更好的用户体验和满足搜索引擎的要求。</p>
<p>我们还将讨论Magento 2中的技术SEO优化。这包括使用友好的URL重写（URL Rewrites）来消除重复内容和优化链接结构，设置301重定向以处理页面重定向和更改，以及使用Canonical标签来处理重复内容和规范化网页版本。</p>
<p>除了基本的SEO优化，我们还将介绍一些高级策略和技巧。这包括优化图像和多媒体内容、集成社交媒体和用户生成内容、以及使用结构化数据（Schema Markup）来增强搜索结果的显示。</p>
<p>最后，我们将分享一些Magento 2 SEO优化的最佳实践和工具。这些实践包括进行关键词研究和竞争分析、定期监测和跟踪搜索排名和流量、以及参与社区和论坛来获取更多的SEO建议和支持。</p>]]></description>
      <pubDate>Fri, 29 Dec 2023 03:09:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 REST API]]></title>
      <link>https://www.360magento.com/blog/mobile-development-with-magento-2-rest-api/</link>
      <description><![CDATA[<p>Magento 2提供了完整的RESTful API接口,开发者可以基于此为移动端应用快速开发 order 管理、商品浏览等功能:</p>
<ol>
<li>获取Access Token</li>
</ol>
<p>调用OAuth接口获取长期有效的访问令牌。</p>
<ol start="2">
<li>API路由与权限</li>
</ol>
<p>了解各API接口地址与需要的权限级别。</p>
<ol start="3">
<li>数据模型与实体</li>
</ol>
<p>传输的JSON格式与Magento对象对应。</p>
<ol start="4">
<li>订单管理API</li>
</ol>
<p>创建、更新订单以及查询订单详情状态。</p>
<ol start="5">
<li>商品资源API</li>
</ol>
<p>搜索、浏览分类和商品详情信息。</p>
<ol start="6">
<li>客户资源API</li>
</ol>
<p>管理用户地址单和客户账户信息。</p>
<ol start="7">
<li>配置API</li>
</ol>
<p>获取系统配置如货币的信息。</p>
<ol start="8">
<li>异步任务API</li>
</ol>
<p>支持定期同步更新订单等后台任务。</p>
<ol start="9">
<li>错误处理</li>
</ol>
<p>标准化处理各类API调用错误。</p>
<p>利用REST API可以快速构建跨平台的移动解决方案,有效扩展Magento商城业务。</p>]]></description>
      <pubDate>Thu, 28 Dec 2023 07:04:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2插件开发]]></title>
      <link>https://www.360magento.com/blog/magento-2-plugin-development/</link>
      <description><![CDATA[<p>Magento 2作为一款功能强大的电商平台，提供了插件开发的灵活性，使您能够扩展和定制化您的电商网站功能。在本篇博客中，我们将深入探讨Magento 2插件开发，帮助您扩展网站功能，满足特定业务需求和提供更好的用户体验。</p>
<p>首先，我们将介绍Magento 2插件的基本概念和结构。了解插件的目录结构、配置文件和代码组成是进行插件开发的关键。我们还将探讨插件的类型，包括观察者（Observers）、插件（Plugins）和扩展（Extensions），以及它们在Magento 2中的应用场景和用途。</p>
<p>接下来，我们将深入研究Magento 2插件开发中的关键技术和功能。您将学习如何使用观察者模式来监听和响应Magento 2中的事件，以实现定制化的业务逻辑。我们还将介绍如何使用插件来修改和扩展Magento 2的核心功能，如模型（Models）、控制器（Controllers）和块（Blocks）。</p>
<p>我们还将讨论Magento 2插件开发中的最佳实践和调试技巧。这些实践包括使用正确的事件和插件顺序、编写干净和可维护的代码、以及使用调试工具和日志记录来排查问题和优化性能。</p>
<p>除了基本的插件开发，我们还将介绍一些高级功能和应用。这包括创建自定义的插件配置、实现插件的版本控制和升级、以及在多个Magento 2实例之间共享和复用插件。</p>
<p>最后，我们将分享一些Magento 2插件开发的资源和社区支持。您将了解到可以获取插件开发文档、示例代码和教程的官方资源，以及参与Magento 2开发者社区和论坛的机会。</p>]]></description>
      <pubDate>Wed, 27 Dec 2023 16:09:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[了解Magento 2的模块开发]]></title>
      <link>https://www.360magento.com/blog/magento-2-module-development/</link>
      <description><![CDATA[<p>Magento 2是一款功能强大的开源电商平台，广泛应用于各种规模的电商网站。其中，模块开发是扩展和定制Magento 2功能的关键部分。在本篇博客中，我们将深入了解Magento 2的模块开发，为您提供宝贵的指导和技巧。</p>
<p>首先，我们将介绍Magento 2模块的基本结构和组成部分。了解模块的目录结构、配置文件和代码组织对于正确开发和集成模块至关重要。</p>
<p>接下来，我们将深入探讨Magento 2模块的事件（Event）和观察者（Observer）系统。通过使用事件和观察者，您可以在Magento 2的各个关键点插入自定义逻辑，实现个性化的功能扩展。</p>
<p>我们还将介绍Magento 2模块的插件（Plugin）机制。插件提供了一种非侵入性的方式，允许您修改和扩展Magento 2核心类的行为。我们将详细讨论插件的创建、配置和使用。</p>
<p>此外，我们将研究Magento 2模块的数据库操作和数据迁移。您将学习如何使用Magento 2提供的资源模型和安装脚本来管理数据库结构和数据。</p>
<p>最后，我们将分享一些Magento 2模块开发的最佳实践。这些实践包括代码质量、性能优化和安全性等方面的建议，以确保您开发的模块在生产环境中稳定可靠。</p>]]></description>
      <pubDate>Wed, 27 Dec 2023 07:03:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2数据迁移]]></title>
      <link>https://www.360magento.com/blog/comprehensive-guide-magento-2-data-migration/</link>
      <description><![CDATA[<p>在将您的电商网站迁移到Magento 2平台时，数据迁移是一个至关重要的任务。为了帮助您顺利迁移数据并确保数据完整性，本篇博客将提供Magento 2数据迁移的综合指南，涵盖关键步骤、工具和最佳实践。</p>
<p>首先，我们将介绍Magento 2数据迁移的准备工作。这包括了解您当前网站的数据结构、数据库和文件系统，以及评估迁移的范围和复杂性。我们还将讨论如何创建备份和快照，以防止数据丢失或损坏。</p>
<p>接下来，我们将深入探讨Magento 2数据迁移的不同方法。您将了解到使用Magento 2的数据迁移工具（Data Migration Tool）的步骤和流程。我们还将介绍如何使用第三方迁移工具和扩展，以满足特定的迁移需求。</p>
<p>我们将讨论Magento 2数据迁移中的常见挑战和解决方案。这包括处理数据格式的不兼容性、解决数据库架构差异、以及处理自定义模块和功能的迁移问题。我们还将提供一些建议和技巧，帮助您克服潜在的问题和障碍。</p>
<p>除了基本的数据迁移，我们还将介绍如何迁移其他关键数据，如产品、订单、客户和库存。您将学习如何映射和转换数据字段、处理数据关联性、以及确保数据的一致性和准确性。</p>]]></description>
      <pubDate>Wed, 27 Dec 2023 03:09:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2与跨境电子商务]]></title>
      <link>https://www.360magento.com/blog/magento2-cross-border-ecommerce-strategies/</link>
      <description><![CDATA[<p>随着全球化和数字化的推进，跨境电子商务成为许多商家拓展市场的重要途径。作为一种功能丰富的电子商务平台，Magento 2为商家提供了一系列跨境电子商务策略和扩展功能，帮助他们克服跨境交易中的挑战，并实现全球销售。在本文中，我们将探讨一些适用于Magento 2的跨境电子商务策略和扩展。</p>
<ol>
<li>
<p>多语言和多货币支持：利用Magento 2的多语言和多货币功能，将您的网站本地化以适应不同的目标市场。提供多种语言选项和货币转换功能，可以提高用户的舒适度和购买意愿。</p>
</li>
<li>
<p>地理定位和本地化：通过使用地理定位技术和本地化策略，向用户提供与其所在地区相关的内容、价格和优惠。根据用户的位置和IP地址，自动调整货币、税率和运费等信息，提高用户的购买体验和转化率。</p>
</li>
<li>
<p>国际物流和运输：整合Magento 2与全球物流服务提供商，以简化跨境物流和运输过程。提供多个物流选项、实时运费计算和订单追踪功能，确保订单能够快速、可靠地送达全球各地。</p>
</li>
<li>
<p>海关和税务合规性：了解目标市场的海关和税务规定，并确保您的Magento 2网站符合当地的法规要求。提供正确的产品分类、税率计算和报关文件，以避免海关问题和税务纠纷。</p>
</li>
<li>
<p>支付和结算：提供多种跨境支付选项，如信用卡支付、电子钱包和本地化支付解决方案。整合安全可靠的支付网关，并确保支付过程符合当地的支付安全标准和合规要求。</p>
</li>
<li>
<p>跨境营销和推广：针对不同的目标市场制定跨境营销和推广策略。利用Magento 2的市场营销工具和功能，如SEO优化、社交媒体整合和跨境广告活动，增加品牌曝光和用户参与度。</p>
</li>
<li>
<p>多国家客户支持：提供多语言的客户支持和售后服务，以满足不同国家和地区的用户需求。设立多语言的客服团队，并提供在线聊天、电子邮件和电话支持等渠道，解答用户的疑问和处理问题。</p>
</li>
<li>
<p>跨境数据分析和优化：利用Magento 2的数据分析工具和仪表板，深入了解不同国家和地区的市场表现和用户行为。根据数据结果进行优化和改进，调整产品定价、市场定位和营销策略，以提高跨境电子商务的效果和回报率。</p>
</li>
</ol>
<p>通过采用上述Magento 2中的跨境电子商务策略和扩展，您可以充分利用全球市场的机会，并实现全球范围内的业务增长。</p>]]></description>
      <pubDate>Tue, 26 Dec 2023 08:20:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中的安全性]]></title>
      <link>https://www.360magento.com/blog/mmagento2-security-measures/</link>
      <description><![CDATA[<p>作为一款广受欢迎的电子商务平台，Magento 2提供了一系列强大的安全性措施和最佳实践，以保护您的网站和客户的敏感信息免受潜在的威胁。在本文中，我们将介绍一些适用于Magento 2的关键安全性措施和建议。</p>
<ol>
<li>
<p>及时更新Magento版本：确保您的Magento 2平台及其相关扩展和插件始终使用最新的安全补丁和更新版本。定期检查Magento官方网站和社区，以获取最新的安全性公告和建议，并遵循官方的升级指南。</p>
</li>
<li>
<p>强化管理员访问控制：采取措施限制对Magento管理员后台的访问。创建强密码并定期更改密码，使用双因素身份验证增加额外的安全层级，并仅授予必要的管理员权限给相关人员。</p>
</li>
<li>
<p>安全的扩展和主题：仅从官方Magento Marketplace或可信的第三方开发者处获取和安装扩展和主题。审查扩展和主题的评分、用户评论和开发者声誉，并确保它们是经过安全审计和测试的。</p>
</li>
<li>
<p>进行安全扫描和漏洞测试：定期进行Magento网站的安全扫描和漏洞测试，以检测潜在的漏洞和弱点。使用安全扫描工具和服务来评估您的网站的安全性，并及时修复发现的问题。</p>
</li>
<li>
<p>数据备份和恢复计划：定期备份Magento 2网站的数据，并确保备份数据存储在安全的位置。创建详细的数据恢复计划，以便在发生数据丢失或系统故障时能够快速恢复网站功能。</p>
</li>
<li>
<p>安全的支付和敏感信息保护：采用安全的支付网关和加密技术，以保护客户的支付信息和敏感数据。确保您的网站使用HTTPS协议进行安全的数据传输，并遵守PCI DSS（支付卡行业数据安全标准）的合规要求。</p>
</li>
<li>
<p>监控和日志记录：设置实时监控和日志记录系统，以及时检测和记录异常活动。监测登录尝试、访问模式和异常行为，并建立警报机制，以便在发生安全事件时能够及时采取行动。</p>
</li>
<li>
<p>培训和意识提升：定期为您的团队提供安全意识培训，教育他们识别和应对潜在的网络威胁。强调密码安全、社会工程学攻击和恶意软件防范等关键安全概念。</p>
</li>
</ol>
<p>通过采用上述Magento 2中的安全性措施和最佳实践，您可以提高您的网站和客户数据的安全性，并降低潜在的安全风险和漏洞。</p>]]></description>
      <pubDate>Tue, 26 Dec 2023 03:22:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中的优化建议]]></title>
      <link>https://www.360magento.com/blog/magento2-mobile-optimization/</link>
      <description><![CDATA[<p>随着移动设备的普及和用户购物行为的变化，为移动用户提供优质的体验变得至关重要。作为一种功能强大的电子商务平台，Magento 2提供了一系列移动优化策略和最佳实践，以确保您的网站在移动设备上获得卓越的性能和用户体验。在本文中，我们将分享一些适用于Magento 2的移动优化策略和技巧。</p>
<ol>
<li>
<p>响应式网站设计：采用响应式网站设计，确保您的Magento 2网站能够自适应不同大小的移动设备屏幕。响应式设计可以提供一致的用户体验，并避免为每个设备单独创建独立的网站版本。</p>
</li>
<li>
<p>移动友好的用户界面：优化您的Magento 2网站的用户界面，使其在移动设备上易于导航和操作。确保按钮和链接足够大，并避免使用弹出窗口和复杂的表单输入，以提高用户的互动和转化率。</p>
</li>
<li>
<p>加速网站加载速度：移动设备通常具有较低的带宽和处理能力，因此优化您的Magento 2网站以提高加载速度至关重要。压缩图像、减少HTTP请求、优化CSS和JavaScript文件，并启用浏览器缓存等措施，可以显著提升移动网站的性能。</p>
</li>
<li>
<p>移动支付选项：为移动用户提供多种方便快捷的支付选项，如移动钱包、支付宝、微信支付等。简化结账流程，并确保移动支付体验安全可靠，以提高用户的购买转化率。</p>
</li>
<li>
<p>移动搜索优化：优化您的Magento 2网站以适应移动搜索引擎的需求。重点关注移动关键词和本地化搜索，确保您的网站内容对移动用户具有高度相关性和可见性。</p>
</li>
<li>
<p>视频和图像优化：在移动设备上播放视频和加载图像可能会消耗用户的流量和时间。优化视频和图像的大小和格式，以提供高质量的视觉体验，同时减少加载时间和数据消耗。</p>
</li>
<li>
<p>移动推送通知：利用Magento 2的移动推送通知功能，向用户发送个性化的促销和重要信息。通过向移动用户发送定制化的通知，您可以增加用户参与度和购买动力。</p>
</li>
<li>
<p>移动设备测试：确保定期在各种移动设备上测试您的Magento 2网站。检查页面布局、功能和用户体验，并解决任何移动设备兼容性问题，以提供一致的优质体验。</p>
</li>
</ol>
<p>通过采用上述Magento 2中的移动优化策略和最佳实践，您可以提供出色的移动用户体验，并吸引更多移动用户进行购买和交互。</p>]]></description>
      <pubDate>Mon, 25 Dec 2023 08:18:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的搜索引擎优化（SEO）策略和技巧]]></title>
      <link>https://www.360magento.com/blog/magento-seo-strategies/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务领域中，将您的Magento网站优化为搜索引擎友好的是吸引更多有针对性的流量和提升在线可见性的关键。通过采用一系列的搜索引擎优化（SEO）策略和技巧，您可以提高您的Magento网站在搜索引擎结果页面中的排名。在本文中，我们将介绍一些适用于Magento的SEO策略和最佳实践，帮助您最大程度地优化您的网站。</p>
<ol>
<li>
<p>关键词研究和优化：通过进行关键词研究，确定与您的产品和业务相关的关键词和短语。将这些关键词合理地应用于您的Magento网站的页面标题、元描述、URL和内容中，以帮助搜索引擎了解您的网站内容和关键主题。</p>
</li>
<li>
<p>优化页面元素：确保每个页面都具有唯一且相关的页面标题和元描述。使用有意义的标题标签（H1、H2等）来组织页面内容，并优化页面URL以反映关键词和内容。</p>
</li>
<li>
<p>内部链接优化：在您的Magento网站内部进行链接优化，以建立页面之间的相关性和内部权重传递。使用有关键词的锚文本链接相关页面，并创建一个清晰的网站结构，使搜索引擎和用户都可以轻松导航和理解您的网站。</p>
</li>
<li>
<p>图像优化：对您的Magento网站中的图像进行优化，包括使用描述性的文件名和替代文本（ALT文本），以帮助搜索引擎理解图像内容。还可以压缩图像文件大小，以提高页面加载速度。</p>
</li>
<li>
<p>用户友好的URL结构：使用简洁、描述性和用户友好的URL结构，包括关键词和相关信息。避免使用复杂的参数和动态URL，优先选择静态URL。</p>
</li>
<li>
<p>网站速度优化：优化您的Magento网站以提高页面加载速度。压缩CSS和JavaScript文件，启用浏览器缓存，优化图像大小，减少HTTP请求等，以提供更快的用户体验和搜索引擎的偏好。</p>
</li>
<li>
<p>社交媒体整合：在您的Magento网站上集成社交媒体分享按钮，并确保您的网站内容易于分享和传播。社交媒体的参与和分享可以增加您的网站的曝光度和流量。</p>
</li>
<li>
<p>定期监测和优化：使用分析工具来跟踪您的Magento网站的搜索引擎排名、流量来源和用户行为。根据数据结果，进行定期的优化和调整，以持续改进您的SEO策略和网站性能。</p>
</li>
</ol>
<p>通过采用上述Magento中的搜索引擎优化（SEO）策略和技巧，您可以提升您的网站在搜索引擎中的排名，吸引更多有针对性的流量，并提升在线业务的成功。</p>]]></description>
      <pubDate>Sun, 24 Dec 2023 07:24:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中提高电子商务转化率的关键策略]]></title>
      <link>https://www.360magento.com/blog/magento2-conversion-rate-strategies/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，提高转化率是每个在线商家的关键目标之一。Magento 2作为一种功能强大且灵活的电子商务平台，为商家提供了许多工具和功能来增加销售和转化率。在本文中，我们将分享一些提高您的Magento 2网站转化率的关键策略和技巧。</p>
<ol>
<li>
<p>简化购物体验：确保您的Magento 2网站的购物流程简单、直观且无缝。简化注册和结账过程，减少步骤和信息输入的要求，提供多种支付选项，并优化移动设备上的用户体验。简化购物体验可以减少购物车放弃率，并增加转化率。</p>
</li>
<li>
<p>提供个性化推荐：利用Magento 2的个性化推荐功能，向用户展示与他们兴趣和购买历史相关的产品。通过根据用户的喜好和行为提供相关的产品建议，可以增加交叉销售和重复购买的机会。</p>
</li>
<li>
<p>优化产品页面：确保您的产品页面具有清晰的产品图像、吸引人的描述和详细的规格信息。使用高品质的图像和视频展示产品，提供清晰的产品描述和特色，以吸引用户并增加他们的购买决策。</p>
</li>
<li>
<p>引入客户评价和社交证明：在您的Magento 2网站上添加客户评价和社交证明，如用户评论、评级和社交媒体分享。积极的客户评价和社交证明可以增加信任度，促使其他用户进行购买决策。</p>
</li>
<li>
<p>使用优惠和促销：利用Magento 2的优惠和促销功能，提供吸引人的优惠、折扣和奖励计划。通过限时促销、买一送一和积分奖励等策略，刺激用户的购买欲望，并增加转化率。</p>
</li>
<li>
<p>实施购物车提醒：在用户离开购物车而没有完成购买时，通过电子邮件或弹出窗口提醒他们购物车中的待购商品。这可以提醒用户并鼓励他们完成交易，减少购物车放弃率。</p>
</li>
<li>
<p>优化网站加载速度：确保您的Magento 2网站具有快速的加载速度，以提供流畅的用户体验。优化图像大小、合并和压缩CSS和JavaScript文件、启用浏览器缓存等措施可以提高网站的加载速度，减少用户的等待时间。</p>
</li>
<li>
<p>数据驱动的优化：利用Magento 2的分析工具和报告，深入了解用户行为和转化率数据。根据数据结果进行优化和测试，如A/B测试、多变量测试等，以不断改进您的网站和营销策略。</p>
</li>
</ol>
<p>通过采用上述关键策略和技巧，您可以提高您的Magento 2网站的转化率，增加销售和业务成功。记住，持续的测试、优化和关注用户反馈是实现持续改进的关键。</p>]]></description>
      <pubDate>Sun, 24 Dec 2023 03:27:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的用户体验优化策略和最佳实践]]></title>
      <link>https://www.360magento.com/blog/magento-user-experience-optimization/</link>
      <description><![CDATA[<p>提供卓越的用户体验是在竞争激烈的电子商务市场中脱颖而出的关键。当用户访问您的Magento网站时，他们期望流畅的浏览体验、易于导航的界面和简单的购物过程。在本文中，我们将介绍一些Magento中的用户体验优化策略和最佳实践，帮助您提供令人满意的用户体验并提升转化率。</p>
<ol>
<li>
<p>响应式设计：确保您的Magento网站具有响应式设计，可以自适应不同的设备和屏幕尺寸，包括桌面电脑、平板电脑和移动设备。这样可以确保用户在任何设备上都能获得一致的优质体验。</p>
</li>
<li>
<p>简化导航和布局：设计清晰、直观的导航结构，使用户能够轻松找到他们所需的产品和信息。使用易于理解的标签和菜单，并确保页面布局整洁、有序，减少混乱和冗余的元素。</p>
</li>
<li>
<p>快速加载速度：优化您的Magento网站以提高页面加载速度。压缩图像、合并和缓存CSS和JavaScript文件，并优化服务器响应时间，确保用户在访问您的网站时能够获得快速的响应和流畅的浏览体验。</p>
</li>
<li>
<p>简化购物流程：简化Magento网站的购物流程，使用户能够快速、方便地完成购买。减少步骤和填写字段的数量，提供多种支付选项，并确保购物车和结账过程清晰明了。</p>
</li>
<li>
<p>强调产品和内容：突出展示您的产品和内容，使用高质量的图像和详细的产品描述。提供用户评价和评论，以增加购买决策的信任度和可靠性。</p>
</li>
<li>
<p>个性化推荐：利用Magento的个性化推荐功能，根据用户的兴趣和行为推荐相关的产品和内容。这样可以提高用户的参与度和购买意愿。</p>
</li>
<li>
<p>多语言和多货币支持：如果您的目标市场跨越多个地区和语言，确保您的Magento网站支持多语言和多货币。这样可以为用户提供更个性化和便利的体验。</p>
</li>
<li>
<p>用户反馈和支持：提供易于访问的用户反馈渠道，如在线聊天、联系表单或客户支持热线。及时回应用户的问题和反馈，并持续改进用户支持体系。</p>
</li>
</ol>
<p>通过采用上述Magento中的用户体验优化策略和最佳实践，您可以提升您的网站的用户满意度，增加用户参与度，并提高转化率和客户忠诚度。</p>
<p>请记住，用户体验是一个不断演进的过程，需要不断地监测和改进。定期评估和优化您的Magento网站，以满足用户的期望和不断变化的市场需求。</p>]]></description>
      <pubDate>Sat, 23 Dec 2023 07:20:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的安全性最佳实践和保护策略]]></title>
      <link>https://www.360magento.com/blog/magento-securitys-best-practices/</link>
      <description><![CDATA[<p>保护您的Magento网站免受潜在的安全威胁是至关重要的。在今天的数字环境中，电子商务网站成为了黑客攻击的目标。为了确保您的Magento网站和客户数据的安全，您需要采取一系列的安全性最佳实践和保护策略。在本文中，我们将介绍一些Magento中的安全性最佳实践，帮助您加强网站的安全性。</p>
<ol>
<li>
<p>及时更新Magento版本：确保您的Magento网站始终运行最新版本的软件。Magento定期发布安全更新和补丁程序，以修复已知的漏洞和弱点。定期检查并应用这些更新，以确保您的网站免受已知漏洞的影响。</p>
</li>
<li>
<p>强化管理员访问：限制对Magento后台的访问权限，仅授权给必要的管理员用户。使用强密码和两步验证等安全措施，确保只有授权的用户能够登录和管理网站。</p>
</li>
<li>
<p>安全备份策略：定期备份您的Magento网站和数据库，并将备份存储在安全的位置。这样可以在发生安全事件或数据丢失时快速恢复网站功能。</p>
</li>
<li>
<p>安全扩展和主题：在安装任何Magento扩展或主题之前，确保它们来自可信赖的来源，并经过安全审查。仔细评估扩展和主题的代码质量和安全性，以避免安全漏洞和后门。</p>
</li>
<li>
<p>强化网络安全：使用防火墙和入侵检测系统来保护您的Magento服务器免受未经授权的访问和恶意攻击。定期监测服务器日志和网络活动，及时检测异常行为。</p>
</li>
<li>
<p>安全的支付处理：确保您的Magento网站采用安全的支付处理方式，如使用SSL证书加密用户与网站之间的通信，以保护敏感的支付信息。</p>
</li>
<li>
<p>安全审计和监测：定期进行安全审计和漏洞扫描，以识别潜在的安全风险和漏洞。使用安全监测工具来实时监测您的Magento网站，及时发现和应对任何安全威胁。</p>
</li>
<li>
<p>培训和意识提升：培训您的团队成员，包括管理员和开发人员，关于Magento安全性最佳实践和对抗潜在威胁的方法。增强员工的安全意识和敏感性，以确保他们能够正确处理安全问题和紧急情况。</p>
</li>
</ol>
<p>通过采用上述Magento中的安全性最佳实践和保护策略，您可以加固您的网站的安全防线，降低潜在风险，并保护您的客户数据和业务利益。</p>
<p>请记住，安全是一个持续的过程，需要定期评估和更新。随着安全威胁的不断演变，您需要保持警惕并及时采取相应的安全措施。</p>]]></description>
      <pubDate>Sat, 23 Dec 2023 03:23:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的SEO最佳实践和优化策略]]></title>
      <link>https://www.360magento.com/blog/magento-seo-best-practices/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，优化您的Magento网站以提高搜索引擎排名对于吸引更多的有机流量和增加销售至关重要。在本文中，我们将介绍一些Magento中的SEO最佳实践和优化策略，帮助您在搜索引擎结果页面上脱颖而出。</p>
<ol>
<li>
<p>关键字研究和优化：进行深入的关键字研究，了解您的目标受众在搜索引擎中使用的关键字。将这些关键字合理地应用于您的网站内容、标题、元标签和URL中，以提高页面的相关性和可发现性。</p>
</li>
<li>
<p>优化网站结构：确保您的Magento网站具有清晰的网站结构和导航层次。使用有意义的目录结构和URL结构，使搜索引擎和用户能够轻松浏览和理解您的网站。</p>
</li>
<li>
<p>内容优化：编写高质量、原创和有价值的内容是吸引搜索引擎和用户的关键。在您的Magento网站上创建有吸引力的产品描述、博客文章和页面内容，并确保关键字的自然集成。</p>
</li>
<li>
<p>图像优化：优化您的产品图像以提高搜索引擎的可索引性。使用描述性文件名和ALT标签，并压缩图像以提高页面加载速度。</p>
</li>
<li>
<p>友好的URL结构：使用有意义和描述性的URL，包含关键字，并避免使用动态参数。优化URL可以提高搜索引擎对页面的理解和排名。</p>
</li>
<li>
<p>网站速度优化：确保您的Magento网站具有快速的加载速度，以提供良好的用户体验并获得更好的搜索引擎排名。压缩和合并CSS和JavaScript文件，优化图像，并使用缓存和CDN等技术来减少页面加载时间。</p>
</li>
<li>
<p>社交媒体整合：将您的Magento网站与社交媒体平台整合，以增加社交分享和品牌曝光。通过分享按钮和社交媒体链接，鼓励用户与您的网站内容进行互动和分享。</p>
</li>
<li>
<p>持续监测和优化：使用工具如Google Analytics来监测您的Magento网站的关键指标，如流量来源、页面访问量和转化率。根据数据分析结果，优化您的SEO策略和网站内容，以实现更好的结果。</p>
</li>
</ol>
<p>通过采用上述Magento中的SEO最佳实践和优化策略，您可以提高您的网站在搜索引擎中的可见性和排名，吸引更多的有机流量，并增加销售和转化率。</p>]]></description>
      <pubDate>Fri, 22 Dec 2023 07:18:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的安全性最佳实践和保护策略]]></title>
      <link>https://www.360magento.com/blog/magento-security-best-practices/</link>
      <description><![CDATA[<p>保护您的Magento电子商务网站免受安全威胁是至关重要的。在今天的数字时代，保护客户数据、防止恶意攻击和确保网站的安全性是您作为网站所有者的首要任务。在本文中，我们将介绍一些Magento中的安全性最佳实践和保护策略。</p>
<ol>
<li>
<p>使用最新的Magento版本：始终使用最新的Magento版本，以确保您能够获得最新的安全更新和补丁程序。Magento持续发布安全更新，以解决已知的漏洞和强化系统的安全性。</p>
</li>
<li>
<p>强化管理员访问控制：限制对Magento后台的访问，并为管理员分配强密码和唯一的用户名。另外，使用双因素身份验证（2FA）来提供额外的安全层级。</p>
</li>
<li>
<p>安全的主机环境：选择可信赖的主机提供商，并确保他们提供安全的服务器环境。确保服务器上的操作系统、数据库和软件都得到及时更新和安全配置。</p>
</li>
<li>
<p>使用SSL加密：为您的Magento网站启用SSL证书，通过HTTPS协议来加密用户的敏感数据传输。这样可以防止中间人攻击和数据泄露，并为用户提供更安全的购物环境。</p>
</li>
<li>
<p>定期备份和恢复测试：定期备份Magento网站的数据库和文件，并进行恢复测试，以确保备份的可用性和完整性。这样可以在发生数据丢失或系统故障时快速还原网站。</p>
</li>
<li>
<p>安全扩展和主题：仅从可靠和受信任的源获取Magento扩展和主题。确保它们经过安全审查，并且来自可靠的供应商。定期更新和升级扩展和主题以获取最新的安全修复和功能改进。</p>
</li>
<li>
<p>监控和日志记录：启用Magento的日志记录功能，并监控网站的活动和访问。设置警报系统以及实时监控和检测潜在的安全威胁。</p>
</li>
<li>
<p>安全意识培训：培训您的团队，包括管理员和员工，以提高安全意识和识别潜在的网络威胁。教育他们关于密码安全、社交工程攻击和恶意软件防护等方面的最佳实践。</p>
</li>
</ol>
<p>通过采用上述Magento安全性最佳实践和保护策略，您可以大大提高您的电子商务网站的安全性，降低潜在的风险，并保护用户数据的机密性和完整性。</p>]]></description>
      <pubDate>Thu, 21 Dec 2023 16:16:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento中优化电子商务网站的性能]]></title>
      <link>https://www.360magento.com/blog/magento-performance-optimizations/</link>
      <description><![CDATA[<p>电子商务网站的性能优化对于提供卓越的用户体验、提高转化率和搜索引擎排名至关重要。在Magento中，有许多优化措施可以帮助您提升网站的性能。在本文中，我们将介绍一些Magento中优化电子商务网站性能的最佳实践。</p>
<ol>
<li>
<p>使用全页缓存（Full Page Cache）：Magento提供了全页缓存功能，通过缓存整个页面，可以显著提高页面加载速度。启用全页缓存并配置适当的缓存策略，可以减少数据库查询和动态页面生成的次数，从而提高性能。</p>
</li>
<li>
<p>压缩和合并CSS和JavaScript：将多个CSS和JavaScript文件合并为较少的文件，并使用压缩工具来减小文件大小。这样可以减少HTTP请求次数并提高页面加载速度。Magento提供了内置的资源合并和压缩功能，您可以在Magento后台启用它们。</p>
</li>
<li>
<p>优化图像：优化图像可以减少页面的加载时间。使用适当的图像格式（如JPEG、PNG）并压缩图像以减小文件大小。同时，使用图像的响应式设计，根据设备屏幕的大小提供适当尺寸的图像，避免无谓的带宽浪费。</p>
</li>
<li>
<p>使用CDN（内容分发网络）：通过使用CDN，您可以将网站的静态资源（如图像、CSS和JavaScript文件）分发到全球各地的服务器，从而实现更快的加载速度。选择一个可靠的CDN提供商，并将Magento配置为使用CDN来提供静态资源。</p>
</li>
<li>
<p>优化数据库：通过优化数据库表结构、使用索引和定期清理日志等方法，可以改善Magento网站的性能。使用Magento提供的数据库优化工具或借助第三方扩展来执行这些优化操作。</p>
</li>
<li>
<p>考虑使用缓存扩展：Magento还提供了许多缓存扩展，如Redis、Memcached等。这些扩展可以提供更高效的缓存存储和读取，进一步提升网站的性能。</p>
</li>
</ol>
<p>通过采用上述优化措施，您可以显著提升Magento电子商务网站的性能，提供更好的用户体验，并为您的业务增加竞争力。</p>
<p>请注意，这只是一些Magento性能优化的基本建议，实际的优化策略可能因网站的特定需求和配置而有所不同。建议在进行任何更改之前，先在测试环境中进行测试和验证。</p>]]></description>
      <pubDate>Thu, 21 Dec 2023 07:11:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的移动优化策略和最佳实践]]></title>
      <link>https://www.360magento.com/blog/magento-mobile-optimization/</link>
      <description><![CDATA[<p>移动设备的普及使得移动优化对于电子商务网站至关重要。在Magento中，实施有效的移动优化策略可以提升用户体验、增加转化率，并提高搜索引擎排名。在本文中，我们将介绍一些Magento中的移动优化策略和最佳实践。</p>
<ol>
<li>
<p>响应式设计：使用响应式设计来确保您的Magento网站在各种移动设备上都能够提供良好的用户体验。响应式设计可以根据设备屏幕的大小和分辨率自动调整网站的布局和样式，使其适应不同的屏幕尺寸。</p>
</li>
<li>
<p>移动友好的导航：精简和简化导航栏是移动优化的关键。确保导航栏在移动设备上易于操作，并提供简洁的菜单结构，以便用户能够轻松浏览和导航网站。</p>
</li>
<li>
<p>快速加载速度：移动设备通常具有较低的带宽和处理能力，因此快速加载速度对于移动优化至关重要。通过压缩和合并CSS和JavaScript文件、优化图像、启用缓存以及使用CDN等技术来减少页面加载时间。</p>
</li>
<li>
<p>简化结账流程：移动设备上的结账流程应尽可能简化和优化。减少步骤和输入字段，并提供易于填写的表单和选择器，以提高移动用户的结账转化率。</p>
</li>
<li>
<p>移动支付选项：提供多种移动支付选项，如移动钱包、支付宝、微信支付等，以满足移动用户的支付需求，并提高购物车转化率。</p>
</li>
<li>
<p>点击目标和按钮设计：确保按钮和点击目标具有足够的大小，以便在触摸屏上轻松点击。调整按钮样式和间距，以便移动用户可以轻松识别和操作。</p>
</li>
<li>
<p>测试和优化：在实施移动优化策略之前，进行适当的测试是必要的。使用移动设备和模拟器测试网站的响应性、布局和功能，并根据测试结果进行优化和改进。</p>
</li>
</ol>
<p>通过采用上述Magento移动优化策略和最佳实践，您可以提升移动用户的体验，增加转化率，并确保您的网站在移动设备上获得更好的可见性和排名。</p>
<p>请注意，移动优化是一个持续的过程，需要定期监测和优化。建议根据您的网站和用户需求，定期评估和改进移动优化策略。</p>]]></description>
      <pubDate>Wed, 20 Dec 2023 16:14:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[借助主题优化工具提升Magento模板效率]]></title>
      <link>https://www.360magento.com/blog/enhance-magento-theme-development-with-tools/</link>
      <description><![CDATA[<p>专注开发主题对提升Magento店铺用户体验很重要。为了提高开发效率,可以使用下列主题优化工具:</p>
<ol>
<li>
<p>Less/Sass编译器:比如Dart Sass支持变量、混合、导入等特性,简化CSS书写。</p>
</li>
<li>
<p>工程化工具:如Webpack打包主题资源,自动处理依赖、样式重用等任务。</p>
</li>
<li>
<p>部件库:像Magento UI提供了一套基础组件,减少重复开发工作。</p>
</li>
<li>
<p>主题开发插件:示例VSCode插件支持智能感知Magento路径、代码补全等。</p>
</li>
<li>
<p>模板引擎:例如Pug/Twig可读性好,有效提高模板效率。</p>
</li>
<li>
<p>图片优化:TinyPNG等在线服务可以自动压缩主题图片质量与体积。</p>
</li>
<li>
<p>原型设计工具:Axure或Zeplin可在设计阶段预览主题效果。</p>
</li>
<li>
<p>测试工具:Karma或WebDriver测试模板静动态脚本。</p>
</li>
</ol>
<p>使用这些功能强大的主题开发助手,可以更专注于商业需求,开发出高质量主题。</p>
<div id="gtx-trans" style="position: absolute; left: -186px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 20 Dec 2023 07:09:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[遵循这些Magento开发最佳实践提高项目质量]]></title>
      <link>https://www.360magento.com/blog/magento-development-best-practices/</link>
      <description><![CDATA[<p>开发高质量的Magento项目需要遵循一些开发流程上的最佳实践,包括:</p>
<ol>
<li>
<p>项目设计阶段要定义清晰的架构蓝图和规范。</p>
</li>
<li>
<p>开发前准备好项目环境、依赖和开发工具。</p>
</li>
<li>
<p>每个功能区块使用模块化思想进行解耦开发。</p>
</li>
<li>
<p>基于接口编程,使用依赖注入降低耦合。</p>
</li>
<li>
<p>定义完善的命名标准和注释规范。</p>
</li>
<li>
<p>使用Git版本控制并实施规范的版本管理流程。</p>
</li>
<li>
<p>开发过程中实施中间代码检查和各种测试。</p>
</li>
<li>
<p>发布代码前进行严格的质量检测与评审。</p>
</li>
<li>
<p>开发文档与代码同步,给新人提供参考。</p>
</li>
<li>
<p>监控线上环境并定期进行维护迭代更新。</p>
</li>
</ol>
<p>严格遵循以上最佳实践可以进一步提高项目质量和可控性。这也是每位Magento开发者都应追求的目标。</p>
<div id="gtx-trans" style="position: absolute; left: -106px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 20 Dec 2023 03:10:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[搭建基于Magento 2的PWA应用]]></title>
      <link>https://www.360magento.com/blog/building-pwa-with-magento-2/</link>
      <description><![CDATA[<p>正如我们所知,PWA(渐进式网络应用)可以将移动应用的用户体验带到网上,它利用了Service Worker、HTTP/2等现代Web技术。</p>
<p>在Magento2中构建PWA应用需要以下步骤:</p>
<ol>
<li>
<p>引入PWA Studio库。它包含构建PWA必需的依赖和配置。</p>
</li>
<li>
<p>添加Manifest文件。定义应用名称、图标、启动页面等元数据。</p>
</li>
<li>
<p>设置Service Worker。用于缓存依赖资源,实现离线访问能力。</p>
</li>
<li>
<p>使用前端框架。例如React构建单页应用体验页面。</p>
</li>
<li>
<p>集成推送通知。使用Web Push API给用户发送推送。</p>
</li>
<li>
<p>主题和部署配置。专门为移动端定制界面样式和优化部署。</p>
</li>
<li>
<p>性能监控和优化。分析打包大小、命中率等指标。</p>
</li>
<li>
<p>A/B测试和迭代。在PWA Studio中支持实验发布机制。</p>
</li>
</ol>
<p>以上实现可让Magento商城应用拥有原生APP体验,大幅提升用户粘性。这将是未来一条重要的发展方向。</p>]]></description>
      <pubDate>Tue, 19 Dec 2023 07:18:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何系统化开发优质的Magento模块]]></title>
      <link>https://www.360magento.com/blog/systematic-magento-module-development/</link>
      <description><![CDATA[<p>开发Magento模块需要遵循清晰的原则,以下几点可以帮助系统化提质量:</p>
<ol>
<li>
<p>设计模块功能和架构</p>
</li>
<li>
<p>使用组件化思想划分模块</p>
</li>
<li>
<p>注重模块解耦和服务分层</p>
</li>
<li>
<p>声明模块配置和依赖</p>
</li>
<li>
<p>开发基于接口的模块类</p>
</li>
<li>
<p>使用Factory和Repository模式</p>
</li>
<li>
<p>定义通用模块事件与观察者</p>
</li>
<li>
<p>使用注解完成IoC绑定</p>
</li>
<li>
<p>编写单元与集成测试用例</p>
</li>
<li>
<p>规范代码样式与注释</p>
</li>
<li>
<p>发布模块到Composer仓库</p>
</li>
<li>
<p>持续迭代与优化模块</p>
</li>
</ol>
<p>遵循这些建议可以打造模块功能强大、测试覆盖率高、质量可靠。这将给用户提供一流的开发体验。</p>]]></description>
      <pubDate>Tue, 19 Dec 2023 03:21:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento中优化电子商务网站的性能]]></title>
      <link>https://www.360magento.com/blog/magento-performance-optimization/</link>
      <description><![CDATA[<p>Magento是一种功能强大的电子商务平台，但在处理大量产品和高流量时，可能会面临性能方面的挑战。优化Magento网站的性能对于提供良好的用户体验、提高转化率和搜索引擎排名至关重要。在本文中，我们将介绍一些优化Magento网站性能的最佳实践。</p>
<ol>
<li>
<p>选择合适的主机：选择一个可靠且专门针对Magento优化的主机提供商，确保您的网站能够获得足够的服务器资源和性能。</p>
</li>
<li>
<p>使用全页缓存：Magento提供了一个全页缓存功能，它可以缓存整个页面，从而提高页面加载速度。确保启用并配置全页缓存以获得最佳性能。</p>
</li>
<li>
<p>优化图像：优化图像可以大幅度减少页面加载时间。使用适当的图像格式（如JPEG、PNG）并压缩图像以减小文件大小。还可以使用懒加载技术，在用户滚动到图像时再加载它们。</p>
</li>
<li>
<p>合并和压缩CSS和JavaScript：将多个CSS和JavaScript文件合并为较少的文件，并使用压缩工具来减小文件大小。这将减少HTTP请求次数并提高页面加载速度。</p>
</li>
<li>
<p>使用CDN</p>
</li>
</ol>
<p></p>]]></description>
      <pubDate>Mon, 18 Dec 2023 07:13:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[提升Magento网站访问速度的7个有效方式]]></title>
      <link>https://www.360magento.com/blog/7-ways-to-boost-magento-site-performance/</link>
      <description><![CDATA[<p>随着电商业务量的增长,网站访问性能优化变得尤为重要。这里介绍7个可以有效提升Magento速度的方法:</p>
<ol>
<li>浏览器缓存静态资源</li>
</ol>
<p>正确配置Expires头和缓存策略,让浏览器长期缓存JavaScript、CSS、图片等静态文件。</p>
<ol start="2">
<li>CDN加速静态内容访问</li>
</ol>
<p>使用内容分发网络(CDN)将静态文件部署至就近节点,大幅减少下载时间。</p>
<ol start="3">
<li>数据库和对象缓存</li>
</ol>
<p>利用Memcached/Redis缓存常用数据库查询和模型访问,降低数据库压力。</p>
<ol start="4">
<li>页面缓存</li>
</ol>
<p>通过Varnish或FPC对频繁访问页面进行缓存,只在必要时才重新生成HTML。</p>
<ol start="5">
<li>数据库索引优化</li>
</ol>
<p>根据查询需求添加合理索引,提升数据库查询效率。</p>
<ol start="6">
<li>JS和CSS合并压缩</li>
</ol>
<p>合并JavaScript和CSS文件,减少HTTP请求数,同时压缩ToFile大小。</p>
<ol start="7">
<li>错误日志和访问日志分析</li>
</ol>
<p>分析错误日志排查性能问题,优化访问热点流量瓶颈。</p>
<p>贯彻应用以上方法可以在很大程度上提升Magento网站的整体性能,提升用户体验。</p>
<div id="gtx-trans" style="position: absolute; left: -78px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 18 Dec 2023 03:16:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[全面了解Magento扩展开发的重要概念]]></title>
      <link>https://www.360magento.com/blog/important-concepts-for-magento-extension-development/</link>
      <description><![CDATA[<p>正如之前所介绍的,开发扩展是给Magento网站添加新功能的主要方式。要深入掌握扩展开发,有必要了解其中的一些关键概念:</p>
<p>模块(Module)</p>
<p>这个是Magento扩展的基本单位,每个扩展都是一个模块。它封装了完整的功能逻辑和资源。</p>
<p>配置(Configuration)</p>
<p>模型(Model)</p>
<p>资源模型(Resource Model)</p>
<p>集合(Collections)</p>
<p>块(Block)</p>
<p>控制器(Controller)</p>
<p>事件观察者(Event/Observer)</p>
<p>配置风格(Configuration Types)</p>
<p>这些建构扩展的基础概念都需要掌握,将有助于设计出高内聚的架构。后续还可以关注测试、打包等工程实践。</p>
<div id="gtx-trans" style="position: absolute; left: -90px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 17 Dec 2023 07:12:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[从零开始构建你的第一个Magento扩展]]></title>
      <link>https://www.360magento.com/blog/how-to-build-your-first-magento-extension/</link>
      <description><![CDATA[<p>如果你想给Magento网站添加新的功能特性,最简单直接的方法就是开发一个Magento扩展模块。本文将分步给出构建简单Magento扩展的入门过程:</p>
<ol>
<li>
<p>创建基本文件结构</p>
</li>
<li>
<p>注册模块</p>
</li>
<li>
<p>创建模型类</p>
</li>
<li>
<p>定义数据库表</p>
</li>
<li>
<p>定义控制器</p>
</li>
<li>
<p>创建配置文件</p>
</li>
<li>
<p>定义模板文件</p>
</li>
<li>
<p>测试与调试</p>
</li>
<li>
<p>打包发布</p>
</li>
</ol>
<p>此流程快速为你构建了一个简单的工作扩展。熟悉后可以根据实际需求进行功能充实。</p>
<div id="gtx-trans" style="position: absolute; left: -125px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 17 Dec 2023 03:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何进行有效的Magento模块测试]]></title>
      <link>https://www.360magento.com/blog/effective-testing-for-magento-modules/</link>
      <description><![CDATA[<p>测试工作对保证Magento模块质量极为重要。这里介绍几种常用的Magento模块测试方法:</p>
<ul>
<li>
<p>单元测试:使用PHPUnit测试模块类、函数等单个逻辑单元,检查输入输出是否符合预期。</p>
</li>
<li>
<p>集成测试:测试模块间交互是否正常,如调用其它模块功能流程。此类测试需要模拟完整环境。</p>
</li>
<li>
<p>功能测试:从用户视角测试模块关键功能是否可用,如从前端提交表单数据流程。可使用Selenium自动化测试。</p>
</li>
<li>
<p>验收测试:在实际业务场景下,验证模块是否满足原先设计的功能需求规格。</p>
</li>
<li>
<p>回归测试:发布新版本后,重新运行历史用例以防新问题。</p>
</li>
<li>
<p>性能测试:使用工具测试模块性能指标,如响应时间是否在合理范围。</p>
</li>
<li>
<p>安全测试:通过fuzz测试与漏洞扫描测试模块安全强度。</p>
</li>
<li>
<p>本地测试:在开发环境下运行AutoTests套件进行快速测试。</p>
</li>
<li>
<p>线上测试:在测试环境或线上真实数据下进行黑盒测试。</p>
</li>
</ul>
<p>持续完善模块测试套件,保证各种场景下都有覆盖性,给开发带来靠谱的 feedback,也能在发布前锤炼代码质量。测试工作需要在全生命周期贯穿始终。</p>
<div id="gtx-trans" style="position: absolute; left: -136px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 16 Dec 2023 07:09:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用这些工具提升Magento网站的效能]]></title>
      <link>https://www.360magento.com/blog/tools-for-magento-performance-optimization/</link>
      <description><![CDATA[<p>性能优化对每个Magento网站都很重要。这里介绍几种有效的工具可以帮助优化Magento性能:</p>
<ul>
<li>
<p>Google PageSpeed:分析网站速度和体验级数,提供优化建议。</p>
</li>
<li>
<p>GTmetrix:类似PageSpeed但报告更详细,也支持mobile测试。</p>
</li>
</ul>
<p>-黑灯瞎火:分析网站各项性能指标如图像大小、加载时间等。</p>
<p>-图表分析工具:如DareBoost可以视觉化展示各项metrics变化趋势。</p>
<p>-YSlow:检查网站按照Yahoo!的规则是否优化,定位坑点。</p>
<p>-轻量级缓存:如Varnish缓存HTML提速访问。</p>
<p>-数据库优化:正确索引、缓存查询等提升数据库性能。</p>
<p>-图像优化:压缩图片尺寸、格式提升加载速度。</p>
<p>-资源优化:合并JS/CSS、启用Gzip前端持续减少请求。</p>
<p>-CDN:通过内容分发网络降低访问延迟。</p>
<p>-异步任务:使用延迟队列处理低优先级任务。</p>
<p>结合这些建议跟工具,能有效提升Magento网站的性能表现。定期监控也很关键。</p>
<div id="gtx-trans" style="position: absolute; left: -186px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 16 Dec 2023 03:09:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[入门Magento主题开发需要掌握的技能]]></title>
      <link>https://www.360magento.com/blog/skills-for-magento-theme-development/</link>
      <description><![CDATA[<p>与网站前端设计息息相关的Magento主题开发是广大前端开发者常接触的一个领域。要想开发出高质量的Magento主题,开发者需要掌握一定的技能。本文将介绍入门Magento主题开发需要了解的一些基础知识。</p>
<ul>
<li>
<p>HTML/CSS基础:了解网页结构标签和css样式规则。这是开发主题的基础。</p>
</li>
<li>
<p>响应式设计:如何通过流式布局、媒体查询等手段开发出支持不同屏幕大小的响应式主题。</p>
</li>
<li>
<p>Less/Sass预处理器:使用变量、混合宏等特性高效开发主题样式表。</p>
</li>
<li>
<p>Magento模板系统:了解主题文件与模板的对应关系以及坐标查找规则。</p>
</li>
<li>
<p>网格系统:Magento使用网格系统布局,需要掌握其工作原理。</p>
</li>
<li>
<p>图片优化:如何优化图片尺寸和格式,减轻页面加载压力。</p>
</li>
<li>
<p>主题自定义化:通过配置修改主题外观与功能,如更换logo颜色等。</p>
</li>
<li>
<p>PHP语法基础:需要处理少量PHP逻辑代码,如if条件判断。</p>
</li>
<li>
<p>使用版本管理:使用Git等工具管理主题文件版本更新。</p>
</li>
</ul>
<p>掌握这些基础知识即可快速上手Magento主题开发。初期可以参考官方主题进行修改,并通过测试期迭代优化主题质量。掌握技巧后能自主设计主题。</p>
<div id="gtx-trans" style="position: absolute; left: -140px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 15 Dec 2023 07:07:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用模块化思想来优化你的Magento项目]]></title>
      <link>https://www.360magento.com/blog/optimize-magento-project-with-modular-thinking/</link>
      <description><![CDATA[<p>模块化开发已成为目前前端和后端开发中的主流思路。将完整项目拆分成各个完整的模块,可以有效提高代码可维护性和扩展能力。但是在Magento项目中,我们仍常见将所有代码集中在一个核心模块中。这就失去了模块化的诸多优点。</p>
<p>所以要真正利用模块化思想优化Magento项目,需要遵循以下设计原则:</p>
<ol>
<li>
<p>根据功能域划分模块边界,将一个大的需求区域抽象为一个独立的模块。</p>
</li>
<li>
<p>每个模块只负责自己的职责,对外提供明确的接口和契约。</p>
</li>
<li>
<p>模块间交互使用解耦的方式,如通过发布/订阅事件或基于接口编程。</p>
</li>
<li>
<p>各模块可以单独开发、测试和部署,不依赖其他模块的内部实现。</p>
</li>
<li>
<p>引用关系使用配置实现,如Composer,而不是硬编码。</p>
</li>
<li>
<p>提供完整的开发和运行环境以支持模块的快速迭代。</p>
</li>
</ol>
<p>将一个可复用的功能单元模块化实现后,我们可以灵活组合这些模块构建项目;代码可以每个小片段独立优化;将来也可以动态加载新模块扩展功能。这将带来开发效率和项目可维护性的很大提升。</p>
<p>正确使用模块化思想是优化Magento项目的一个重要方面。希望这些经验可以给您的开发带来帮助。</p>
<div id="gtx-trans" style="position: absolute; left: -70px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 15 Dec 2023 03:08:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2: 提供客户体验的关键功能]]></title>
      <link>https://www.360magento.com/blog/magento2-customer-experience/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，提供优质的客户体验是吸引和保留客户的关键。Magento 2作为一款功能强大的电子商务平台，提供了许多功能和工具，帮助您提供卓越的客户体验。在本篇博客中，我们将探讨Magento 2的关键功能，这些功能可以提升您的在线商店的客户体验，并分享一些最佳实践和技巧。</p>
<ol>
<li>
<p>响应式和移动友好的设计：<br />Magento 2提供了响应式设计，使您的在线商店能够自适应不同的设备和屏幕尺寸，包括桌面电脑、平板电脑和手机。移动友好的设计确保用户可以在任何设备上无缝浏览和购物，并提供一致的用户体验。</p>
</li>
<li>
<p>个性化内容和推荐：<br />Magento 2允许您根据客户的兴趣、购买历史和行为数据，提供个性化的内容和推荐。通过使用Magento 2的营销工具和规则引擎，您可以向客户展示相关的产品、优惠和推广活动，提高购买转化率并增强客户满意度。</p>
</li>
<li>
<p>简化的购物流程：<br />Magento 2的购物流程经过优化，使用户可以轻松浏览产品、添加到购物车、结账和支付。通过提供简化且直观的界面，减少步骤和点击次数，您可以提高购物的便捷性和顺畅性，从而增加销售机会。</p>
</li>
<li>
<p>多语言和多货币支持：<br />如果您的在线商店面向国际客户，Magento 2提供了多语言和多货币支持。您可以轻松创建多个语言版本和货币设置，以满足不同地区和用户的需求，提供本地化的购物体验，增强全球客户的满意度。</p>
</li>
<li>
<p>顾客自助服务：<br />Magento 2的自助服务功能允许客户进行自主管理，如查看订单状态、修改个人信息、申请退款等。通过提供自助服务，您可以减轻客户支持负担，提供便利和灵活性，增强客户对您品牌的忠诚度。</p>
</li>
</ol>
<p>结论：<br />Magento 2的关键功能帮助您提供卓越的客户体验，从而增加客户满意度、提高销售转化率并促进业务增长。通过响应式设计、个性化内容和推荐、简化的购物流程、多语言和多货币支持以及顾客自助服务，您可以满足用户的期望，并建立良好的品牌形象。</p>
<div id="gtx-trans" style="position: absolute; left: -33px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 14 Dec 2023 08:14:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2: 提高销售和营销的关键策略]]></title>
      <link>https://www.360magento.com/blog/magento2-sales-marketing/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，提高销售和营销的效果对于在线商店的成功至关重要。Magento 2作为一款强大的电子商务平台，提供了多种功能和策略，帮助您增加销售额并改进营销活动的效果。在本篇博客中，我们将探讨Magento 2的关键策略，以提高您的在线商店的销售和营销成果，并分享一些最佳实践。</p>
<ol>
<li>
<p>促销和特价活动：<br />Magento 2提供了丰富的促销和特价活动功能，使您能够轻松创建各种促销策略，如折扣码、团购、限时特价等。通过运用这些策略，您可以吸引客户，促进购买决策，并增加销售额。</p>
</li>
<li>
<p>奖励计划和积分系统：<br />Magento 2允许您设置奖励计划和积分系统，以激励和回馈忠诚的客户。通过给予积分、折扣券或兑换礼品等奖励，您可以鼓励客户的重复购买行为，并建立长期客户关系。</p>
</li>
<li>
<p>个性化营销：<br />利用Magento 2的个性化营销功能，您可以根据客户的行为、喜好和购买历史，发送定制化的营销内容和推荐。通过向客户提供个性化的体验，您可以增加购买转化率，并提高客户满意度和忠诚度。</p>
</li>
<li>
<p>购物车和结账优化：<br />优化购物车和结账流程对于提高销售转化率至关重要。Magento 2提供了简化和优化的购物车和结账界面，使用户能够轻松添加商品、查看订单总结和进行安全快速的支付。通过提供顺畅的购物体验，您可以减少购物车遗弃率并促进完成订单。</p>
</li>
<li>
<p>数据驱动的决策：<br />Magento 2的报告和分析功能提供了关键的业务数据和指标，帮助您了解销售趋势、顾客行为和营销活动的效果。通过基于数据做出决策，您可以优化产品定位、调整价格策略，并改进营销活动，以达到更好的销售和营销结果。</p>
</li>
</ol>
<p>结论：<br />Magento 2的关键策略可以帮助您提高销售额并改进营销活动的效果。通过运用促销和特价活动、奖励计划和积分系统、个性化营销、购物车和结账优化以及数据驱动的决策，您可以吸引客户、促进购买决策，并提升客户满意度和忠诚度。</p>
<div id="gtx-trans" style="position: absolute; left: -112px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 14 Dec 2023 03:16:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：提升电商运营效率的关键]]></title>
      <link>https://www.360magento.com/blog/magento2-ecommerce-efficiency/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，高效运营是一个成功在线商店的关键要素。Magento 2作为一款功能强大的电子商务平台，提供了许多工具和功能，可以显著提升您的电商运营效率。在本篇博客中，我们将探讨Magento 2如何成为提升电商运营效率的关键，并分享一些最佳实践和技巧。</p>
<ol>
<li>
<p>自动化流程：<br />Magento 2允许您自动化许多重复性任务和流程，从而节省时间和减少错误。您可以设置自动化库存管理、订单处理、发货通知等功能，以提高处理效率并提供更快的客户服务。此外，Magento 2还提供了自动化报表和分析工具，帮助您快速了解业务绩效并做出相应的决策。</p>
</li>
<li>
<p>强大的管理工具：<br />Magento 2提供了直观且易于使用的后台管理界面，使您能够轻松管理产品、库存、订单和客户等关键业务数据。您可以快速添加和编辑产品信息、创建和跟踪订单、管理客户信息，并进行灵活的报价和促销活动。这些管理工具帮助您更高效地处理日常任务，提高运营效率。</p>
</li>
<li>
<p>广泛的集成能力：<br />Magento 2支持与第三方系统和服务的集成，如支付网关、物流服务、CRM系统等。通过集成这些关键系统，您可以实现数据的自动同步和流程的无缝连接，从而提高工作效率和减少人工干预。Magento 2的开放式API和扩展点使得集成变得更加简便和灵活。</p>
</li>
<li>
<p>多店铺管理：<br />对于企业经营多个在线商店的情况，Magento 2提供了多店铺管理功能。您可以在单个Magento 2安装中运行多个商店，并共享产品目录、客户数据库和订单管理系统。这样，您可以通过一个统一的后台管理界面轻松管理多个商店，提高运营效率并降低维护成本。</p>
</li>
<li>
<p>数据驱动的决策：<br />Magento 2提供了丰富的报表和分析功能，帮助您深入了解销售趋势、客户行为和产品表现。通过对这些数据的分析，您可以做出明智的决策和战略规划，以优化运营效率并提高业绩。Magento 2还支持与Google Analytics等第三方分析工具的集成，让您能够更全面地了解您的在线商店。</p>
</li>
</ol>
<p>结论：<br />Magento 2是一个提升电商运营效率的强大工具。通过自动化流程、强大的管理工具、广泛的集成能力、多店铺管理和数据驱动的决策，Magento 2帮助企业更高效地管理和运营在线商店。无论是小型企业还是大型企业，Magento 2都能满足其不断增长的业务需求，并提供卓越的运营效率。</p>
<div id="gtx-trans" style="position: absolute; left: -26px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 13 Dec 2023 08:11:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ Magento 2的安全性与风险管理]]></title>
      <link>https://www.360magento.com/blog/magento2-security1/</link>
      <description><![CDATA[<p>在当今数字化时代，保护在线商店和客户的安全成为了至关重要的任务。作为一款广泛使用的电子商务平台，Magento 2注重安全性，并提供了一系列功能和最佳实践来帮助您管理安全风险。在本篇博客中，我们将探讨Magento 2的安全性与风险管理，并分享一些保护您的在线商店的关键措施。</p>
<ol>
<li>
<p>安全更新和补丁：<br />Magento 2定期发布安全更新和补丁，修复已知漏洞和弱点。及时安装这些更新是保护您的在线商店的重要步骤。Magento 2的后台管理界面提供了方便的升级和安装工具，使您能够轻松获取最新的安全修复程序。</p>
</li>
<li>
<p>SSL加密：<br />Magento 2支持SSL加密技术，通过为数据传输提供安全通道来保护敏感信息。使用有效的SSL证书可以确保客户的个人数据、支付信息和登录凭据得到加密，并防止被非法获取。启用SSL加密可提高您的在线商店的安全性，并增强客户对您的信任。</p>
</li>
<li>
<p>访问控制和身份验证：<br />Magento 2提供了强大的访问控制和身份验证功能，以保护管理员和用户账户的安全。您可以设置复杂的密码策略、多因素身份验证和限制登录尝试次数等措施，减少未经授权的访问和潜在的安全风险。</p>
</li>
<li>
<p>PCI DSS合规性：<br />Magento 2符合PCI DSS（Payment Card Industry Data Security Standard）标准，这是一套涵盖支付卡数据安全的全球性标准。通过使用Magento 2与符合PCI DSS标准的支付网关集成，您可以确保客户的支付信息得到保护，并遵守相关的合规要求。</p>
</li>
<li>
<p>安全审计和监控：<br />Magento 2提供了日志记录、事件监控和异常检测等功能，以帮助您跟踪和分析潜在的安全问题。通过监控登录活动、异常请求和系统日志，您可以及时发现和应对安全威胁，并采取适当的措施来保护您的在线商店。</p>
</li>
</ol>
<p>结论：<br />Magento 2的安全性与风险管理功能使得保护您的在线商店和客户变得更加可靠和高效。通过及时安装安全更新、使用SSL加密、实施访问控制和身份验证、遵守PCI DSS合规性要求，并进行安全审计和监控，您可以降低安全风险，保护您的在线业务和客户数据。</p>
<div id="gtx-trans" style="position: absolute; left: -47px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 13 Dec 2023 03:13:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：强大而灵活的电子商务平台]]></title>
      <link>https://www.360magento.com/blog/magento-saa-dev-safsmasla/</link>
      <description><![CDATA[<p>Magento是目前最受欢迎的开源电子商务平台之一，提供了丰富的功能和灵活性，使商家能够轻松创建和管理在线商店。在本篇博客中，我们将介绍Magento 2的一些关键功能和技术优势，以及为什么它是许多企业选择的首选电子商务解决方案。</p>
<ol>
<li>
<p>强大的功能套件:<br />Magento 2提供了一整套功能，包括目录管理、产品管理、订单管理、支付和结账、客户管理、营销工具等。无论是小型企业还是大型企业，都可以根据其需求自定义和配置这些功能，以满足其特定的电子商务需求。</p>
</li>
<li>
<p>可扩展的架构:<br />Magento 2采用了现代化的模块化架构，使开发人员能够轻松扩展和定制平台。它提供了丰富的API和扩展点，使开发人员可以根据需要添加新功能、集成第三方系统和服务，并优化性能。</p>
</li>
<li>
<p>强大的性能和可伸缩性:<br />Magento 2通过使用Varnish缓存、数据库优化、页面片段缓存和延迟加载等技术，提供了卓越的性能。它还支持多服务器部署和负载均衡，以实现高可用性和可伸缩性，确保您的在线商店能够处理高流量和快速增长。</p>
</li>
<li>
<p>多店铺和多语言支持:<br />Magento 2允许您在单个安装中运行多个在线商店，并为每个商店设置不同的产品目录、价格、支付选项和运费规则。此外，它还提供了多语言支持，使您能够轻松创建多语言版本的商店，以满足全球客户的需求。</p>
</li>
<li>
<p>丰富的市场和社区生态系统:<br />Magento拥有庞大的市场和社区生态系统，提供了各种主题、模板、插件和扩展，以满足不同行业和业务需求。从设计到支付网关，从物流到营销自动化，您可以在Magento市场上找到适合您的解决方案。</p>
</li>
</ol>
<p>总结起来，Magento 2是一款功能强大、灵活可扩展的电子商务平台，适用于各种规模和类型的企业。它具有丰富的功能、可定制性强、性能优越，并拥有庞大的市场和社区支持。如果您正在寻找一个可靠的电子商务解决方案，Magento 2值得您的考虑</p>
<div id="gtx-trans" style="position: absolute; left: -114px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 12 Dec 2023 08:02:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用Magento 2构建出色的电子商务体验]]></title>
      <link>https://www.360magento.com/blog/magento2-ecommerce-experience/</link>
      <description><![CDATA[<p>在当今数字化时代，电子商务已经成为许多企业成功的关键。为了在竞争激烈的市场中脱颖而出，选择一个功能强大、灵活且可定制的电子商务平台至关重要。在本篇博客中，我们将探讨如何使用Magento 2构建出色的电子商务体验，并为您提供一些最佳实践和技巧。</p>
<ol>
<li>
<p>定制化能力：<br />Magento 2是一款高度可定制的电子商务平台，可以满足各种业务需求。从产品目录和定价策略到支付和结账流程，您可以根据您的品牌和目标受众来定制和配置每个细节。利用Magento 2的灵活性，您可以为您的客户提供独特而个性化的购物体验。</p>
</li>
<li>
<p>响应式设计：<br />移动设备的普及使得移动购物成为一种趋势。Magento 2提供了响应式设计的主题和布局，确保您的在线商店在各种设备上都能提供一致且优秀的用户体验。通过优化移动界面和用户导航，您可以提高移动用户的参与度和转化率。</p>
</li>
<li>
<p>强大的营销工具：<br />Magento 2提供了丰富的营销工具，帮助您吸引潜在客户并提高销售额。您可以通过设置促销活动、优惠券和购物车价格规则来诱导购买行为。此外，Magento 2还具备强大的SEO功能，帮助您优化网站内容，提高搜索引擎排名。</p>
</li>
<li>
<p>高性能和可扩展性：<br />Magento 2通过使用高级缓存技术、数据库优化和延迟加载等功能，提供卓越的性能。此外，它支持多服务器部署和负载均衡，保证您的在线商店能够处理高流量和快速增长。无论您的业务规模如何，Magento 2都能轻松应对。</p>
</li>
<li>
<p>安全性和可靠性：<br />Magento 2以安全性为重点，提供多层次的安全措施来保护您和客户的数据。它支持符合PCI DSS标准的支付网关，并提供强大的身份验证和访问控制。此外，Magento 2还提供了可靠的备份和恢复功能，保障您的业务连续运行。</p>
</li>
</ol>
<p>结论：<br />Magento 2是一个强大而灵活的电子商务平台，为企业提供了构建出色电子商务体验的工具和功能。定制化能力、响应式设计、强大的营销工具、高性能和可扩展性，以及安全性和可靠性，使得Magento 2成为许多企业的首选平台。通过利用Magento 2的优势，您可以建立一个引人注目且成功的在线商店</p>
<div id="gtx-trans" style="position: absolute; left: -5px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 12 Dec 2023 03:10:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 电子商务：提升销售的战略和工具]]></title>
      <link>https://www.360magento.com/blog/magento-ecommerce-sales-strategies/</link>
      <description><![CDATA[<p>Magento作为一款强大的电子商务平台，提供了多种战略和工具，可帮助企业提升销售业绩。在这篇文章中，我们将深入研究一些Magento电子商务的关键战略和工具，以助力你的在线业务取得更大的成功。</p>
<h2>1. <span>个性化用户体验</span></h2>
<p>通过Magento的个性化功能，你可以根据用户的历史购买记录、浏览行为和个人喜好，为他们呈现定制化的内容和推荐产品。这有助于提高购物体验，增加转化率。</p>
<h2>2. <span>强大的促销和优惠工具</span></h2>
<p>Magento提供丰富的促销和优惠工具，如限时促销、购物车规则和优惠券。合理运用这些工具可以刺激销售，吸引更多顾客完成购买。</p>
<h2>3. <span>全渠道销售整合</span></h2>
<p>整合线上线下销售渠道，创造一致的购物体验。Magento支持多个销售渠道的管理，使你能够更好地满足多样化的客户需求。</p>
<h2>4. <span>移动优化与响应式设计</span></h2>
<p>通过Magento的响应式设计，确保你的在线商店在各种移动设备上都能够提供优秀的用户体验。移动优化对于现代消费者至关重要，有助于提高销售。</p>
<h2>5. <span>实时库存管理</span></h2>
<p>保持实时库存追踪，避免因库存不足而失去销售机会。Magento的库存管理工具可以帮助你及时了解库存情况，制定合理的补货策略。</p>
<h2>6. <span>社交媒体整合</span></h2>
<p>整合社交媒体渠道，通过Magento的社交媒体整合工具将产品直接推送到各大平台。这有助于提高品牌知名度，吸引更多目标受众。</p>]]></description>
      <pubDate>Mon, 11 Dec 2023 07:41:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 营销大全：提升销售、拓展市场份额]]></title>
      <link>https://www.360magento.com/blog/magento-2-marketing-strategies/</link>
      <description><![CDATA[<p>Magento 2作为一款强大的电子商务平台，提供了丰富的营销工具，帮助你提升销售、拓展市场份额。在本文中，我们将深入研究一些Magento 2的营销策略，助你在激烈的市场竞争中脱颖而出。</p>
<h2>1. <span>优化搜索引擎排名（SEO）</span></h2>
<p>通过Magento 2的SEO工具，优化产品页面、元标签和网站结构，提高在搜索引擎中的排名。这有助于增加有机流量，提高网站曝光度。</p>
<h2>2. <span>电子邮件营销</span></h2>
<p>建立强大的电子邮件营销策略，包括定期发送营销邮件、促销活动和新产品通知。通过Magento 2的电子邮件营销工具，保持与客户的紧密联系。</p>
<h2>3. <span>社交媒体推广</span></h2>
<p>整合社交媒体推广，通过Magento 2的社交媒体整合工具分享产品信息、促销活动，增加品牌曝光度。与潜在客户建立更紧密的联系。</p>
<h2>4. <span>积分与奖励计划</span></h2>
<p>建立积分与奖励计划，激励客户进行购物并参与其他活动。通过Magento 2的积分系统，提高用户忠诚度，增加重复购买率。</p>
<h2>5. <span>合作与联盟营销</span></h2>
<p>与其他品牌或业务建立合作与联盟关系，共同进行营销活动。通过Magento 2的合作伙伴管理，实施有效的联合营销计划。</p>
<h2>6. <span>满减与促销活动</span></h2>
<p>定期进行满减和促销活动，通过Magento 2的促销工具设置吸引人的优惠，促进销售增长。这可以提高购物车价值和客户满意度。</p>
<h2>结论</h2>
<p>通过这些Magento 2的营销策略，你可以在激烈的市场竞争中脱颖而出，提升销售业绩。精心设计的营销计划将有助于吸引新客户、保留现有客户，并在竞争激烈的市场中保持竞争力。</p>]]></description>
      <pubDate>Mon, 11 Dec 2023 03:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 进阶性能优化：提升网站速度与用户满意度]]></title>
      <link>https://www.360magento.com/blog/magento-2-advanced-performance-optimization-s2/</link>
      <description><![CDATA[<p>Magento 2的进阶性能优化是提高网站速度和用户满意度的关键步骤。通过深入优化技术和实施高级策略，你可以为用户提供更快速、更流畅的购物体验。在本文中，我们将探讨一些Magento 2的高级性能优化策略，以帮助你实现网站速度的巅峰状态。</p>
<h2>1. <span>精细化代码优化</span></h2>
<p>进行更深入的代码优化，包括删除冗余代码、减少数据库查询次数和优化算法。通过审查代码，找到性能瓶颈并进行改进，提高系统响应速度。</p>
<h2>2. <span>高级缓存策略</span></h2>
<p>实施更高级的缓存策略，如Full Page Cache（FPC）和Object Caching。这些策略可以大幅度减少服务器响应时间，提升网站性能。</p>
<h2>3. <span>无限滚动与异步加载</span></h2>
<p>引入无限滚动和异步加载技术，以减少页面的加载次数。通过仅在需要时加载内容，提高用户体验，减轻服务器负担。</p>
<h2>4. <span>前端资源优化</span></h2>
<p>精细化前端资源的加载，包括压缩CSS和JavaScript文件、延迟加载和最小化HTTP请求。这有助于减少页面加载时间，改善用户感知。</p>
<h2>5. <span>自动化任务调度</span></h2>
<p>使用任务调度系统自动化任务，如数据清理、索引重建等。通过将这些任务放入后台进行处理，避免阻塞前台操作，提高网站的即时响应性。</p>
<h2>6. <span>高级性能监控和分析</span></h2>
<p>引入高级性能监控和分析工具，以实时追踪性能指标、错误率和用户行为。通过深入分析，及时发现潜在问题并采取相应措施。</p>
<h2>结论</h2>
<p>通过实施这些高级性能优化策略，你将能够将Magento 2网站的性能提升到一个全新的水平。这不仅将满足用户的高期望，同时也将有助于提高搜索引擎排名和用户满意度。</p>]]></description>
      <pubDate>Sun, 10 Dec 2023 07:10:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2进阶性能优化：更高速、更出色的电商体验]]></title>
      <link>https://www.360magento.com/blog/magento-2-advanced-performance-optimization/</link>
      <description><![CDATA[<p>Magento 2的性能优化是一个不断演进的过程，通过更进一步的优化策略，可以进一步提升网站速度，提供更出色的电商体验。在本文中，我们将深入研究一些Magento 2的进阶性能优化策略，帮助你实现更高速、更卓越的网站性能。</p>
<h2>1. <span>使用缓存层</span></h2>
<p>在Magento 2上使用额外的缓存层，如Varnish或Redis，以加速页面交付。这样可以减轻服务器负担，提高响应速度。</p>
<h2>2. <span>优化数据库查询</span></h2>
<p>深入优化Magento 2的数据库查询，使用索引、合理的查询语句，以确保数据库操作的效率。定期清理无用的数据，保持数据库的轻量级。</p>
<h2>3. <span>服务端优化</span></h2>
<p>优化服务器设置，包括Web服务器（如Nginx或Apache）和数据库服务器。调整服务器参数，增加硬件资源，以适应不断增长的访问量。</p>
<h2>4. <span>使用异步任务</span></h2>
<p>将一些耗时的任务转换为异步任务，如图片处理、邮件发送等。这样可以避免阻塞主要操作，提高页面加载速度。</p>
<h2>5. <span>定期监控和调整</span></h2>
<p>使用监控工具，定期检查网站性能。根据监控结果，调整配置、优化代码，以适应不断变化的需求和流量。</p>
<h2>6. <span>内容优化和CDN进阶应用</span></h2>
<p>进一步优化网站内容，确保高质量的内容交付。将CDN的应用进一步优化，选择更适合你网站的CDN服务商，提供更广泛的内容分发。</p>
<h2>结论</h2>
<p>通过这些进阶性能优化策略，你可以将Magento 2网站的性能提升到一个新的水平。这将不仅为用户提供更出色的体验，同时也为你的电商业务的成功打下坚实的基础。</p>
<div id="gtx-trans" style="position: absolute; left: -168px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 10 Dec 2023 03:27:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2安全性策略：保护商店和客户的隐私安全]]></title>
      <link>https://www.360magento.com/blog/magento-Security-policy/</link>
      <description><![CDATA[<p>Magento 2作为一款广受欢迎的电子商务平台，安全性至关重要。保护商店和客户的隐私安全是维护声誉和业务持续发展的关键因素。在本文中，我们将深入研究一些Magento 2的安全性策略，以确保你的商店和客户信息的安全。</p>
<h2>1. <span>及时更新Magento 2</span></h2>
<p>保持Magento 2平台及其组件的更新非常重要。及时应用最新的补丁和安全更新，以防范潜在的漏洞和安全威胁。</p>
<h2>2. <span>强化管理员账户安全性</span></h2>
<p>确保管理员账户具有足够的安全性。使用强密码，并定期更改密码。限制管理员账户的访问权限，只允许必要的操作，以降低潜在威胁。</p>
<h2>3. <span>启用SSL加密</span></h2>
<p>使用SSL（安全套接层）加密来保护客户在网站上的敏感信息。确保在Magento 2中启用SSL，特别是在结账过程中，以加密付款信息等关键数据。</p>
<h2>4. <span>实施两步验证（2FA）</span></h2>
<p>在Magento 2中启用两步验证，增加对管理员和用户账户的额外层次的安全验证。这种额外的认证步骤有助于防止未经授权的访问。</p>
<h2>5. <span>监控日志和报警</span></h2>
<p>启用Magento 2的日志记录功能，并设置报警系统，以及时获得异常活动的通知。监控日志有助于及时发现潜在的安全问题，并采取必要的措施。</p>
<h2>6. <span>备份数据</span></h2>
<p>定期备份Magento 2的数据库和文件，确保在发生数据丢失或系统崩溃时能够快速恢复。存储备份文件在安全的位置，以防止未经授权的访问。</p>
<h2>结论</h2>
<p>通过严格执行这些Magento 2安全性策略，你可以有效地保护商店和客户的隐私安全。安全性是建立信任、确保商业连续性的关键环节，务必引起足够的重视。</p>]]></description>
      <pubDate>Sat, 09 Dec 2023 08:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2性能优化策略：提升网站速度，优化用户体验]]></title>
      <link>https://www.360magento.com/blog/magento-2-performance-optimization-s/</link>
      <description><![CDATA[<p>Magento 2作为一款功能丰富的电子商务平台，优化性能对于提供卓越的用户体验至关重要。在本文中，我们将深入研究一些Magento 2的性能优化策略，帮助你提升网站速度，优化用户体验。</p>
<h2>1. <span>启用页面缓存</span></h2>
<p>在Magento 2中启用页面缓存，以减少页面加载时间。缓存页面的静态内容，使用户在访问相同页面时能够更快地加载。</p>
<h2>2. <span>图片优化</span></h2>
<p>对产品图片进行优化，包括压缩图片和使用适当的图片格式。确保图片文件大小合理，以减少页面加载时间，提高性能。</p>
<h2>3. <span>延迟加载（Lazy Loading）</span></h2>
<p>使用延迟加载技术，使页面上的图片和其他资源在用户滚动到它们时才加载。这有助于加速初始页面加载时间，提升用户体验。</p>
<h2>4. <span>合并和压缩CSS和JavaScript文件</span></h2>
<p>合并和压缩Magento 2的CSS和JavaScript文件，减少文件大小，加快页面加载速度。这可以通过Magento 2的后台设置或使用优化工具实现。</p>
<h2>5. <span>使用CDN加速</span></h2>
<p>整合内容分发网络（CDN）以加速静态资源的加载。CDN可以将这些资源分发到全球多个服务器，使用户从最近的服务器加载资源，提高访问速度。</p>
<h2>6. <span>优化数据库</span></h2>
<p>定期优化Magento 2的数据库，删除无用的数据和日志。一个清理的数据库有助于提高数据库查询性能，加速页面加载。</p>
<h2>结论</h2>
<p>通过实施这些Magento 2性能优化策略，你可以显著提升网站速度，优化用户体验。快速加载的网站不仅有助于留住访问者，还对搜索引擎排名产生积极影响。</p>]]></description>
      <pubDate>Sat, 09 Dec 2023 03:26:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2社交媒体整合与影响力营销：拓展品牌影响力，吸引更多客户]]></title>
      <link>https://www.360magento.com/blog/magento-Social-media/</link>
      <description><![CDATA[<h2>1. <span>社交媒体账号整合</span></h2>
<p>整合Magento 2与你的社交媒体账号，包括Facebook、Instagram、Twitter等平台。确保产品页面、促销信息都能方便地分享到社交媒体，扩大品牌曝光。</p>
<h2>2. <span>社交分享和互动</span></h2>
<p>在Magento 2商店中添加社交分享按钮，鼓励用户分享他们的购物体验、喜欢的产品或促销信息。及时回复用户在社交媒体上的评论和提问，建立积极的互动关系。</p>
<h2>3. <span>社交媒体广告整合</span></h2>
<p>结合Magento 2的广告整合功能，将社交媒体广告与你的电商活动相结合。通过有针对性的社交广告，提高品牌知名度，引导潜在客户访问你的网站。</p>
<h2>4. <span>合作和赞助</span></h2>
<p>与有影响力的社交媒体用户、博主或其他品牌进行合作和赞助。这样的合作可以为你的品牌带来更广泛的关注，提高潜在客户的信任度。</p>
<h2>5. <span>创建有趣的社交媒体内容</span></h2>
<p>通过Magento 2的内容管理系统，创建有趣而有吸引力的社交媒体内容。这可以包括教程、产品展示、幕后故事等，以提升品牌故事性和用户互动性。</p>
<h2>6. <span>用户生成内容（UGC）活动</span></h2>
<p>鼓励用户生成内容，例如上传他们使用你产品的照片或分享使用心得。通过Magento 2的UGC活动，可以在社交媒体上展示这些内容，增强社区感和用户参与度。</p>
<h2>结论</h2>
<p>Magento 2的社交媒体整合和影响力营销工具可以帮助你更好地利用社交平台，与潜在客户建立连接，提高品牌影响力。通过巧妙整合社交媒体，你将能够在竞争激烈的市场中脱颖而出。</p>]]></description>
      <pubDate>Fri, 08 Dec 2023 07:21:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2客户服务与忠诚度建设：创造卓越体验，促进长期关系]]></title>
      <link>https://www.360magento.com/blog/magento-customer-service/</link>
      <description><![CDATA[<p>Magento 2作为一款综合性的电子商务平台，提供了丰富的客户服务和忠诚度建设工具，帮助你创造卓越的购物体验，促进客户忠诚度。在本文中，我们将深入研究一些Magento 2的客户服务和忠诚度建设策略，助力你在竞争激烈的市场中赢得客户的长期支持。</p>
<h2>1. <span>多渠道客服支持</span></h2>
<p>整合多渠道客服支持，包括在线聊天、电子邮件、电话等。确保客户可以轻松找到并选择最适合他们的联系方式，解决问题和提供支持。</p>
<h2>2. <span>实时在线聊天</span></h2>
<p>在Magento 2商店中添加实时在线聊天功能，使客户能够立即与客服代表互动。这有助于解决即时问题，提高购物体验。</p>
<h2>3. <span>积分和奖励计划</span></h2>
<p>建立积分和奖励计划，激励客户进行购物并参与其他活动。通过Magento 2的积分系统，为客户提供折扣、礼品或会员特权，增加他们的忠诚度。</p>
<h2>4. <span>个性化服务</span></h2>
<p>利用Magento 2的客户分析工具，了解客户的购物历史和偏好。基于这些信息，提供个性化的产品建议、促销和服务，使客户感到特别重视。</p>
<h2>5. <span>定期沟通和回馈</span></h2>
<p>建立定期沟通和反馈机制，通过电子邮件、短信或其他渠道与客户保持联系。向客户发送特别优惠、新产品信息，并鼓励他们提供反馈，以改善服务。</p>
<h2>6. <span>售后服务和保修政策</span></h2>
<p>明确的售后服务和保修政策是建立客户信任的重要因素。在Magento 2商店中清晰地展示售后服务政策，确保客户在购物后有可靠的支持。</p>
<h2>结论</h2>
<p>通过提供卓越的客户服务和实施忠诚度建设策略，你可以在Magento 2平台上建立长期关系，促进客户忠诚度。满足客户需求、提供个性化服务将帮助你在激烈的市场竞争中脱颖而出。</p>
<div id="gtx-trans" style="position: absolute; left: -38px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 08 Dec 2023 03:22:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 Data analysis and marketing strateg：基于洞察力制定成功计划]]></title>
      <link>https://www.360magento.com/blog/Magento-Data-analysis-and-marketing/</link>
      <description><![CDATA[<p>Magento 2作为一款全面的电子商务平台，提供了丰富的数据分析工具，帮助你更好地理解用户行为并制定有效的营销策略。在本文中，我们将深入研究一些Magento 2的数据分析和营销策略，以基于深入洞察力制定成功的电商计划。</p>
<h2>1. <span>使用Google Analytics整合</span></h2>
<p>整合Google Analytics到你的Magento 2商店，以获取全面的网站访问数据。通过分析用户行为、流量来源和转化率等指标，你可以更好地了解用户喜好和购物习惯，从而调整营销策略。</p>
<h2>2. <span>购物者流程分析</span></h2>
<p>使用Magento 2的购物者流程分析工具，深入了解用户在购物过程中的行为路径。确定用户在网站上的关键互动点，并优化这些步骤，以提高转化率和销售。</p>
<h2>3. <span>利用A/B测试</span></h2>
<p>进行A/B测试，测试不同的页面布局、促销活动或产品展示方式。通过比较不同变体的性能，你可以确定哪种设计或策略更有效，从而优化用户体验和提高转化率。</p>
<h2>4. <span>分析购物篮放弃率</span></h2>
<p>深入分析购物篮放弃率，找出用户在结账前放弃购物篮的原因。可能是高额的运费、繁琐的结账流程等问题。通过解决这些问题，可以提高结账完成率。</p>
<h2>5. <span>客户分群和个性化营销</span></h2>
<p>使用Magento 2的客户分群功能，将用户划分为不同的群体，根据其行为和偏好制定个性化的营销计划。通过向特定群体发送定制的促销信息，提高用户参与度和购买意愿。</p>
<h2>6. <span>实时销售和库存分析</span></h2>
<p>通过实时销售和库存分析，了解热门产品、畅销时段和库存水平。基于这些信息，可以调整库存管理、推动促销活动，并在高需求时提供更多库存。</p>
<h2>结论</h2>
<p>Magento 2提供了强大的数据分析工具，帮助你更好地理解用户行为和网站性能。通过深入洞察力，你可以制定更精准的营销策略，提高销售效果，促使业务的不断增长。</p>]]></description>
      <pubDate>Thu, 07 Dec 2023 07:20:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Improve Magento 2 User experience (UX)：创造令人难忘的购物旅程]]></title>
      <link>https://www.360magento.com/blog/Improve-Magento-User-experience/</link>
      <description><![CDATA[<p>Magento 2作为一款强大的电子商务平台，注重用户体验至关重要。在本文中，我们将深入了解一些提升Magento 2用户体验的关键策略，以创造令人难忘的购物旅程，促进客户忠诚度和提高销售。</p>
<h2>1. <span>响应式设计</span></h2>
<p>确保你的Magento 2商店采用响应式设计，以确保在各种设备上都能提供一致而流畅的用户体验。无论是在台式电脑、平板还是手机上，用户都应该能够轻松访问和浏览你的网站。</p>
<h2>2. <span>简洁而直观的导航</span></h2>
<p>设计简洁而直观的导航结构，让用户能够轻松找到他们想要的产品。清晰的菜单、有效的筛选和搜索功能都是帮助用户快速导航的关键。</p>
<h2>3. <span>快速的页面加载速度</span></h2>
<p>优化Magento 2商店的页面加载速度，确保用户能够快速访问产品页面。压缩图像、启用浏览器缓存、减少HTTP请求等优化措施，都有助于提高页面加载速度。</p>
<h2>4. <span>个性化推荐和建议</span></h2>
<p>利用Magento 2的个性化推荐功能，向用户展示他们可能感兴趣的产品。根据用户的浏览历史、购买记录和个人喜好，定制推荐，提升购物体验。</p>
<h2>5. <span>简化结账流程</span></h2>
<p>简化Magento 2商店的结账流程，减少用户的购物车放弃率。优化每个结账步骤，提供明确的指导，尽量减少填写表单的步骤，让结账过程更加顺畅。</p>
<h2>6. <span>实时支持和反馈</span></h2>
<p>提供实时支持和反馈机制，确保用户在购物过程中能够得到及时的帮助。集成在线聊天、客服热线或提供详细的帮助文档，为用户提供全方位的支持。</p>
<h2>结论</h2>
<p>通过关注用户体验，你可以建立一个引人入胜的购物旅程，增加用户满意度和忠诚度。Magento 2提供了丰富的工具，帮助你优化用户体验，为用户创造难忘的购物体验</p>]]></description>
      <pubDate>Thu, 07 Dec 2023 03:03:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 e-commerce marketing strategy：吸引客户、提升销售]]></title>
      <link>https://www.360magento.com/blog/Magento-2-e-commerce-marketing-strategy/</link>
      <description><![CDATA[<p>Magento 2作为一款强大的电子商务平台，提供了丰富的营销工具，帮助商家吸引客户、提高销售。在本文中，我们将深入探讨一些Magento 2的营销策略，让你更好地利用平台功能，打造成功的电商业务。</p>
<h2>1. <span>创建引人注目的产品页面</span></h2>
<p>首先，确保你的产品页面设计引人注目。清晰的产品图片、详细的产品描述以及明确的购买按钮都是关键因素。采用响应式设计，确保在各种设备上都能提供出色的用户体验。</p>
<h2>2. <span>优惠券和促销活动</span></h2>
<p>Magento 2提供了灵活的优惠券和促销活动功能。利用这些功能，制定吸引人的促销策略，如打折、满减、赠品等，以激发客户的购买欲望。定期举办促销活动，吸引新客户并保持现有客户的忠诚度。</p>
<h2>3. <span>电子邮件营销</span></h2>
<p>建立强大的电子邮件营销策略，与客户保持联系。Magento 2允许你轻松地发送订单确认、促销信息、新产品推介等电子邮件。利用个性化的邮件内容，提高打开率和转化率。</p>
<h2>4. <span>社交媒体整合</span></h2>
<p>将社交媒体整合到Magento 2中，以扩大你的品牌影响力。分享产品、举办社交媒体竞赛、与客户互动，都是有效的社交媒体策略。通过社交分享按钮，让客户方便地分享他们的购物体验。</p>
<h2>5. <span>客户评论和建议</span></h2>
<p>鼓励客户留下产品评论和建议，这有助于增强信任感。正面的评价和建议对于其他潜在客户的购物决策起到重要作用。及时回复客户的评论，显示关注和专业。</p>
<h2>6. <span>购物车提醒和放弃购物车恢复</span></h2>
<p>Magento 2允许你设置购物车提醒，提醒客户他们的购物车中尚有未结账的商品。同时，设置放弃购物车恢复策略，通过电子邮件或其他渠道引导客户完成购买。</p>
<h2>结论</h2>
<p>Magento 2提供了丰富的营销工具，帮助你吸引客户、提高销售。通过巧妙利用这些功能，你可以制定出成功的电商营销策略，提升品牌知名度并增加盈利。</p>]]></description>
      <pubDate>Wed, 06 Dec 2023 07:16:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2搜索引擎优化（SEO）策略：提高在线商店可见性]]></title>
      <link>https://www.360magento.com/blog/Magento-Search-Engine-Optimization/</link>
      <description><![CDATA[<p>Magento 2作为一款强大的电子商务平台，提供了丰富的搜索引擎优化（SEO）功能，帮助商家提高在线商店在搜索引擎中的可见性。在本文中，我们将深入了解一些Magento 2的SEO策略，让你的商店在搜索结果中脱颖而出。</p>
<h2>1. <span>优化产品页面标题和描述</span></h2>
<p>确保每个产品页面都有独特、吸引人的标题和描述。标题和描述是搜索引擎展示结果中的第一印象，因此要使它们既包含关键词，又能吸引用户点击。</p>
<h2>2. <span>友好的URL结构</span></h2>
<p>设置Magento 2的URL结构为友好的形式。清晰、简洁的URL不仅有助于搜索引擎理解页面内容，还提升用户体验。使用描述性词汇和关键词来构建URL。</p>
<h2>3. <span>关键词研究和使用</span></h2>
<p>进行关键词研究，了解潜在客户在搜索引擎中使用的关键词。在产品描述、页面标题、标签等位置巧妙地使用这些关键词，以提高页面在搜索结果中的排名。</p>
<h2>4. <span>创建XML网站地图</span></h2>
<p>Magento 2允许你创建XML网站地图，这有助于搜索引擎索引你的网站。确保地图包含所有重要的页面链接，并在网站根目录下提供sitemap.xml文件。</p>
<h2>5. <span>优化图片</span></h2>
<p>对产品图片进行优化，包括使用描述性文件名和ALT文本。优化后的图片有助于提高页面加载速度，同时也能在图像搜索结果中显示。</p>
<h2>6. <span>社交媒体整合</span></h2>
<p>整合社交媒体到你的Magento 2商店，通过社交分享和互动来增强在线商店的社交信号。社交信号对搜索引擎排名有一定影响，因此积极参与社交媒体是一项有效的SEO策略。</p>
<h2>结论</h2>
<p>Magento 2的SEO功能为优化在线商店提供了丰富的工具。通过合理利用这些功能，你可以提高商店在搜索引擎中的可见性，吸引更多潜在客户，并提升销售。</p>]]></description>
      <pubDate>Wed, 06 Dec 2023 03:17:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[深入了解Magento 2主题定制：打造独特的在线商店外观]]></title>
      <link>https://www.360magento.com/blog/magento-stheme-customer/</link>
      <description><![CDATA[<p>Magento 2 是一款强大而灵活的电子商务平台，而主题定制是确保你的在线商店在外观上与众不同的关键步骤之一。在本文中，我们将探讨如何定制Magento 2主题，以便根据你的品牌和业务需求创建一个独特的用户体验。</p>
<h2>1. <span>了解Magento 2主题结构</span></h2>
<p>首先，理解Magento 2主题的结构是至关重要的。主题通常包括布局文件、模板文件、样式表和JavaScript文件。深入研究Magento 2主题结构将使你能够更有效地进行定制。</p>
<h2>2. <span>创建自定义主题</span></h2>
<p>Magento 2允许你创建自定义主题，以便轻松地进行定制。通过在<code>app/design/frontend</code>目录下创建你自己的主题，你可以开始定制你的商店的外观。确保你的主题从Magento 2的默认主题或其他现有主题继承，以便获取基本的样式和功能。</p>
<h2>3. <span>修改样式和布局</span></h2>
<p>通过修改主题的样式表和布局文件，你可以调整商店的颜色、字体、排列方式等。使用LESS或CSS预处理器，可以更轻松地管理样式。同时，Magento 2的布局文件允许你重新排列页面元素，以满足你的布局需求。</p>
<h2>4. <span>添加自定义图像和图标</span></h2>
<p>通过替换默认的图像和图标，可以将商店的外观与品牌形象相匹配。确保你的图像符合Magento 2的建议尺寸和规范，以确保页面加载速度和用户体验。</p>
<h2>5. <span>集成自定义JavaScript</span></h2>
<p>如果你需要添加特定的交互性或功能，可以通过集成自定义JavaScript来实现。例如，实现产品页面上的动画效果或改进购物车的交互性。</p>
<h2>结论</h2>
<p>通过深入了解Magento 2主题定制，你可以打造一个独特、引人注目的在线商店外观，与众不同地展示你的品牌。通过合理使用Magento 2的主题定制功能，你将能够为你的客户提供一个独特而难忘的购物体验。</p>]]></description>
      <pubDate>Tue, 05 Dec 2023 07:13:15 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[提升Magento 2安全性：保护你的在线商店和客户信息]]></title>
      <link>https://www.360magento.com/blog/magento2-Improved/</link>
      <description><![CDATA[<p>Magento 2是一款功能丰富的电子商务平台，而安全性是确保商店和客户信息安全的至关重要的方面。在本文中，我们将深入探讨一些提升Magento 2安全性的关键步骤，以确保你的电子商务运营得到充分的保护。</p>
<h2>1. <span>及时更新Magento 2</span></h2>
<p>始终保持Magento 2的更新是确保安全性的基本步骤。Magento的更新通常包括对潜在漏洞的修复和增强安全性的改进。定期检查并应用最新的Magento 2版本，以确保你的商店处于最安全的状态。</p>
<h2>2. <span>使用SSL加密</span></h2>
<p>使用SSL（安全套接层）加密是保护客户信息不被窃取的重要手段。确保在Magento 2中启用SSL，以加密数据传输，包括用户登录信息、付款详情等。购物车和结账过程中使用SSL是至关重要的。</p>
<h2>3. <span>强化管理员账户安全</span></h2>
<p>采取措施确保管理员账户的强大安全性是至关重要的。使用强密码，并定期更改密码。另外，限制管理员账户的访问权限，只允许必要的操作。</p>
<h2>4. <span>监控日志和报警</span></h2>
<p>启用Magento 2的日志记录功能，并设置报警系统，以便在发生异常活动时及时获得通知。通过监控日志，你可以及时发现潜在的安全威胁，并采取必要的措施。</p>
<h2>5. <span>防火墙和安全插件</span></h2>
<p>考虑在Magento 2中使用防火墙和安全插件，以提供额外的保护层。这些工具可以帮助检测和阻止潜在的恶意活动，增加商店的整体安全性。</p>
<h2>6. <span>定期备份</span></h2>
<p>定期备份Magento 2的数据库和文件是一种防范措施，可以在发生数据丢失或系统崩溃时快速恢复。确保备份是可用的，并存储在安全的位置。</p>
<h2>结论</h2>
<p>通过采取这些关键步骤，你可以显著提升Magento 2商店的安全性，保护客户信息免受潜在威胁。安全性是电子商务成功运营的基石，因此投资于Magento 2的安全性绝对是值得的。</p>]]></description>
      <pubDate>Tue, 05 Dec 2023 03:15:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[深入了解Magento 2：强大的电子商务平台]]></title>
      <link>https://www.360magento.com/blog/about-magento-shop/</link>
      <description><![CDATA[<p>Magento 2 是一款领先的开源电子商务平台，为在线商店提供了出色的灵活性和功能。在本文中，我们将深入探讨Magento 2的一些主要功能和优势。</p>
<h2>1. <span>现代化的架构</span></h2>
<p>Magento 2采用了现代化的架构，利用了最新的技术和最佳实践。这包括使用PHP 7和HTML5等技术，为用户提供更快、更可靠的购物体验。</p>
<h2>2. <span>响应式设计</span></h2>
<p>随着移动设备的普及，响应式设计变得至关重要。Magento 2通过提供响应式主题确保你的在线商店在各种设备上都能够提供优质的用户体验，从而提高销售和客户满意度。</p>
<h2>3. <span>强大的扩展性</span></h2>
<p>Magento 2提供了丰富的扩展性，允许你通过安装插件和扩展来定制和扩展你的商店功能。这使得Magento 2成为适应不同业务需求的理想选择。</p>
<h2>4. <span>全球化支持</span></h2>
<p>对于国际业务而言，Magento 2提供了多语言和多货币支持，使你的商店能够轻松扩展到全球市场。同时，它还支持不同的税收和运费规则，以适应不同的地理位置。</p>
<h2>5. <span>先进的安全性</span></h2>
<p>Magento 2致力于保护你的在线业务免受潜在威胁。通过使用SSL加密、安全支付网关和数据备份等功能，Magento 2确保你的商店和客户数据得到充分的保护。</p>
<h2>结论</h2>
<p>Magento 2是一款功能强大、灵活且现代的电子商务平台，适用于各种规模的企业。无论你是刚刚起步还是已经运营多年的企业，Magento 2都能提供所需的工具和功能，帮助你建立成功的在线业务。</p>]]></description>
      <pubDate>Mon, 04 Dec 2023 07:11:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[深入了解Magento 2扩展开发：为你的在线商店增加定制功能]]></title>
      <link>https://www.360magento.com/blog/magento-dev-enline-shop/</link>
      <description><![CDATA[<p>Magento 2是一款功能强大的电子商务平台，而通过扩展开发，你可以为你的在线商店增加各种定制功能，以满足特定业务需求。在本文中，我们将深入了解Magento 2扩展开发的基础知识，帮助你打造一个更强大、更灵活的电子商务解决方案。</p>
<h2>1. <span>创建自定义Magento 2扩展</span></h2>
<p>首先，了解如何创建自定义Magento 2扩展是至关重要的。通过在<code>app/code</code>目录下创建自己的扩展，你可以开始为商店添加新功能。确保你的扩展结构符合Magento 2的标准，以便顺利运行。</p>
<h2>2. <span>了解Magento 2扩展的结构</span></h2>
<p>了解Magento 2扩展的结构将有助于更好地组织和管理你的代码。Magento 2扩展通常包括控制器、模型、观察者和布局文件等元素。深入了解这些组件将有助于你更好地理解扩展的工作原理。</p>
<h2>3. <span>创建自定义控制器和模型</span></h2>
<p>通过创建自定义控制器和模型，你可以在Magento 2中添加新的业务逻辑。这使你能够处理特定的请求、生成自定义数据或与数据库交互。确保你的控制器和模型遵循Magento 2的最佳实践，以确保性能和稳定性。</p>
<h2>4. <span>使用观察者添加事件</span></h2>
<p>Magento 2的事件和观察者模式允许你在系统中添加自定义事件，并在需要时执行相应的操作。通过创建观察者，你可以在Magento 2中捕获特定的事件，并在事件发生时执行自定义代码，以实现更高度定制化的功能。</p>
<h2>5. <span>布局文件和前端资产</span></h2>
<p>通过创建自定义布局文件，你可以更改页面的结构和元素排列。同时，通过添加前端资产，如JavaScript和CSS文件，可以改进用户界面的外观和交互性。</p>
<h2>结论</h2>
<p>通过深入了解Magento 2扩展开发，你可以为你的在线商店添加各种自定义功能，从而提升用户体验并满足特定业务需求。合理利用Magento 2的扩展开发功能，将使你的电子商务解决方案更具竞争力。</p>]]></description>
      <pubDate>Mon, 04 Dec 2023 04:14:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 移动应用开发与响应式设计]]></title>
      <link>https://www.360magento.com/blog/magento2-mobile-app-development-responsive-design/</link>
      <description><![CDATA[<p>在当今数字化时代，移动设备的普及使得移动应用开发和响应式设计成为电子商务领域的重要趋势之一。对于使用 Magento 2 的电商网站，开发移动应用以及实施响应式设计可以为用户提供更好的移动体验，增强用户参与度和提升销售业绩。本篇博文将介绍 Magento 2 移动应用开发和响应式设计的关键要点。</p>
<p><strong>移动应用开发：</strong></p>
<ol>
<li>
<p>选择适当的移动应用开发框架：Magento 2 提供了 REST API，使得开发人员能够构建自定义的移动应用。您可以选择流行的移动应用开发框架，如 React Native、Flutter 或 Ionic，来构建跨平台的移动应用。</p>
</li>
<li>
<p>集成 Magento 2 API：使用 Magento 2 的 REST API，您可以在移动应用中访问和管理产品、订单、客户等数据。确保使用安全的认证方式，以保护敏感数据。</p>
</li>
<li>
<p>优化移动应用性能：移动应用的性能对于用户体验至关重要。优化应用的加载速度、响应时间和资源管理，以确保流畅的用户体验。</p>
</li>
<li>
<p>设计用户友好的界面：在移动应用中，设计简洁、直观且易于操作的用户界面非常重要。遵循移动应用设计准则，并确保应用的布局和导航在不同屏幕尺寸上都能良好地适应。</p>
</li>
</ol>
<p><strong>响应式设计：</strong></p>
<ol>
<li>
<p>使用响应式主题：Magento 2 提供了多个响应式主题，可以根据不同设备的屏幕尺寸和分辨率来自动调整布局和样式。选择适合您品牌形象和用户体验的主题，并进行必要的定制。</p>
</li>
<li>
<p>图片优化：针对移动设备，优化网站中的图片以减少加载时间。使用适当的图像压缩和缩放技术，确保在保持良好视觉质量的同时减小文件大小。</p>
</li>
<li>
<p>响应式导航和交互元素：设计导航和交互元素，以便在不同设备上易于触摸和操作。使用移动友好的菜单和按钮样式，确保用户能够轻松导航和与网站进行交互。</p>
</li>
<li>
<p>跨浏览器和设备测试：在实施响应式设计之前，进行广泛的测试，以确保您的网站在各种浏览器和设备上都能提供一致的用户体验。</p>
</li>
</ol>
<p>通过在 Magento 2 上进行移动应用开发和响应式设计，您可以为用户提供无缝的移动体验，并达到更高的用户满意度和销售转化率。</p>]]></description>
      <pubDate>Sun, 03 Dec 2023 07:44:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[了解Magento布局：构建强大的电子商务网站]]></title>
      <link>https://www.360magento.com/blog/understanding-magento-layout-building-powerful-ecommerce-website/</link>
      <description><![CDATA[<p>Magento是一个功能强大的电子商务平台，它提供了灵活的布局系统，使您能够构建定制化和响应式的电子商务网站。在本文中，我们将深入了解Magento的布局系统，了解它的工作原理以及如何利用它来构建强大的电子商务网站。</p>
<h3>什么是Magento布局？</h3>
<p>Magento布局是指定义和组织页面结构的XML文件。它决定了页面中各个元素的位置、顺序和外观。布局文件位于Magento主题的<code>app/design/frontend/{Vendor}/{Theme}/Magento_Theme/layout</code>目录下，其中<code>{Vendor}</code>和<code>{Theme}</code>是您当前使用的主题的名称。</p>
<h3>布局文件的结构</h3>
<p>Magento布局文件由一个或多个XML文件组成。其中最重要的文件是<code>default.xml</code>，它定义了网站的默认布局。其他布局文件可以覆盖和扩展默认布局，以适应不同的页面和区域。</p>
<p>布局文件通常包含以下几个主要部分：</p>
<ol>
<li><code>&lt;layout&gt;</code>&nbsp;根元素：它是布局文件的根元素，包含所有其他元素。</li>
<li><code>&lt;head&gt;</code>&nbsp;元素：它定义了页面的头部部分，通常用于引入CSS和JavaScript文件。</li>
<li><code>&lt;body&gt;</code>&nbsp;元素：它定义了页面的主体部分，包含各个区块和容器。</li>
<li><code>&lt;referenceContainer&gt;</code>&nbsp;元素：它用于定义和配置容器，容器将包含其他区块。</li>
<li><code>&lt;block&gt;</code>&nbsp;元素：它用于定义和配置区块，区块是页面上的可重用组件，例如导航栏、产品列表等。</li>
<li><code>&lt;referenceBlock&gt;</code>&nbsp;元素：它用于引用和配置已定义的区块，并进行进一步的配置或修改。</li>
<li><code>&lt;referenceContainer&gt;</code>&nbsp;和&nbsp;<code>&lt;referenceBlock&gt;</code>&nbsp;元素也可以包含其他元素，以实现更高级的布局操作。</li>
</ol>
<h3>使用Magento布局构建网站</h3>
<p>通过使用Magento布局，您可以根据需要自定义和调整页面的结构和外观。以下是一些在构建Magento网站时使用布局的常见场景和操作：</p>
<ol>
<li>
<p>添加、移除或修改区块（Blocks）：使用&nbsp;<code>&lt;referenceBlock&gt;</code>&nbsp;元素可以引用已定义的区块，并进行进一步的配置或修改。您可以修改区块的属性、位置和样式，或者添加新的区块来扩展页面功能。</p>
</li>
<li>
<p>调整容器（Containers）：使用&nbsp;<code>&lt;referenceContainer&gt;</code>&nbsp;元素可以引用已定义的容器，并进行进一步的配置或修改。您可以通过添加、移除或重新排序容器中的区块来调整页面的布局和结构。</p>
</li>
<li>
<p>扩展和重写布局文件：您可以创建自定义的布局文件，并将其放置在主题目录中，以覆盖或扩展默认布局文件。这使您能够根据需要自定义特定页面或区域的布局。</p>
</li>
<li>
<p>响应式布局：Magento提供了响应式设计的支持，使您可以根据不同的设备和屏幕尺寸调整页面的布局和外观。通过使用CSS媒体查询和Magento的响应式类，您可以为不同的设备提供定制的布局和样式。</p>
</li>
</ol>
<h3>总结</h3>
<p>Magento的布局系统为构建强大的电子商务网站提供了灵活而强大的工具。通过了解Magento布局文件的结构和使用方法，您可以根据需要自定义和调整页面的结构、布局和外观。使用Magento的布局系统可以创建灵活且独特的电子商务网站，为用户提供出色的购物体验。</p>]]></description>
      <pubDate>Sun, 03 Dec 2023 03:06:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2性能优化和缓存管理：加速您的电子商务网站]]></title>
      <link>https://www.360magento.com/blog/magento-2-performance-optimization-and-cache-management/</link>
      <description><![CDATA[<ol>
<li>理解Magento 2性能瓶颈</li>
</ol>
<p>首先，我们需要了解Magento 2可能面临的性能瓶颈。这些包括数据库查询、代码优化、资源加载、HTTP请求和响应时间等。通过识别和解决这些瓶颈，您可以显著提高网站的性能。</p>
<ol start="2">
<li>Magento 2缓存机制</li>
</ol>
<p>Magento 2提供了多种缓存机制来加速网站加载速度。了解Magento 2的缓存类型，如页面缓存、块缓存、配置缓存等，以及如何启用、配置和清除缓存，是优化性能的关键。</p>
<ol start="3">
<li>优化策略和技巧</li>
</ol>
<p>在Magento 2中，有许多优化策略和技巧可帮助您提升网站性能。这些包括使用CDN（内容分发网络）、压缩和合并CSS和JavaScript文件、优化图像、启用代码缓存和自动优化、使用高性能服务器和数据库等。了解这些策略并实施它们，将显著改善网站的性能。</p>
<ol start="4">
<li>工具和技术</li>
</ol>
<p>在优化Magento 2性能时，有一些有用的工具和技术可帮助您监测和分析性能瓶颈。这些工具包括Magento自带的性能配置、第三方性能分析工具（如New Relic、Blackfire等）、代码审查工具和调试工具。通过使用这些工具，您可以获得关于性能瓶颈的详细信息，并采取相应的措施来解决它们。</p>
<p>总结：</p>
<p>本篇博文提供了关于Magento 2性能优化和缓存管理的指导和技巧，帮助您加速和提升电子商务网站的性能。通过理解Magento 2的性能瓶颈、缓存机制、优化策略以及使用相关工具和技术，您将能够实现更快、更高效的网站加载和响应速度。</p>]]></description>
      <pubDate>Sat, 02 Dec 2023 07:51:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2多语言和多货币支持：扩展您的电子商务业务]]></title>
      <link>https://www.360magento.com/blog/magento-2-multilingual-multicurrency-support/</link>
      <description><![CDATA[<ol>
<li>多语言设置</li>
</ol>
<p>了解Magento 2的多语言设置是实现多语言支持的第一步。Magento 2提供了多语言包，您可以选择适合您目标市场的语言包进行安装和配置。同时，了解如何管理翻译文件、启用和禁用语言、处理静态文本和动态内容，将帮助您实现网站的多语言支持。</p>
<ol start="2">
<li>翻译和本地化</li>
</ol>
<p>为了确保网站内容的准确翻译和本地化，您可以使用Magento 2的翻译工具或第三方翻译服务。这包括对产品描述、页面文本、导航菜单、错误消息等的本地化处理。通过提供本地化的内容，您能够更好地满足不同语言用户的需求。</p>
<ol start="3">
<li>多货币配置</li>
</ol>
<p>Magento 2还提供了多货币配置功能，使您能够根据不同市场的需求设置不同的货币。您可以配置货币符号、汇率转换、税收设置等，以确保正确显示和计算不同货币的价格。这将帮助您吸引全球客户并提高销售效益。</p>
<ol start="4">
<li>扩展和技巧</li>
</ol>
<p>Magento 2的市场上有许多扩展和技巧可帮助您更好地实现多语言和多货币支持。这些扩展包括多语言翻译扩展、货币切换扩展、自动地理定位扩展等。了解这些扩展和技巧，并根据您的需求选择适合的解决方案，将为您的电子商务业务带来便利和优势。</p>
<p>总结：</p>
<p>本篇博文介绍了Magento 2多语言和多货币支持的重要性，并提供了实现这些功能的指导和建议。通过正确配置多语言设置、翻译和本地化处理、多货币配置以及应用相关的扩展和技巧，您将能够扩展您的电子商务业务，提供更广泛的市场覆盖并提升用户体验。</p>]]></description>
      <pubDate>Sat, 02 Dec 2023 02:53:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2数据库管理和数据迁移：最佳实践和工具]]></title>
      <link>https://www.360magento.com/blog/magento-2-database-management-and-data-migration/</link>
      <description><![CDATA[<ol>
<li>Magento 2数据库结构</li>
</ol>
<p>了解Magento 2的数据库结构是有效管理和操作数据库的关键。Magento 2使用EAV（Entity-Attribute-Value）模型来存储和管理数据，这个模型可以灵活地扩展和定制。您应该熟悉Magento 2的核心表和关系，以及自定义模块和扩展可能涉及的表和字段。</p>
<ol start="2">
<li>数据库备份和恢复</li>
</ol>
<p>定期备份Magento 2的数据库是保护数据完整性的重要步骤。您可以使用数据库管理工具或通过命令行执行备份操作。同时，了解如何恢复数据库备份以应对意外数据丢失或损坏的情况也是至关重要的。</p>
<ol start="3">
<li>数据迁移策略</li>
</ol>
<p>当您需要将Magento 2网站从一个环境迁移到另一个环境时，制定一个有效的数据迁移策略非常重要。您可以选择使用Magento 2提供的数据迁移工具，如Magento 2迁移工具（Migration Tool）或使用第三方工具和脚本来执行迁移操作。确保在迁移过程中保持数据的一致性和准确性。</p>
<ol start="4">
<li>数据迁移工具和技术</li>
</ol>
<p>有几个流行的工具和技术可用于Magento 2数据迁移。其中包括Magento 2迁移工具（Migration Tool）、Data Migration Pro（DMC）扩展、第三方ETL（Extract, Transform, Load）工具等。了解这些工具的使用方法和适用场景，可以帮助您更好地管理和执行数据迁移任务。</p>
<p>总结：</p>
<p>本篇博文提供了有关Magento 2数据库管理和数据迁移的最佳实践和工具。通过了解Magento 2的数据库结构、备份和恢复数据库、数据迁移策略以及常用的数据迁移工具和技术，您将能够有效地管理和迁移Magento 2网站的数据库。</p>]]></description>
      <pubDate>Fri, 01 Dec 2023 07:49:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 开发技术指南：构建强大的电子商务网站]]></title>
      <link>https://www.360magento.com/blog/magento-2-developer-guide/</link>
      <description><![CDATA[<p>Magento 2是一个流行且功能强大的开源电子商务平台，为企业提供了构建可扩展、高性能的在线商店的解决方案。如果您正在考虑使用Magento 2来开发您的电子商务网站，那么本篇博文将为您提供一些有用的技术指导。</p>
<ol>
<li>Magento 2基本架构</li>
</ol>
<p>了解Magento 2的基本架构对于开发者来说至关重要。Magento 2采用了模块化的体系结构，每个功能模块都以自己的方式工作，并可以通过Magento Marketplace进行扩展。熟悉Magento 2的基本组件和模块之间的关系，将帮助您更好地理解和开发您的网站。</p>
<ol start="2">
<li>模块开发</li>
</ol>
<p>Magento 2的模块开发是扩展和定制平台功能的关键。您可以根据特定需求创建自定义模块，并将其集成到Magento 2中。了解如何创建和配置模块、添加新功能、覆盖现有功能以及处理事件和触发器等关键概念，将帮助您更好地开发和管理自定义模块。</p>
<ol start="3">
<li>主题定制</li>
</ol>
<p>Magento 2的主题定制使您能够为您的电子商务网站创建独特的外观和用户体验。了解主题的结构、创建自定义主题、修改样式和布局，以及处理静态资源等方面的知识，将使您能够根据品牌需求定制您的网站外观。</p>
<ol start="4">
<li>最佳实践</li>
</ol>
<p>在开发Magento 2网站时，遵循一些最佳实践可以提高性能、安全性和用户体验。这包括使用缓存和索引、优化数据库查询、进行代码审查和测试、实施安全措施等。本文还将介绍一些最佳实践，以帮助您开发高质量的Magento 2网站。</p>
<p>总结：</p>
<p>本篇博文提供了关于Magento 2开发的一些基本指导和资源，帮助您构建功能强大的电子商务网站。通过了解Magento 2的基本架构、模块开发、主题定制以及一些最佳实践，您将能够充分利用Magento 2平台的优势，并为您的客户提供卓越的在线购物体验。</p>]]></description>
      <pubDate>Fri, 01 Dec 2023 03:47:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2性能优化：提升您的电子商务网站速度]]></title>
      <link>https://www.360magento.com/blog/magento-e-commerce-website-speed/</link>
      <description><![CDATA[<p>在竞争激烈的电子商务市场中，网站速度是吸引和保留客户的关键因素之一。Magento 2作为一款功能强大的电子商务平台，可以通过一些性能优化技巧来提高网站速度和响应时间。本文将介绍一些Magento 2性能优化的实践方法，帮助您提升电子商务网站的性能。</p>
<ol>
<li>
<p>使用最新版本的Magento 2：<br />始终使用最新版本的Magento 2是提升性能的重要步骤之一。每个版本都包含了对性能的改进和优化，包括代码优化、缓存机制改进和Bug修复等。确保您的网站已经升级到最新版本，以获得最佳性能和安全性。</p>
</li>
<li>
<p>启用缓存：<br />Magento 2提供了强大的缓存功能，通过缓存页面内容和数据库查询结果，可以大大减少页面加载时间。在Magento 2的后台设置中，您可以启用各种缓存类型，包括页面缓存、块缓存和数据库查询结果缓存等。启用适当的缓存类型可以显著提高网站的响应速度。</p>
</li>
<li>
<p>优化图片：<br />图片通常是网站加载时间较长的主要原因之一。通过优化图片大小和压缩，可以减少它们的文件大小，从而加快页面加载速度。使用适当的图片格式（如JPEG、PNG）和工具来优化图片，以确保它们在保持质量的同时具有较小的文件大小。</p>
</li>
<li>
<p>使用CDN（内容分发网络）：<br />CDN是一个分布式网络，可以将您的网站内容缓存到全球各个位置的服务器上。当用户访问您的网站时，他们将从最接近他们位置的服务器上加载内容，从而减少了网络延迟和传输时间。使用CDN可以显著提高网站的加载速度和性能。</p>
</li>
<li>
<p>优化数据库：<br />Magento 2使用数据库存储大量的网站数据，因此优化数据库性能对于提高网站速度至关重要。您可以执行数据库索引优化、删除不必要的数据和日志、优化数据库查询等操作来改善数据库性能。此外，使用数据库缓存和查询缓存也是提高性能的有效方法。</p>
</li>
<li>
<p>压缩和合并CSS和JavaScript文件：<br />通过压缩和合并网站的CSS和JavaScript文件，可以减少文件的数量和总体文件大小，从而加快页面加载速度。使用合适的工具和技术，将多个CSS文件合并为一个文件，并压缩JavaScript文件，以减少网络请求和提高性能。</p>
</li>
</ol>
<p>结论：<br />通过采取以上的Magento 2性能优化措施，您可以大大提升您的电子商务网站的速度和响应时间。优化网站性能不仅可以提供更好的用户体验，还能提高搜索引擎排名并吸引更多的访问者。始终关注网站性能，并定期评估和优化它，是保持竞争力的关键之一。</p>]]></description>
      <pubDate>Thu, 30 Nov 2023 07:49:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 数据迁移：顺畅升级您的电子商务平台]]></title>
      <link>https://www.360magento.com/blog/magento-data-platform/</link>
      <description><![CDATA[<p>升级到Magento 2是许多电子商务商家追求的目标，因为它提供了更好的功能和性能。然而，数据迁移可能是一个复杂的任务。本文将介绍Magento 2数据迁移的基本原理和技巧，帮助您顺畅升级您的电子商务平台。</p>
<p>首先，了解数据迁移的范围和目标是很重要的。数据迁移涉及将现有的商店数据从旧的Magento版本或其他电子商务平台迁移到Magento 2。这包括产品、订单、客户、库存、支付信息等。</p>
<p>在进行数据迁移之前，建议先备份您的现有数据。这将确保在迁移过程中出现问题时可以恢复数据。您可以使用Magento提供的备份工具或第三方备份解决方案进行数据备份。</p>
<p>接下来，需要评估数据的结构和格式。不同的电子商务平台使用不同的数据结构和格式，因此在迁移数据之前，您需要对源数据进行分析和转换。这可能涉及数据映射、转换和清理等操作。</p>
<p>在进行数据迁移时，Magento 2提供了Data Migration Tool，它是一个强大的工具，用于处理数据的迁移和转换。该工具使用命令行界面，并提供了丰富的选项和配置文件，以满足各种迁移需求。</p>
<p>在配置数据迁移工具时，您需要指定源数据和目标数据的连接信息，并定义迁移的范围和规则。根据具体情况，您可能需要编写自定义的映射和转换逻辑，以确保数据正确地迁移到Magento 2。</p>
<p>在迁移过程中，建议进行逐步迁移，逐个实体地迁移数据。这将有助于排查和解决任何迁移问题，同时减少对商店运营的干扰。</p>
<p>最后，进行数据迁移后，建议进行数据验证和测试。确保已迁移的数据在Magento 2中正确显示和运行。您可以手动检查数据的准确性，或者使用自动化测试工具进行功能和性能测试。</p>
<p>综上所述，Magento 2数据迁移是一个复杂但关键的任务。</p>
<div id="gtx-trans" style="position: absolute; left: 329px; top: 388px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 30 Nov 2023 02:48:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 主题开发：定制您的在线商店外观]]></title>
      <link>https://www.360magento.com/blog/magento-theme-customize/</link>
      <description><![CDATA[<p>Magento 2是一个功能强大的电子商务平台，允许您根据自己的品牌形象定制在线商店的外观。本文将介绍Magento 2主题开发的基础知识和技巧，帮助您创建一个独特而引人注目的在线商店外观。</p>
<p>首先，了解Magento 2主题的结构是很重要的。一个Magento 2主题通常由多个文件组成，包括布局文件、模板文件、CSS文件和JavaScript文件。通过编辑这些文件，您可以控制商店的整体布局、页面元素和样式。</p>
<p>要开始主题开发，您可以从Magento 2的默认主题Luma或Blank开始，或者从头开始创建一个全新的主题。无论您选择哪种方式，都可以通过覆盖和修改现有文件来实现自定义。</p>
<p>在主题开发过程中，布局文件（layout files）起着重要的作用。布局文件定义了页面的结构和组件的位置。通过修改布局文件，您可以调整页面的布局、添加、删除或重新排列组件。</p>
<p>此外，模板文件（template files）允许您直接编辑和控制页面的内容。您可以在模板文件中添加动态内容、自定义样式和布局，并与后端代码进行交互。</p>
<p>在定制主题外观时，CSS和JavaScript文件是不可或缺的。通过编辑这些文件，您可以调整颜色、字体、边距以及添加交互效果和动画等。</p>
<p>除了基本的主题开发，Magento 2还提供了丰富的主题扩展和市场，您可以从中选择适合您需求的主题。这些主题具有不同的风格和功能，可以满足各种电子商务业务的需求。</p>
<p>总而言之，Magento 2主题开发为您提供了无限的定制化可能性，帮助您打造一个独特而符合品牌形象的在线商店外观。通过熟悉Magento 2主题的结构和编辑相应的文件，您可以轻松创建一个引人注目的电子商务平台。</p>]]></description>
      <pubDate>Wed, 29 Nov 2023 06:45:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 扩展开发：定制化您的电子商务功能]]></title>
      <link>https://www.360magento.com/blog/magento-ecommerce-custome/</link>
      <description><![CDATA[<p>Magento 2是一款功能丰富的电子商务平台，但有时您可能需要特定的功能来满足业务需求。这就是Magento 2扩展开发的重要性所在。本文将介绍Magento 2扩展开发的基础知识和技巧，帮助您定制化您的电子商务功能。</p>
<p>要开始扩展开发，您需要了解Magento 2的扩展结构。一个Magento 2扩展通常由多个文件和目录组成，包括模块目录、配置文件、控制器、模型、观察者、布局文件等。这些组件共同工作，实现特定的功能。</p>
<p>首先，您需要创建一个自定义的模块。模块是Magento 2扩展的基本单元，用于组织和管理扩展的代码和资源。创建一个模块需要定义模块的标识符、名称、版本等信息，并将其放置在正确的目录结构中。</p>
<p>在模块中，您可以创建控制器来处理用户请求和响应。控制器是实现特定功能的核心部分，它接收用户的输入并生成相应的输出。通过编写控制器代码，您可以实现自定义的业务逻辑和流程。</p>
<p>除了控制器，模型是另一个重要的组件。模型用于处理数据和业务逻辑。通过创建和修改模型，您可以与数据库交互、处理数据操作，并为您的电子商务功能提供数据支持。</p>
<p>此外，观察者（Observers）也是Magento 2扩展开发中常用的组件。观察者允许您在特定事件发生时执行自定义的操作。通过定义观察者并使用事件和触发器，您可以实现特定功能的扩展和定制。</p>
<p>在扩展开发过程中，布局文件（layout files）也是不可或缺的。通过编辑布局文件，您可以调整页面的结构和组件的位置，定制页面的布局和外观。</p>
<p>最后，测试是扩展开发的重要环节。确保您的扩展在不同情况下能够正常运行，并与其他模块和功能兼容。Magento 2提供了丰富的测试工具和框架，帮助您进行单元测试、功能测试和集成测试。</p>
<p>总结起来，Magento 2扩展开发为您定制化电子商务功能提供了灵活性和无限可能性。通过了解Magento 2扩展的结构和组件，以及熟悉相应的开发技术和工具，您可以创建定制化的功能，满足您的业务需求。</p>]]></description>
      <pubDate>Wed, 29 Nov 2023 03:47:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：构建强大的电子商务平台]]></title>
      <link>https://www.360magento.com/blog/magento-shop-b2c-mage/</link>
      <description><![CDATA[<p>Magento 2是一款广泛使用的开源电子商务平台，为企业和商家提供了一个强大而灵活的在线销售解决方案。本文将介绍Magento 2的一些重要特性和优势，以及为什么它是构建强大的电子商务平台的理想选择。</p>
<p>Magento 2通过提供丰富的功能和灵活的架构，使得构建和管理电子商务网站变得更加容易。它具有以下几个关键特性：</p>
<ol>
<li>
<p><strong>模块化架构</strong>：Magento 2采用模块化的架构，使得扩展和定制变得简单。开发人员可以轻松添加新的功能和扩展，或者自定义现有功能以满足特定的业务需求。</p>
</li>
<li>
<p><strong>强大的前端体系</strong>：Magento 2采用现代化的前端技术，如HTML5、CSS3和JavaScript框架，为用户提供优雅而响应式的用户体验。它还支持移动设备优先的设计，确保您的网站在各种设备上都能良好运行。</p>
</li>
<li>
<p><strong>多店铺支持</strong>：Magento 2允许您在单个安装中创建和管理多个在线商店。这对于企业和多品牌零售商来说非常有用，因为它们可以在一个统一的界面下管理所有的在线业务。</p>
</li>
<li>
<p><strong>强大的产品目录管理</strong>：Magento 2提供了全面的产品目录管理功能。您可以创建和管理产品、分类、价格、库存等，并支持多种产品类型，如简单产品、配置产品和分组产品。</p>
</li>
<li>
<p><strong>高级营销工具</strong>：Magento 2提供了一套强大的营销工具，如促销规则、优惠券、购物车价格规则等。这些工具可以帮助您制定和执行各种营销策略，吸引和留住客户。</p>
</li>
<li>
<p><strong>稳定和可扩展</strong>：Magento 2经过了全面的重构和优化，提高了性能和稳定性。它采用现代的技术栈，并具有可扩展的架构，可以处理大量的流量和订单。</p>
</li>
</ol>
<p>总之，Magento 2是一个功能强大、灵活且可扩展的电子商务平台，适用于各种规模和类型的在线商店。它提供了丰富的功能和工具，帮助企业和商家建立成功的在线业务。如果您正在寻找一个可靠和强大的电子商务平台，Magento 2将是一个理想的选择。</p>
<p>无论是小型创业公司还是大型企业，Magento 2都为您提供了一套完整的解决方案，满足您的电子商务需求。开始使用Magento 2，构建一个强大而成功的在线商店吧！</p>]]></description>
      <pubDate>Tue, 28 Nov 2023 07:39:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：为您的电子商务业务带来无限可能]]></title>
      <link>https://www.360magento.com/blog/magento-possibilities/</link>
      <description><![CDATA[<p>Magento 2是当前最受欢迎和广泛使用的开源电子商务平台之一。作为Magento的最新版本，Magento 2为企业和商家提供了一个功能强大和灵活的在线销售解决方案。本文将探讨Magento 2的关键特性和优势，以及为什么选择Magento 2是为您的电子商务业务带来无限可能的正确决策。</p>
<p>首先，Magento 2采用了现代化的技术栈和模块化的架构，使得构建和管理电子商务网站变得更加容易。它提供了广泛的功能和灵活的自定义选项，使您能够根据业务需求轻松扩展和定制您的在线商店。无论是创建新的功能模块，还是修改现有功能，Magento 2都提供了强大的工具和API，使开发变得高效而灵活。</p>
<p>其次，Magento 2具有出色的性能和可扩展性。它经过全面的优化和重构，提高了网站的加载速度和响应能力。不仅如此，Magento 2还支持高并发访问和大规模交易处理，使您能够应对不断增长的业务需求。这对于那些追求扩展和持续增长的企业来说尤为重要。</p>
<p>Magento 2还提供了出色的用户体验和设计。它具有现代化的前端技术，使您的网站在各种设备上都能完美展现，无论是桌面还是移动设备。此外，Magento 2提供了丰富的主题和布局选项，使您能够轻松创建个性化的品牌形象，吸引并保留用户。</p>
<p>另一个令人印象深刻的功能是Magento 2的营销工具套件。它提供了广泛的促销规则、优惠券和购物车价格规则等功能，帮助您制定和执行各种营销策略，提高销售和客户参与度。无论是打折促销、交叉销售还是推荐产品，Magento 2都能满足您的需求。</p>
<p>最后，Magento 2拥有一个庞大的社区和丰富的资源库。您可以从社区获取支持、交流经验，并获取各种扩展和主题来增强您的在线商店。这个活跃的社区为Magento 2提供了持续的更新和改进，确保您始终处于技术的最前沿。</p>
<p>综上所述，Magento 2是为您的电子商务业务带来无限可能的绝佳选择。它提供了强大的功能、灵活的自定义选项、卓越的性能和用户体验，以及丰富的营销工具和社区支持。无论您是创业初创公司还是大型企业，Magento 2都能满足您的需求并帮助您实现在线销售的成功。赶紧选择Magento 2，为您的电子商务业务开启新的篇章吧！</p>]]></description>
      <pubDate>Tue, 28 Nov 2023 03:41:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何使用Magento 2的工厂创建新的集合实例？]]></title>
      <link>https://www.360magento.com/blog/magento-factory-devlop/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">在Magento 2中，您可以使用工厂（Factory）来创建新的集合实例。下面是使用工厂创建新的集合实例的步骤：</p>
<ol>
<li>首先，在您的类中注入集合工厂。您可以在构造函数中注入集合工厂，如下所示：</li>
</ol>
<pre>use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;

class YourClass
{
    protected $productCollectionFactory;

    public function __construct(
        ProductCollectionFactory $productCollectionFactory
    ) {
        $this-&gt;productCollectionFactory = $productCollectionFactory;
    }
}</pre>
<pre></pre>
<ol start="2">
<li>然后，您可以使用工厂创建新的集合实例。在需要创建集合的方法中，使用以下代码：</li>
</ol>
<pre>$productCollection = $this-&gt;productCollectionFactory-&gt;create();</pre>
<ol start="3">
<li>现在，您可以使用&nbsp;<code>$productCollection</code>&nbsp;对象来操作集合，例如添加过滤器、排序等。以下是一个示例：</li>
</ol>
<pre>$productCollection-&gt;addAttributeToFilter('status', ['eq' =&gt; 1])
    -&gt;addAttributeToFilter('price', ['gt' =&gt; 100])
    -&gt;setPageSize(10)
    -&gt;setCurPage(1);</pre>
<ol start="4">
<li>最后，您可以使用&nbsp;<code>$productCollection</code>&nbsp;对象来迭代集合中的每个元素，或者获取集合的其他属性。以下是一个示例：</li>
</ol>
<pre>foreach ($productCollection as $product) {
    echo $product-&gt;getName();
}<br /><span>通过使用工厂创建新的集合实例，您可以在Magento 2中更好地管理和操作数据。希望这个解答对您有帮助！</span>
</pre>
<div id="gtx-trans" style="position: absolute; left: -2px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 27 Nov 2023 07:50:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2除了集合工厂，还有其他方法可以创建新的集合实例吗？]]></title>
      <link>https://www.360magento.com/blog/magento-collection-factory/</link>
      <description><![CDATA[<ol>
<li>使用集合管理器（Collection Manager）：集合管理器是Magento 2中的一个核心类，它可以帮助您创建和管理集合实例。您可以通过依赖注入将集合管理器注入到您的类中，并使用它来创建新的集合实例。以下是一个示例：</li>
</ol>
<pre>use Magento\Framework\App\ResourceConnection;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Framework\Model\ResourceModel\Db\Collection\CollectionFactoryInterface;

class YourClass
{
    protected $collectionFactory;

    public function __construct(
        CollectionFactoryInterface $collectionFactory
    ) {
        $this-&gt;collectionFactory = $collectionFactory;
    }

    public function createNewCollection()
    {
        $collection = $this-&gt;collectionFactory-&gt;create();
        // 对集合进行操作
        return $collection;
    }
}</pre>
<ol start="2">
<li>使用对象管理器（Object Manager）：虽然不推荐直接使用对象管理器，但在某些情况下，您可以使用对象管理器来创建新的集合实例。以下是一个示例：</li>
</ol>
<pre>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$collection = $objectManager-&gt;create('Magento\Catalog\Model\ResourceModel\Product\Collection');
// 对集合进行操作<br /><span>请注意，使用对象管理器可能会导致依赖注入的问题，并且不符合Magento 2的最佳实践。因此，建议优先考虑使用集合工厂或集合管理器来创建新的集合实例。</span>
</pre>]]></description>
      <pubDate>Mon, 27 Nov 2023 03:54:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的高级搜索和过滤功能如何帮助顾客找到他们需要的产品？]]></title>
      <link>https://www.360magento.com/blog/magento-advance-search/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento的高级搜索和过滤功能通过以下方式帮助顾客找到他们需要的产品：</p>
<ol>
<li>
<p class="mb-2 last:mb-0">关键词搜索：顾客可以在Magento的搜索栏中输入关键词，例如产品名称、描述、型号等，以快速找到相关的产品。这使顾客能够通过简单的关键词搜索快速定位到他们感兴趣的产品。</p>
</li>
<li>
<p class="mb-2 last:mb-0">价格范围筛选：Magento允许顾客根据价格范围进行筛选，以便在他们预算范围内查找产品。顾客可以设置最低和最高价格，系统将只显示符合这个价格范围的产品，帮助顾客更快地找到合适的产品。</p>
</li>
<li>
<p class="mb-2 last:mb-0">属性筛选：Magento允许企业为产品定义各种属性，例如颜色、尺寸、材质等。顾客可以使用这些属性进行筛选，以便根据自己的偏好和需求找到符合要求的产品。例如，顾客可以选择特定颜色的衣服或特定尺寸的电子设备。</p>
</li>
<li>
<p class="mb-2 last:mb-0">类别筛选：Magento的产品目录可以根据不同的类别进行组织和分类。顾客可以通过选择特定的类别来缩小搜索范围，只显示该类别下的产品。这使顾客能够更快地找到他们感兴趣的产品，而无需浏览整个产品目录。</p>
</li>
<li>
<p class="mb-2 last:mb-0">标签和标识筛选：Magento允许企业为产品添加标签和标识，例如热销、新品、特价等。顾客可以使用这些标签和标识进行筛选，以便找到符合自己需求的特定类型的产品。这使顾客能够更轻松地发现促销产品或最新上市的产品。</p>
</li>
</ol>
<p class="mb-2 last:mb-0">通过这些高级搜索和过滤功能，顾客可以根据自己的需求和偏好快速准确地找到他们需要的产品。这提供了更好的购物体验，节省了顾客的时间和精力，并增加了他们对企业的满意度。</p>]]></description>
      <pubDate>Sun, 26 Nov 2023 07:50:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento的搜索栏中实现自动补全功能？]]></title>
      <link>https://www.360magento.com/blog/magento-link-search-by-customer/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">要在Magento的搜索栏中实现自动补全功能，可以按照以下步骤进行操作：</p>
<ol>
<li>登录到Magento的后台管理面板。</li>
<li>导航到&ldquo;Stores（商店）&rdquo;&gt;&ldquo;Configuration（配置）&rdquo;&gt;&ldquo;Catalog（目录）&rdquo;&gt;&ldquo;Catalog Search（目录搜索）&rdquo;。</li>
<li>在&ldquo;Search Options（搜索选项）&rdquo;部分，找到&ldquo;Enable Search Suggestions（启用搜索建议）&rdquo;选项。</li>
<li>将&ldquo;Enable Search Suggestions（启用搜索建议）&rdquo;设置为&ldquo;Yes（是）&rdquo;。</li>
<li>保存配置更改。</li>
</ol>
<p class="mb-2 last:mb-0">完成上述步骤后，Magento的搜索栏将开始显示自动补全建议。当顾客在搜索栏中输入关键词时，系统将根据已有的产品和搜索历史提供相关的建议。这些建议将在下拉菜单中显示，帮助顾客更快地找到他们想要的产品。</p>
<p class="mb-2 last:mb-0">请注意，要使自动补全功能正常工作，您的Magento网站需要有足够的产品数据和搜索历史数据。此外，确保您的服务器和数据库能够处理自动补全功能的负载。</p>
<p class="mb-2 last:mb-0">通过在Magento的搜索栏中启用自动补全功能，您可以提供更智能和便捷的搜索体验，帮助顾客更快速地找到他们需要的产品。</p>
<div id="gtx-trans" style="position: absolute; left: 472px; top: 108.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 26 Nov 2023 03:52:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 的电子商务功能是如何帮助公司提供无缝购物体验的？]]></title>
      <link>https://www.360magento.com/blog/mageno-company-shop/</link>
      <description><![CDATA[Magento的电子商务功能通过以下方式帮助这些公司提供无缝购物体验：

灵活的产品目录管理：Magento允许企业轻松管理和组织产品目录。它提供了丰富的产品属性和分类选项，使企业能够清晰地展示和描述其产品。这有助于顾客快速找到他们想要的产品。

强大的搜索和过滤功能：Magento提供高级搜索和过滤功能，使顾客能够快速准确地找到他们需要的产品。顾客可以根据关键词、价格范围、品牌、属性等进行搜索和筛选，从而缩小选择范围，节省时间。

个性化推荐和建议：Magento可以根据顾客的购买历史、浏览行为和偏好提供个性化的产品推荐和建议。这使顾客能够发现他们可能感兴趣的产品，提高购买决策的准确性和速度。

流畅的购物车和结账流程：Magento的购物车和结账流程设计简洁明了，使顾客能够轻松添加和管理购物车中的产品，并快速完成结账过程。它支持多种支付方式和配送选项，提供灵活的选择，满足顾客的个性化需求。

响应式设计和移动优化：Magento具有响应式设计，能够自适应不同设备和屏幕尺寸，提供一致的用户体验。它还提供移动优化功能，使顾客可以在移动设备上轻松浏览和购买产品，无论是在手机还是平板电脑上。

多语言和多货币支持：Magento支持多语言和多货币，使企业能够为全球顾客提供本地化的购物体验。顾客可以选择自己熟悉的语言和货币，方便地浏览和购买产品。

通过这些功能，Magento帮助企业提供无缝购物体验，使顾客能够轻松找到并购买他们想要的产品。这提高了顾客的满意度和忠诚度，促进了销售增长和业务成功。]]></description>
      <pubDate>Sat, 25 Nov 2023 07:45:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的栅格系统如何帮助开发人员创建响应式布局？]]></title>
      <link>https://www.360magento.com/blog/magento-grid-dev/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento的栅格系统是一种基于栅格布局的响应式设计工具，可以帮助开发人员创建适应不同设备的响应式布局。以下是栅格系统如何帮助开发人员创建响应式布局的几个关键点：</p>
<ol>
<li>
<p class="mb-2 last:mb-0">划分页面：栅格系统将页面划分为多个列，开发人员可以根据需要将内容放置在不同的列中。这样可以确保页面的布局在不同设备上自动适应。</p>
</li>
<li>
<p class="mb-2 last:mb-0">响应式列：栅格系统中的列具有响应式特性，它们可以根据设备的屏幕大小自动调整宽度。开发人员可以定义每个列在不同屏幕尺寸下所占的宽度比例，从而实现自适应布局。</p>
</li>
<li>
<p class="mb-2 last:mb-0">响应式偏移：栅格系统还支持响应式偏移，开发人员可以通过设置列的偏移量来调整内容在页面上的位置。这对于在不同设备上重新排列内容非常有用。</p>
</li>
<li>
<p class="mb-2 last:mb-0">响应式嵌套：栅格系统允许开发人员在列内部创建更深层次的嵌套结构。这样可以更灵活地组织和布局页面的内容，以适应不同设备的显示需求。</p>
</li>
</ol>
<p class="mb-2 last:mb-0">通过使用Magento的栅格系统，开发人员可以轻松创建具有响应式布局的网页。栅格系统提供了一种灵活的方式来划分和组织页面的内容，使其能够在不同设备上自动适应并提供一致的用户体验。开发人员可以根据需要定义列的宽度比例和偏移量，以实现所需的布局效果</p>]]></description>
      <pubDate>Sat, 25 Nov 2023 03:43:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的响应式设计如何提供一致的购物体验？]]></title>
      <link>https://www.360magento.com/blog/magento-respose/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento的响应式设计通过自动适应不同设备的屏幕大小和分辨率，提供一致的购物体验。以下是Magento响应式设计如何实现一致购物体验的几个关键点：</p>
<ol>
<li>
<p class="mb-2 last:mb-0">自适应布局：Magento的响应式设计使用自适应布局，使网站的布局和元素能够根据设备的屏幕大小和分辨率进行调整。无论用户是在桌面电脑、平板电脑还是手机上访问网站，页面的布局都会自动适应，确保内容的可读性和可操作性。</p>
</li>
<li>
<p class="mb-2 last:mb-0">图片优化：Magento的响应式设计会对图片进行优化，使其在不同设备上加载速度更快。通过使用适当的图像压缩和缩放技术，确保图片在不同屏幕上显示清晰，并且加载时间不会过长。</p>
</li>
<li>
<p class="mb-2 last:mb-0">导航和菜单：Magento的响应式设计会对导航和菜单进行优化，以适应不同设备的触摸操作和屏幕尺寸。在移动设备上，导航和菜单通常会以折叠或下拉的形式呈现，以节省屏幕空间并提供更好的用户体验。</p>
</li>
<li>
<p class="mb-2 last:mb-0">内容排版：Magento的响应式设计会对内容进行排版调整，以适应不同设备的屏幕大小和分辨率。文字、标题和其他内容元素会根据屏幕尺寸进行调整，以确保用户可以轻松阅读和理解页面上的信息。</p>
</li>
<li>
<p class="mb-2 last:mb-0">表单和输入：Magento的响应式设计会对表单和输入字段进行优化，以适应不同设备的触摸操作和输入方式。输入字段的大小和间距会根据屏幕尺寸进行调整，以提供更好的用户体验和易用性。</p>
</li>
</ol>
<p class="mb-2 last:mb-0">通过这些响应式设计的优化，Magento确保用户在不同设备上都能够获得一致的购物体验。无论用户是在桌面电脑、平板电脑还是手机上访问网站，他们都可以轻松浏览产品、添加到购物车并完成购买，从而提高用户满意度和转化率。</p>]]></description>
      <pubDate>Fri, 24 Nov 2023 07:41:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的响应式设计如何实现自适应布局]]></title>
      <link>https://www.360magento.com/blog/magento-res-layout/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento的响应式设计通过以下方式实现自适应布局：</p>
<ol>
<li>
<p class="mb-2 last:mb-0">媒体查询（Media Queries）：Magento使用CSS3的媒体查询功能来根据设备的屏幕大小和分辨率应用不同的样式。媒体查询允许开发人员根据不同的屏幕尺寸定义不同的CSS规则，从而实现自适应布局。</p>
</li>
<li>
<p class="mb-2 last:mb-0">栅格系统（Grid System）：Magento使用栅格系统来创建响应式布局。栅格系统将页面划分为多个列，开发人员可以根据不同的屏幕尺寸和布局需求，将内容放置在不同的列中。这样可以确保页面在不同设备上的布局和排列方式都能够自动适应。</p>
</li>
<li>
<p class="mb-2 last:mb-0">弹性图像（Flexible Images）：Magento使用弹性图像技术来确保图像在不同设备上的自适应显示。弹性图像使用CSS属性来控制图像的大小和比例，使其能够根据屏幕尺寸自动调整大小，从而适应不同设备的显示需求。</p>
</li>
<li>
<p class="mb-2 last:mb-0">响应式导航（Responsive Navigation）：Magento的响应式设计还包括响应式导航菜单。在小屏幕设备上，导航菜单通常会以折叠或下拉的形式呈现，以节省屏幕空间并提供更好的用户体验。当屏幕尺寸增大时，导航菜单会自动展开或以水平方式显示，以适应更大的屏幕空间。</p>
</li>
</ol>
<p class="mb-2 last:mb-0">通过这些技术和方法，Magento的响应式设计能够实现自适应布局，使网站能够在不同设备上提供一致的用户体验。用户无论是在桌面电脑、平板电脑还是手机上访问网站，都能够获得良好的浏览和交互体验。</p>
<div id="gtx-trans" style="position: absolute; left: 436px; top: 286px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 24 Nov 2023 03:42:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[关于magento的介绍]]></title>
      <link>https://www.360magento.com/blog/magento-detial/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento是一个基于开源技术构建的电子商务平台，由Magento, Inc.开发。它于2008年首次发布，使用PHP编写。目前，Adobe已将Magento Commerce整合到Adobe Commerce中，但Magento Open Source品牌和支持保持不变。Magento是最受欢迎的电子商务平台之一，被许多顶级电子商务网站采用。以下是关于Magento的一些事实、优势和劣势。</p>
<p class="mb-2 last:mb-0">Magento的优势包括：</p>
<ol>
<li>提供卓越的可扩展性和性能。</li>
<li>提供增强的用户购物体验。</li>
<li>提供强大的平台功能。</li>
<li>兼容移动设备。</li>
<li>可扩展性强，支持高级SEO功能。</li>
<li>提供可定制的安全功能。</li>
<li>支持市场集成和第三方集成。</li>
<li>提供智能搜索选项。</li>
<li>可选择任何托管服务。</li>
<li>拥有庞大的专业社区。</li>
</ol>
<p class="mb-2 last:mb-0">Magento的一些主要功能包括：</p>
<ol>
<li>产品管理：管理产品目录、库存和价格。</li>
<li>类别管理：创建和管理产品类别。</li>
<li>国际支持：支持多语言和多货币。</li>
<li>客户账户：管理客户账户和订单。</li>
<li>库存管理：跟踪库存和库存变化。</li>
<li>促销和营销工具：提供各种促销和营销工具。</li>
<li>搜索技术：提供高级搜索功能。</li>
<li>客户服务：提供客户支持和服务。</li>
<li>分析和报告：提供分析和报告功能。</li>
</ol>
<p class="mb-2 last:mb-0">Magento还提供了许多扩展，这些扩展可以增加特定的功能。扩展是一组代码，用于实现Magento的特定功能。</p>
<p class="mb-2 last:mb-0">Magento有两个版本：Magento 1和Magento 2。Magento 1是较旧的版本，稳定性较高，但即将到达生命周期的尽头。Magento 2是较新的版本，功能更强大，但复杂性也更高。</p>
<p class="mb-2 last:mb-0">Magento有两个版本：Magento Open Source（以前称为Magento Community Edition）和Magento Commerce（以前称为Magento Enterprise Edition）。Magento Open Source是免费的，提供基本功能。Magento Commerce是付费版本，提供更多高级功能和支持。</p>
<p class="mb-2 last:mb-0">总之，Magento是一个功能强大、灵活可定制的电子商务平台，适用于个人和企业建立长期、专业的电子商务网站。它具有丰富的功能和强大的社区支持，可以满足各种电子商务需求。</p>]]></description>
      <pubDate>Thu, 23 Nov 2023 07:39:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的可扩展性和性能如何提高用户购物体验？]]></title>
      <link>https://www.360magento.com/blog/magento-2mdsdms-shop/</link>
      <description><![CDATA[<p class="mb-2 last:mb-0">Magento通过其可扩展性和性能提高用户购物体验的方式有以下几点：</p>
<ol>
<li>
<p class="mb-2 last:mb-0">快速加载速度：Magento通过使用高级缓存技术和优化代码来提高网站的加载速度。快速加载速度可以减少用户等待时间，提高用户体验，并降低购物车放弃率。</p>
</li>
<li>
<p class="mb-2 last:mb-0">响应式设计：Magento具有响应式设计，可以自动适应不同设备的屏幕大小和分辨率。这意味着用户无论使用桌面电脑、平板电脑还是手机，都可以获得一致的购物体验。</p>
</li>
<li>
<p class="mb-2 last:mb-0">多语言和多货币支持：Magento支持多语言和多货币功能，使您能够为全球用户提供本地化的购物体验。用户可以在他们熟悉的语言和货币下浏览和购买产品，这提高了用户的舒适度和满意度。</p>
</li>
<li>
<p class="mb-2 last:mb-0">强大的搜索功能：Magento具有强大的搜索功能，可以帮助用户快速找到他们想要的产品。它支持高级搜索选项，如过滤器、排序和自定义搜索条件，使用户能够更轻松地浏览和筛选产品。</p>
</li>
<li>
<p class="mb-2 last:mb-0">个性化推荐：Magento可以根据用户的浏览和购买历史，提供个性化的产品推荐。这可以帮助用户发现他们可能感兴趣的产品，提高购买意愿和转化率。</p>
</li>
<li>
<p class="mb-2 last:mb-0">简化的结账流程：Magento提供了简化的结账流程，使用户能够快速、轻松地完成购买。它支持多种支付方式和快速结账选项，如快速填写表单和保存付款信息，提高了用户的购物体验。</p>
</li>
</ol>
<p class="mb-2 last:mb-0">总之，Magento通过其可扩展性和性能优化，提供了一个快速、响应式和个性化的购物体验。这些功能可以提高用户的满意度和购买意愿，帮助您的电子商务网站取得成功。</p>
<div id="gtx-trans" style="position: absolute; left: 352px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 23 Nov 2023 03:33:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[创建可配置产品：Magento 2的灵活性与个性化定制的利器]]></title>
      <link>https://www.360magento.com/blog/Magento-2-create-configurable/</link>
      <description><![CDATA[<p>对于电商平台而言，提供灵活的产品配置和个性化定制是吸引客户和提高销售的重要因素之一。Magento 2提供了强大的功能，使您能够轻松创建可配置产品，满足客户的不同需求。本文将详细介绍在Magento 2中创建可配置产品的过程和优势。</p>
<p><strong>1. 什么是可配置产品？</strong></p>
<p>可配置产品是指具有多个配置选项和变体的产品。例如，一件衣服的可配置选项可能包括颜色、尺寸和款式等。通过选择不同的配置选项，客户可以根据自己的喜好和需求来个性化定制产品。</p>
<p><strong>2. 创建可配置产品的步骤：</strong></p>
<p>在Magento 2中创建可配置产品需要按照以下步骤进行操作：</p>
<p><strong>步骤 1：创建属性</strong>：在Magento后台，创建与产品相关的属性。例如，对于衣服，您可以创建颜色和尺寸属性。</p>
<p><strong>步骤 2：创建属性集（Attribute Set）</strong>：属性集是一组属性的集合，用于定义产品的属性。创建一个属性集，并将相关属性添加到该属性集中。</p>
<p><strong>步骤 3：创建可配置产品</strong>：在Magento后台，创建一个新产品，并选择刚才创建的属性集。在产品配置选项中，启用"Create Configurations"选项，并选择相关的属性。</p>
<p><strong>步骤 4：配置选项设置</strong>：为每个属性设置相应的选项值。例如，对于颜色属性，您可以设置红色、蓝色和绿色等选项。</p>
<p><strong>步骤 5：创建产品变体</strong>：通过选择不同的配置选项值，创建产品的不同变体。例如，在颜色属性中选择红色，在尺寸属性中选择大号，就可以创建一个红色大号的产品变体。</p>
<p><strong>3. 可配置产品的优势：</strong></p>
<p>创建可配置产品带来了多个优势，包括：</p>
<p><strong>a. 个性化定制</strong>：可配置产品允许客户根据自己的需求和偏好进行个性化定制，提供更好的购物体验。</p>
<p><strong>b. 简化管理</strong>：通过使用可配置产品，您可以将多个变体整合到一个产品页面中，简化产品管理和库存管理。</p>
<p><strong>c. 提高销售</strong>：提供更多的选择和个性化定制选项可以吸引更多的客户，并增加销售机会。</p>]]></description>
      <pubDate>Wed, 22 Nov 2023 08:42:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[提高协作效率——Magento后台多用户登录功能的优势与用法]]></title>
      <link>https://www.360magento.com/blog/multiple-admin-users-login/</link>
      <description><![CDATA[<p>在一个电商平台上，有效的团队协作是实现高效运营和管理的关键因素之一。Magento电商平台提供了一项强大的功能&mdash;&mdash;后台多用户登录，它允许多个用户同时登录Magento后台管理界面。本文将详细介绍Magento后台多用户登录功能的优势和用法，以帮助您提高团队的协作效率。</p>
<p><strong>1. 优势：</strong></p>
<p>Magento后台多用户登录功能带来了许多优势，包括：</p>
<p><strong>a. 提高团队协作效率</strong>：多用户登录功能使多个团队成员能够同时登录后台管理界面，无需等待其他用户退出登录。这样，不同的团队成员可以同时处理各自的任务，大大提高了团队的协作效率。</p>
<p><strong>b. 灵活的权限管理</strong>：Magento提供了灵活的权限管理系统，您可以根据用户的角色和职责，为每个用户分配特定的权限。这样，您可以确保每个用户只能访问其需要的功能和数据，提高安全性和数据保护。</p>
<p><strong>c. 跟踪和审计</strong>：通过多用户登录功能，您可以轻松跟踪每个用户的活动和操作。这对于审计和故障排除非常有用，您可以快速了解到底是哪个用户进行了特定的更改或操作。</p>
<p><strong>2. 配置和使用Magento后台多用户登录功能：</strong></p>
<p>要配置和使用Magento后台多用户登录功能，您可以按照以下步骤进行操作：</p>
<p><strong>步骤 1：创建用户角色</strong>：在Magento后台，创建不同的用户角色，并为每个角色分配相应的权限。</p>
<p><strong>步骤 2：创建用户账号</strong>：为每个团队成员创建独立的用户账号，并将其分配给相应的用户角色。</p>
<p><strong>步骤 3：启用多用户登录</strong>：在Magento后台的系统设置中，启用多用户登录功能。</p>
<p><strong>步骤 4：登录后台</strong>：团队成员可以使用自己的用户账号登录Magento后台，开始进行相应的操作和管理任务。</p>]]></description>
      <pubDate>Wed, 22 Nov 2023 03:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2教程：如何创建新的商店视图]]></title>
      <link>https://www.360magento.com/blog/magento2-create-new-store-view/</link>
      <description><![CDATA[<p>在Magento 2中，商店视图（Store View）是一种用于展示商城内容的配置。通过创建新的商店视图，您可以将商城扩展到不同的语言、货币和地理位置，以满足全球用户的需求，并提供个性化的商城体验。下面是在Magento 2中创建新的商店视图的简明教程。</p>
<p>步骤1：登录到Magento 2后台管理面板。</p>
<ul>
<li>使用管理员帐户登录到Magento 2后台。</li>
</ul>
<p>步骤2：导航到商店视图设置。</p>
<ul>
<li>在Magento 2的管理面板中，导航到"商店" &gt; "设置（Configuration）"。</li>
<li>在左侧导航中，找到"商店"部分，并点击"商店视图（Store View）"选项。</li>
</ul>
<p>步骤3：创建新的商店视图。</p>
<ul>
<li>在商店视图页面，点击"创建商店视图（Create Store View）"按钮。</li>
<li>在"商店（Store）"字段中，选择要与新视图关联的商店。</li>
<li>在"名称（Name）"字段中，输入商店视图的名称，例如"英文商店"。</li>
<li>在"代码（Code）"字段中，输入商店视图的唯一代码，例如"en"。</li>
<li>在"状态（Status）"字段中，选择"启用（Enabled）"以激活商店视图。</li>
<li>在"排序（Sort Order）"字段中，输入商店视图的排序顺序（可选）。</li>
<li>点击"保存（Save Store View）"按钮以创建商店视图。</li>
</ul>
<p>步骤4：配置商店视图选项（可选）。</p>
<ul>
<li>在商店视图页面，找到您刚创建的商店视图，并点击进入编辑页面。</li>
<li>在编辑页面，您可以配置商店视图的各种选项，如语言、货币、时区等。</li>
<li>根据您的需求进行相应的配置，并点击"保存（Save Store View）"按钮以保存更改。</li>
</ul>
<p>通过按照上述步骤，在Magento 2中创建新的商店视图将变得简单而直观。您可以根据您的业务需求创建多个商店视图，以满足不同目标市场的需求，并提供个性化的商城体验。</p>]]></description>
      <pubDate>Tue, 21 Nov 2023 07:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2教程：如何创建CMS页面重写]]></title>
      <link>https://www.360magento.com/blog/magento2-create-cms-page-rewrite/</link>
      <description><![CDATA[<p>在Magento 2中，CMS页面重写允许您自定义CMS页面的链接路径和URL。这对于优化页面链接的可读性、提高用户体验和搜索引擎优化（SEO）效果非常有用。通过创建CMS页面重写，您可以使用自定义的URL路径来替代默认的CMS页面链接，使其更加友好和易于理解。下面是在Magento 2中创建CMS页面重写的简明教程。</p>
<p>步骤1：登录到Magento 2后台管理面板。</p>
<ul>
<li>使用管理员帐户登录到Magento 2后台。</li>
</ul>
<p>步骤2：导航到CMS页面设置。</p>
<ul>
<li>在Magento 2的管理面板中，导航到"内容" &gt; "页面（Pages）"。</li>
<li>找到您想要创建URL重写的CMS页面，点击进入页面编辑页面。</li>
</ul>
<p>步骤3：创建URL重写。</p>
<ul>
<li>在页面编辑页面的左侧导航中，展开"搜索引擎优化（SEO）"部分。</li>
<li>在"URL键（URL Key）"字段中，输入您想要自定义的页面链接路径。</li>
<li>Magento 2会自动检测并验证URL键的唯一性。如果URL键已经被使用，您需要选择其他唯一的键。</li>
<li>点击"保存（Save）"按钮以保存页面更改。</li>
</ul>
<p>步骤4：刷新前台页面并查看结果。</p>
<ul>
<li>在Magento 2后台管理面板的顶部菜单中，点击"清除缓存（Flush Cache Storage）"。</li>
<li>访问您的Magento 2商城，并导航到已创建URL重写的CMS页面。</li>
<li>您将看到页面链接已被自定义为新的URL路径。</li>
</ul>
<p>通过按照上述步骤，在Magento 2中创建CMS页面重写将变得简单而直观。请注意，创建URL重写后，确保更新站点地图和搜索引擎索引，以确保新的URL路径被正确引导和索引。</p>]]></description>
      <pubDate>Tue, 21 Nov 2023 03:43:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2教程：如何创建产品URL重写]]></title>
      <link>https://www.360magento.com/blog/magento2-create-product-url-rewrite/</link>
      <description><![CDATA[<p>在Magento 2中，产品URL重写是一种强大的功能，可以帮助您优化产品链接的结构和可读性，同时提升搜索引擎优化（SEO）效果。通过创建产品URL重写，您可以使用自定义的URL路径替代默认的产品链接，使其更加友好和易于理解。下面是在Magento 2中创建产品URL重写的简明教程。</p>
<p>步骤1：登录到Magento 2后台管理面板。</p>
<ul>
<li>使用管理员帐户登录到Magento 2后台。</li>
</ul>
<p>步骤2：导航到产品URL重写设置。</p>
<ul>
<li>在Magento 2的管理面板中，导航到"产品" &gt; "目录（Catalog）" &gt; "产品"。</li>
<li>找到您想要创建URL重写的产品，点击进入产品编辑页面。</li>
</ul>
<p>步骤3：创建URL重写。</p>
<ul>
<li>在产品编辑页面的左侧导航中，展开"搜索引擎优化（SEO）"部分。</li>
<li>在"URL键（URL Key）"字段中，输入您想要自定义的产品链接路径。</li>
<li>Magento 2会自动检测并验证URL键的唯一性。如果URL键已经被使用，您需要选择其他唯一的键。</li>
<li>点击"保存（Save）"按钮以保存产品更改。</li>
</ul>
<p>步骤4：刷新前台页面并查看结果。</p>
<ul>
<li>在Magento 2后台管理面板的顶部菜单中，点击"清除缓存（Flush Cache Storage）"。</li>
<li>访问您的Magento 2商城，并导航到已创建URL重写的产品页面。</li>
<li>您将看到产品链接已被自定义为新的URL路径。</li>
</ul>
<p>通过按照上述步骤，在Magento 2中创建产品URL重写将变得简单而直观。请注意，创建URL重写后，确保更新站点地图和搜索引擎索引，以确保新的URL路径被正确引导和索引。</p>]]></description>
      <pubDate>Mon, 20 Nov 2023 07:42:08 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2教程：如何在主页上插入产品]]></title>
      <link>https://www.360magento.com/blog/magento2-insert-products-homepage/</link>
      <description><![CDATA[<p>主页是Magento 2商城中最重要的页面之一，为您的客户提供了第一印象和导航入口。通过在主页上插入产品，您可以突出展示您的热门产品、特别推荐或促销活动，吸引客户并提高销售。下面是在Magento 2主页上插入产品的简明教程。</p>
<p>步骤1：登录到Magento 2后台管理面板。</p>
<ul>
<li>使用管理员帐户登录到Magento 2后台。</li>
</ul>
<p>步骤2：创建产品的产品块（Product Block）。</p>
<ul>
<li>在Magento 2的管理面板中，导航到"内容" &gt; "块（Blocks）"。</li>
<li>点击"添加新块（Add New Block）"按钮。</li>
<li>在"标识符（Identifier）"字段中输入一个唯一的标识符，例如"homepage-products"。</li>
<li>在"标题（Title）"字段中输入块的标题，例如"主页产品"。</li>
<li>在"内容（Content）"字段中输入以下代码：
<div>
<pre class="MarkdownCodeBlock_preTag__QMZEO"><code class="MarkdownCodeBlock_codeTag__5BV0Z"><span>{{</span><span>widget</span><span> </span><span class="hljs-attr">type</span><span>=</span><span>"Magento\Catalog\Block\Product\Widget\NewWidget"</span><span> </span><span class="hljs-attr">display_type</span><span>=</span><span>"all_products"</span><span>
</span><span></span><span class="hljs-attr">products_count</span><span>=</span><span>"4"</span><span> </span><span class="hljs-attr">template</span><span>=</span><span>"product/widget/new/content/new_grid.phtml"</span><span>}}</span><span class="xml">
</span><span class="xml"></span></code></pre>
</div>
</li>
<li>点击"保存和继续编辑（Save and Continue Edit）"按钮。</li>
</ul>
<p>步骤3：编辑主页布局并插入产品块。</p>
<ul>
<li>在Magento 2的管理面板中，导航到"内容" &gt; "页面（Pages）"。</li>
<li>找到并点击编辑您的主页。</li>
<li>在主页编辑器中，找到您想插入产品的位置，将光标放置在那里。</li>
<li>点击编辑器工具栏上的"插入变量（Insert Variable）"按钮。</li>
<li>在弹出窗口中，选择"产品块（Blocks）"选项。</li>
<li>在下拉菜单中选择您在步骤2中创建的产品块（例如"主页产品"）。</li>
<li>点击"插入（Insert）"按钮。</li>
<li>点击"保存（Save）"按钮以保存主页更改。</li>
</ul>
<p>步骤4：刷新前台页面并查看结果。</p>
<ul>
<li>在Magento 2后台管理面板的顶部菜单中，点击"清除缓存（Flush Cache Storage）"。</li>
<li>访问您的Magento 2商城的主页，刷新页面，您将看到插入的产品块显示在主页上。</li>
</ul>
<p>通过按照上述步骤，在Magento 2主页上插入产品将变得简单而直观。您可以根据需要自定义产品块的数量、样式和展示方式，以实现最佳的产品展示效果。</p>
<div id="gtx-trans" style="position: absolute; left: -10px; top: 239.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 20 Nov 2023 03:40:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2订单状态工作流程详解]]></title>
      <link>https://www.360magento.com/blog/magento2-order-status-workflow/</link>
      <description><![CDATA[<p>订单状态是Magento 2中跟踪和管理订单进程的关键组成部分。了解订单状态的工作流程对于运营一个Magento 2商城至关重要。下面是Magento 2中订单状态的详细工作流程。</p>
<ol>
<li>
<p>新订单（New）：</p>
<ul>
<li>当客户成功下单后，订单状态被设置为新订单。</li>
<li>在此状态下，商家可以进行一些操作，如编辑订单、添加备注等。</li>
<li>新订单通常需要进一步处理，以满足库存、支付和配送等需求。</li>
</ul>
</li>
<li>
<p>处理中（Processing）：</p>
<ul>
<li>当商家开始处理订单时，订单状态会从新订单转换为处理中。</li>
<li>处理中状态表示商家正在处理订单，并可能涉及库存扣减、支付确认等操作。</li>
</ul>
</li>
<li>
<p>完成（Complete）：</p>
<ul>
<li>当订单中的所有产品都已经准备好并发货时，订单状态会从处理中转换为完成。</li>
<li>完成状态表示订单已经处理完毕，并且产品已经交付给客户。</li>
</ul>
</li>
<li>
<p>部分发货（Partially Shipped）：</p>
<ul>
<li>如果订单中的一部分产品已经发货，但还有其他产品未发货，订单状态会变为部分发货。</li>
<li>部分发货状态允许商家在等待所有产品准备好后一次性发货。</li>
</ul>
</li>
<li>
<p>部分退款（Partially Refunded）：</p>
<ul>
<li>如果订单中的一部分金额被退款，订单状态会变为部分退款。</li>
<li>部分退款状态表示商家已经处理了部分退款请求。</li>
</ul>
</li>
<li>
<p>已取消（Canceled）：</p>
<ul>
<li>如果订单在处理过程中被取消，或者客户请求取消订单，订单状态会变为已取消。</li>
<li>已取消状态表示订单已被取消，不再需要进一步处理。</li>
</ul>
</li>
<li>
<p>已关闭（Closed）：</p>
<ul>
<li>当订单完成并且不再需要进一步操作时，订单状态会变为已关闭。</li>
<li>已关闭状态表示订单已经结束，不再进行任何操作。</li>
</ul>
</li>
</ol>
<p>请注意，以上是Magento 2中常见的订单状态，具体的订单状态可能会因商城设置和定制而有所不同。</p>
<p>通过了解Magento 2中订单状态的工作流程，您可以更好地管理和跟踪订单的状态变化，从而提供更好的客户体验和订单处理效率。</p>]]></description>
      <pubDate>Sun, 19 Nov 2023 07:37:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2备份指南：保护您的商城数据]]></title>
      <link>https://www.360magento.com/blog/magento2-backup-guide/</link>
      <description><![CDATA[<p>在Magento 2开发中，定期进行备份是保护您商城数据的重要措施之一。本文将为您提供一份详细的Magento 2备份指南，涵盖了数据库备份、文件备份以及备份策略的建议，帮助您确保数据的安全性和可恢复性。</p>
<p>正文：<br />在运营一个Magento 2商城时，保护商城数据的安全性至关重要。定期备份是一项关键任务，以确保您的数据在意外事件发生时能够恢复。以下是一份Magento 2备份指南，帮助您制定备份策略并执行备份操作。</p>
<ol>
<li>
<p>数据库备份：</p>
<ul>
<li>使用命令行工具（如mysqldump）或数据库管理工具（如phpMyAdmin）创建数据库备份。</li>
<li>将备份文件保存在安全的位置，最好是离线存储或云存储服务。</li>
</ul>
</li>
<li>
<p>文件备份：</p>
<ul>
<li>备份Magento 2的代码文件和媒体文件（如产品图片、CMS页面图片等）。</li>
<li>使用文件同步工具（如rsync）或压缩工具（如tar）创建文件备份。</li>
<li>将备份文件保存在安全的位置，与数据库备份分开存储。</li>
</ul>
</li>
<li>
<p>定期备份策略：</p>
<ul>
<li>确定备份频率，根据您的商城活动和数据增长情况制定备份计划。通常建议每日备份。</li>
<li>考虑创建完整备份和增量备份的组合，以减少备份时间和存储空间的使用。</li>
<li>保留历史备份，以便您可以根据需要恢复到特定时间点的数据。</li>
</ul>
</li>
<li>
<p>自动化备份：</p>
<ul>
<li>配置定时任务或使用备份工具自动执行备份操作，确保备份过程的一致性和可靠性。</li>
<li>监控备份过程，确保备份成功完成，并及时处理任何备份错误或警告。</li>
</ul>
</li>
<li>
<p>测试和恢复：</p>
<ul>
<li>定期测试备份文件的完整性和可恢复性，确保备份数据的有效性。</li>
<li>在安全的测试环境中进行恢复测试，以验证备份的可用性和恢复过程的正确性。</li>
</ul>
</li>
</ol>
<p>通过遵循这些Magento 2备份指南，您可以确保商城数据的安全性和可恢复性。备份是一项关键任务，不容忽视。</p>]]></description>
      <pubDate>Sun, 19 Nov 2023 03:29:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[10个实用的Magento 2开发小技巧]]></title>
      <link>https://www.360magento.com/blog/magento2-development-tips/</link>
      <description><![CDATA[<p>在Magento 2开发中，掌握一些实用的小技巧可以提高您的效率并优化您的代码。本文将分享10个实用的Magento 2开发小技巧，涵盖了从调试到性能优化的各个方面，帮助您更好地开发和定制Magento 2。</p>
<p>正文：<br />Magento 2是一个功能强大的电子商务平台，为开发人员提供了丰富的工具和功能。以下是一些实用的Magento 2开发小技巧，可以帮助您更好地利用这个平台：</p>
<ol>
<li>
<p>使用模板路径提示：在开发过程中，您可以在Magento 2后台启用模板路径提示，以快速找到当前页面使用的模板文件的路径。</p>
</li>
<li>
<p>自定义日志记录：使用Magento 2的日志记录功能，您可以在代码中轻松添加自定义日志语句，以便调试和跟踪问题。</p>
</li>
<li>
<p>使用插件（Plugins）进行修改：Magento 2的插件机制允许您在不修改核心代码的情况下修改或扩展现有的类和方法。</p>
</li>
<li>
<p>使用代码生成器：Magento 2提供了代码生成器（Code Generator）工具，可以帮助您快速生成模块、控制器、模型等基本代码结构。</p>
</li>
<li>
<p>启用缓存：在开发过程中，及时禁用或清除缓存以查看实时更改。但在生产环境中，启用缓存以提高性能是非常重要的。</p>
</li>
<li>
<p>使用命令行工具：Magento 2提供了许多强大的命令行工具，如数据库迁移、静态资源部署、索引重建等，可以简化开发流程。</p>
</li>
<li>
<p>使用代码嗅探器（Code Sniffer）：Magento 2附带了一个代码嗅探器工具，可以帮助您遵循Magento开发最佳实践，并确保代码质量。</p>
</li>
<li>
<p>优化数据库查询：在编写自定义代码时，尽量减少数据库查询次数，并使用Magento 2提供的查询优化技术，如使用索引、批处理操作等。</p>
</li>
<li>
<p>启用Varnish缓存：Varnish是一个流行的HTTP加速器，通过缓存页面内容来提高Magento 2的性能。在生产环境中启用Varnish缓存可以显著提升网站的加载速度。</p>
</li>
<li>
<p>及时更新和备份：确保您的Magento 2安装是最新版本，并定期备份您的代码和数据库，以便在需要时进行恢复。</p>
</li>
</ol>
<p>这些实用的Magento 2开发小技巧可以帮助您更高效地开发和定制Magento 2，并提升您的开发体验。</p>]]></description>
      <pubDate>Sat, 18 Nov 2023 08:28:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用观察者模式扩展Magento 2功能]]></title>
      <link>https://www.360magento.com/blog/magento2-observer-pattern/</link>
      <description><![CDATA[<p>观察者模式是Magento 2开发中一个强大而灵活的工具，它允许您在系统中的特定事件发生时执行自定义操作。本文将介绍Magento 2中的观察者模式，并提供一些示例代码，帮助您理解如何使用观察者模式来扩展和定制Magento 2的功能。</p>
<p>正文：<br />在Magento 2中，观察者模式是通过事件（Event）和调度程序（Dispatcher）的结合来实现的。事件是系统中发生的特定动作或状态的表示，而调度程序则负责监听和触发这些事件。当事件发生时，调度程序将通知所有注册的观察者，并执行它们所定义的操作。</p>
<p>首先，我们需要定义一个触发事件的点，并在需要监听的地方注册观察者。例如，假设我们想在添加商品到购物车时执行一些自定义操作。我们可以在<code>checkout_cart_add_product_complete</code>事件上注册一个观察者。</p>
<p>以下是一个基本的观察者类的示例代码：</p>
<div>
<div class="MarkdownCodeBlock_codeHeader__zWt_V">
<div class="MarkdownCodeBlock_languageName__4_BF8">php</div>
<button class="Button_buttonBase__Bv9Vx Button_flat__dcKQ1 MarkdownCodeBlock_copyButton__1_hA9">复制</button></div>
<pre class="MarkdownCodeBlock_preTag__QMZEO"><code class="MarkdownCodeBlock_codeTag__5BV0Z"><span>&lt;?php</span>
<span>namespace</span> <span>Vendor</span>\<span>Module</span>\<span>Observer</span>;

<span>use</span> <span>Magento</span>\<span>Framework</span>\<span>Event</span>\<span>ObserverInterface</span>;

<span class="hljs-class">class</span><span class="hljs-class"> </span><span class="hljs-class">AddToCartObserver</span><span class="hljs-class"> </span><span class="hljs-class">implements</span><span class="hljs-class"> </span><span class="hljs-class">ObserverInterface</span><span class="hljs-class">
</span><span class="hljs-class"></span>{
    <span>public</span> <span class="hljs-function">function</span><span class="hljs-function"> </span><span class="hljs-function">execute</span><span class="hljs-function">(</span><span class="hljs-function">\Magento\Framework\Event\Observer </span><span class="hljs-function">$observer</span><span class="hljs-function">)
</span><span class="hljs-function">    </span>{
        <span>// 在此处编写您的自定义操作代码</span>
    }
}
</code></pre>
</div>
<p>然后，我们需要在模块的<code>etc/events.xml</code>文件中定义观察者的配置：</p>
<div>
<div class="MarkdownCodeBlock_codeHeader__zWt_V">
<div class="MarkdownCodeBlock_languageName__4_BF8">xml</div>
<button class="Button_buttonBase__Bv9Vx Button_flat__dcKQ1 MarkdownCodeBlock_copyButton__1_hA9">复制</button></div>
<pre class="MarkdownCodeBlock_preTag__QMZEO"><code class="MarkdownCodeBlock_codeTag__5BV0Z"><span>&lt;?xml version="1.0"?&gt;</span>
<span>&lt;</span><span>config</span><span> </span><span class="hljs-attr">xmlns:xsi</span><span>=</span><span>"http://www.w3.org/2001/XMLSchema-instance"</span><span> </span><span class="hljs-attr">xsi:noNamespaceSchemaLocation</span><span>=</span><span>"urn:magento:framework:Event/etc/events.xsd"</span><span>&gt;</span>
    <span>&lt;</span><span>event</span><span> </span><span class="hljs-attr">name</span><span>=</span><span>"checkout_cart_add_product_complete"</span><span>&gt;</span>
        <span>&lt;</span><span>observer</span><span> </span><span class="hljs-attr">name</span><span>=</span><span>"vendor_module_addtocart_observer"</span><span> </span><span class="hljs-attr">instance</span><span>=</span><span>"Vendor\Module\Observer\AddToCartObserver"</span><span> /&gt;</span>
    <span>&lt;/</span><span>event</span><span>&gt;</span>
<span>&lt;/</span><span>config</span><span>&gt;</span>
</code></pre>
</div>
<p>在上述示例中，我们将<code>checkout_cart_add_product_complete</code>事件与<code>Vendor\Module\Observer\AddToCartObserver</code>观察者关联起来。当该事件在系统中被触发时，观察者的<code>execute</code>方法将会被调用。</p>
<p>您可以根据需要注册多个观察者，并在每个观察者的<code>execute</code>方法中编写自己的逻辑。</p>
<p>通过使用观察者模式，您可以方便地扩展和定制Magento 2的功能，而无需修改核心代码。观察者模式使得系统的各个部分能够松散地耦合在一起，提供了更高的可维护性和可扩展性。</p>]]></description>
      <pubDate>Sat, 18 Nov 2023 03:27:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中使用XML在首页插入静态块的方法]]></title>
      <link>https://www.360magento.com/blog/magento-insert-static-block-homepage-xml/</link>
      <description><![CDATA[<p>在Magento中，您可以使用XML布局文件来在首页或其他页面中插入静态块，以便在页面上显示自定义内容。本篇博文将介绍如何使用XML在Magento的首页插入静态块。</p>
<p>步骤 1：登录到Magento后台管理区域<br />使用管理员凭据登录到您的Magento后台管理区域。</p>
<p>步骤 2：创建静态块<br />在Magento后台管理区域，导航到左侧菜单中的&ldquo;内容&rdquo; &gt; &ldquo;块&rdquo;。点击&ldquo;创建新块&rdquo;按钮，创建一个新的静态块。填写块的相关信息，包括标识符和内容。</p>
<p>步骤 3：编辑首页布局文件<br />在Magento的主题中，找到用于首页的布局文件。通常，首页的布局文件位于以下路径：`app/design/frontend/{Vendor}/{Theme}/Magento_Theme/layout/default.xml`。如果您使用的是自定义主题，请相应地修改路径。</p>
<p>步骤 4：插入静态块的XML代码<br />在首页布局文件中，找到`&lt;body&gt;`标签，并在其中插入以下XML代码：</p>
<p>```xml<br />&lt;referenceContainer name="content"&gt;<br /> &lt;block class="Magento\Cms\Block\Block" name="your_block_name"&gt;<br /> &lt;arguments&gt;<br /> &lt;argument name="block_id" xsi:type="string"&gt;your_block_identifier&lt;/argument&gt;<br /> &lt;/arguments&gt;<br /> &lt;/block&gt;<br />&lt;/referenceContainer&gt;<br />```</p>
<p>将`your_block_name`替换为您希望为该静态块定义的名称，并将`your_block_identifier`替换为之前创建的静态块的标识符。</p>
<p>步骤 5：保存并清除缓存<br />保存并关闭首页布局文件。然后，登录到Magento后台管理区域，导航到&ldquo;系统&rdquo; &gt; &ldquo;缓存管理&rdquo;，并清除页面缓存，以便使更改生效。</p>
<p>步骤 6：查看首页上的静态块<br />现在，打开Magento商店的首页，您将看到之前创建的静态块已成功插入到首页中，并显示相应的内容。</p>
<p>使用XML在Magento的首页插入静态块使您能够轻松地自定义首页内容，并在页面上显示自定义的静态块。</p>
<p></p>]]></description>
      <pubDate>Fri, 17 Nov 2023 07:16:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中自定义首页页面的方法]]></title>
      <link>https://www.360magento.com/blog/magento2-customize-homepage/</link>
      <description><![CDATA[<p></p>
<p>Magento 2是一个功能强大的电子商务平台，允许您自定义和配置各个页面以满足您的商店需求。在本篇博文中，我们将介绍如何在Magento 2中自定义首页页面。</p>
<p>步骤 1：登录到Magento 2后台管理区域<br />使用管理员凭据登录到您的Magento 2后台管理区域。</p>
<p>步骤 2：创建自定义首页布局文件<br />在Magento的主题中，找到用于首页的布局文件。通常，首页的布局文件位于以下路径：`app/design/frontend/{Vendor}/{Theme}/Magento_Theme/layout/default.xml`。如果您使用的是自定义主题，请相应地修改路径。</p>
<p>步骤 3：编辑自定义首页布局文件<br />打开自定义首页布局文件，并根据您的需求进行编辑。您可以使用XML标签和属性来定义页面的结构、内容和布局。</p>
<p>以下是一些常见的自定义首页布局设置示例：</p>
<p>- 增加静态块：您可以使用`&lt;referenceContainer&gt;`标签和`&lt;block&gt;`标签来插入静态块到首页。您可以在适当的位置添加以下代码来插入静态块：</p>
<p>```xml<br />&lt;referenceContainer name="content"&gt;<br /> &lt;block class="Magento\Cms\Block\Block" name="your_block_name"&gt;<br /> &lt;arguments&gt;<br /> &lt;argument name="block_id" xsi:type="string"&gt;your_block_identifier&lt;/argument&gt;<br /> &lt;/arguments&gt;<br /> &lt;/block&gt;<br />&lt;/referenceContainer&gt;<br />```</p>
<p>将`your_block_name`替换为您给定的静态块名称，将`your_block_identifier`替换为静态块的标识符。</p>
<p>- 调整页面布局：您可以使用不同的容器名称和块标签来调整页面布局。通过在布局文件中的适当位置添加或修改容器和块标签，您可以重新排列页面的各个部分，如页眉、页脚、侧边栏等。</p>
<p>步骤 4：保存并清除缓存<br />保存并关闭自定义首页布局文件。然后，登录到Magento后台管理区域，导航到&ldquo;系统&rdquo; &gt; &ldquo;缓存管理&rdquo;，并清除页面缓存，以便使更改生效。</p>
<p>步骤 5：查看自定义的首页页面<br />现在，打开Magento商店的首页，您将看到您的自定义布局和修改已成功应用于首页页面。</p>
<p>通过自定义Magento 2的首页页面，您可以完全控制首页的布局、内容和呈现方式，以提供独特而个性化的用户体验。</p>
<p></p>
<div id="gtx-trans" style="position: absolute; left: -15px; top: 11.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 17 Nov 2023 03:57:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中添加CMS页面的步骤和说明]]></title>
      <link>https://www.360magento.com/blog/magento2-add-cms-page/</link>
      <description><![CDATA[<p></p>
<p>---</p>
<p>在Magento 2中，CMS页面允许您创建和管理自定义内容，如关于我们、联系我们、常见问题等页面。本篇博文将介绍在Magento 2中添加CMS页面的详细步骤和说明。</p>
<p>步骤 1：登录到Magento 2后台管理区域<br />在您的浏览器中打开Magento 2后台管理页面，并使用管理员凭据登录到您的商店。</p>
<p>步骤 2：导航到CMS页面管理<br />导航到左侧菜单中的&ldquo;内容&rdquo; &gt; &ldquo;页面&rdquo;下的&ldquo;页面&rdquo;选项。这将打开CMS页面管理区域。</p>
<p>步骤 3：创建新CMS页面<br />点击&ldquo;创建新页面&rdquo;按钮，开始创建新的CMS页面。</p>
<p>步骤 4：填写CMS页面信息<br />在创建CMS页面的编辑界面，您需要填写以下信息：<br />- 标题：输入CMS页面的标题。这是显示在前端页面上的页面名称。<br />- 标识符：输入CMS页面的唯一标识符。这将用于生成CMS页面的URL。<br />- 页面布局：选择页面布局。您可以选择全宽布局或左右侧边栏布局，具体取决于您的设计需求。<br />- 激活：选择是否激活该CMS页面。<br />- 排序：指定CMS页面的排序顺序。</p>
<p>步骤 5：编辑CMS页面内容<br />在&ldquo;内容&rdquo;选项卡下，您可以使用WYSIWYG编辑器输入和格式化CMS页面的内容。您可以添加文本、图像、链接和其他元素来定制页面。</p>
<p>步骤 6：保存并发布CMS页面<br />完成CMS页面内容编辑后，点击右上角的&ldquo;保存并发布&rdquo;按钮，保存并发布CMS页面。您的CMS页面现在已经创建成功并可在前端页面上访问。</p>
<p>步骤 7：查看CMS页面<br />要查看新添加的CMS页面，您可以导航到前端页面，并在导航菜单或链接中找到相应的CMS页面。</p>
<p>这些是在Magento 2中添加CMS页面的基本步骤和说明。通过创建自定义的CMS页面，您可以灵活地管理和展示内容，以满足您的商店需求。</p>
<p></p>
<div id="gtx-trans" style="position: absolute; left: 356px; top: 600.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 16 Nov 2023 07:11:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中添加CMS块的步骤和说明]]></title>
      <link>https://www.360magento.com/blog/magento2-add-cms-block/</link>
      <description><![CDATA[<p>在Magento 2中，CMS块是可重复使用的内容片段，可以在多个页面和布局中使用。本篇博文将介绍在Magento 2中添加CMS块的详细步骤和说明。</p>
<p>步骤 1：登录到Magento 2后台管理区域<br />在您的浏览器中打开Magento 2后台管理页面，并使用管理员凭据登录到您的商店。</p>
<p>步骤 2：导航到CMS块管理<br />导航到左侧菜单中的&ldquo;内容&rdquo; &gt; &ldquo;块&rdquo;下的&ldquo;块&rdquo;选项。这将打开CMS块管理区域。</p>
<p>步骤 3：创建新CMS块<br />点击&ldquo;创建新块&rdquo;按钮，开始创建新的CMS块。</p>
<p>步骤 4：填写CMS块信息<br />在创建CMS块的编辑界面，您需要填写以下信息：<br />- 标识符：输入CMS块的唯一标识符。这将用于在页面或布局中调用CMS块。<br />- 标题：输入CMS块的标题。这是显示在后台管理区域中的标识块的名称。<br />- 激活：选择是否激活该CMS块。</p>
<p>步骤 5：编辑CMS块内容<br />在&ldquo;内容&rdquo;选项卡下，您可以使用WYSIWYG编辑器输入和格式化CMS块的内容。您可以添加文本、图像、链接和其他元素来定制块。</p>
<p>步骤 6：保存并发布CMS块<br />完成CMS块内容编辑后，点击右上角的&ldquo;保存并发布&rdquo;按钮，保存并发布CMS块。您的CMS块现在已经创建成功并可在页面和布局中使用。</p>
<p>步骤 7：调用CMS块<br />要在页面或布局中调用CMS块，您可以使用以下代码：<br />```<br /><br />```<br />将`YOUR_BLOCK_IDENTIFIER`替换为您之前创建的CMS块的标识符。</p>
<p>步骤 8：保存并更新页面或布局<br />在调用CMS块的页面或布局中，点击右上角的&ldquo;保存&rdquo;按钮，保存并更新页面或布局。这将使CMS块在前端页面上显示。</p>
<p>这些是在Magento 2中添加CMS块的基本步骤和说明。通过创建和使用CMS块，您可以轻松地重复使用和管理内容片段，提高网站的灵活性和可维护性。</p>
<p></p>
<div id="gtx-trans" style="position: absolute; left: -29px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 16 Nov 2023 03:13:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[探索Magento 2的电商优势]]></title>
      <link>https://www.360magento.com/blog/magento2-ecommerce-advantages/</link>
      <description><![CDATA[<p>Magento 2是一款功能强大的开源电子商务平台，为在线商家提供了许多优势和功能。在本篇博文中，我们将探索Magento 2作为电子商务系统的一些主要优势。</p>
<p>1. 强大的扩展性：Magento 2提供了广泛的扩展和定制选项，使商家能够根据自己的需求和业务模型来定制和扩展其电子商务平台。通过丰富的市场和开发者社区，商家可以轻松地添加新功能、集成第三方服务和扩展其在线业务。</p>
<p>2. 灵活和可定制的设计：Magento 2提供了丰富的主题和布局选项，使商家能够根据自己的品牌形象和目标受众来设计独特和个性化的在线商店。商家可以轻松地更改颜色、字体、布局和其他设计元素，以创建具有吸引力和专业性的电子商务界面。</p>
<p>3. 强大的商品管理功能：Magento 2提供了全面的商品管理功能，包括库存管理、商品属性、产品类型和价格规则等。商家可以轻松地管理大量商品，设置不同的产品选项和价格策略，并使用灵活的目录结构来组织商品。</p>
<p>4. 多语言和多货币支持：作为一个全球化的电子商务平台，Magento 2支持多语言和多货币。商家可以轻松地创建多语言站点，并为不同地区的客户提供本地化的购物体验。多货币功能使商家能够在不同国家和地区接受多种货币的支付。</p>
<p>5. 强大的营销和促销工具：Magento 2提供了各种营销和促销工具，帮助商家吸引和留住客户。商家可以设置特价商品、优惠券、购物车价格规则等，以提供个性化和有吸引力的购物体验，并增加销售和转化率。</p>
<p>6. 高级搜索和过滤功能：Magento 2具有强大的搜索和过滤功能，使客户能够快速找到他们想要的商品。商家可以配置高级搜索引擎、设置筛选器和排序选项，提供优化的商品浏览和购物体验。</p>
<p>综上所述，Magento 2作为一款先进的电子商务系统，为商家提供了强大的功能和灵活性，能够满足各种在线商务需求。无论是中小型企业还是大型企业，Magento 2都为其提供了一个可靠和可扩展的电子商务平台。</p>
<p></p>
<div id="gtx-trans" style="position: absolute; left: -122px; top: 345.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 15 Nov 2023 07:04:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[成为一名出色的Magento前端开发人员所需的知识和技能]]></title>
      <link>https://www.360magento.com/blog/magento-frontend-developer-skills/</link>
      <description><![CDATA[<p></p>
<p>作为一名Magento前端开发人员，需要具备一系列的知识和技能，以便在开发过程中能够高效地创建出色的用户界面和用户体验。在本篇博文中，我们将探讨成为一名出色的Magento前端开发人员所需的关键知识和技能。</p>
<p>1. HTML、CSS和JavaScript：作为前端开发人员，掌握HTML、CSS和JavaScript是基础中的基础。深入了解HTML标记、CSS样式和JavaScript交互能力，能够构建具有良好结构、样式和交互的网页。</p>
<p>2. Magento主题开发：了解Magento的主题开发是成为一名优秀的Magento前端开发人员的关键。熟悉Magento主题的结构和层次结构，能够创建自定义主题、定制样式和布局，并应用到Magento商店中。</p>
<p>3. 响应式设计和移动优化：在移动设备使用的普及下，响应式设计和移动优化变得至关重要。具备响应式设计和移动优化的技能，能够确保Magento商店在各种设备上都能提供出色的用户体验。</p>
<p>4. 前端框架和库：掌握流行的前端框架和库，例如Bootstrap、jQuery等，能够使用这些工具来加速开发过程、提高效率，并实现更复杂的交互效果。</p>
<p>5. Sass或Less等CSS预处理器：使用CSS预处理器能够提供更灵活和可维护的CSS代码。熟悉Sass、Less等CSS预处理器，能够使用变量、嵌套规则和混合等功能，简化CSS开发并提高代码的可重用性。</p>
<p>6. 版本控制系统：熟悉版本控制系统，例如Git，能够有效地管理和追踪代码更改。掌握版本控制系统的基本操作和工作流程，能够与团队协作，并轻松地回溯和管理代码版本。</p>
<p>7. 网页性能优化：优化Magento商店的网页性能对于提供卓越的用户体验至关重要。了解前端性能优化的最佳实践，如减少HTTP请求、压缩和合并资源、使用缓存等技术，能够提高Magento商店的加载速度和响应性。</p>
<p>8. 调试和故障排除：作为一名前端开发人员，需要具备调试和故障排除的技能。能够使用浏览器开发者工具、日志和其他调试工具，快速定位和解决前端问题。</p>
<p>综上所述，成为一名出色的Magento前端开发人员需要掌握HTML、CSS和JavaScript等基础知识，具备Magento主题开发、响应式设计和移动优化等技能，并熟悉前端框架、CSS预处理器和网页性能优化等工具和技术。</p>
<div id="gtx-trans" style="position: absolute; left: -52px; top: 11.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 15 Nov 2023 03:07:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento程序中记录日志并保存在var/log目录]]></title>
      <link>https://www.360magento.com/blog/logging-in-magento-ultimate-guide/</link>
      <description><![CDATA[<p>在Magento开发中，记录日志是一种有用的方式来跟踪和调试应用程序中的问题。本文将提供一份详细的指南，教您如何在Magento程序中使用代码记录日志，并将日志保存在var/log目录中，以便轻松地管理和分析日志信息。</p>
<p>步骤1：创建日志记录器实例<br />首先，在您的Magento程序中，您需要创建一个日志记录器实例。您可以使用Magento的内置日志记录器类`\Psr\Log\LoggerInterface`来实现这一点。可以在您的类构造函数或需要记录日志的方法中注入该日志记录器实例。</p>
<pre>use Psr\Log\LoggerInterface;

class YourClass
{
    protected $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this-&gt;logger = $logger;
    }

    // ...
}</pre>
<p>步骤2：记录日志消息<br />一旦您有了日志记录器实例，您可以使用该实例记录日志消息。`LoggerInterface`接口提供了几个常用的日志级别，例如`debug`、`info`、`warning`和`error`。您可以根据需要选择适当的级别。</p>
<pre>// 在您的方法中记录日志
public function yourMethod()
{
    // ...

    $this-&gt;logger-&gt;debug('This is a debug message.');
    $this-&gt;logger-&gt;info('This is an info message.');
    $this-&gt;logger-&gt;warning('This is a warning message.');
    $this-&gt;logger-&gt;error('This is an error message.');

    // ...
}
</pre>
<p>步骤3：配置日志保存路径</p>
<p>默认情况下，Magento将日志保存在var/log目录下。确保该目录具有适当的写入权限，以便Magento可以在其中创建和写入日志文件。</p>
<p>步骤4：查看和管理日志<br />记录的日志将保存在var/log目录中的不同日志文件中。您可以使用SSH或FTP等工具，访问Magento安装目录下的var/log目录，以查看和管理生成的日志文件。根据需要，您可以在开发或调试过程中定期检查日志文件，以获取有关应用程序运行状况和潜在问题的详细信息。</p>
<p>结束语<br />通过按照上述步骤，在Magento程序中记录日志并将其保存在var/log目录中，您将能够轻松地跟踪和调试应用程序中的问题。日志记录是开发过程中的重要工具，可以帮助您定位和解决潜在的错误和异常情况。希望本篇指南对Magento程序中的日志记录有所帮助！</p>
<p></p>]]></description>
      <pubDate>Tue, 14 Nov 2023 08:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento电商网站购物车流程详细指南]]></title>
      <link>https://www.360magento.com/blog/magento-ecommerce-shopping-cart-guide/</link>
      <description><![CDATA[<p>购物车是电商网站中至关重要的一环，为用户提供了方便的购物体验和订单管理。本文将为您提供一份详细的指南，介绍Magento电商网站的购物车流程，从添加商品到结算订单的完整过程，帮助您了解和优化购物车流程，提升用户的购物体验。</p>
<p>步骤1：商品浏览和选择<br />用户首先浏览Magento电商网站上的商品列表，可以通过分类、搜索或推荐等方式找到感兴趣的商品。用户可以查看商品详情、价格、库存情况和其他相关信息，并选择要购买的商品。</p>
<p>步骤2：添加商品到购物车<br />一旦用户决定购买商品，他们可以将商品添加到购物车。在商品页面上，通常有一个"加入购物车"按钮，用户点击后，商品将被添加到购物车中。</p>
<p>步骤3：购物车页面<br />添加商品到购物车后，用户会被重定向到购物车页面，展示他们添加的商品列表。在购物车页面上，用户可以查看每个商品的详细信息，如名称、价格、数量和小计。用户可以修改商品数量、移除商品或清空整个购物车。</p>
<p>步骤4：结算流程<br />当用户完成商品选择并准备结算时，他们可以点击"结算"按钮，进入结算流程。在这一步骤中，Magento网站通常要求用户登录或创建一个新账户。用户需要提供相关信息，如收货地址、付款方式和配送方式。</p>
<p>步骤5：订单确认<br />在结算流程的最后一步，用户将被导向订单确认页面。在此页面上，用户可以再次检查订单的详细信息，包括商品列表、收货地址、付款方式和配送方式。用户可以确认订单细节，并选择提交订单。</p>
<p>步骤6：订单完成<br />一旦用户提交订单，Magento电商网站会生成订单号并显示订单确认页面。用户可以在订单确认页面上查看订单摘要和详细信息，并收到订单确认的电子邮件通知。此时，用户可以选择继续购物或返回网站主页。</p>
<p>结束语<br />购物车流程是Magento电商网站中至关重要的一环，对用户的购物体验和订单管理起着关键作用。通过本文提供的详细指南，您可以了解Magento购物车流程的各个步骤，并通过优化和改进购物车流程来提升用户的购物体验。希望本篇指南对Magento电商网站的购物车流程有所帮助！</p>
<div id="gtx-trans" style="position: absolute; left: 527px; top: 477.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 14 Nov 2023 03:04:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[成为一名优秀的Magento开发人员所需的关键技能]]></title>
      <link>https://www.360magento.com/blog/skills-magento-developer/</link>
      <description><![CDATA[<p>导语：Magento是一种广泛使用的电子商务平台，作为一名Magento开发人员，掌握关键技能至关重要。本文将详细介绍成为一名优秀的Magento开发人员所需的关键技能，帮助您迈向成功的Magento开发之路。</p>
<ol>
<li>
<p>熟悉PHP编程语言：<br />作为Magento的主要开发语言，对PHP的熟悉程度对于成功开发和定制Magento非常重要。掌握PHP的基本语法、面向对象编程（OOP）和相关的设计模式是必不可少的。</p>
</li>
<li>
<p>Magento架构的理解：<br />深入了解Magento的架构和工作原理对于开发定制模块和主题至关重要。掌握Magento的模块结构、数据库架构、事件系统和前端技术栈（如布局、块和模板）是非常重要的。</p>
</li>
<li>
<p>Magento扩展和模块开发：<br />熟悉Magento扩展和模块开发是成为一名优秀Magento开发人员的关键。了解如何创建自定义模块、添加新功能、覆盖现有功能和扩展Magento的核心功能是必备技能。</p>
</li>
<li>
<p>前端开发技能：<br />熟悉HTML、CSS和JavaScript等前端技术，以及流行的前端框架（如Bootstrap）是非常有帮助的。这将使您能够定制Magento的前端样式和布局，提供出色的用户体验。</p>
</li>
<li>
<p>数据库管理：<br />熟悉MySQL或其他关系型数据库管理系统对于在Magento中处理数据非常重要。了解数据库设计、查询优化和索引的基本原理是必要的。</p>
</li>
<li>
<p>版本控制和团队协作：<br />掌握版本控制工具（如Git）和团队协作工具（如GitHub或Bitbucket）是必备技能。这将使您能够有效地管理代码、合作开发和进行版本控制。</p>
</li>
<li>
<p>问题排查和调试能力：<br />成为一名优秀的Magento开发人员需要具备良好的问题排查和调试能力。熟悉使用调试工具、查看错误日志和分析代码以解决问题是必要的技能。</p>
</li>
<li>
<p>学习和自我提升：<br />Magento是一个不断发展和更新的平台，作为开发人员，持续学习和自我提升是必须的。掌握新的技术和工具，关注Magento的最新版本和最佳实践将有助于您不断提升技能水平。</p>
</li>
</ol>
<p>结语：成为一名优秀的Magento开发人员需要综合运用多种技能和知识。通过熟悉PHP编程语言、深入了解Magento架构、掌握扩展开发和前端技术、熟悉数据库管理等关键技能，您将能够在Magento开发领域脱颖而出。同时，不断学习和自我提升是不可或缺的，以跟上Magento平台的发展和最新技术趋势。希望本文对您成为一名优秀的Magento开发人员有所帮助。</p>
<div id="gtx-trans" style="position: absolute; left: 31px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 13 Nov 2023 07:46:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何导入Magento的产品和图片]]></title>
      <link>https://www.360magento.com/blog/how-to-import-products-and-images-in-magento/</link>
      <description><![CDATA[<p>在Magento中导入产品和图片是建立和管理电子商务网站的重要任务。本文将提供一份详尽的指南，帮助您了解如何顺利导入产品和图片到Magento平台，并确保产品数据和图片正确关联，以提供出色的购物体验。</p>
<p>步骤1：准备产品和图片数据<br />首先，准备好产品和图片数据。确保产品数据以CSV或Excel文件的形式保存，其中包含产品的详细信息，如名称、描述、价格、SKU等。同时，收集产品图片并确保每个产品的图片与其对应的信息匹配。</p>
<p>步骤2：登录到Magento后台管理面板<br />使用管理员凭据登录到Magento的后台管理面板。确保您具备导入产品和管理目录的权限。</p>
<p>步骤3：导入产品数据<br />在Magento后台管理面板的左侧导航栏中，选择"System"，然后选择"Import"。在导入页面中，切换到"Products"选项卡，并点击"Choose File"按钮，选择包含产品数据的CSV或Excel文件。</p>
<p>步骤4：配置产品导入设置<br />在导入页面中，您可以配置各种产品导入设置。确保正确地映射CSV/Excel文件中的每个列与Magento的相应产品属性。您还可以设置其他选项，如处理重复产品、更新现有产品等。</p>
<p>步骤5：导入产品<br />配置完毕后，点击"Check Data"按钮，确保产品数据符合预期。如果没有错误，点击"Import"按钮开始导入产品数据。在导入过程中，系统将显示进度和结果。</p>
<p>步骤6：导入产品图片<br />在导入产品数据后，您需要导入相应的产品图片。将产品图片上传到Magento的媒体库，并将其与相应的产品关联。在Magento后台管理面板的左侧导航栏中，选择"Products"，然后选择"Catalog"。找到要导入图片的产品，并编辑每个产品的详细信息。在"Images and Videos"选项卡下，上传产品图片并设置其顺序和类型。</p>
<p>步骤7：保存和更新产品<br />在完成产品和图片导入后，确保点击保存并更新每个产品的信息。这将确保产品和图片正确关联和显示。</p>
<p>结束语<br />通过按照上述步骤，您可以顺利地将产品和图片导入到Magento平台，并确保它们正确关联和显示。这样，您将为您的电子商务网站提供丰富的产品信息和吸引人的图片，提升用户的购物体验。请记住，在进行任何导入之前，建议在测试环境中进行实验，以确保导入过程不会影响您的实际网站。希望本篇指南对您的Magento产品和图片导入过程有所帮助！</p>
<div id="gtx-trans" style="position: absolute; left: -53px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 13 Nov 2023 03:54:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[提高Magento外贸网站运行速度的关键措施]]></title>
      <link>https://www.360magento.com/blog/key-measures-to-improve-operating-speed-of-magento-foreign-trade-websites/</link>
      <description><![CDATA[<p>导语：在竞争激烈的外贸市场中，一个快速响应的网站对于吸引客户和提升销售至关重要。然而，许多Magento外贸网站可能存在速度较慢的问题，影响用户体验和搜索引擎排名。本文将分享一些权威的专业技巧，帮助您提高Magento外贸网站的运行速度，以获得更好的业务结果。</p>
<p>1. 优化图像和媒体文件：<br /> - 压缩和优化网站上的图像和媒体文件，以减少其文件大小并提高加载速度。<br /> - 使用适当的图像格式（如JPEG、PNG）并设置适当的压缩级别。</p>
<p>2. 使用缓存和CDN：<br /> - 配置Magento的缓存系统，包括页面缓存、对象缓存和数据库查询缓存。<br /> - 使用内容分发网络（CDN）将网站内容分发到全球各地的服务器，加快用户访问速度。</p>
<p>3. 压缩和合并CSS和JavaScript文件：<br /> - 压缩CSS和JavaScript文件，以减少其文件大小。<br /> - 合并多个CSS和JavaScript文件，减少HTTP请求的数量。</p>
<p>4. 使用优化的主题和扩展：<br /> - 选择优化的Magento主题和扩展，确保其代码质量和性能优化。<br /> - 定期检查和更新主题和扩展，以确保其与最新版本的Magento兼容。</p>
<p>5. 延迟加载和异步加载内容：<br /> - 使用延迟加载技术加载页面上的图片、视频和其他资源，以减少初始页面加载时间。<br /> - 将非关键的内容（如社交媒体插件）异步加载，确保页面的主要内容优先加载。</p>
<p>6. 优化数据库：<br /> - 定期清理Magento数据库中的无用数据，如日志、临时表等。<br /> - 优化数据库查询，包括创建索引、删除重复数据等。</p>
<p>7. 使用高速托管和服务器优化：<br /> - 将Magento网站托管在高速和可靠的服务器上，确保服务器响应时间快。<br /> - 配置服务器缓存和压缩，以提高网站性能。</p>
<p>8. 前端优化：<br /> - 最小化HTTP请求，减少页面加载时间。<br /> - 使用浏览器缓存和Gzip压缩，提高页面加载速度。</p>
<p>结语：通过采取以上关键措施，您可以显著提高Magento外贸网站的运行速度，提升用户体验和搜索引擎可见性。请记住，优化网站速度是一个持续的过程，建议定期进行测试和优化，以确保网站始终处于最佳状态。作为一个专业的外贸网站，快速响应和流畅的用户体验将为您赢得更多的客户和业务机会。</p>
<div id="gtx-trans" style="position: absolute; left: 120px; top: 61px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 12 Nov 2023 07:38:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何启用Magento的页面缓存功能以提升网站速度]]></title>
      <link>https://www.360magento.com/blog/enable-magento-page-caching/</link>
      <description><![CDATA[<p>Magento是一个功能强大的电子商务平台，为了提高网站速度和性能，启用页面缓存功能是至关重要的。本文将详细介绍如何在Magento中启用页面缓存功能，以加快网站加载速度并提升用户体验。</p>
<p>步骤1：登录Magento后台管理面板<br />首先，使用管理员凭据登录到Magento的后台管理面板。在成功登录后，您将进入控制面板，准备进行页面缓存的配置。</p>
<p>步骤2：进入配置页面<br />在控制面板中，点击左上角的"Stores"（商店）选项卡，然后选择"Configuration"（配置）。</p>
<p>步骤3：打开缓存配置<br />在左侧导航栏中，找到并展开"Advanced"（高级）选项。然后，点击"System"（系统）下的"Cache Management"（缓存管理）。</p>
<p>步骤4：启用页面缓存<br />在缓存管理页面中，您将看到各种缓存选项。找到"Full Page Cache"（完整页面缓存）并确保其状态为"Enabled"（已启用）。</p>
<p>步骤5：保存配置更改点击页面右上方的"Save Config"（保存配置）按钮，将您的更改保存到Magento配置中。</p>
<p>步骤6：清除缓存启用页面缓存后，您需要清除现有的缓存以使更改生效。点击页面右上方的"Flush Magento Cache"（清除Magento缓存）按钮，然后确认清除操作。</p>
<p>步骤7：测试页面缓存现在，您的Magento网站已经启用了页面缓存功能。为了确保缓存正常工作，您可以打开您的网站并浏览几个页面。注意观察页面加载速度的改善。</p>
<p>结语：通过启用Magento的页面缓存功能，您可以显著提升网站的加载速度和性能。这将改善用户体验、提高转化率，并有助于提升搜索引擎排名。记得定期清除缓存以确保最新的数据和内容被缓存。</p>
<p>优化网站速度是一个持续的过程，建议您定期进行测试和优化，以确保网站保持最佳状态。希望本文对您启用Magento页面缓存功能有所帮助。</p>]]></description>
      <pubDate>Sun, 12 Nov 2023 03:39:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用Magento构建强大的电子商务网站的亮点]]></title>
      <link>https://www.360magento.com/blog/highlights-of-building-powerful-ecommerce-sites-with-magento/</link>
      <description><![CDATA[<p>在当今数字化时代，拥有一个优秀的电子商务网站对于企业的成功至关重要。作为一种功能强大的电子商务平台，Magento为企业提供了一个全面而灵活的解决方案。本文将介绍使用Magento构建强大的电子商务网站的优势和关键功能。</p>
<ol>
<li>
<p>强大的功能和灵活性：<br />Magento提供了丰富的功能和灵活的架构，使企业能够构建适应其业务需求的定制化网站。无论是中小型企业还是大型企业，Magento都可以根据需求进行扩展和定制，满足各种电子商务业务模型。</p>
</li>
<li>
<p>多店铺管理：<br />Magento允许通过单个后台管理多个在线商店。这对于拥有多个品牌、产品线或地理位置的企业来说非常有用。通过统一的管理界面，您可以轻松地管理和监控各个店铺的库存、订单、支付和运输等。</p>
</li>
<li>
<p>丰富的扩展和集成：<br />Magento提供了一个庞大的扩展市场，您可以通过集成各种插件和模块来增强您的网站功能。无论是支付网关、物流服务、市场营销工具还是客户支持系统，Magento都有相应的扩展可供选择。</p>
</li>
<li>
<p>灵活的主题和设计：<br />Magento提供了丰富的主题和模板选择，使您能够根据品牌形象和用户体验需求来定制网站的外观和用户界面。您可以选择现有主题或进行定制开发，以实现独特的品牌风格和用户友好的设计。</p>
</li>
<li>
<p>强大的营销和SEO功能：<br />Magento内置了一系列强大的营销工具，包括促销活动、优惠券、产品推荐和客户分群等。此外，Magento还具有友好的搜索引擎优化（SEO）功能，有助于提高网站在搜索引擎中的可见性和排名。</p>
</li>
<li>
<p>安全和可靠性：<br />Magento提供了一系列安全性功能和措施，以确保网站和用户数据的安全。它具有强大的身份验证、加密和防范欺诈的功能，保护您的网站免受潜在的安全威胁。</p>
</li>
</ol>
<p>总而言之，使用Magento构建电子商务网站是一个明智的选择。其强大的功能、灵活性和可扩展性使企业能够打造出符合业务需求的出色网站。无论您是中小型企业还是大型企业，Magento都提供了一套完整的解决方案，帮助您实现在线销售的成功。开始使用Magento，为您的电子商务业务开辟一个新的篇章吧！</p>
<div id="gtx-trans" style="position: absolute; left: -175px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 11 Nov 2023 07:30:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento有哪些适用于中小型企业的定制化功能？]]></title>
      <link>https://www.360magento.com/blog/customizable-features-of-magento-suitable-for-smes/</link>
      <description><![CDATA[<p>导语：构建一个强大而灵活的电子商务网站对于中小型企业来说至关重要。而Magento作为一款功能强大的电子商务平台，为企业提供了全面的解决方案。本文将为您介绍如何利用Magento的定制化功能，为中小型企业打造一个令人印象深刻的在线销售平台。无论是个性化设计、促销活动还是客户管理，Magento都能满足您的需求，助力您实现电子商务的成功。让我们一起探索Magento的定制化功能，为您的企业开辟新的商机！</p>
<p>Magento提供了许多适用于中小型企业的定制化功能，以下是其中一些主要功能：</p>
<p>1. 主题和布局定制：Magento允许中小型企业根据自身品牌形象和用户需求进行网站主题和布局的定制。您可以选择现有的主题，进行自定义调整，或者进行定制开发以满足特定的设计要求。</p>
<p>2. 商品管理：中小型企业可以使用Magento的商品管理功能来管理产品目录、库存和价格。您可以轻松添加、编辑和删除产品，并设置不同的属性和选项。</p>
<p>3. 促销和优惠券：Magento提供了灵活的促销工具，中小型企业可以使用这些工具来创建各种促销活动和优惠券。您可以设置折扣、特价商品、买一送一等促销策略，以吸引和激励客户购买。</p>
<p>4. 客户管理：通过Magento的客户管理功能，中小型企业可以管理客户信息、订单历史和购物车内容。您可以查看和跟踪客户活动，为客户提供个性化的服务和推荐。</p>
<p>5. 支付和物流集成：中小型企业可以通过Magento集成各种支付网关和物流服务，以提供方便的支付和快速的配送选项。您可以选择适合您业务的支付解决方案，并与物流服务商合作，提供灵活的配送选择。</p>
<p>6. 多语言和多货币支持：如果您的中小型企业面向国际市场，Magento提供了多语言和多货币支持的功能。您可以轻松地创建多语言版本的网站，并根据不同地区的货币设置定价和支付选项。</p>
<p>7. 数据分析和报告：通过Magento的数据分析和报告功能，中小型企业可以获取关键的业务指标和销售数据。您可以监控网站流量、销售趋势和客户行为，以便做出战略决策和优化业务运营。</p>
<p>这些功能只是Magento提供给中小型企业的一小部分定制化功能。通过灵活的架构和丰富的扩展市场，企业可以根据自身需求进行更多的定制化开发，满足特定的业务需求。</p>]]></description>
      <pubDate>Sat, 11 Nov 2023 03:32:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2的发展前景：持续创新与市场机遇]]></title>
      <link>https://www.360magento.com/blog/magento-2-continued-innovation-and-market-opportunities/</link>
      <description><![CDATA[<p>导语：Magento 2作为一款强大而灵活的电商平台，一直以来都备受关注。在本文中，我们将探讨Magento 2的发展前景，包括其持续创新、市场机遇以及为企业带来的价值。</p>
<p>1. 持续创新与功能增强</p>
<p>Magento 2在推出以来一直致力于持续创新和功能增强。相对于Magento 1，Magento 2引入了一系列的改进和新功能，包括更强大的性能、更直观的后台管理界面、更好的移动端支持等。这些改进使得Magento 2成为一个更现代化、更易用的电商平台，能够帮助企业满足不断变化的市场需求。</p>
<p>2. 强大的生态系统和扩展库</p>
<p>Magento 2拥有一个庞大而活跃的生态系统，包括开发者、合作伙伴和社区。这个生态系统为Magento 2提供了丰富的扩展和集成选项，使得企业能够根据自身需求定制和扩展他们的电商平台。无论是支付网关、物流集成还是营销工具，都能够在Magento 2的扩展库中找到适合的解决方案。</p>
<p>3. 响应式设计和移动优化</p>
<p>随着移动互联网的普及，移动端的重要性不言而喻。Magento 2具备响应式设计和移动优化的特点，能够自适应不同屏幕尺寸，并提供出色的移动购物体验。这使得企业能够更好地满足消费者的移动购物需求，提高转化率和用户满意度。</p>
<p>4. 全球化和多语言支持</p>
<p>Magento 2具备全球化的能力，支持多语言和多货币。这使得企业能够轻松扩展到不同的国家和地区，拓展全球市场。无论是本地化的内容、价格还是支付方式，Magento 2都提供了强大的工具和功能，帮助企业实现全球化战略。</p>
<p>5. 企业级功能和可扩展性</p>
<p>Magento 2是一款强大的企业级电商平台，适用于各种规模和行业的企业。它提供了丰富的功能和可扩展性，能够满足复杂的业务需求。无论是B2C还是B2B电商，Magento 2都能够提供强大的功能和灵活的定制选项，支持企业实现增长和创新。</p>
<p>结论：</p>
<p>总体而言，Magento 2具备强大的发展前景。它不仅在技术上持续创新和改进，还能够满足企业的多样化需求。随着电商市场的不断发展和竞争的加剧，有一个可靠、灵活的电商平台是企业成功的关键。Magento 2通过其强大的功能、扩展库和全球化支持，成为许多企业的首选。无论是新兴企业还是已有企业的升级，选择Magento 2都能够为他们带来成功和增长的机会。因此，我们可以乐观地预见Magento 2在未来的市场中将继续保持领先地位，为企业带来持续的价值和竞争优势。</p>]]></description>
      <pubDate>Fri, 10 Nov 2023 07:36:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的发展历程：在当今电商领域的优势与突破]]></title>
      <link>https://www.360magento.com/blog/evolution-magento-advantages-current-ecommerce-landscape/</link>
      <description><![CDATA[<p>导语:<br />Magento作为一款知名的电子商务平台，在当前的电商领域中展现出了许多独特的优势。本文将为您详细介绍Magento的发展历程，并探讨它在当今社会电商领域的优势和突破。</p>
<ol>
<li>
<p>创立与初期发展<br />Magento于2007年由Roy Rubin和Yoav Kutner共同创立。他们致力于打造一款灵活、可扩展的电子商务平台，以满足不断变化的市场需求。Magento的创立标志着一个全新的电商时代的开始。</p>
</li>
<li>
<p>功能丰富与可定制性<br />Magento以其丰富的功能和可定制性而闻名。它提供了强大的产品目录管理、安全的支付网关、订单处理和客户关系管理等功能。商家可以根据自身需求对Magento进行定制，打造独特的在线购物体验。</p>
</li>
<li>
<p>开源优势<br />作为一款开源平台，Magento具有开放的架构和源代码。这使得开发者可以根据自己的需求对平台进行自由的扩展和定制。开源的特性使得Magento拥有庞大的开发者社区，为商家提供了丰富的资源和支持。</p>
</li>
<li>
<p>可扩展性与性能<br />随着电商行业的快速发展，可扩展性和性能成为了一个关键因素。Magento凭借其可扩展的架构和强大的性能，能够处理大规模的产品目录、高订单量和高流量的网站访问。即使在高峰期，Magento也能保持稳定的运行，为用户提供无缝的购物体验。</p>
</li>
<li>
<p>移动端和全渠道能力<br />在移动互联时代，移动端的重要性不可忽视。Magento提供了响应式设计和移动友好的功能，确保了在不同设备上的无缝购物体验。此外，Magento还提供了全渠道能力，商家可以将线上商店与实体零售店、在线市场和社交媒体平台进行整合，为用户提供统一和一致的品牌体验。</p>
</li>
</ol>
<p>结论:<br />Magento在电商领域的发展历程令人瞩目。其功能丰富的平台、可扩展性、开源灵活性以及活跃的社区支持使其成为商家建立强大在线存在的首选。通过充分利用Magento的优势，商家可以打造引人入胜的在线商店，适应不断变化的市场需求，并在当今竞争激烈的电商领域蓬勃发展。</p>]]></description>
      <pubDate>Fri, 10 Nov 2023 02:54:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何启用和优化Magento的缓存功能，提升网站性能]]></title>
      <link>https://www.360magento.com/blog/how-do-i-enable-and-optimize-magento-caching/</link>
      <description><![CDATA[<p>导语：Magento的缓存功能是提高网站性能和用户体验的重要工具。本文将介绍如何启用和优化Magento的缓存功能，以加快网站加载速度并提升性能。</p>
<p>Magento是一款功能强大的电子商务平台，但由于其复杂性，网站性能可能会受到影响。启用和优化Magento的缓存功能可以缓解这个问题，并提供更快的页面加载速度和更好的用户体验。下面是一些步骤和技巧，帮助您启用和优化Magento的缓存功能。</p>
<p>1. 启用Magento的缓存功能：</p>
<p>- 登录到Magento后台管理面板。<br />- 在侧边栏菜单中，选择"商店"（Store）&gt; "设置"（Configuration）。<br />- 在左侧菜单中，找到并点击"高级"（Advanced）&gt; "系统"（System）。<br />- 在"缓存管理器"（Cache Management）部分，您将看到各种缓存类型的列表。<br />- 选择您想要启用的缓存类型，如页面缓存（Page Cache）、块缓存（Block Cache）、对象缓存（Object Cache）等。<br />- 对于每种选择的缓存类型，使用下拉菜单选择"启用"（Enable）。<br />- 点击"提交"（Submit）按钮以保存更改。</p>
<p>2. 优化Magento缓存的设置：</p>
<p>- 精细调整缓存类型：根据您的网站需求，选择启用适当的缓存类型。页面缓存（Page Cache）适用于不经常更改的页面，而块缓存（Block Cache）适用于经常重复的页面元素。对象缓存（Object Cache）则用于存储数据库查询结果。<br />- 清除缓存：在进行更改之后，务必清除缓存以确保更改生效。在Magento后台的"缓存管理器"页面中，您可以选择清除整个缓存或仅清除特定缓存类型。<br />- 定期刷新缓存：设置Magento的缓存刷新时间，以确保缓存内容始终保持最新。通过定期刷新缓存，您可以在不影响网站性能的情况下更新内容。</p>
<p>3. 配置页面缓存：</p>
<p>- 使用Varnish缓存：Varnish是一个流行的反向代理缓存服务器，可以显著提高Magento网站的性能。通过配置Magento和Varnish之间的集成，您可以实现高速的页面缓存，减少服务器负载和网络延迟。<br />- 配置CDN（内容分发网络）：使用CDN来分发Magento网站的静态资源，如图像、CSS和JavaScript文件。CDN能够将这些资源缓存在全球各地的服务器上，从而加速资源加载速度。</p>
<p>通过启用和优化Magento的缓存功能，您可以显著提高网站的性能和用户体验。确保定期清除缓存、刷新缓存并根据网站需求进行适当的缓存类型选择。结合其他性能优化策略，如压缩图像、合并CSS和JavaScript文件等，您将创建一个快速、高效的Magento网站，为访问者提供卓越的用户体验。</p>
<div id="gtx-trans" style="position: absolute; left: 32px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 09 Nov 2023 07:31:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento站点技巧和对手分析方法：提升电商竞争力的关键]]></title>
      <link>https://www.360magento.com/blog/magento-site-tips-and-adversary-analysis-methods/</link>
      <description><![CDATA[<p>导语：在竞争激烈的电商市场中，建立一个成功的Magento站点需要掌握一些关键的技巧，并且了解对手分析的方法。本文将为您介绍一些提升Magento站点竞争力的技巧，并分享有效的对手分析方法。</p>
<p>一、Magento站点技巧：</p>
<ol>
<li>
<p>优化网站速度：网站速度直接影响用户体验和搜索引擎排名。优化图片大小、使用缓存技术、压缩文件等方法可以显著提高网站的加载速度。</p>
</li>
<li>
<p>响应式设计：确保您的Magento站点具有响应式设计，能够适应不同设备的屏幕尺寸。这将提供良好的移动用户体验，并有助于提高搜索引擎排名。</p>
</li>
<li>
<p>简化结账流程：简化结账流程可减少购物车放弃率，提高转化率。通过减少步骤、提供多种支付选项和优化表单填写等方式，使结账过程更加便捷和用户友好。</p>
</li>
<li>
<p>强化产品页面：优化产品页面的布局、描述和图片，确保清晰的产品信息和吸引人的展示效果。添加用户评价和社交分享功能，增加用户参与度和信任度。</p>
</li>
<li>
<p>SEO优化：对Magento站点进行关键词研究，并在标题、描述、URL和内容中合理地应用。创建有价值的内容和外部链接，提高搜索引擎的可见性和排名。</p>
</li>
</ol>
<p>二、对手分析方法：</p>
<ol>
<li>
<p>竞争对手识别：确定您的主要竞争对手，这些对手在目标市场上与您竞争相似的产品或服务。</p>
</li>
<li>
<p>网站分析：分析竞争对手的网站结构、设计和功能。注意他们的用户体验、页面加载速度、购物流程等关键因素。</p>
</li>
<li>
<p>关键词研究：研究竞争对手在搜索引擎上的关键词排名和搜索量。确定他们的关键词策略，并找到可以与之竞争的关键词。</p>
</li>
<li>
<p>社交媒体分析：了解竞争对手在社交媒体上的活动和影响力。分析他们的社交媒体策略、受众互动和内容推广方式。</p>
</li>
<li>
<p>价格和促销策略：了解竞争对手的定价策略和促销活动。分析他们的价格优势、销售策略和客户忠诚度计划。</p>
</li>
<li>
<p>用户反馈和评价：查看竞争对手的用户反馈和评价，了解他们的优点和不足之处。从中吸取经验教训，并改进您的Magento站点。</p>
</li>
</ol>
<p>结论：</p>
<p>通过掌握Magento站点的关键技巧和对手分析方法，您可以提升电商竞争力并实现业务增长。优化网站速度、响应式设计、简化结账流程、强化产品页面和SEO优化都是提升Magento站点的关键技巧。同时，通过竞争对手的分析，您可以了解他们的策略和优势，并从中汲取经验教训。记住，持续的优化和创新是保持竞争优势的关键，将这些技巧和对手分析方法应用于您的Magento站点，将为您带来更多的成功和增长机会。</p>]]></description>
      <pubDate>Thu, 09 Nov 2023 03:47:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[关于Magento网站优化的实用技巧]]></title>
      <link>https://www.360magento.com/blog/Practical_tips_on_Magento_website_optimization/</link>
      <description><![CDATA[<p>标题：提升Magento网站性能和用户体验的实用技巧</p>
<p>导语：优化Magento网站是提高性能、加速加载时间和提升用户体验的关键。在本文中，我们将分享一些实用的技巧和建议，帮助您提升Magento网站的性能和用户体验。</p>
<p>1. 优化网站速度</p>
<p>网站速度是用户体验的重要因素。以下是一些优化网站速度的技巧：</p>
<p>- 使用缓存：启用Magento的缓存功能，包括页面缓存、块缓存和对象缓存，以减少页面加载时间。<br />- 压缩图像：使用适当的图像压缩工具来减小图像文件的大小，以加快页面加载速度。<br />- 合并和压缩CSS和JavaScript：将多个CSS和JavaScript文件合并为较少的文件，并使用压缩工具减小文件大小。<br />- 使用CDN：使用内容分发网络（CDN）来分发网站的静态资源，以加快资源加载速度。</p>
<p>2. 优化网站结构</p>
<p>优化网站结构可以提高用户体验和搜索引擎的索引能力：</p>
<p>- 优化URL结构：使用有意义的、描述性的URL，包含关键词，并避免使用过长或复杂的URL。<br />- 良好的网站导航：设计清晰的网站导航结构，使用户能够轻松浏览和导航网站的不同部分。<br />- 改善内部链接：使用相关的内部链接将页面连接起来，以提高用户体验和搜索引擎的索引能力。</p>
<p>3. 优化网站内容</p>
<p>优化网站内容有助于提高搜索引擎可见性和用户体验：</p>
<p>- 关键词研究：进行关键词研究，了解您的目标受众在搜索引擎上使用的关键词，并将其应用到网站的元标记、标题和内容中。<br />- 内容优化：编写高质量、有用且相关的内容，符合SEO最佳实践，并包含目标关键词。<br />- 使用标签和标题：为每个页面使用恰当的标题标签（H1、H2等）和页面描述，以提高搜索引擎可读性和用户体验。</p>
<p>4. 优化网站安全性</p>
<p>确保Magento网站的安全性对于保护用户数据和信任度至关重要：</p>
<p>- 更新Magento版本：及时更新Magento版本以获取最新的安全补丁和功能改进。<br />- 强密码和访问控制：使用强密码保护Magento后台，并限制对敏感文件和目录的访问权限。<br />- 使用SSL证书：为网站启用SSL证书，以加密访问并增加用户信任度。</p>
<p>5. 监控和优化</p>
<p>定期监控和优化Magento网站是持续提高性能和用户体验的关键：</p>
<p>- 网站分析：使用网站分析工具（如Google Analytics）来监控网站性能、用户行为和流量来源，以做出优化决策。<br />- 错误日志和性能监控：定期检查Magento的错误日志和性能监控工具，以寻找潜在的问题并及时解决。</p>
<p>结语</p>
<p>通过遵循这些实用技巧和建议，您可以提升Magento网站的性能、用户体验和搜索引擎可见性。记住，优化是一个持续的过程，不断监控和改进是确保网站持续优化的关键。让我们一起努力，打造出卓越的Magento网站吧！</p>]]></description>
      <pubDate>Wed, 08 Nov 2023 07:26:49 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento开发人员的实用性技巧和方案：提高效率与质量]]></title>
      <link>https://www.360magento.com/blog/practical-tips-for-magento-developers/</link>
      <description><![CDATA[<p></p>
<p>作为Magento开发人员，提高开发效率和代码质量是至关重要的。在本文中，我们将分享一些实用的技巧和方案，帮助您更高效地开发Magento站点，并提供高质量的代码和功能。</p>
<p>1. 使用代码版本控制<br />使用Git或其他代码版本控制工具来管理您的Magento项目代码。通过版本控制，您可以轻松跟踪代码更改、回滚错误和协作开发。这样可以提高代码管理和团队协作的效率。</p>
<p>2. 自定义模块开发<br />遵循Magento的模块化开发原则，将自定义功能封装为模块。这样可以保持代码的可维护性和可扩展性，并避免直接修改核心文件。模块化的开发方式使得代码修改和更新更加灵活和可控。</p>
<p>3. 使用事件和观察者<br />利用Magento的事件和观察者模式，以松耦合的方式扩展和修改Magento的功能。通过触发和监听事件，可以在不修改核心代码的情况下实现自定义逻辑。这样可以提高代码的可维护性和可扩展性。</p>
<p>4. 数据库迁移和更新<br />使用Magento的数据库迁移工具（如Magento 2的Schema和Data Patch）来管理数据库的变更和更新。这样可以跟踪和应用数据库变更，并确保在不同环境之间的一致性。数据库迁移工具可以提高开发团队的协作效率和代码质量。</p>
<p>5. 优化数据库查询<br />在编写自定义查询时，遵循Magento的最佳实践，使用索引、缓存和合理的查询语句来优化数据库查询。避免在循环中执行查询，而是尽可能使用集合操作。优化数据库查询可以提高Magento站点的性能和响应速度。</p>
<p>6. 使用代码生成器<br />Magento提供了代码生成器工具（如命令行工具和代码模板），可以加快开发速度。使用这些工具可以自动生成常见的代码结构和文件，减少手动编写的重复工作。代码生成器可以节省时间并提高代码的一致性和规范性。</p>
<p>7. 测试和调试<br />编写单元测试和集成测试来验证您的代码的正确性。使用调试工具和日志记录来排查和解决问题。通过测试和调试，可以提高代码的质量和稳定性，减少潜在的错误和问题。</p>
<p>8. 安全性和性能优化<br />遵循Magento的安全性和性能优化指南，确保您的代码和配置符合最佳实践。保护网站免受潜在的安全漏洞，并实施性能优化措施，如缓存、CDN集成和代码优化。安全性和性能优化是确保Magento站点稳定和高效运行的关键。</p>
<p>9. 持续集成和部署<br />使用自动化工具和流程来实现持续集成和部署。通过自动构建、测试和部署代码，可以减少人工操作和减少错误。持续集成和部署可以提高开发团队的效率和代码交付的质量。</p>
<p>总结:<br />通过应用这些实用的技巧和方案，您可以提高Magento开发的效率和质量。代码版本控制、模块化开发、事件和观察者模式、数据库迁移、优化查询、代码生成器、测试和调试、安全性和性能优化，以及持续集成和部署等方法都能帮助您更好地管理和开发Magento站点。这些实践将帮助您节省时间、减少错误，并提供稳定高效的Magento站点。始终记住，不断学习和探索新的技术和最佳实践，以跟上Magento的发展和提高您的开发技能。祝您在Magento开发中取得成功！</p>
<div id="gtx-trans" style="position: absolute; left: -12px; top: 584px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 08 Nov 2023 03:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[选择Magento作为您的电子商务网站:优势和好处]]></title>
      <link>https://www.360magento.com/blog/choosing-magento-for-your-ecommerce-website/</link>
      <description><![CDATA[<h2><span>了解 Magento</span></h2>
<p><span><span><span><span>Magento</span></span></span><span><span>是一个功能强大且功能丰富的开源</span></span><span><span>电子商务平台</span></span><span><span>，使企业能够创建和管理在线商店。</span><span>它提供了一个灵活且可定制的框架，用于构建具有许多特性和功能的电子商务网站。&nbsp;</span></span></span></p>
<p><span><span><span>Magento采用</span></span><span><span>PHP</span></span><span><span>开发，提供可伸缩性、可扩展性以及丰富的插件和主题生态系统，使其成为各种规模的企业建立和发展在线业务的热门选择。</span></span></span></p>
<p><span><span><span>Magento 的两个版本是</span></span><span><span>Magento Open Source</span></span><span><span>和</span></span><span><span>Magento Commerce</span></span><span><span>。</span><span>这些版本满足不同的需求和业务要求，提供不同级别的功能、支持、可扩展性等。</span></span></span></p>
<h2><span>Magento 开源与 Magento 商务</span></h2>
<h4><span>Magento 开源&nbsp;</span></h4>
<p><span><span><span>Magento 开源提供强大的电子商务功能，包括产品目录管理、购物车功能、结帐选项、支付网关集成、SEO 优化等。</span><span>它还支持多商店和多语言功能，适合中小型企业。</span></span></span></p>
<h4><span>Magento 商务&nbsp;</span></h4>
<p><span><span><span>Magento Commerce 包含 Magento 开源的所有功能。</span><span>尽管如此，它还引入了先进的功能，例如个性化购物体验、客户细分、先进的营销工具、B2B 商务功能、增强的搜索功能等等。</span><span>这些功能旨在满足具有更复杂电子商务需求的大型企业。</span></span></span></p>
<h4><span>Magento 开源</span></h4>
<p><span>作为一个开源版本，Magento 开源受益于提供支持、扩展和更新的开发人员和贡献者社区。</span></p>
<h4><span>Magento 商务</span></h4>
<p><span><span><span>Magento Commerce 提供专门的技术支持、安全更新和性能优化。</span><span>对于需要在线商店保持一致的正常运行时间和可靠性的企业来说，这种级别的支持非常重要。</span></span></span></p>
<p><span><span><span><span>当您</span></span></span><span><span>看到 Magento Open sourse 和 Magento Commerce 之间的根本区别时，您可以选择最适合您的需求、预算和增长愿望的版本。&nbsp;</span></span></span></p>
<p><span>但是，如果您对哪个版本适合您的业务感到困惑，您可以从</span>Magento 开发公司<span><span><span>获得帮助。</span><span>他们将分析您的业务和您的需求。</span><span>之后，他们会建议最合适的选择。</span></span><a href="https://www.pixlogix.com/hire-certified-magento-developers-in-india/" rel="noopener" target="_blank"><span><span></span></span></a><span><span>可以节省大量资源和时间。&nbsp;</span></span></span></p>
<p><span><span><span>选择合适的公司后，您可以从他们那里获得高度可定制和可扩展的电子商务商店。</span></span><span><span>因此，如果您对Magento 版本</span></span><span><span>感到困惑</span><span>，请向他们寻求帮助。</span></span></span></p>
<p><span>此外，让我们看看使用两个版本的 Magento 电子商务网站构建器框架为您的企业带来的好处。&nbsp;</span></p>
<h2><span>Magento 的优点：-</span></h2>
<p><span>以下是使用 Magento 框架为像您这样的企业开发电子商务商店的一些主要好处。&nbsp;</span></p>
<h3><span>#1：可扩展性&nbsp;</span></h3>
<p><span><span><span>可扩展性对于确保在线商店能够容纳不断增长的客户、产品和交易而不会减慢或崩溃至关重要。</span><span>凭借其可扩展的架构和性能优化功能，Magento 能够很好地处理大型产品目录和高流量网站。</span></span></span></p>
<p><span><span><span>它支持批量产品导入、可配置产品和分层导航等功能，使企业能够有效地管理和展示广泛的产品范围。</span><span>其缓存机制和优化技术也确保即使在流量高峰期也能保证流畅的用户体验。</span></span></span></p>
<p><span><span><span>Magento 采用模块化和分层架构，将不同的组件和功能分开。</span><span>这使得企业能够根据需要扩展系统的各个部分，例如数据库服务器、应用程序服务器和缓存机制。</span></span></span></p>
<p><span>此外，它还支持多种缓存机制，例如全页缓存和对象缓存，可显着提高网站性能并减少服务器负载，使平台能够处理更高的流量。</span></p>
<h3><span>#2：灵活性</span></h3>
<p><span><span><span>Magento 提供了大量的自定义选项。</span><span>您可以修改前端设计、创建自定义主题并实施独特的功能，以使在线商店与其品牌标识和客户期望保持一致。</span></span></span></p>
<p><span><span><span><span>扩展：-</span></span></span><span><span>&nbsp;Magento 市场提供了广泛的</span></span><span><span>扩展</span></span><span><span>和插件，可以集成到平台中以增强功能。</span><span>这些扩展涵盖了支付网关、运输方式、营销工具等领域。</span></span></span></p>
<p><span><span><span>此外，Magento 支持 API 和集成框架，允许与 ERP、CRM 和库存管理工具等第三方系统无缝连接。</span><span>这使企业能够构建定制的工作流程并自动化各种流程。</span></span></span></p>
<p><span><span><span>Magento 的架构允许在单个安装中创建多个商店。</span><span>这对于管理多个品牌或迎合不同市场的企业来说是有益的，因为它可以集中管理，同时允许每个商店拥有独特的品牌和产品分类。</span></span></span></p>
<h3><span>#3：广泛的功能</span></h3>
<p><span><span><span>Magento 提供了一组广泛的内置功能，使电子商务企业能够创建全面且功能丰富的在线商店。</span><span>这些功能涵盖电子商务生命周期的各个方面。&nbsp;</span></span></span></p>
<p><span><span><span><span>例如</span></span></span><span><span>，产品管理有助于管理产品属性、变体、自定义选项、产品详细信息、图像、类别、折扣和特别优惠。</span><span>其次，库存控制功能提供了实时监控和管理库存水平、处理低库存产品通知、延期交货和库存产品以及仓库管理系统的灵活性。</span></span></span></p>
<p><span><span></span><span><span><span>管理中的订单处理</span></span></span><span><span>功能</span><span>也使订单处理和管理更加有效。</span><span>借助 Magento，电子商务商店所有者可以增强客户体验。</span><span>您可以提供个性化的购物体验，另外实施具有保存的地址和订单历史记录的用户帐户，启用访客结账或注册选项等。</span></span></span></p>
<p><span><span></span><span><span>此外，庞大的第三方扩展</span></span><span><span>和主题市场丰富了 Magento 的生态系统</span><span>。</span><span>这些扩展可以轻松集成到平台中，以增强功能并提高在线商店的美观度。</span></span></span></p>
<h3><span>#4：移动响应式设计</span></h3>
<p><span><span><span>越来越多的消费者使用移动设备在线浏览和购物。</span><span>移动设备已成为许多人访问互联网的主要方式。</span></span></span></p>
<p><span><span><span>移动响应式设计可确保网站或在线商店在各种设备和屏幕尺寸（包括智能手机、平板电脑和台式机）上正确显示和运行。</span><span>Magento 非常重视移动响应式设计，为用户提供无缝的购物体验，无论他们使用什么设备。</span></span></span></p>
<p><span><span><span>Magento 提供固有的移动响应式设计功能，使在线商店能够适应不同的屏幕尺寸和方向。</span><span>Magento 移动响应式设计的一些关键功能包括灵活的布局、触摸友好的界面、优化的图像、响应式菜单、用户友好的表单和性能优化。&nbsp;</span></span></span></p>
<h3><span>#5：SEO 友好</span></h3>
<p><span>Magento的架构和功能旨在支持SEO，确保在该平台上构建的在线商店可以轻松地被搜索引擎发现，并在搜索结果中获得更高的排名。</span></p>
<p><span><span><span>Magento 的代码库结构良好并遵循最佳实践，使搜索引擎机器人可以更轻松地导航和索引网站内容。</span><span>它允许用户为产品页面、类别和内容页面创建 SEO 友好的 URL。</span><span>这些 URL 可以定制为用户可读且搜索引擎友好的。</span><span>此外，它还提供产品和页面自定义过程的简单元标题和元描述，以便您可以在搜索引擎结果中创建相关片段。</span></span></span></p>
<p><span><span><span>此外，Magento 的架构和功能在设计时考虑了 SEO，为企业提供了创建 SEO 友好的在线商店所需的工具和实践。</span><span>利用 Magento 的功能并实施有效的 SEO 策略最终会提高转化率和销售额。</span></span></span></p>
<h3><span>#6：多语言和多货币支持</span></h3>
<p><span><span><span>全球市场提供的客户群比单一国内市场大得多。</span><span>针对来自不同国家的客户可以让企业开拓新的收入来源并最大限度地发挥其增长潜力。</span></span></span></p>
<p><span><span><span>Magento 的国际化能力使企业能够通过提供多语言内容和多货币选项来瞄准全球受众。</span><span>该功能集对于旨在扩大业务范围和服务客户​​的电子商务企业来说非常宝贵。&nbsp;</span></span></span></p>
<p><span><span><span>使用 Magento，您可以创建多个商店视图，每个视图都有其相关的语言、内容和产品信息。</span><span>借助 Milt 货币支持，Magento 使客户能够查看产品价格并以当地货币完成交易。</span><span>兑换率可以手动设置或与实时汇率数据集成，以确保为国际客户提供准确的定价。</span></span></span></p>
<h3><span>#7：强大的安全性</span></h3>
<p><span><span><span>Magento 非常重视</span></span><span><span>安全性</span></span><span><span>，以确保保护客户数据、敏感信息和在线交易。</span><span>它与各种安全支付网关集成，确保客户支付数据在交易过程中得到加密和安全传输。</span></span></span></p>
<p><span><span><span>通过 PCI DSS 和数据加密，它可以保护电子商务商店的内部数据。</span><span>强大的用户身份验证机制（包括密码策略和多因素身份验证）有助于防止未经授权访问管理面板和客户帐户。</span></span></span></p>
<p><span><span><span>Magento 定期发布安全补丁和更新以解决已知漏洞。</span><span>我们鼓励商家及时应用这些更新，以保护他们的商店。</span></span></span></p>
<p><span>除此之外，扩展安全、管理安全、监控和入侵检测使像您这样的在线商家更加安全。</span></p>
<h3><span>#8：社区支持</span></h3>
<p><span><span><span>Magento 社区由开发人员、设计师、商人和爱好者组成，他们积极参与讨论、论坛和知识共享平台。</span><span>社区成员提供协助、分享最佳实践并解决问题，使商家更轻松地找到解决方案并优化他们的商店。</span></span></span></p>
<p><span><span><span>Magento 社区论坛等平台使用户能够发布问题、寻求建议和分享经验。</span><span>经验丰富的社区成员经常提供有价值的见解和解决方案。</span><span>社区成员经常创建教程、指南和文章来帮助其他人理解和掌握该平台的不同方面。</span></span></span></p>
<p><span><span><span>此外，许多第三方开发人员向 Magento Marketplace 贡献免费和付费扩展和主题，扩展了该平台的功能和自定义选项。</span><span>此外，Magento 社区成员还组织活动、会议和聚会，以促进交流、学习和协作。</span></span></span></p>
<p><span></span></p>]]></description>
      <pubDate>Tue, 07 Nov 2023 08:37:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 产品推荐：优点和技巧]]></title>
      <link>https://www.360magento.com/blog/magento-product-recommendations/</link>
      <description><![CDATA[<h2 id="what-are-magento-product-recommendations">Magento 产品推荐是什么？</h2>
<p>Magento 产品推荐是一个帮助在目录中的产品页面上显示相关产品的工具。它们可以与某个商品相关，或者只是与它一起购买，这会产生相当诱人的报价。</p>
<p>因此，这些建议会促使您的客户购买更多产品并探索更多产品。鉴于您将某些产品放在客户眼前，这也可能会导致冲动购买。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/QQ20231106-114450_2x.png" /></p>
<p><span><span>借助 Magento 产品推荐引擎，一个产品页面可以包含多个项目。</span><span>相应地，这会给您带来许多好处。</span></span></p>
<h2 id="benefits-of-product-recommendations"><span>产品推荐的好处</span></h2>
<p><span><span>由于我们已经知道 Magento 2 产品推荐是什么，因此了解这些产品块如何使您的商店受益是合乎逻辑的。</span><span>那么，让我们来看看此功能的一些主要优点。</span></span></p>
<h3 class="notoc"><span>1.平均订单价值（AOV）的增加</span></h3>
<p><span><span>精心挑选的产品推荐巧妙地鼓励您的客户购买更多产品。</span><span>因此，当顾客购买额外的商品以及他们打算购买的商品时，订单总数就会增加。</span><span>如果该策略运行得足够好，您可以看到平均订单价值整体上的增长。</span></span></p>
<h3 class="notoc"><span>2. 销售和转化率改善</span></h3>
<p><span><span>从长远来看，AOV 的增加会带来销售额和转化率的提高。</span><span>客户可以使用更多商品，从而浏览您的网站并更多地与您的商店互动。</span><span>因此，您有机会降低购物车放弃率，并将闲置访客转变为买家。&nbsp;</span></span></p>
<h3 class="notoc"><span>3.交叉销售和追加销售</span></h3>
<p><span><span>每家商店都有一个比其他商店表现更好的产品。</span><span>可悲的是，仍然有一些商品卖得不好。</span><span>Magento 2 产品推荐可以完美地消除此类情况。</span><span>它们可以让您推广表现较差的产品，并让它们更容易被发现。</span></span></p>
<h3 class="notoc"><span>4. 增强客户体验</span></h3>
<p><span><span>最后，使用产品推荐对您和您的客户都有好处。</span><span>如果你能满足客户的需求，他们在做出选择时可能会感到更自由。</span><span>因此，您可以通过适量的个性化营销活动极大地改善客户的体验。</span></span></p>]]></description>
      <pubDate>Mon, 06 Nov 2023 07:42:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置联系我们表单的电子邮件 ID]]></title>
      <link>https://www.360magento.com/blog/setup-email-id-for-contact-us-form-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Enable_Magento_2_Contact_Us_Form">启用 Magento 2 联系我们表格的步骤</span></h2>
<p><span>第1步：</span><span>登录您的商店后台并进入管理面板，选择</span><span>商店 &gt; 设置 &gt; 配置</span></p>
<p><span>步骤 2：</span><span>展开</span><span>配置</span><span>并选择&nbsp;&nbsp;</span><span><span><span>常规部分</span></span><span><span>下的</span></span></span><span>联系人</span><span><span><span>。</span></span><span><span>然后转到</span></span><span><span>联系我们</span></span><span><span>设置。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/QQ20231103-101722_2x.png" /></span></p>
<p><span>步骤 3：</span><span><span><span>确保取消选中&ldquo;使用系统值&rdquo;。</span><span>默认情况下，要</span></span></span><span>启用&ldquo;联系我们&rdquo;，</span><span>该值将为&ldquo;是&rdquo;以激活联系我们线路。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Enable-Contact-Us-opotion-for-store-view.png" /></span></p>
<p><span>步骤 4：</span><span>转到</span><span>电子邮件选项</span><span>部分。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Email-Options-for-sender.png" /></span></p>
<ul>
<li><span>发送电子邮件至</span><span>：您需要在此处输入管理员电子邮件或您希望接收联系我们查询的电子邮件。</span></li>
<li><span>电子邮件发件人：</span><span>选择您希望看到的商店发件人作为电子邮件发件人。</span></li>
</ul>
<ul>
<li><span>电子邮件模板：</span><span>从现有模板中选择电子邮件模板，或从下拉菜单中选择默认模板选项。</span></li>
</ul>]]></description>
      <pubDate>Sun, 05 Nov 2023 07:16:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 的发票、发货和贷项凭证 PDF 中显示/隐藏订单 ID]]></title>
      <link>https://www.360magento.com/blog/show-hide-order-id-in-invoice-shipment-credit-memo-pdf-of-magento-2/</link>
      <description><![CDATA[<p><span><span>众所周知，Magento 是构建电子商务网站的强大 CMS 之一。</span><span>它提供了许多预加载的功能，为此，您无需编写一行代码，只需在 Magento 2 后端中设置一些配置即可启用这些功能。</span></span><br /><span><span>很多时候，当您的客户在您的 Magento 2 商店下订单时，他们会收到大量附有订单电子邮件的文档。</span><span>到时候他们就很难找到哪个文档与哪个订单相关了？</span><span>原因 Magento 不会在 Magento 2 的发票、发货和贷项凭证 PDF 标题的顶部显示订单 ID。这可能会让您的客户感到困惑。</span><span>但是，您可以在上述所有 Magento 生成的文档上显示订单 ID，而无需编写任何代码。</span><span>想知道如何正确？</span><span>嗯，Magento 2 后端预加载了一个配置，您只需启用它就可以了！</span></span></p>
<p><span>转到&nbsp;<span>Store &ndash;&gt; Configuration -&gt; Sales &ndash;&gt; PDF Printouts</span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/PDF-Printouts-Backend-Settings.png" /></span></p>
<p><span>默认情况下，所有这些配置都设置为&ldquo;是&rdquo;，但如果您想隐藏订单 ID，只需从下拉列表中选择&ldquo;否&rdquo;将其关闭。</span></p>]]></description>
      <pubDate>Sat, 04 Nov 2023 08:10:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[什么是基础货币以及如何在 Magento 2 中设置货币选项]]></title>
      <link>https://www.360magento.com/blog/what-is-base-currency-and-how-to-set-currency-options-in-your-magento/</link>
      <description><![CDATA[<p>电子商务是增长最快的技术型业务，许多成熟企业正在走向全球。因此，在向其他国家推出之前设置货币设置已成为每个电子商务商店的首要任务。</p>
<p>Magento 2 作为电子商务平台在世界各地广泛使用。它具有默认功能，可以为全球多达 200 个国家/地区设置货币。您可以设置要在产品价格、订单和发票中显示的货币符号。管理员可以自定义货币符号的外观。</p>
<p>将会有来自不同国家的商家利用 Magento 的力量来建立他们的电子商务商店。商家来自不同的国家，因此您可能需要当地货币作为主要货币，如果您不从事国际业务，则您的商店必须只需要启用当地货币。</p>
<p>如果您从事国际业务，那么您可能已经在 Magento 2 商店中设置了多网站或多商店视图，以使您的商店全球化。在这种情况下，您需要设置不同国家/地区的货币，例如，对于印度，您需要 INR，对于英国，您可以启用 GBP，对于美国和世界其他地区，假设您想要美国。所有这些都可以使用默认的 Magento 功能进行配置，甚至无需一行代码。</p>
<p>导航到<span>Store &gt;Configuration &gt;General &gt;Currency Setup &gt;Currency Options</span><span>,</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/currency-options.png" /></p>
<p><span>基础货币：</span><span><span>基础货币用于所有在线支付交易。</span><span>基础货币范围由目录价格范围定义（&ldquo;目录&rdquo;&gt;&ldquo;价格&rdquo;&gt;&ldquo;目录价格范围&rdquo;）。</span></span></p>
<p><span>默认显示货币：</span><span><span>默认显示货币是您要为商店设置的默认货币，如果您的商店仅限于您所在的国家/地区，则您可以设置自己的货币并保存。</span><span>例如，对于印度商店，我们将在此字段中选择印度卢比。</span></span></p>
<p>如果您有国际业务、多商店视图或多网站设置，则需要根据商店选择相应的货币。例如，印度商店为印度卢比，英国商店为英镑，美国和世界其他地区为美元。</p>
<p>允许的货币：当您开展国际业务并在全球范围内销售产品时，您将需要提供多种货币可供选择。如果客户有能力更改货币，他将获得更多信任，或者您可以允许全球接受的货币，例如美元和英镑。</p>
<p>无论您在此处选择哪种货币，这些货币都将在前端可供客户选择。在下面的示例中，我启用了美元和欧元。</p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/default-welcome-msg.png" /></span></span></p>]]></description>
      <pubDate>Fri, 03 Nov 2023 07:06:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更改 Magento 2 中的 Favicon 图像]]></title>
      <link>https://www.360magento.com/blog/how-to-change-the-favicon-image-in-magento-2/</link>
      <description><![CDATA[<p><span><span>今天，我们将学习如何更改默认 Magento 2 中的 favicon（图标）。我不需要告诉你太多关于 favicon 是什么，但如果我必须简短介绍它，那么让我告诉你它就是与站点标题一起出现在浏览器选项卡顶部的图标。</span><span>在某些浏览器中，它还可能出现在 URL 旁边。</span></span></p>
<p><span><span>它本质上代表了您的网站，因此根据您的需要设置或更改网站图标非常重要。</span><span>一些网络服务和搜索引擎也可能使用该图标。</span><span>默认情况下，Magento 有很多功能可供您使用。</span><span>这个简单的教程将帮助您如何自行更改网站图标。</span><span>Favicon 图标的大小应为 12 x 12 或 32 x 32。</span><span>它应该是 .ico 格式。</span></span></p>
<p><span>按照下面描述的步骤更改 Magento 2 商店的图标。</span></p>
<ol>
<li><span>登录到您的管理面板</span></li>
<li><span><span>选择菜单Content&nbsp;</span><span>&rarr;</span><span>&nbsp;Configuration&nbsp;</span><span>&rarr;</span><span>&nbsp;Select Your Theme&nbsp;</span><span>&rarr;</span><span>&nbsp;Edit<br /><img src="https://www.360magento.com/media/wysiwyg/change_fevicon_in_magento_2.png" /><br /></span></span></li>
<li><span><span><span>找到 HTML Head 部分<br /><img src="https://www.360magento.com/media/wysiwyg/upload_fevicon_in_magento_2.png" /><br /></span></span></span></li>
<li>您将看到一个上传图标的选项，点击上传并在此处上传您的图标。</li>
<li><span>保存配置</span></li>
</ol>]]></description>
      <pubDate>Thu, 02 Nov 2023 07:45:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中按产品 ID 和 SKU 加载产品？]]></title>
      <link>https://www.360magento.com/blog/load-products-by-id-and-sku-in-magento/</link>
      <description><![CDATA[<p><span>如何借助 Magento 推荐的一些简单代码从产品 ID 和 SKU 加载产品。</span></p>
<p><span>让我们首先看看如何从产品 ID 加载产品。</span></p>
<p><span>方法 &ndash; 1：</span><span>&nbsp;Magento 不推荐使用这种简短的方法，因此我们也不使用。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321b9227639086604729" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227639086604729-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227639086604729-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227639086604729-3">3</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227639086604729-1"><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-cn">32</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227639086604729-2"><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Framework</span><span class="crayon-sy">\</span><span class="crayon-v">App</span><span class="crayon-sy">\</span><span class="crayon-v">ObjectManager</span><span class="crayon-o">::</span><span class="crayon-e">getInstance</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227639086604729-3"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-s">'Magento\Catalog\Api\ProductRepositoryInterface'</span><span class="crayon-sy">)</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getById</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>方法 - 2：</span><span>当您需要产品信息时，Magento 强烈推荐使用此方法。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321b9227650167612899" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-16">16</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-17">17</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-18">18</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227650167612899-19">19</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-1"><span class="crayon-o">&lt;</span><span class="crayon-sy">?</span><span class="crayon-e">php</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-2"><span class="crayon-t">namespace</span><span class="crayon-h"> </span><span class="crayon-v">Vendor</span><span class="crayon-sy">\</span><span class="crayon-v">Extension</span><span class="crayon-sy">\</span><span class="crayon-v">Block</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-3">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-4"><span class="crayon-t">class</span><span class="crayon-h"> </span><span class="crayon-e">Product</span><span class="crayon-h"> </span><span class="crayon-r">extends</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-e">Magento</span><span class="crayon-sy">\</span><span class="crayon-e">Framework</span><span class="crayon-sy">\</span><span class="crayon-e">View</span><span class="crayon-sy">\</span><span class="crayon-e">Element</span><span class="crayon-sy">\</span><span class="crayon-e">Template</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-5"><span class="crayon-sy">{</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-6"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">protected</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span><span class="crayon-h">&nbsp;&nbsp;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-7">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-8"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">__construct</span><span class="crayon-sy">(</span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Catalog</span><span class="crayon-sy">\</span><span class="crayon-v">Api</span><span class="crayon-sy">\</span><span class="crayon-i">ProductRepositoryInterface</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-9"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-10"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-11">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-12"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">getProductDataUsingId</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-13"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-st">return</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getById</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-14"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-15"><span class="crayon-sy">}</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-16">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-17"><span class="crayon-e">PHTML </span><span class="crayon-e">file </span><span class="crayon-v">code</span><span class="crayon-sy">,</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227650167612899-18"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">block</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getProductDataUsingId</span><span class="crayon-sy">(</span><span class="crayon-cn">32</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227650167612899-19"><span class="crayon-i">echo</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getName</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>现在，我们来看看如何按产品SKU加载产品。</span></p>
<p><span>方法 &ndash; 1：</span><span>&nbsp;Magento 不推荐使用这种简短的方法，因此我们也不使用。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321b9227652368748903" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227652368748903-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227652368748903-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227652368748903-3">3</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227652368748903-1"><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-s">"productsku"</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227652368748903-2"><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Framework</span><span class="crayon-sy">\</span><span class="crayon-v">App</span><span class="crayon-sy">\</span><span class="crayon-v">ObjectManager</span><span class="crayon-o">::</span><span class="crayon-e">getInstance</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227652368748903-3"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-s">'Magento\Catalog\Api\ProductRepositoryInterface'</span><span class="crayon-sy">)</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>方法 - 2：</span><span>当您需要产品信息时，Magento 强烈推荐使用此方法。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321b9227654818005108" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-16">16</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-17">17</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-18">18</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-19">19</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321b9227654818005108-20">20</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-1"><span class="crayon-o">&lt;</span><span class="crayon-sy">?</span><span class="crayon-e">php </span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-2"><span class="crayon-t">namespace</span><span class="crayon-h"> </span><span class="crayon-v">Vendor</span><span class="crayon-sy">\</span><span class="crayon-v">Extension</span><span class="crayon-sy">\</span><span class="crayon-v">Block</span><span class="crayon-sy">;</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-3">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-4"><span class="crayon-t">class</span><span class="crayon-h"> </span><span class="crayon-e">Product</span><span class="crayon-h"> </span><span class="crayon-r">extends</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-e">Magento</span><span class="crayon-sy">\</span><span class="crayon-e">Framework</span><span class="crayon-sy">\</span><span class="crayon-e">View</span><span class="crayon-sy">\</span><span class="crayon-e">Element</span><span class="crayon-sy">\</span><span class="crayon-e">Template</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-5"><span class="crayon-sy">{</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-6"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">protected</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-7">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-8"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">__construct</span><span class="crayon-sy">(</span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Catalog</span><span class="crayon-sy">\</span><span class="crayon-v">Api</span><span class="crayon-sy">\</span><span class="crayon-i">ProductRepositoryInterface</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-9"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-10"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-11">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-12"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">getProductDataUsingSku</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-13"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-st">return</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-14"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-15"><span class="crayon-sy">}</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-16">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-17">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-18"><span class="crayon-e">PHTML </span><span class="crayon-e">file </span><span class="crayon-v">code</span><span class="crayon-sy">,</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321b9227654818005108-19"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">block</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getProductDataUsingSku</span><span class="crayon-sy">(</span>&ldquo;<span class="crayon-i">productsku</span>&rdquo;<span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321b9227654818005108-20"><span class="crayon-i">echo</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getName</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span><span>所以，现在就这样了。</span><span>使用这些代码，您将能够按 ID 或 SKU 加载产品信息。</span><span><br /></span></span></p>]]></description>
      <pubDate>Wed, 01 Nov 2023 07:44:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何删除 Magento 2 中不必要的客户帐户链接]]></title>
      <link>https://www.360magento.com/blog/remove-customer-account-navigation-links-magento-2/</link>
      <description><![CDATA[<h2><span id="How_to_remove_unnecessary_customer_account_links_in_Magento_2">如何删除 Magento 2 中不必要的客户帐户链接</span></h2>
<p>Magento 默认情况下会在客户帐户页面上显示大量客户帐户链接列表。如果您的业务与其他业务不同，并且不支持新闻通讯订阅，那么在客户帐户页面显示的链接列表中就没有必要。而且很多时候需要自定义所有默认链接，因为对于客户帐户页面上显示的所有链接没有具体要求。有一些要求可以删除一些对客户来说不必要的链接。</p>
<p><span>在下面的客户帐户屏幕上显示 Magento 2 默认提供的链接列表：&nbsp;</span></p>
<ul>
<li><span>My Orders</span></li>
<li><span>My Downloadable Products</span></li>
<li><span>Account Dashboard</span></li>
<li><span>Newsletter Subscriptions</span></li>
<li><span>Stored Payment Methods</span></li>
<li><span>Address Book</span></li>
<li><span>Account Information</span></li>
<li><span>Billing Agreements</span></li>
<li><span>My Wish List</span></li>
<li><span>My Product Reviews<br /><br /></span></li>
</ul>
<h2><span id="Steps_to_How_to_remove_navigational_links">如何删除导航链接的步骤</span></h2>
<p><span>第 1 步：首先，创建自定义扩展或主题并覆盖客户布局文件</span></p>
<p><span>创建扩展并覆盖布局 XML 文件</span></p>
<p><span><span>app/design/frontend/</span>[命名空间]/[主题]/Magento_Customer/layout/customer_account.xml</span></p>
<p><span>第 2 步：使用标签从我的帐户中删除任何额外的链接。</span></p>
<p>&nbsp; &nbsp;&lt;!-- Remove unwanted account navigation links --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Put this file in: app/design/frontend/[Namespace]/[Theme]/Magento_Customer/layout/customer_account.xml --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Store credit --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-customer-balance-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Downloadable product link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-downloadable-products-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Subscription link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-newsletter-subscriptions-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Billing agreement link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-billing-agreements-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Product review link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-product-reviews-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- My credit card link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-my-credit-cards-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Account link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-account-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Account edit link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-account-edit-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Address link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-address-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Orders link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-orders-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Wish list link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-wish-list-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Gift card link --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-gift-card-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Order by SKU --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-checkout-sku-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Gift registry --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-giftregistry-link" remove="true"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;!-- Reward points --&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="customer-account-navigation-reward-link" remove="true"/&gt;</p>
<p></p>
<p><span>第 3 步：现在，只需清除缓存并验证&ldquo;我的帐户&rdquo;页面上的链接将被删除。</span></p>]]></description>
      <pubDate>Tue, 31 Oct 2023 07:45:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中安装主题]]></title>
      <link>https://www.360magento.com/blog/install-theme-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Install_Theme_In_Magento_2">在 Magento 2 中配置安装主题的步骤：</span></h2>
<h3><span id="Download_the_Theme">下载主题</span></h3>
<p><span><span><span>下载您选择的 Magento 2 主题，该主题将以压缩形式提供。</span><span>下载主题后，请解压下载的主题，您将得到两个文件夹，即 App 和 Pub。</span></span></span></p>
<h3><span id="Upload_the_Theme">上传主题</span></h3>
<p><span>完成上述步骤后，只需导航到您的商店并将 App 和 Pub 文件夹上传到 Magento 2 商店的根目录。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/image_2020_04_14T13_13_05_540Z.png" /></span></p>
<p><span><span><span></span></span></span></p>
<p><span><span><span></span></span></span></p>
<h3><span id="Run_Commands">运行命令</span></h3>
<p><span>现在，使用 SSH 连接您的 Magento 2 商店并导航到 Magento 2 商店的根目录。</span></p>
<p><span>然后运行以下给出的升级命令：</span></p>
<p><span>php bin/magento setup:upgrade</span></p>
<p><span>执行上述步骤后，运行以下给出的命令来部署静态内容：</span></p>
<p><span><span>php bin/magento setup:static-content:deploy</span><br /></span></p>
<h3><span id="Apply_the_Theme">应用主题</span></h3>
<p><span>现在，转到管理面板并导航到<span>Content &rarr; Configuration&nbsp;</span>，如下面的屏幕截图所示。</span></p>
<p><span>现在单击编辑按钮，如下面的屏幕截图所示</span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/Apply-theme-to-magento-2.png" /></span></span></span></p>
<p><span><span><span><span>从下拉列表中选择您上传的主题，然后单击保存配置，如下面的屏幕截图所示。</span></span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/click-to-edit-for-install-theme-in-magento-2.png" />&nbsp;</span></span></span></p>
<p><span><span><span><span>从下拉列表中选择您上传的主题，然后单击保存配置，如下面的屏幕截图所示。</span></span></span></span></p>
<p></p>
<p><img src="https://www.360magento.com/media/wysiwyg/save-configuration-to-install-theme-in-magento-2.png" /></p>
<p><span>执行完上述简单步骤后，您可以访问应用主题的网站。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Mon, 30 Oct 2023 07:38:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何解决Magento 2 索引过程中的问题]]></title>
      <link>https://www.360magento.com/blog/unlock-reindex-process-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Unlock_Reindex_Process_in_Magento_2">在 Magento 2 中重新索引的步骤：</span></h2>
<h3><span id="Step_1_Reindex_when_Index_is_Locked">第 1 步：索引锁定时重新索引</span></h3>
<p><span>运行以下命令来重新索引：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed95a753269457" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed95a753269457-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed95a753269457-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">reindex</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>您会发现库存流程被跳过，如下所示</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed961780411970" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed961780411970-10">10</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-1"><span class="crayon-e">Design </span><span class="crayon-e">Config </span><span class="crayon-e">Grid </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">04</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-2"><span class="crayon-e">Customer </span><span class="crayon-e">Grid </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">06</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-3"><span class="crayon-e">Category </span><span class="crayon-e">Products </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">02</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-4"><span class="crayon-e">Product </span><span class="crayon-e">Categories </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-5"><span class="crayon-e">Product </span><span class="crayon-e">Price </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">01</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-6"><span class="crayon-e">Product </span><span class="crayon-e">EAV </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-7"><span class="crayon-e">Catalog </span><span class="crayon-e">Search </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">04</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-8"><span class="crayon-e">Stock </span><span class="crayon-e">index </span><span class="crayon-st">is</span><span class="crayon-h"> </span><span class="crayon-e">locked </span><span class="crayon-e">by </span><span class="crayon-e">another </span><span class="crayon-e">reindex </span><span class="crayon-v">process</span><span class="crayon-sy">.</span><span class="crayon-h"> </span><span class="crayon-v">Skipping</span><span class="crayon-sy">.</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-9"><span class="crayon-e">Catalog </span><span class="crayon-e">Rule </span><span class="crayon-e">Product </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed961780411970-10"><span class="crayon-e">Catalog </span><span class="crayon-e">Product </span><span class="crayon-e">Rule </span><span class="crayon-e">index </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-e">rebuilt </span><span class="crayon-e">successfully </span><span class="crayon-st">in</span><span class="crayon-h"> </span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span><span class="crayon-o">:</span><span class="crayon-cn">00</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p></p>
<h3><span id="Step_2_Get_Index_Types_Info">第 2 步：获取索引类型信息</span></h3>
<p><span>首先，您必须查看 Magento 2 的索引类型列表，然后运行以下命令：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed963004878639" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed963004878639-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed963004878639-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">info</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行该命令后，您将得到以下输出：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed964735073337" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed964735073337-10">10</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-1"><span class="crayon-e">design_config_grid </span><span class="crayon-e">Design </span><span class="crayon-e">Config </span><span class="crayon-e">Grid</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-2"><span class="crayon-e">customer_grid </span><span class="crayon-e">Customer </span><span class="crayon-e">Grid</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-3"><span class="crayon-e">catalog_category_product </span><span class="crayon-e">Category </span><span class="crayon-e">Products</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-4"><span class="crayon-e">catalog_product_category </span><span class="crayon-e">Product </span><span class="crayon-e">Categories</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-5"><span class="crayon-e">catalog_product_price </span><span class="crayon-e">Product </span><span class="crayon-e">Price</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-6"><span class="crayon-e">catalog_product_attribute </span><span class="crayon-e">Product </span><span class="crayon-e">EAV</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-7"><span class="crayon-e">catalogsearch_fulltext </span><span class="crayon-e">Catalog </span><span class="crayon-e">Search</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-8"><span class="crayon-e">cataloginventory_stock </span><span class="crayon-e">Stock</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-9"><span class="crayon-e">catalogrule_rule </span><span class="crayon-e">Catalog </span><span class="crayon-e">Rule </span><span class="crayon-e">Product</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed964735073337-10"><span class="crayon-e">catalogrule_product </span><span class="crayon-e">Catalog </span><span class="crayon-e">Product </span><span class="crayon-v">Rule</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p></p>
<h3><span id="Step_3_Check_Index_Types_Status">步骤 3：检查索引类型状态</span></h3>
<p><span>现在通过运行下面给出的命令检查所有索引类型的状态：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed966830880262" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed966830880262-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed966830880262-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">status</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行该命令后，您将得到以下输出：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed967535497546" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed967535497546-15">15</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-1"><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-2"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">ID</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Title</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Status</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Update </span><span class="crayon-v">On</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Schedule </span><span class="crayon-v">Status</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Schedule </span><span class="crayon-v">Updated</span><span class="crayon-h"> </span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-3"><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-4"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogrule_product</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-e">Product </span><span class="crayon-v">Rule</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-5"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogrule_rule</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-e">Rule </span><span class="crayon-v">Product</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-6"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogsearch_fulltext</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-v">Search</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-7"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_category_product</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Category </span><span class="crayon-v">Products</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-8"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">customer_grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Customer </span><span class="crayon-v">Grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-9"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">design_config_grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Design </span><span class="crayon-e">Config </span><span class="crayon-v">Grid</span><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-10"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">inventory</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Inventory</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-11"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_category</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">Categories</span><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-12"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_attribute</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">EAV</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-13"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_price</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">Price</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-14"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">cataloginventory_stock</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Stock</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-v">Processing</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed967535497546-15"><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p></p>
<h3><span id="Step_4_Reset_Index_Types"><span><span><span>步骤 4：</span></span></span>&nbsp;<span><span><span>重置索引类型</span></span></span></span></h3>
<p><span>为了解决这个问题，您必须重置在给定命令下运行的锁定索引类型：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed969938848984" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed969938848984-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed969938848984-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">reset</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>要重置多个索引类型，请运行以下命令：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed96a275154305" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96a275154305-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96a275154305-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-e">reset </span><span class="crayon-e">IndexType1 </span><span class="crayon-e">IndexType2 </span><span class="crayon-v">IndexType3</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>这里只有一种索引类型被锁定，因此我们将运行以下给出的命令：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed96b028755039" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96b028755039-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96b028755039-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-e">reset </span><span class="crayon-v">cataloginventory_stock</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行上述命令后的输出将类似于：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed96c955371675" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96c955371675-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96c955371675-1"><span class="crayon-e">Stock </span><span class="crayon-e">indexer </span><span class="crayon-e">has </span><span class="crayon-e">been </span><span class="crayon-v">invalidated</span><span class="crayon-sy">.</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p></p>
<h3><span id="Step_5_Reindex_Index_Types">第 5 步：重新索引索引类型&nbsp;</span></h3>
<p><span>您必须再次检查索引器状态，因此再次运行以下命令：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed96e485479010" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96e485479010-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96e485479010-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">status</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行上述命令后的输出将是：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321f96ed96f850343336" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-65321f96ed96f850343336-15">15</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-1"><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-2"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">ID</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Title</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Status</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Update </span><span class="crayon-v">On</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Schedule </span><span class="crayon-v">Status</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Schedule </span><span class="crayon-v">Updated</span><span class="crayon-h"> </span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-3"><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">-</span><span class="crayon-o">+</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">--</span><span class="crayon-o">+</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-4"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogrule_product</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-e">Product </span><span class="crayon-v">Rule</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-5"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogrule_rule</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-e">Rule </span><span class="crayon-v">Product</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-6"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalogsearch_fulltext</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Catalog </span><span class="crayon-v">Search</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-7"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_category_product</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Category </span><span class="crayon-v">Products</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-8"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">customer_grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Customer </span><span class="crayon-v">Grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-9"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">design_config_grid</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Design </span><span class="crayon-e">Config </span><span class="crayon-v">Grid</span><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-10"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">inventory</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Inventory</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-11"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_category</span><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">Categories</span><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-12"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_attribute</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">EAV</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-13"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">catalog_product_price</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Product </span><span class="crayon-v">Price</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Ready</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">|</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321f96ed96f850343336-14"><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">cataloginventory_stock</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Stock</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-e">Reindex </span><span class="crayon-v">required</span><span class="crayon-h"> </span><span class="crayon-o">|</span><span class="crayon-h"> </span><span class="crayon-v">Save</span><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">|</span><span cla]]></description>
      <pubDate>Sun, 29 Oct 2023 07:32:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中 SEO 设置的最佳配置指南[2023]]]></title>
      <link>https://www.360magento.com/blog/seo-configuration-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure">配置步骤：</span></h2>
<p><span>设置 SEO 的Homepage&nbsp; 主页标题</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Setup-Homepage-title-for-SEO.png" /></span></p>
<p></p>
<h2><span id="Metadata_SEO_optimization">元数据SEO优化：</span></h2>
<p><span>类别设置的元数据</span></p>
<p><span><span><span>导航到<span>Catalog&gt;Categories&gt;Search Engine Optimization.&nbsp;</span>。在</span><span>这里，您可以根据您的要求轻松添加所有元标题、元描述和元关键字。</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/Metadata-SEO-optimization.png" />&nbsp;</span></span></span></p>
<p><span>元标题</span></p>
<p><span><span><span>元标题显示为产品页面的标​​题。</span><span>元标题的字符数限制为 70 个，因此您必须明智地创建它，并利用最丰富的关键字。</span></span></span></p>
<p><span>元描述</span></p>
<p><span><span><span>元描述的默认限制为 255 个字符，所有首选数字都在 150-160 个字符之间。</span><span>点击的机会更多，您可以通过在元描述中添加中等数量的字符来吸引用户</span></span></span></p>
<p><span>元关键词</span></p>
<p><span><span><span>基本上，元关键字没有限制，但您应该确保不要完全填写关键字。</span><span>人们应该添加与其在商店中提供的产品和服务相关的关键字。</span></span></span></p>
<p><span>产品设置的元数据</span></p>
<p><span>如果存在这种情况，您想要为产品的元数据设置模板，请导航到<span>Stores&gt;Configuration&gt;Catalog&gt;Catalog&gt;Product Fields Auto-Generation&nbsp;</span>，然后轻松为在线商店中的所有产品进行设置</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/pasted-image-0-5.png" /></span></p>
<p><span>设置Robots.txt</span></p>
<p><span><span><span>Magento 2 所做的最佳和高级改进之一是编辑 robots.txt 文件的功能，导航到<span>Stores&gt;Configuration&gt;Catalog&gt;Design&gt; Search Engine Robots.</span>。</span><span>有时，许多 Magento 2 店主都会忽略这一点，并且许多人无法以正确的方式做到这一点。</span><span>如果您的页面不需要索引，请将设置设置为&ldquo;noindex，nofollow&rdquo;，默认设置将为&ldquo;index，follow&rdquo;。</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/pasted-image-0-3.png" /></span></span></span></p>
<p></p>
<p><span>SEO XML 站点地图生成</span></p>
<p><span><span><span>SEO 中非常重要的任务是站点地图，因为站点地图可以帮助您在搜索引擎索引期间将您的网站放置在 SERP 中。</span><span>为此，导航至<span>Store &gt; Configuration &gt; Catalog &gt; XML Sitemap</span>。</span><span>如果您想直接将站点地图发送到 robots.txt，则只需启用&ldquo;启用提交到 robots.txt&rdquo;即可。</span></span></span></p>
<p><span>SEO 图像的 Alt 标签</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/pasted-image-0-1.png" /></span></p>
<p></p>
<p><span>SEO 图像的 Alt 标签</span></p>
<p><span>当涉及到 SEO 时，所有图像的 Alt 标签非常重要，因此导航至<span>Stores&gt;Configuration&gt;General&gt; Design&gt;HTML Head&gt;Header.</span></span></p>]]></description>
      <pubDate>Sat, 28 Oct 2023 07:19:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[从 Magento 2 中的 URL 中删除 Index.php]]></title>
      <link>https://www.360magento.com/blog/remove-index--url-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_remove_indexphp_from_your_URL">从 URL 中删除 index.php 的步骤。</span></h2>
<p><span>第 1 步：</span><span>导航到 Magento 2 站点的管理面板。</span></p>
<p><span>第 2 步：</span><span>现在，转到&nbsp;<span>Stores &gt; Configuration &gt; General &gt; Web</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/remove-index.php-from-your-URL.png" /></span></span></p>
<p></p>
<p><span>第 3 步：</span><span>之后您需要探索搜索引擎优化部分。</span></p>
<p><span>第 4 步：</span><span>现在您需要在&ldquo;使用 Web 服务器重写&rdquo;中设置&ldquo;YES&rdquo;。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Set-YES-in-Use-Web-Server-Rewrites.png" /></span></p>
<p><span>第 5 步：</span><span>现在您需要探索&ldquo;基本 URL（安全）&rdquo;选项。</span></p>
<p><span>第 6 步：</span><span>将&ldquo;在店面中使用安全 URL&rdquo;设置为&ldquo;YES&rdquo;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Turn-the-Use-Secure-URLs-on-Storefront.png" /></span></p>
<p></p>
<p><span>第 7 步：</span><span>完成上述步骤后保存配置。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Fri, 27 Oct 2023 07:14:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中所有页面的前端添加 JS 文件]]></title>
      <link>https://www.360magento.com/blog/add-js-file-frontend-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_JS_File_in_Frontend_for_All_Pages_in_Magento_2">在 Magento 2 中所有页面的前端添加 JS 文件的步骤：</span></h2>
<p><span><span><span><span>步骤1：</span></span></span><span><span>首先你需要在app\code\[Vendor]\[Module]\view\frontend\layout\default.xml创建default.xml</span></span></span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-1"><span class="crayon-ta">&lt;?</span><span class="crayon-e">xml </span><span class="crayon-i">version</span><span class="crayon-o">=</span><span class="crayon-s">"1.0"</span><span class="crayon-ta">?&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-2">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-3"><span class="crayon-o">&lt;</span><span class="crayon-e">page </span><span class="crayon-v">xmlns</span><span class="crayon-o">:</span><span class="crayon-v">xsi</span><span class="crayon-o">=</span><span class="crayon-s">"http://www.w3.org/2001/XMLSchema-instance"</span><span class="crayon-h"> </span><span class="crayon-v">xsi</span><span class="crayon-o">:</span><span class="crayon-v">noNamespaceSchemaLocation</span><span class="crayon-o">=</span><span class="crayon-s">"urn:magento:framework:View/Layout/etc/page_configuration.xsd"</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-4">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-5">&nbsp;&nbsp;&nbsp;&nbsp;<span class="crayon-o">&lt;</span><span class="crayon-v">head</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-6">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-7">&nbsp;&nbsp;&nbsp;&nbsp;<span class="crayon-o">&lt;</span><span class="crayon-e">link </span><span class="crayon-v">src</span><span class="crayon-o">=</span><span class="crayon-s">"[Vendor]_[Module]::js/js_fileName.js"</span><span class="crayon-o">/</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-8">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-9">&nbsp;&nbsp;&nbsp;&nbsp;<span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">head</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-10">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-65321bcaa7f2c413984403-11"><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">page</span><span class="crayon-o">&gt;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span><span><span><span>步骤2：</span></span></span><span><span>现在，在 app\code\[Vendor]\[Module]\view\frontend\web\js\js_fileName.js 创建 JS 文件</span></span></span></p>
<p><span><span><span><span>步骤 3：</span></span></span><span><span>执行 setup Upgrade 命令和 setup:static-content:deploy 命令，刷新页面即可。</span></span></span></p>
<div id="gtx-trans" style="position: absolute; left: 602px; top: 331.875px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 26 Oct 2023 07:07:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取商店信息（商店 ID、代码、名称）]]></title>
      <link>https://www.360magento.com/blog/how-get-store-information-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong><span style="font-size: 1.5em;">在 Magento 2 中获取商店信息概述</span></strong></p>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：获取<code>phtml</code>文件中的商店信息</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">第 1 步：声明<code>Example_HelloWorld</code></h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类，然后可能在模块的块类的构造函数中<code>Example_HelloWorld</code>注入 的对象。<code>StoreManagerInterface</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
    protected $_storeManager;    
    
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Store\Model\StoreManagerInterface $storeManager,        
        array $data = []
    )
    {        
        $this-&gt;_storeManager = $storeManager;        
        parent::__construct($context, $data);
    }
    
    /**
     * Get store identifier
     *
     * @return  int
     */
    public function getStoreId()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getId();
    }
    
    /**
     * Get website identifier
     *
     * @return string|int|null
     */
    public function getWebsiteId()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getWebsiteId();
    }
    
    /**
     * Get Store code
     *
     * @return string
     */
    public function getStoreCode()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getCode();
    }
    
    /**
     * Get Store name
     *
     * @return string
     */
    public function getStoreName()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getName();
    }
    
    /**
     * Get current url for store
     *
     * @param bool|string $fromStore Include/Exclude from_store parameter from URL
     * @return string     
     */
    public function getStoreUrl($fromStore = true)
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getCurrentUrl($fromStore);
    }
    
    /**
     * Check if store is active
     *
     * @return boolean
     */
    public function isStoreActive()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;isActive();
    }
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-get-store-information-in-phtml-file">步骤2：获取<code>.phtml</code>文件中的商店信息</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在文件中使用以下脚本<code>.phtml</code>并打印商店信息。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>echo $block-&gt;getStoreId() . '&lt;br /&gt;';
echo $block-&gt;getStoreCode() . '&lt;br /&gt;';
echo $block-&gt;getWebsiteId() . '&lt;br /&gt;';
echo $block-&gt;getStoreName() . '&lt;br /&gt;';
echo $block-&gt;getStoreUrl() . '&lt;br /&gt;';
echo $block-&gt;isStoreActive() . '&lt;br /&gt;';</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -51px; top: -13.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 25 Oct 2023 07:20:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取相关、追加销售和交叉销售产品]]></title>
      <link>https://www.360magento.com/blog/how-get-related-upsell-crosssell-products-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>Magento 2 中的相关产品、追加销售产品和交叉销售产品</strong>是可用于营销活动以促进在线发展的产品类型。对于观看产品来说，相关产品是具有相似功能的产品，追加销售产品是比该产品更高版本的产品。交叉销售产品怎么样？它们是完美使用的配套产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-of-magento-2-related-up-sell-cross-sell-products">Magento 2 相关、追加销售、交叉销售产品概述</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><strong>相关产品</strong>是除了客户正在查看的商品之外还向客户展示的产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>追加销售产品</strong>是指价格或质量高于他们正在查看的商品的产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>交叉销售产品</strong>是客户正在关注的商品的相关或互补产品，目的是增加现有产品的价值。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>每种类型的产品都</strong>可以放置在 Magento 2 商店中的不同位置。它们通常用于有效促进销售。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在让我们详细了解如何在 Magento 2 中获取这些产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在 Magento 2 中获取相关产品、追加销售和交叉销售产品的 4 个步骤：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：获取相关产品</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：获取追加销售产品</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 4 步：获取交叉销售产品</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld-block">步骤一：在<code>Mageplaza_HelloWorld</code>区块中声明</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类，然后可能在模块的块类的构造函数中<code>Example_HelloWorld</code>注入 的对象。<code>\Magento\Framework\Registry</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
    protected $_registry;
    
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Framework\Registry $registry,
        array $data = []
    )
    {        
        $this-&gt;_registry = $registry;
        parent::__construct($context, $data);
    }
    
    public function _prepareLayout()
    {
        return parent::_prepareLayout();
    }
    
    public function getCurrentProduct()
    {        
        return $this-&gt;_registry-&gt;registry('current_product');
    }    
    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-get-related-products">第二步：获取相关产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在第2步中，您将申请<code>Object Manager</code>定制班级<code>HelloWorld</code>。通过这种方式，允许调用当前产品信息，则可以一一获取当前产品的相关产品、追加销售产品和交叉销售产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$myBlock = \Magento\Framework\App\ObjectManager::getInstance()-&gt;get('Example\HelloWorld\Block\HelloWorld');
 
$currentProduct = $myBlock-&gt;getCurrentProduct();
 
if ($currentProduct = $myBlock-&gt;getCurrentProduct()) {
    $relatedProducts = $currentProduct-&gt;getRelatedProducts();
    
    if (!empty($relatedProducts)) {
        echo 'Related Products &lt;br /&gt;';    
        foreach ($relatedProducts as $relatedProduct) {
            echo $relatedProduct-&gt;getSku() . '&lt;br /&gt;';  
            echo $relatedProduct-&gt;getName(); //get name
            echo $relatedProduct-&gt;getPrice(); //get price
            echo $relatedProduct-&gt;getData(); //Show all attributes      
        }
    }    
   
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-get-upsell-products">第 3 步：获取追加销售产品</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$myBlock = \Magento\Framework\App\ObjectManager::getInstance()-&gt;get('Example\HelloWorld\Block\HelloWorld');
$currentProduct = $myBlock-&gt;getCurrentProduct();
 
if ($currentProduct = $myBlock-&gt;getCurrentProduct()) {
    $upSellProducts = $currentProduct-&gt;getUpSellProducts();

    if (!empty($upSellProducts)) {
        echo '&lt;h3&gt;UpSell Products&lt;/h3&gt;';
        foreach ($upSellProducts as $upSellProduct) {
            echo $upSellProduct-&gt;getSku() . '&lt;br /&gt;';        
        }
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-4-get-crosssell-products">第 4 步：获取交叉销售产品</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$myBlock = \Magento\Framework\App\ObjectManager::getInstance()-&gt;get('Example\HelloWorld\Block\HelloWorld');
$currentProduct = $myBlock-&gt;getCurrentProduct();
 
if ($currentProduct = $myBlock-&gt;getCurrentProduct()) {
    $crossSellProducts = $currentProduct-&gt;getCrossSellProducts();

    if (!empty($crossSellProduct)) {
        echo 'CrossSell Products &lt;br /&gt;';
        foreach ($crossSellProducts as $crossSellProduct) {
            echo $crossSellProduct-&gt;getSku() . '&lt;br /&gt;';        
        }
    }
}
</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Tue, 24 Oct 2023 07:13:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中获取产品库存信息？]]></title>
      <link>https://www.360magento.com/blog/how-get-product-stock-information-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>获取产品库存信息</strong>意味着您可以获取一些详细信息，例如最小数量（min_qty），最小销售数量（min_sale_qty），最大销售数量（max_sale_qty），检查产品是否有库存（is_in_stock），缺货等在Magento 2中，在线商店需要获取库存变化数据进行定期跟踪，这可以帮助他们做出未来的业务决策。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="2-steps-to-get-product-stock-information-in-magento-2">在 Magento 2 中获取产品库存信息的 2 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明获取产品库存信息的命令</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：在模板文件中加载产品 id 和 sku</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">步骤1：声明获取产品库存信息的命令</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>首先，您将使用 module 的块类<code>Example_HelloWorld</code>，然后可能将类的对象注入<code>\Magento\CatalogInventory\Model\Stock\StockItemRepository</code>到模块的块类的构造函数中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{    
    protected $_stockItemRepository;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\CatalogInventory\Model\Stock\StockItemRepository $stockItemRepository,
        array $data = []
    )
    {
        $this-&gt;_stockItemRepository = $stockItemRepository;
        parent::__construct($context, $data);
    }
    
    public function getStockItem($productId)
    {
        return $this-&gt;_stockItemRepository-&gt;get($productId);
    }
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">第 2 步：在模板文件中加载产品 id 和 sku</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>接下来，请使用以下脚本通过模板文件中的id 和 sku 加载产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$id = 123;
$_productStock = $block-&gt;getStockItem($id);
//print_r($_productStock-&gt;getData()); 
echo $_productStock-&gt;getQty(); echo '&lt;br /&gt;';
echo $_productStock-&gt;getMinQty(); echo '&lt;br /&gt;';
echo $_productStock-&gt;getMinSaleQty(); echo '&lt;br /&gt;';
echo $_productStock-&gt;getMaxSaleQty(); echo '&lt;br /&gt;';
echo $_productStock-&gt;getIsInStock(); echo '&lt;br /&gt;';</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Mon, 23 Oct 2023 06:59:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取产品集合]]></title>
      <link>https://www.360magento.com/blog/how-get-product-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-of-getting-product-collection-in-magento-2">在 Magento 2 中获取产品集合</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>虽然在 Magento 2 中获取特定产品集合有不同的操作，但它们是加载、过滤（例如按属性）和排序。在本文中，我将仅介绍帮助您开始使用产品集合的基本步骤。以下是两个初始步骤：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>步骤一：在<code>Example_HelloWorld</code>区块中声明</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 2：显示<code>phtml</code>文件中的产品集合</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld-block">步骤一：在<code>Example_HelloWorld</code>区块中声明</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类，然后可能在模块的块类的构造函数中<code>Example_HelloWorld</code>注入 的对象。<code>\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{    
    protected $_productCollectionFactory;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,        
        array $data = []
    )
    {    
        $this-&gt;_productCollectionFactory = $productCollectionFactory;    
        parent::__construct($context, $data);
    }
    
    public function getProductCollection()
    {
        $collection = $this-&gt;_productCollectionFactory-&gt;create();
        $collection-&gt;addAttributeToSelect('*');
        $collection-&gt;setPageSize(3); // fetching only 3 products
        return $collection;
    }
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>注：您可以请求产品集合的数量，数量是有限的或无限的。在实现该功能时，您需要根据需求扩展代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2-display-product-collection-in-phtml-file">步骤 2：显示<code>phtml</code>文件中的产品集合</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>phtml</code>使用以下代码打印文件中的产品集合：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$productCollection = $block-&gt;getProductCollection();
foreach ($productCollection as $product) {
    print_r($product-&gt;getData());     
    echo "&lt;br&gt;";
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>现在，您可以获取请求的集合中每个产品的数据。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -60px; top: -10.5625px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 22 Oct 2023 07:54:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取徽标 url、图像 URL、替代文本、徽标大小]]></title>
      <link>https://www.360magento.com/blog/how-get-logo-url-alt-text-logo-size-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>徽标 URL</strong>、<strong>ALT 文本</strong>、<strong>图像 URL</strong>和<strong>徽标尺寸</strong>（包括高度和宽度）是徽标应用到您的商店时您完全获得的基本信息。具体来说，徽标 URL 是只要有人单击徽标就会显示该页面的直接链接。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>这些元素在提高您的品牌形象和确保 SEO 排名中获得良好分数方面发挥着重要作用。这就是为什么您需要完美的徽标尺寸、相关的 ALT 文本和优化的徽标 URL。在此之前，您需要获取所有现有的标志信息，以便以后轻松进行比较、优化、更新。<a href="https://www.mageplaza.com/kb/magento-2-demo.html"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>主要内容</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 2：在模板 (.phtml) 文件中声明函数</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">第 1 步：声明<code>Example_HelloWorld</code></h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类<code>Example_HelloWorld</code>，然后可能将类的对象注入<code>Logo</code>到模块的块类的构造函数中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
    protected $_logo;    
    
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,
        \Magento\Theme\Block\Html\Header\Logo $logo,
        array $data = []
    )
    {        
        $this-&gt;_logo = $logo;
        parent::__construct($context, $data);
    }
    
    /**
     * Get logo image URL
     *
     * @return string
     */
    public function getLogoSrc()
    {    
        return $this-&gt;_logo-&gt;getLogoSrc();
    }
    
    /**
     * Get logo text
     *
     * @return string
     */
    public function getLogoAlt()
    {    
        return $this-&gt;_logo-&gt;getLogoAlt();
    }
    
    /**
     * Get logo width
     *
     * @return int
     */
    public function getLogoWidth()
    {    
        return $this-&gt;_logo-&gt;getLogoWidth();
    }
    
    /**
     * Get logo height
     *
     * @return int
     */
    public function getLogoHeight()
    {    
        return $this-&gt;_logo-&gt;getLogoHeight();
    }    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以在 中看到更多功能<code>vendor/magento/module-theme/Block/Html/Header/Logo.php</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-declare-function-in-template-phtml-file">步骤 2：在模板 (.phtml) 文件中声明函数</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在模板 (.phtml) 文件中运行以下函数</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>echo $block-&gt;getLogoSrc() . '&lt;br /&gt;';
echo $block-&gt;getLogoAlt() . '&lt;br /&gt;';
echo $block-&gt;getLogoWidth() . '&lt;br /&gt;';
echo $block-&gt;getLogoHeight() . '&lt;br /&gt;';
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以在 中看到更多功能<code>vendor/magento/module-theme/Block/Html/Header/Logo.php</code>。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -58px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 21 Oct 2023 07:46:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取购物车商品、小计、总计、账单和送货地址的数据]]></title>
      <link>https://www.360magento.com/blog/how-get-data-shopping-cart-items-subtotal-grand-total-billing/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 2 平台上运行您的商店时，可以获得<strong>购物车商品、小计、总计、账单和送货地址的数据</strong>。本指南将应用于​​许多与购物车信息相关的功能开发流程，例如共享购物车或保存购物车。因此，在本文中，我们将向您展示如何使用代码获取数据。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-of-retrieving-the-data-of-shopping-cart-items-subtotal-grand-total-billing--shipping-address-in-magento-2">Magento 2 中检索购物车商品、小计、总计、账单和送货地址数据的概述</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您可以获取购物车商品的整体或单独信息，例如小计、总计以及账单和送货地址。这里有四种方法：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在您的购物车中获取所有需要的信息。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取购物车中的商品数量和购物车中的总数量。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取购物车中商品的基本总价和总价。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取选定的帐单和送货地址。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-all-needed-information-in-your-cart">在您的购物车中获取所有需要的信息。</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$cart = $objectManager-&gt;get('\Magento\Checkout\Model\Cart'); 
 
// get quote items collection
$itemsCollection = $cart-&gt;getQuote()-&gt;getItemsCollection();
 
// get array of all items what can be display directly
$itemsVisible = $cart-&gt;getQuote()-&gt;getAllVisibleItems();
 
// get quote items array
$items = $cart-&gt;getQuote()-&gt;getAllItems();
 
foreach($items as $item) {
    echo 'ID: '.$item-&gt;getProductId().'&lt;br /&gt;';
    echo 'Name: '.$item-&gt;getName().'&lt;br /&gt;';
    echo 'Sku: '.$item-&gt;getSku().'&lt;br /&gt;';
    echo 'Quantity: '.$item-&gt;getQty().'&lt;br /&gt;';
    echo 'Price: '.$item-&gt;getPrice().'&lt;br /&gt;';
    echo "&lt;br /&gt;";            
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-the-number-of-items-in-cart-and-total-quantity-in-cart">获取购物车中的商品数量和购物车中的总数量。</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$cart = $objectManager-&gt;get('\Magento\Checkout\Model\Cart'); 
 
$totalItems = $cart-&gt;getQuote()-&gt;getItemsCount();
$totalQuantity = $cart-&gt;getQuote()-&gt;getItemsQty();
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-base-total-price-and-grand-total-price-of-items-in-cart">获取购物车中商品的基本总价和总价。</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$cart = $objectManager-&gt;get('\Magento\Checkout\Model\Cart'); 
 
$subTotal = $cart-&gt;getQuote()-&gt;getSubtotal();
$grandTotal = $cart-&gt;getQuote()-&gt;getGrandTotal();
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-chosen-billing-and-shipping-addresses">获取选定的帐单和送货地址。</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$cart = $objectManager-&gt;get('\Magento\Checkout\Model\Cart'); 
 
$billingAddress = $cart-&gt;getQuote()-&gt;getBillingAddress();
echo '&lt;pre&gt;'; print_r($billingAddress-&gt;getData()); echo '&lt;/pre&gt;';
 
$shippingAddress = $cart-&gt;getQuote()-&gt;getShippingAddress();
echo '&lt;pre&gt;'; print_r($shippingAddress-&gt;getData()); echo '&lt;/pre&gt;';</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Fri, 20 Oct 2023 07:42:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中将订单电子邮件发送到自定义电子邮件地址]]></title>
      <link>https://www.360magento.com/blog/how-send-order-email-custom-email-address-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在这篇博文中，向您介绍如何使用自定义代码将订单电子邮件发送到Magento 2中的<strong>自定义电子邮件地址。</strong>本主题将通过以下两个步骤涵盖所有必要的操作。<a href="https://www.mageplaza.com/magento-2-extensions/"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="2-steps-to-send-order-email-to-a-custom-email-address-in-magento-2">将订单电子邮件发送到 Magento 2 中的自定义电子邮件地址的 2 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第一步：设置邮件格式</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第二步：设置控制器文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-set-a-form-of-the-email">第一步：设置邮件格式</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>使用输入字段行设置电子邮件的格式如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;form id="send-order-email" action="&lt;?php $block-&gt;getUrl('helloworld/order/sendemail'); ?&gt;"&gt;
    &lt;label&gt;Email Address&lt;/label&gt;
    &lt;input type="text" class="input-text" id="email"&gt;
&lt;/form&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-set-a-controller-file">第2步：设置控制器文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>文件路径：<code>app\code\Example\HelloWorld\Controller\Order\Email</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app\code\<code>Example</code>\HelloWorld\Controller\Order\Email</code>添加基于 class 的文件<code>\Magento\Framework\App\Action\Action</code>。该文件将从上面的表单中执行提交操作，但首先，请插入以下操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>public function execute()
    {
        $email = $this-&gt;getRequest()-&gt;getParam('email');
        $order = $this-&gt;_objectManager-&gt;create('Magento\Sales\Model\Order')-&gt;load(1); // this is entity id
        $order-&gt;setCustomerEmail($email);
        if ($order) {
            try {
                $this-&gt;_objectManager-&gt;create('\Magento\Sales\Model\OrderNotifier')
                    -&gt;notify($order);
                $this-&gt;messageManager-&gt;addSuccess(__('You sent the order email.'));
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                $this-&gt;messageManager-&gt;addError($e-&gt;getMessage());
            } catch (\Exception $e) {
                $this-&gt;messageManager-&gt;addError(__('We can\'t send the email order right now.'));
                $this-&gt;_objectManager-&gt;create('Magento\Sales\Model\OrderNotifier')-&gt;critical($e);
            }
        }
    }</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Fri, 20 Oct 2023 03:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取客户组]]></title>
      <link>https://www.360magento.com/blog/how-get-customer-groups-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>如果您经营的 Magento 2 商店拥有大量产品和庞大的客户群，则必须将客户分组。客户群体帮助您更好地管理客户。您可以通过更相关和个性化的优惠更好地了解和服务他们。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>Magento 2 支持三个默认客户组：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>一般的</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>未登录</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>批发的</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>然而，在 Magento 2 中创建额外的客户群体也很容易、快捷。这通常取决于每个店主的需求。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在这篇文章中，我将为您带来在 Magento 2 中顺利获取客户群的最简单方法。为此，请复制以下代码并将其添加到您的块类中。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-customer-groups-in-magento-2">在 Magento 2 中获取客户组</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>/**
 * Customer Group
 *
 * @var \Magento\Customer\Model\ResourceModel\Group\Collection
 */
protected $_customerGroup;
    
/**
 * @param \Magento\Backend\Block\Template\Context $context
 * @param \Magento\Customer\Model\ResourceModel\Group\Collection $customerGroup
 * @param array $data
 */
public function __construct(
    \Magento\Backend\Block\Template\Context $context,
    \Magento\Customer\Model\ResourceModel\Group\Collection $customerGroup,        
    array $data = []
) {
    $this-&gt;_customerGroup = $customerGroup;        
    parent::__construct($context, $data);
}
/**
 * Get customer groups
 * 
 * @return array
 */ 
public function getCustomerGroups() {
    $customerGroups = $this-&gt;_customerGroup-&gt;toOptionArray();
    array_unshift($customerGroups, array('value'=&gt;'', 'label'=&gt;'Any'));
    return $customerGroups;
}</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -145px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 19 Oct 2023 07:39:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置、取消Session]]></title>
      <link>https://www.360magento.com/blog/how-set-unset-session-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>今天，我们将讨论如何通过运行代码快速设置和取消session。随着Magento 2的定制化开发和定制，有时候获取Session信息是非常有必要的。对于 Magento 2 商店管理员来说，了解session并随时调整它们以在一定时间内获取重要信息是必要的。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="magento-2-session-types">Magento 2 session类型</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>那么 Magento 2 中的session是什么？</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>session是一种在 Magento 2 商店的每个页面上排序和存储变量的方法。它允许您的用户在您的商店中临时存储一些值，例如购物车中的商品、个人信息等。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>当用户在您的商店中注册帐户时，session允许您存储他们的信息，例如名字、姓氏或 ID。然后，通过在 Magento 2 中设置自定义session变量，您可以存储更多附加信息。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，让我们看一下 Magento 2 中的session类型列表：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>vendor/magento/module-catalog/Model/Session.php
 
vendor/magento/module-newsletter/Model/Session.php
 
vendor/magento/module-persistent/Model/Session.php
 
vendor/magento/framework/Message/Session.php
 
vendor/magento/module-customer/Model/Session.php
 
vendor/magento/module-backend/Model/Session.php
 
vendor/magento/module-checkout/Model/Session.php
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>查看以下方法，可以随时轻松快速地在 Magento 2 中设置或取消session。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="set-sessions-in-magento-2">在 Magento 2 中设置session</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在，您将开始通过以下代码调用 Catalog、Customer 和 Checkout session。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{    
    protected $_catalogSession;
    protected $_customerSession;
    protected $_checkoutSession;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\Session $catalogSession,
        \Magento\Customer\Model\Session $customerSession,
        \Magento\Checkout\Model\Session $checkoutSession,
        array $data = []
    )
    {        
        $this-&gt;_catalogSession = $catalogSession;
        $this-&gt;_checkoutSession = $checkoutSession;
        $this-&gt;_customerSession = $customerSession;
        parent::__construct($context, $data);
    }
    
    public function _prepareLayout()
    {
        return parent::_prepareLayout();
    }
        
    public function getCatalogSession() 
    {
        return $this-&gt;_catalogSession;
    }
    
    public function getCustomerSession() 
    {
        return $this-&gt;_customerSession;
    }
    
    public function getCheckoutSession() 
    {
        return $this-&gt;_checkoutSession;
    }    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>然后，通过 Catalog、Customer 和 Checkout session，可以从<code>.phtml</code>文件中设置它们。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$block-&gt;getCatalogSession()-&gt;setMyName('Mageplaza');
echo $block-&gt;getCatalogSession()-&gt;getMyName() . '&lt;br /&gt;'; // output: Mageplaza
 
$block-&gt;getCheckoutSession()-&gt;setTestData('Hello World');
echo $block-&gt;getCheckoutSession()-&gt;getTestData() . '&lt;br /&gt;'; // output: Hello World
 
$block-&gt;getCheckoutSession()-&gt;setTestHello('Test Hello Value');
echo $block-&gt;getCheckoutSession()-&gt;getTestHello() . '&lt;br /&gt;'; // output: Test Hello Value
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="unset-sessions-in-magento-2">在 Magento 2 中取消Session</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果您想取消设置这些session，请按以下步骤操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$block-&gt;getCatalogSession()-&gt;unsMyName();
$block-&gt;getCheckoutSession()-&gt;unsTestData();
$block-&gt;getCustomerSession()-&gt;unsTestHello();
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>具体来说，客户session允许收集客户信息，例如客户姓名和电子邮件。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>// get customer data
if ($block-&gt;getCustomerSession()-&gt;isLoggedIn()) {
    $customerId = $block-&gt;getCustomerSession()-&gt;getCustomerId();
    $customerData = $block-&gt;getCustomerSession()-&gt;getCustomer();
    echo $customerId . '&lt;br /&gt;';
    echo $customerData-&gt;getFirstname() . ' ' . $customerData-&gt;getLastname() . '&lt;br /&gt;';
    echo $customerData-&gt;getEmail() . '&lt;br /&gt;';
    print_r($block-&gt;getCustomerSession()-&gt;getCustomer()-&gt;getData());
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>结帐session将显示报价信息。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>// get checkout session data
echo $block-&gt;getCheckoutSession()-&gt;getQuoteId();
print_r($block-&gt;getCheckoutSession()-&gt;getQuote()-&gt;getData());</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -154px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 19 Oct 2023 03:20:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取当前产品和当前类别]]></title>
      <link>https://www.360magento.com/blog/how-get-current-product-category-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>产品名称、产品 ID、产品价格或类别 URL 等信息对于任何 Magento 2 在线商家都至关重要，因为它使他们能够更好地访问足够的信息来实施合适的业务策略。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="3-steps-to-get-current-product--current-category-in-magento-2">在 Magento 2 中获取当前产品和当前类别的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第二步：打印出模板<code>phtml</code>文件中当前的产品</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第三步：打印出模板<code>phtml</code>文件中当前的类别</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">步骤1：在Mageplaza_HelloWorld中声明</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用模块 Example_HelloWorld的块类，然后可能<code>\Magento\Framework\Registry</code>在模块块类的构造函数中注入 的对象。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
        protected $_registry;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Framework\Registry $registry,
        array $data = []
    )
    {        
        $this-&gt;_registry = $registry;
        parent::__construct($context, $data);
    }
    
    public function _prepareLayout()
    {
        return parent::_prepareLayout();
    }
    
    public function getCurrentCategory()
    {        
        return $this-&gt;_registry-&gt;registry('current_category');
    }
    
    public function getCurrentProduct()
    {        
        return $this-&gt;_registry-&gt;registry('current_product');
    }    
    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-get-current-product-in-the-template-phtml-file">步骤2：在模板<code>phtml</code>文件中获取当前产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>当前产品包括以下信息：名称、SKU、最终价格、URL 和关联的类别 ID。当前类别带有名称和网址等信息。现在请运行命令打印出当前产品和当前类别。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$myBlock = \Magento\Framework\App\ObjectManager::getInstance()-&gt;get('Example\HelloWorld\Block\HelloWorld');
 

// print current product data
if ($currentProduct = $myBlock-&gt;getCurrentProduct()) {
    echo $currentProduct-&gt;getName() . '&lt;br /&gt;';
    echo $currentProduct-&gt;getSku() . '&lt;br /&gt;';
    echo $currentProduct-&gt;getFinalPrice() . '&lt;br /&gt;';
    echo $currentProduct-&gt;getProductUrl() . '&lt;br /&gt;';
    print_r ($currentProduct-&gt;getCategoryIds()) . '&lt;br /&gt;';    
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-get-current-category-in-the-template-phtml-file">步骤3：获取模板<code>phtml</code>文件中当前的类别</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$myBlock = \Magento\Framework\App\ObjectManager::getInstance()-&gt;get('Example\HelloWorld\Block\HelloWorld');
 
// print current category data
if ($currentCategory = $myBlock-&gt;getCurrentCategory()) {    
    echo $currentCategory-&gt;getName() . '&lt;br /&gt;';
    echo $currentCategory-&gt;getUrl() . '&lt;br /&gt;';        
}
 </code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -191px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 18 Oct 2023 07:25:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示模板 phtml 文件中的 cms 静态块]]></title>
      <link>https://www.360magento.com/blog/how-show-cms-static-block-template-phtml-file-magento-2/</link>
      <description><![CDATA[<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-show-cms-static-block-from-template-phtml-file-in-magento-2">如何在 Magento 2 中从模板 PHTML 文件显示 CMS 静态块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 2 为用户提供了 CMS Static Block，这对于在网页上显示文本、照片、视频和其他材料非常有用。动态内容也可以通过静态块中的小部件添加。使用<strong>Magento 2 CMS 静态块</strong>使您可以轻松编辑和设计这些内容。当您创建了块并希望从 phtml 文件中显示它时，本教程适合您。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您想在 Magento 2 中的<strong>模板<code>phtml</code>文件中显示 CMS 静态块，请使用以下代码片段：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>echo $this-&gt;getLayout()
          -&gt;createBlock('Magento\Cms\Block\Block')
          -&gt;setBlockId('your_block_identifier')
          -&gt;toHtml();
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p><strong>在 CMS 内容中显示 CMS 静态块</strong>：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code></code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p><strong>在 XML 中显示 CMS 静态块</strong>：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;referenceContainer name="content"&gt; 
    &lt;block class="Magento\Cms\Block\Block" name="block_identifier"&gt; 
        &lt;arguments&gt; 
            &lt;argument name="block_id" xsi:type="string"&gt;block_identifier&lt;/argument&gt; 
        &lt;/arguments&gt; 
    &lt;/block&gt; 
&lt;/referenceContainer&gt;</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -111px; top: 28.375px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 18 Oct 2023 03:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何获取货币数据：Magento 2 中的代码、汇率、符号]]></title>
      <link>https://www.360magento.com/blog/how-get-currency-data-code-rate-symbol-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>当您使用Magento 2平台建立您的电子商店时，您可以接受多种货币，这取决于目标客户。通过本指南，我们将清楚地获取所有基础、默认和当前货币代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-magento-2-get-currency-data">概述 Magento 2 获取货币数据</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>phtml</code>步骤2：获取文件中货币数据的输出</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">第 1 步：声明<code>Example_HelloWorld</code></h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类<code>Example_HelloWorld</code>，然后可能将类的对象注入<code>StoreManagerInterface &amp; Currency</code>到模块的块类的构造函数中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
    protected $_storeManager;
    protected $_currency;
    
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Directory\Model\Currency $currency,        
        array $data = []
    )
    {        
        $this-&gt;_storeManager = $storeManager;
        $this-&gt;_currency = $currency;        
        parent::__construct($context, $data);
    }
    
        
    /**
     * Get store base currency code
     *
     * @return string
     */
    public function getBaseCurrencyCode()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getBaseCurrencyCode();
    }
    
     /**
     * Get current store currency code
     *
     * @return string
     */
    public function getCurrentCurrencyCode()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getCurrentCurrencyCode();
    }    
    
    /**
     * Get default store currency code
     *
     * @return string
     */
    public function getDefaultCurrencyCode()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getDefaultCurrencyCode();
    }
    
    /**
     * Get allowed store currency codes
     *
     * If base currency is not allowed in current website config scope,
     * then it can be disabled with $skipBaseNotAllowed
     *
     * @param bool $skipBaseNotAllowed
     * @return array
     */
    public function getAvailableCurrencyCodes($skipBaseNotAllowed = false)
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getAvailableCurrencyCodes($skipBaseNotAllowed);
    }
    
    /**
     * Get array of installed currencies for the scope
     *
     * @return array
     */
    public function getAllowedCurrencies()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getAllowedCurrencies();
    }
    
    /**
     * Get current currency rate
     *
     * @return float
     */
    public function getCurrentCurrencyRate()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;getCurrentCurrencyRate();
    }
    
    /**
     * Get currency symbol for current locale and currency code
     *
     * @return string
     */    
    public function getCurrentCurrencySymbol()
    {
        return $this-&gt;_currency-&gt;getCurrencySymbol();
    }    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p><code>vendor/magento/module-store/Model/Store.php</code>您可以在和中看到更多功能<code>vendor/magento/module-directory/Model/Currency.php</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-get-the-output-of-the-currency-data-in-phtml-file"><code>phtml</code>步骤2：获取文件中货币数据的输出</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>当您在模板文件中运行以下命令时，允许获取并打印<strong>货币汇率</strong>、<strong>货币代码</strong>和<strong>货币符号</strong><code>phtml</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>echo $block-&gt;getCurrentCurrencySymbol() . '&lt;br /&gt;';
echo $block-&gt;getCurrentCurrencyCode() . '&lt;br /&gt;';
echo $block-&gt;getBaseCurrencyCode() . '&lt;br /&gt;';
echo $block-&gt;getDefaultCurrencyCode() . '&lt;br /&gt;';
echo $block-&gt;getCurrentCurrencyRate() . '&lt;br /&gt;';
 
print_r($block-&gt;getAvailableCurrencyCodes()) . '&lt;br /&gt;';
print_r($block-&gt;getAllowedCurrencies()) . '&lt;br /&gt;';
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>到这里就结束了，希望对你有帮助。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -169px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 17 Oct 2023 07:53:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加顶部链接]]></title>
      <link>https://www.360magento.com/blog/how-add-top-link-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>在 Magento 2 中添加顶部链接</strong>意味着在页面顶部显示一些有用的链接。我们将在本教程中了解如何完成。这是CMS 块，包括客户的一些个人信息，如我的帐户、我的愿望清单、登录名或您需要的任何信息。单击顶部链接并将用户重定向到包含更多特定信息的CMS 页面。创建顶部链接还可以推动他们的愿望，鼓励客户购买越来越多的东西。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，在顶部菜单上，&ldquo;我的愿望清单&rdquo;链接将保存并直接引导他们到他们之前感兴趣的产品列表，而无需结账。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-of-adding-top-link-in-magento-2">在 Magento 2 中添加顶部链接的概述</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：添加/修改<code>default.xml</code>文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：添加<code>Link.php</code>文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存并测试</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-add-modify-defaultxml-file">第1步：添加/修改<code>default.xml</code>文件</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>找到路径<code>app/code/Example/HelloWorld/view/frontend/layout</code>，然后通过以下方式添加/修改<code>default.xml</code>文件：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
&lt;body&gt;
     &lt;referenceBlock name="header.links"&gt;
         &lt;block class="Example\HelloWorld\Block\Link" name="add-new-header-link"&gt;
             &lt;arguments&gt;
     &lt;argument name="label" xsi:type="string" translate="true"&gt;New Link&lt;/argument&gt;
     &lt;argument name="path" xsi:type="string" translate="true"&gt;new-link&lt;/argument&gt;
     &lt;/arguments&gt;
         &lt;/block&gt;
     &lt;/referenceBlock&gt;
&lt;/body&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2-add-linkphp-file">第 2 步：添加<code>Link.php</code>文件</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>继续输入路径<code>app/code/Example/HelloWorld/Block</code>，您将添加<code>link.php</code>文件：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
 
namespace Example\HelloWorld\Block;
 
class Link extends \Magento\Framework\View\Element\Html\Link
{
/**
* Render block HTML.
*
* @return string
*/
protected function _toHtml()
    {
     if (false != $this-&gt;getTemplate()) {
     return parent::_toHtml();
     }
     return '&lt;li&gt;&lt;a ' . $this-&gt;getLinkAttributes() . ' &gt;' . $this-&gt;escapeHtml($this-&gt;getLabel()) . '&lt;/a&gt;&lt;/li&gt;';
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-3-flush-cache-and-test-your-top-link-result">第 3 步：刷新缓存并测试</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>清理缓存</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Tue, 17 Oct 2023 03:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何从 Magento 2 中的特定产品获取类别]]></title>
      <link>https://www.360magento.com/blog/how-get-categories-specific-product-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>有时您可能需要从您看到的特定产品中收集整个产品列表或产品类别。可以使用快速解决方案来获取产品类别，而无需在您的网站内来回切换。您将以省时且准确的方式从任何您想要的产品中获得类别。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在让我们看看如何<strong>从 Magento 2 中的特定产品获取类别</strong>。此方法使您能够根据需要从当前或任何产品中获取列表。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>首先，您需要打开我的自定义模块（<code>Example_HelloWorld</code>）的块类，然后在该块类的构造函数中注入<code>\Magento\Catalog\Model\ResourceModel\Category\CollectionFactory</code>,<code>\Magento\Catalog\Model\ProductRepository</code>和类的对象。<code>\Magento\Framework\Registry</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{    
    protected $_categoryCollectionFactory;
    protected $_productRepository;
    protected $_registry;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\ResourceModel\Category\CollectionFactory $categoryCollectionFactory,
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \Magento\Framework\Registry $registry,
        array $data = []
        )
        {
            $this-&gt;_categoryCollectionFactory = $categoryCollectionFactory;
            $this-&gt;_productRepository = $productRepository;
            $this-&gt;_registry = $registry;
            parent::__construct($context, $data);
    }
    
    /**
     * Get category collection
     *
     * @param bool $isActive
     * @param bool|int $level
     * @param bool|string $sortBy
     * @param bool|int $pageSize
     * @return \Magento\Catalog\Model\ResourceModel\Category\Collection or array
     */
    public function getCategoryCollection($isActive = true, $level = false, $sortBy = false, $pageSize = false)
    {
        $collection = $this-&gt;_categoryCollectionFactory-&gt;create();
        $collection-&gt;addAttributeToSelect('*');        
        
        // select only active categories
        if ($isActive) {
            $collection-&gt;addIsActiveFilter();
        }
                
        // select categories of certain level
        if ($level) {
            $collection-&gt;addLevelFilter($level);
        }
        
        // sort categories by some value
        if ($sortBy) {
            $collection-&gt;addOrderField($sortBy);
        }
        
        // select certain number of categories
        if ($pageSize) {
            $collection-&gt;setPageSize($pageSize); 
        }    
        
        return $collection;
    }
    
    public function getProductById($id)
    {        
        return $this-&gt;_productRepository-&gt;getById($id);
    }
    
    public function getCurrentProduct()
    {        
        return $this-&gt;_registry-&gt;registry('current_product');
    }
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>如果您想使用当前产品，则该<code>getCurrentProduct()</code>功能处于活动状态。如果来自任何特定项目，请启用<code>getProductById($id)</code>该功能。之后，您可以从链接到该产品的类别 ID 中检索类别的集合。在该<code>.phtml</code>文件中，您需要添加以下代码片段：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$productId = 1; // YOUR PRODUCT ID
$product = $block-&gt;getProductById($productId);
 
// for current product
// $product = $block-&gt;getCurrentProduct();
 
$categoryIds = $product-&gt;getCategoryIds();
 
$categories = $block-&gt;getCategoryCollection()
                    -&gt;addAttributeToFilter('entity_id', $categoryIds);
                    
foreach ($categories as $category) {
    echo $category-&gt;getName() . '&lt;br&gt;';
}</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Mon, 16 Oct 2023 07:48:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 的 InstallSchema 中创建自动更新时间属性]]></title>
      <link>https://www.360magento.com/blog/how-to-create-auto-update-time-attributes-in-installschema-of-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>本主题的目的是帮助您使用 MYSQL<strong>在 Magento 2 的 InstallSchema 中创建自动更新时间属性。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-create-auto-update-time-attributes-in-installschema-of-magento-2">如何在 Magento 2 的 InstallSchema 中创建自动更新时间属性</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>MYSQL 将直接使用 TIMESTAMP 和 DATETIME，允许自动初始化、更新和显示网站上的当前日期和时间，而不必手动将正确的日期和时间值插入到 PHP 代码中，具体如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>自动初始化时间属性意味着自动加载当前时间戳和日期时间。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>自动更新时间属性意味着自动更新到当前时间戳和日期时间。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>为了在Magento 2商店中完美构建自动更新时间属性，您可以参考以下脚本代码。需要将代码添加到 InstallSchema 文件中。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>app/code/Example/HelloWorld/Setup/InstallSchema.php</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>这里有两列<code>created_at</code>并<code>update_at</code>包含在您的表格中。当您向数据表中设置新行时，created_at 列将进行自动初始化，如果您继续更新数据表中的一行，updated_at 将发生更改。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>...
-&gt;addColumn(
    'created_at',
    \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
    null,
    ['nullable' =&gt; false, 'default' =&gt; \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
    'Created At'
)-&gt;addColumn(
    'updated_at',
    \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
    null,
    ['nullable' =&gt; false, 'default' =&gt; \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
    'Updated At'
)
-&gt;addColumn(
    'created_at',
    \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
    null,
    ['nullable' =&gt; false, 'default' =&gt; \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
    'Created At'
)-&gt;addColumn(
    'updated_at',
    \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
    null,
    ['nullable' =&gt; false, 'default' =&gt; \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
    'Updated At'
)
...
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>最后，您需要<code>php bin/magento setup:upgrade</code>在控制台中运行该命令，之后，<code>created_at</code>和<code>updated_at</code>字段将在 MYSQL 中建立。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -113px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 16 Oct 2023 03:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何从 Magento 2 的模板文件 phtml 中获取区块]]></title>
      <link>https://www.360magento.com/blog/how-get-block-from-template-file-phtml-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>块是内容的模块化单元，可以放置在页面上的任何位置。块通常用于显示来自小部件、视频或文本的动态内容。以块的方式显示元素可以让商店管理员更轻松地随时管理和编辑。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>通常将内容块视为静态块或 CMS 块，用作促销横幅、图像或信息文本。您可以通过调用 PHTML 文件中的块来在 Magento 2 网站的每个页面上显示这些块，而无需花费大量时间进行配置。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>phtml</code>使用 PHTML 文件是在 Magento 2 中调用块的最佳方法之一。在这篇文章中，我将向您展示如何通过 PHP 代码从Magento 2 中的模板文件获取块。我将给出两个示例你在这里。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="example-1-to-get-block-in-phtml">示例 1 在 phtml 中获取块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果需要调用 的模板块<code>helloworld.phtml</code>，<code>Example_HelloWorld</code>请使用以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>echo $this-&gt;getLayout()
          -&gt;createBlock('Example\HelloWorld\Block\HelloWorld')
          -&gt;setTemplate('Example_HelloWorld::helloworld.phtml')
          -&gt;toHtml();
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="example-2-to-call-block-in-phtml">示例2在phtml中调用块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果您需要在Magento 2中的CMS静态块或CMS页面中调用模板块，请使用以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>
block class="Example\HelloWorld\Block\HelloWorld" name="your_block_name" template="Example_HelloWorld::helloworld.phtml"

</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>希望这是从模板文件中获取块的有用文章<code>phtml</code>。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sun, 15 Oct 2023 07:26:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何从 Magento 2 中的目录规则条件获取列表产品]]></title>
      <link>https://www.360magento.com/blog/how-to-get-list-product-from-catalog-rule-condition-in-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>从 Magento 2 中的目录规则条件获取列表产品</strong>是帮助您创建和观察所有促销活动的方法。在Magento 2商店中，您可以设置两种类型的促销规则：目录规则和购物车规则，但是我们都引用目录规则。根据您的需要，您可以<strong>生成多个目录促销规则</strong>并为每个规则应用多种条件。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-list-products-from-catalog-rule-condition-in-magento-2">从 Magento 2 中的目录规则条件获取列表产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>以下是如何通过在目录中创建类来从目录规则条件中获取列表产品的详细指南<code>\Magento\Rule\Model\AbstractModel</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
 
namespace Example\HelloWorld\Model;
class Rule extends \Magento\Rule\Model\AbstractModel
{
   protected $_productIds;
/**
* Get array of product ids which are matched by rule
*
* @return array
*/
public function getListProductIdsInRule()
{
     $productCollection = \Magento\Framework\App\ObjectManager::getInstance()-&gt;create(
         '\Magento\Catalog\Model\ResourceModel\Product\Collection'
     );
     $productFactory = \Magento\Framework\App\ObjectManager::getInstance()-&gt;create(
         '\Magento\Catalog\Model\ProductFactory'
     );
     $this-&gt;_productIds = [];
     $this-&gt;setCollectedAttributes([]);
     $this-&gt;getConditions()-&gt;collectValidatedAttributes($productCollection);
     \Magento\Framework\App\ObjectManager::getInstance()-&gt;create(
         '\Magento\Framework\Model\ResourceModel\Iterator'
     )-&gt;walk(
         $this-&gt;_productCollection-&gt;getSelect(),
         [[$this, 'callbackValidateProduct']],
         [
             'attributes' =&gt; $this-&gt;getCollectedAttributes(),
             'product' =&gt; $productFactory-&gt;create()
         ]
     );
     return $this-&gt;_productIds;
}
/**
* Callback function for product matching
*
* @param array $args
* @return void
*/
public function callbackValidateProduct($args)
{
     $product = clone $args['product'];
     $product-&gt;setData($args['row']);
     $websites = $this-&gt;_getWebsitesMap();
     foreach ($websites as $websiteId =&gt; $defaultStoreId) {
         $product-&gt;setStoreId($defaultStoreId);
         if ($this-&gt;getConditions()-&gt;validate($product)) {
             $this-&gt;_productIds[] = $product-&gt;getId();
         }
     }
}
/**
* Prepare website map
*
* @return array
*/
protected function _getWebsitesMap()
{
     $map = [];
     $websites = \Magento\Framework\App\ObjectManager::getInstance()-&gt;create(
         '\Magento\Store\Model\StoreManagerInterface'
     )-&gt;getWebsites();
     foreach ($websites as $website) {
         // Continue if website has no store to be able to create catalog rule for website without store
         if ($website-&gt;getDefaultStore() === null) {
             continue;
         }
         $map[$website-&gt;getId()] = $website-&gt;getDefaultStore()-&gt;getId();
     }
     return $map;
}
}</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -110px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 15 Oct 2023 03:18:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[系统配置中的 Magento 2 文件上传]]></title>
      <link>https://www.360magento.com/blog/how-file-upload-sytem-configuration-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>当您使用 Magento 2 管理界面时，完全可以<strong>在 Magento 2 系统配置中上传文件。</strong>在Magento 2中，管理界面接受各种输入类型，例如文本文件、单选按钮、下拉列表和多选，这些输入类型是纯文本、加密或序列化的，然后以不同的方式显示，例如网格、表单、简单字段和图像。支持多种文件类型，例如 XML、PHP、JPG、CSV、DOCS、XLS。特别是，Magento 还允许您扩展默认接口，然后您可以自由添加字段。现在让我们阅读这篇文章并获取详细说明。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-to-upload-the-file-in-magento-2-store-configuration">Magento 2商店配置中上传文件的方法</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>步骤1：创建system.xml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤2：刷新缓存并检查结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-create-systemxml-file">步骤1：创建system.xml文件。</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>按照路径<code>Store &gt; Configuration</code>，在<code>Sales</code>部分下，您可以创建一个新部分<code>custom_section</code>，创建一组新字段<code>custom_group</code>，并<code>custom_file_upload</code>通过<code>system.xml</code>在模块中添加文件来创建文件上传</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>应用以下代码片段。文件路径：<code>app/code/Example/HelloWorld/etc/adminhtml/system.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;section id="<span>example</span>_helloworld_section" translate="label" type="text" sortOrder="301" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
    &lt;label&gt;Sales&lt;/label&gt;
    &lt;tab&gt;sales&lt;/tab&gt;
    &lt;resource&gt;Magento_Sales::config_sales&lt;/resource&gt;
    &lt;group id="custom_group" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="1" &gt;
        &lt;label&gt;Custom group&lt;/label&gt;
        &lt;field id="custom_file_upload" translate="label" type="Magento\Config\Block\System\Config\Form\Field\File" sortOrder="6" showInDefault="1" showInWebsite="1" &gt;
            &lt;label&gt;Upload custom file&lt;/label&gt;
        &lt;/field&gt;
    &lt;/group&gt;
&lt;/section&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在上面的脚本中，有一些点您需要知道它们是什么。首先，<code>Section</code>字段是不言自明的，而<strong>选项卡</strong>是该部分的确切位置，<strong>销售</strong>选项卡是从 中设置的<code>Magento_Sales::etc/adminhtml/system.xml file</code>，<strong>资源</strong>将应用于ACL。但是，请记住，只有管理员才能<code>Magento_Sales::config_sales</code>访问此部分。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>接下来，<code>Group</code>在脚本代码中需要包含允许您根据需要上传文件的字段。该组包含<strong>id</strong>和<strong>type</strong>属性。<strong>id</strong>指向某些自定义文件上传，但它对于每个组来说肯定是唯一的。并且<strong>类型</strong>设置为<code>Magento\Config\Block\System\Config\Form\Field\File</code>，但是如果要上传图片，请记住类型<code>Magento\Config\Block\System\Config\Form\Field\Image</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>最后虽然得到了上传文件，但是还是不行。为您建议以下两件事。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在此后端模块中，您应该设置上传目录，检查允许的扩展名，验证文件大小并将文件路径保存到数据库。文件上传的默认后端模型是<code>Magento\Config\Model\Config\Backend\File</code>.&nbsp;然后我们添加<code>&lt;upload_dir&gt;</code>-上传目录来运行文件。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;backend_model&gt;Magento\Config\Model\Config\Backend\File&lt;/backend_model&gt;
&lt;upload_dir&gt;upload&lt;/upload_dir&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>从应用程序根目录，上传的文件将放在<code>magento_root/upload/</code>.&nbsp;但是，当您在上传目录中插入scope_info=&rdquo;1&rdquo;时，上传的文件将保存到基于范围的位置。如果您应用默认范围，文件将位于<code>magento_root/upload/default</code>.&nbsp;网站 1 会给我们<code>magento_root/upload/websites/1/</code>等。运行配置以清除所有内容：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;section id="<span>example</span>_helloworld_section" translate="label" type="text" sortOrder="301" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
    &lt;label&gt;Sales&lt;/label&gt;
    &lt;tab&gt;sales&lt;/tab&gt;
    &lt;resource&gt;Magento_Sales::config_sales&lt;/resource&gt;
    &lt;group id="custom_group" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="1" &gt;
        &lt;label&gt;Security&lt;/label&gt;
        &lt;field id="custom_file_upload" translate="label" type="Magento\Config\Block\System\Config\Form\Field\File" sortOrder="6" showInDefault="1" showInWebsite="1" &gt;
            &lt;label&gt;Upload custom file&lt;/label&gt;
            &lt;backend_model&gt;Magento\Config\Model\Config\Backend\File&lt;/backend_model&gt;
            &lt;upload_dir config="system" scope_info="1"&gt;test&lt;/upload_dir&gt;
        &lt;/field&gt;
    &lt;/group&gt;
&lt;/section&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>除了后端模型之外，您还可以参考其他选项，例如 frontend_model （例如，用于自定义&ldquo;拖放&rdquo;文件上传）、注释、工具提示、提示、验证等。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>在 Magento 2 商店配置中上传文件时，许多类型的文件都会被接受。但如果你想限制的话，这是不允许的。为此，请在<code>system.xml</code>文件 中<code>\<span>Example</span>\HelloWorld\Model\Config\Backend\CustomFileType</code>查看以下仅包含<code>csv</code>并<code>xls</code>感谢函数的示例<code>getAllowedExtensions()</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
 
namespace <span>Example</span>\HelloWorld\Model\Config\Backend;
 
class CustomFileType extends \Magento\Config\Model\Config\Backend\File
{
    /**
     * @return string[]
     */
    public function getAllowedExtensions() {
        return ['csv', 'xls'];
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-flush-cache-and-check-result">步骤2：刷新缓存并检查结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>刷新 Magento 缓存并检查结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -50px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 14 Oct 2023 07:29:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中将订单电子邮件发送到自定义电子邮件地址]]></title>
      <link>https://www.360magento.com/blog/how-to-crete-update-delete-cookie-in-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在这篇博文中，向您介绍如何使用自定义代码将订单电子邮件发送到Magento 2中的<strong>自定义电子邮件地址。</strong>本主题将通过以下两个步骤涵盖所有必要的操作。<a href="https://www.mageplaza.com/magento-2-extensions/"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="2-steps-to-send-order-email-to-a-custom-email-address-in-magento-2">将订单电子邮件发送到 Magento 2 中的自定义电子邮件地址的 2 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第一步：设置邮件格式</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第二步：设置控制器文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-set-a-form-of-the-email">第一步：设置邮件格式</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>使用输入字段行设置电子邮件的格式如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;form id="send-order-email" action="&lt;?php $block-&gt;getUrl('helloworld/order/sendemail'); ?&gt;"&gt;
    &lt;label&gt;Email Address&lt;/label&gt;
    &lt;input type="text" class="input-text" id="email"&gt;
&lt;/form&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-set-a-controller-file">第2步：设置控制器文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>文件路径：<code>app\code\Example\HelloWorld\Controller\Order\Email</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app\code\<code>Example</code>\HelloWorld\Controller\Order\Email</code>添加基于 class 的文件<code>\Magento\Framework\App\Action\Action</code>。该文件将从上面的表单中执行提交操作，但首先，请插入以下操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>public function execute()
    {
        $email = $this-&gt;getRequest()-&gt;getParam('email');
        $order = $this-&gt;_objectManager-&gt;create('Magento\Sales\Model\Order')-&gt;load(1); // this is entity id
        $order-&gt;setCustomerEmail($email);
        if ($order) {
            try {
                $this-&gt;_objectManager-&gt;create('\Magento\Sales\Model\OrderNotifier')
                    -&gt;notify($order);
                $this-&gt;messageManager-&gt;addSuccess(__('You sent the order email.'));
            } catch (\Magento\Framework\Exception\LocalizedException $e) {
                $this-&gt;messageManager-&gt;addError($e-&gt;getMessage());
            } catch (\Exception $e) {
                $this-&gt;messageManager-&gt;addError(__('We can\'t send the email order right now.'));
                $this-&gt;_objectManager-&gt;create('Magento\Sales\Model\OrderNotifier')-&gt;critical($e);
            }
        }
    }</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Sat, 14 Oct 2023 03:04:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中检查网址是否已通过 https、SSL 加密]]></title>
      <link>https://www.360magento.com/blog/how-check-url-secured-https-ssl-magento-2/</link>
      <description><![CDATA[<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="2-steps-to-check-if-the-url-is-secured-https-ssl-in-magento-2">在 Magento 2 中检查 url 是否安全 https、ssl 的 2 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>.phtml</code>步骤2：在模板文件中声明函数</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">第 1 步：声明<code>Mageplaza_HelloWorld</code></h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类，然后可能在模块的块类的构造函数中<code>Example_HelloWorld</code>注入 的对象。<code>StoreManagerInterface</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Mageplaza/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
    protected $_storeManager;    
    
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Store\Model\StoreManagerInterface $storeManager,        
        array $data = []
    )
    {        
        $this-&gt;_storeManager = $storeManager;        
        parent::__construct($context, $data);
    }
    
    /**
     * Check if frontend URL is secure
     *
     * @return boolean
     */
    public function isFrontUrlSecure()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;isFrontUrlSecure();
    }
    
    /**
     * Check if current requested URL is secure
     *
     * @return boolean
     */    
    public function isCurrentlySecure()
    {
        return $this-&gt;_storeManager-&gt;getStore()-&gt;isCurrentlySecure();
    }    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以在 中看到更多功能<code>vendor/magento/module-store/Model/Store.php</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-declare-function-in-template-phtml-file"><code>.phtml</code>步骤2：在模板文件中声明函数</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>.phtml</code>在模板文件中运行以下函数</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>var_dump($block-&gt;isFrontUrlSecure()) . '&lt;br /&gt;';
var_dump($block-&gt;isCurrentlySecure()) . '&lt;br /&gt;';</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -64px; top: -10.5625px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 13 Oct 2023 07:11:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 部署命令行]]></title>
      <link>https://www.360magento.com/blog/magento-2-deploy-command-line/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在本教程中，我们将讨论如何在命令行系列中<strong>部署命令</strong>行来执行 Magento 2 功能。如您所知，从 Magento 2 开始，他们在.&nbsp;Magento 开发人员对命令行太熟悉了，但如果您是这个领域的新手。本文将带您更深入地了解 Magento 2 命令行以及如何以易于理解的方式在 Magento 2 中部署它们。<a href="https://www.mageplaza.com/devdocs/magento-2-command-line-interface-cli.html"></a><code>bin/magento</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>让我们开始吧！</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="deploy-command-line">部署命令行</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>命令语法：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento setup:static-content:deploy &lt;lang&gt; ... &lt;lang&gt; [--dry-run] </code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="how-to-run-deploy-static-content">如何运行部署静态内容</h4>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento setup:static-content:deploy</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>它将显示如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$ php bin/magento setup:static-content:deploy

Requested languages: en_US
=== frontend -&gt; Magento/blank -&gt; en_US ===
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>默认情况下，它将运行默认语言的部署静态内容：<code>en_EN</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您想部署其他语言的静态内容，例如：<code>pt_BR</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento setup:static-content:deploy pt_BR</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>然后得到结果：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>Requested languages: pt_BR
=== frontend -&gt; Magento/luma -&gt; pt_BR ===
... progress indicator ...
Successful: 1613 files; errors: 0

=== frontend -&gt; Magento/blank -&gt; pt_BR ===
... progress indicator ...
Successful: 1620 files; errors: 0

=== adminhtml -&gt; Magento/backend -&gt; pt_BR ===
... progress indicator ...
Successful: 1626 files; errors: 0

=== Minify templates ===
... progress indicator ...
Successful: 858 files modified
---</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -229px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 13 Oct 2023 03:14:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何检查当前网址是否是 Magento 2 中的主页]]></title>
      <link>https://www.360magento.com/blog/how-check-current-url-homepage-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>如何检查当前URL是否为首页URL？</strong>您也想知道这个问题，并为您的Magento 2 商店寻找完美的方式。如果您曾经不确定某个页面是否是主页，这篇文章将指导您使用 PHP 代码来澄清它。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>开始吧！</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="3-steps-to-check-if-current-url-is-homepage-in-magento-2">检查当前 url 是否为 Magento 2 主页的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：声明<code>Example_HelloWorld</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>.phtml</code>步骤2：在模板文件中声明函数</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 3：获取<code>index.php</code>文件中的输出</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-declare-in-mageplaza_helloworld">第 1 步：声明<code>Example_HelloWorld</code></h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类<code>Example_HelloWorld</code>，然后可能将类的对象注入<code>Logo</code>到模块的块类的构造函数中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{
	protected $_logo;	
	
	public function __construct(
		\Magento\Backend\Block\Template\Context $context,
		\Magento\Theme\Block\Html\Header\Logo $logo,
		array $data = []
	)
	{		
		$this-&gt;_logo = $logo;
		parent::__construct($context, $data);
	}
	
	/**
     * Check if current url is url for home page
     *
     * @return bool
     */
    public function isHomePage()
    {	
		return $this-&gt;_logo-&gt;isHomePage();
	}
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以在 中看到更多功能<code>vendor/magento/module-theme/Block/Html/Header/Logo.php</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-declare-function-in-template-phtml-file"><code>.phtml</code>步骤2：在模板文件中声明函数</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>.phtml</code>在模板文件中运行以下函数</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>if ($block-&gt;isHomePage()) {
    // do something
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-get-output-in-indexphp-file">步骤 3：获取<code>index.php</code>文件中的输出</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获取当前页面（主页或其他页面）底部的输出，可以在文件中编写以下脚本<code>index.php</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$helloWorldBlock = $objectManager-&gt;get('Example\HelloWorld\Block\HelloWorld');
var_dump($helloWorldBlock-&gt;isHomePage());
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>请按照三个步骤即可查看当前网址。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -122px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 12 Oct 2023 08:08:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中按产品 ID 和 SKU 加载产品？]]></title>
      <link>https://www.360magento.com/blog/load-products-by-id-and-sku-in-magento-2/</link>
      <description><![CDATA[<p><span>如何通过产品 ID 和 SKU 加载 Magento 2 产品。加载产品是获取产品信息的一件重要事，也是很多商家最追捧的事情。这样做的目的是获取准确的产品信息，以便借助分配给特定产品的产品 ID 或 SKU 进行更改或执行其他操作。</span></p>
<p><span>让我们首先看看如何从产品 ID 加载产品。</span></p>
<p><span>方法 &ndash; 1：</span><span>&nbsp;Magento 不推荐使用这种简短的方法，因此我们也不使用。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-6513ed0a54d6d155848304" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d6d155848304-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d6d155848304-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d6d155848304-3">3</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d6d155848304-1"><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-cn">32</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d6d155848304-2"><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Framework</span><span class="crayon-sy">\</span><span class="crayon-v">App</span><span class="crayon-sy">\</span><span class="crayon-v">ObjectManager</span><span class="crayon-o">::</span><span class="crayon-e">getInstance</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d6d155848304-3"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-s">'Magento\Catalog\Api\ProductRepositoryInterface'</span><span class="crayon-sy">)</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getById</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>方法 - 2：</span><span>当您需要产品信息时，Magento 强烈推荐使用此方法。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-6513ed0a54d75265849036" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-16">16</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-17">17</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-18">18</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d75265849036-19">19</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-1"><span class="crayon-o">&lt;</span><span class="crayon-sy">?</span><span class="crayon-e">php</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-2"><span class="crayon-t">namespace</span><span class="crayon-h"> </span><span class="crayon-v">Vendor</span><span class="crayon-sy">\</span><span class="crayon-v">Extension</span><span class="crayon-sy">\</span><span class="crayon-v">Block</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-3">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-4"><span class="crayon-t">class</span><span class="crayon-h"> </span><span class="crayon-e">Product</span><span class="crayon-h"> </span><span class="crayon-r">extends</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-e">Magento</span><span class="crayon-sy">\</span><span class="crayon-e">Framework</span><span class="crayon-sy">\</span><span class="crayon-e">View</span><span class="crayon-sy">\</span><span class="crayon-e">Element</span><span class="crayon-sy">\</span><span class="crayon-e">Template</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-5"><span class="crayon-sy">{</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-6"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">protected</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span><span class="crayon-h">&nbsp;&nbsp;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-7">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-8"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">__construct</span><span class="crayon-sy">(</span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Catalog</span><span class="crayon-sy">\</span><span class="crayon-v">Api</span><span class="crayon-sy">\</span><span class="crayon-i">ProductRepositoryInterface</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-9"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-10"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-11">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-12"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">getProductDataUsingId</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-13"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-st">return</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getById</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productid</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-14"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-15"><span class="crayon-sy">}</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-16">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-17"><span class="crayon-e">PHTML </span><span class="crayon-e">file </span><span class="crayon-v">code</span><span class="crayon-sy">,</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-18"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">block</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getProductDataUsingId</span><span class="crayon-sy">(</span><span class="crayon-cn">32</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d75265849036-19"><span class="crayon-i">echo</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getName</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>现在，我们来看看如何按产品SKU加载产品。</span></p>
<p><span>方法 &ndash; 1：</span><span>&nbsp;Magento 不推荐使用这种简短的方法，因此我们也不使用。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-6513ed0a54d77046485380" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d77046485380-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d77046485380-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d77046485380-3">3</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d77046485380-1"><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-s">"productsku"</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d77046485380-2"><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Framework</span><span class="crayon-sy">\</span><span class="crayon-v">App</span><span class="crayon-sy">\</span><span class="crayon-v">ObjectManager</span><span class="crayon-o">::</span><span class="crayon-e">getInstance</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d77046485380-3"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">objectManager</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-s">'Magento\Catalog\Api\ProductRepositoryInterface'</span><span class="crayon-sy">)</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>方法 - 2：</span><span>当您需要产品信息时，Magento 强烈推荐使用此方法。</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-pc print-yes notranslate" id="urvanov-syntax-highlighter-6513ed0a54d79404353581" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-2">2</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-4">4</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-6">6</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-8">8</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-10">10</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-12">12</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-14">14</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-16">16</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-17">17</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-18">18</div>
<div class="crayon-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-19">19</div>
<div class="crayon-num crayon-striped-num" data-line="urvanov-syntax-highlighter-6513ed0a54d79404353581-20">20</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-1"><span class="crayon-o">&lt;</span><span class="crayon-sy">?</span><span class="crayon-e">php </span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-2"><span class="crayon-t">namespace</span><span class="crayon-h"> </span><span class="crayon-v">Vendor</span><span class="crayon-sy">\</span><span class="crayon-v">Extension</span><span class="crayon-sy">\</span><span class="crayon-v">Block</span><span class="crayon-sy">;</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-3">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-4"><span class="crayon-t">class</span><span class="crayon-h"> </span><span class="crayon-e">Product</span><span class="crayon-h"> </span><span class="crayon-r">extends</span><span class="crayon-h"> </span><span class="crayon-sy">\</span><span class="crayon-e">Magento</span><span class="crayon-sy">\</span><span class="crayon-e">Framework</span><span class="crayon-sy">\</span><span class="crayon-e">View</span><span class="crayon-sy">\</span><span class="crayon-e">Element</span><span class="crayon-sy">\</span><span class="crayon-e">Template</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-5"><span class="crayon-sy">{</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-6"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">protected</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-7">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-8"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">__construct</span><span class="crayon-sy">(</span><span class="crayon-sy">\</span><span class="crayon-v">Magento</span><span class="crayon-sy">\</span><span class="crayon-v">Catalog</span><span class="crayon-sy">\</span><span class="crayon-v">Api</span><span class="crayon-sy">\</span><span class="crayon-i">ProductRepositoryInterface</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-9"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">productrepository</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-10"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-11">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-12"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-m">public</span><span class="crayon-h"> </span><span class="crayon-t">function</span><span class="crayon-h"> </span><span class="crayon-e">getProductDataUsingSku</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-13"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-st">return</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-r">this</span><span class="crayon-o">-&gt;</span><span class="crayon-v">productrepository</span><span class="crayon-o">-&gt;</span><span class="crayon-e">get</span><span class="crayon-sy">(</span><span class="crayon-sy">$</span><span class="crayon-v">productsku</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-14"><span class="crayon-h">&nbsp;&nbsp;</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-15"><span class="crayon-sy">}</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-16">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-17">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-18"><span class="crayon-e">PHTML </span><span class="crayon-e">file </span><span class="crayon-v">code</span><span class="crayon-sy">,</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-19"><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-h"> </span><span class="crayon-o">=</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">block</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getProductDataUsingSku</span><span class="crayon-sy">(</span>&ldquo;<span class="crayon-i">productsku</span>&rdquo;<span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6513ed0a54d79404353581-20"><span class="crayon-i">echo</span><span class="crayon-h"> </span><span class="crayon-sy">$</span><span class="crayon-v">product</span><span class="crayon-o">-&gt;</span><span class="crayon-e">getName</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span><span>所以，现在就这样了。</span><span>使用这些代码，您将能够按 ID 或 SKU 加载产品信息（无论您喜欢哪种）。</span></span></p>]]></description>
      <pubDate>Thu, 12 Oct 2023 03:06:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中调整产品图像大小]]></title>
      <link>https://www.360magento.com/blog/how-change-product-image-size-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>产品图片尺寸</strong>是一个很好的属性，可以通过产品细节让您的商品更贴近消费者。因为在网上购物时，顾客无法真正触摸到你的商品，他们都是通过你发布的描述和你上传的产品图片来感受的。形象越美丽，他们的欲望就越多。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>而尺寸的标准是你需要学习的主要特征之一。那么如何更改产品图片尺寸以适合您的页面尺寸。<strong>关于Magento 2 图像调整大小</strong>的本主题将通过详细说明向您展示如何执行此操作。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="simple-methods-to-change-the-product-image-size-in-magento-2">在 Magento 2 中更改产品图像尺寸的简单方法</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法1：更改HelloWorld块中的产品图片大小</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法2：更改模板文件中的产品图片尺寸</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-1-change-product-image-in-helloworld-block"><code>HelloWorld</code>方法一：批量更改产品图片</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在 Magento 2 中调整图像大小的第一种方法是通过<strong>HelloWorld 块</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>您将使用 module 的块类，然后可能在模块的块类的构造函数中注入和类<code>Example_HelloWorld</code>的对象。<code>\Magento\Catalog\Model\ProductRepository\Magento\Catalog\Helper\Image</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>app/code/Example/HelloWorld/Block/HelloWorld.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class HelloWorld extends \Magento\Framework\View\Element\Template
{    
    protected $_productRepository;
    protected $_productImageHelper;
        
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\ProductRepository $productRepository,
        \Magento\Catalog\Helper\Image $productImageHelper,
        array $data = []
    )
    {
        $this-&gt;_productRepository = $productRepository;
        $this-&gt;_productImageHelper = $productImageHelper;
        parent::__construct($context, $data);
    }
    
    public function getProductById($id)
    {
        return $this-&gt;_productRepository-&gt;getById($id);
    }
    
    public function getProductBySku($sku)
    {
        return $this-&gt;_productRepository-&gt;get($sku);
    }
    
    /**
     * Schedule resize of the image
     * $width *or* $height can be null - in this case, lacking dimension will be calculated.
     *
     * @see \Magento\Catalog\Model\Product\Image
     * @param int $width
     * @param int $height
     * @return $this
     */
    public function resizeImage($product, $imageId, $width, $height = null)
    {
        $resizedImage = $this-&gt;_productImageHelper
                           -&gt;init($product, $imageId)
                           -&gt;constrainOnly(TRUE)
                           -&gt;keepAspectRatio(TRUE)
                           -&gt;keepTransparency(TRUE)
                           -&gt;keepFrame(FALSE)
                           -&gt;resize($width, $height);
        return $resizedImage;
    }    
}
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>当您将产品基础图像的大小调整为精确的高度和宽度时，请记住约束、长宽比和透明度需要正确。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，您可以按照以下示例加载产品，然后更改产品的图像并显示它。这里，<code>produt_base_image</code>使用 来作为图像 ID。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
//Get product object by ID
$id = 'PRODUCT_ID';
$_product = $block-&gt;getProductById($id);

//Get product object by SKU
// $sku = 'PRODUCT_SKU';
// $_product = $block-&gt;getProductBySku($sku);
 
$imageId = 'product_base_image';
$width = 200;
$height = 300;
 
$resizedImageUrl = $block-&gt;resizeImage($product, 'product_base_image', $width, $height)-&gt;getUrl();
?&gt;
&lt;img src="&lt;?php echo $resizedImageUrl;?&gt;" alt="&lt;?php echo $_product-&gt;getTitle();?&gt;" /&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-2-change-product-image-in-the-template-file">方法二：更改模板文件中的产品图片</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>除了自定义 HelloWorld 块之外，您还可以更改模板 (.phtml) 文件中的产品图像。使用下面的代码片段并在模板文件中运行它。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
//Get product object by ID
$id = 'PRODUCT_ID';
$_product = $block-&gt;getProductById($id);

//Get product object by SKU
// $sku = 'PRODUCT_SKU';
// $_product = $block-&gt;getProductBySku($sku);
 
$imageId = 'product_base_image';
$width = 200;
$height = 300;
 
$resizedImageUrl = $_imageHelper
                        -&gt;init($product, $imageId)
                        -&gt;constrainOnly(true)
                        -&gt;keepAspectRatio(true)
                        -&gt;keepTransparency(true)
                        -&gt;keepFrame(false)
                        -&gt;resize($width, $height)
                        -&gt;getUrl();
?&gt;
&lt;img src="&lt;?php echo $resizedImageUrl;?&gt;" alt="&lt;?php echo $_product-&gt;getTitle();?&gt;" /&gt;
</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Wed, 11 Oct 2023 07:58:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[获取父产品：Magento 2 中的捆绑产品、分组产品]]></title>
      <link>https://www.360magento.com/blog/get-parent-product-bundle-grouped-products-in-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>Magento 2 支持两种类型的父产品，包括捆绑产品和分组产品。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>今天我将引导您以简单的方式获取<strong>父产品：Magento 2 中的捆绑产品和分组产品。</strong>捆绑产品和分组产品是您可以从Magento 2 商店后端创建的两种产品类型，它们包括一些子产品。您想知道如果您持有子产品的 id，是否可以获得父产品的 id。这里是指导您应该做什么的正确地方。让我们来看看每种产品类型的代码片段。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="bundle-product">捆绑产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>进入类<code>Magento\Bundle\Model\Product\Type</code>，有两个函数：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>/**
* Retrieve Required children ids
* Return grouped array, ex array(
*   group =&gt; array(ids)
* )
*
* @param int $parentId
* @param bool $required
* @return array
*/
public function getChildrenIds($parentId, $required = true)
{
   return $this-&gt;_bundleSelection-&gt;getChildrenIds($parentId, $required);
}
 
/**
* Retrieve parent ids array by required child
*
* @param int|array $childId
* @return array
*/
public function getParentIdsByChild($childId)
{
   return $this-&gt;_bundleSelection-&gt;getParentIdsByChild($childId);
}
 
Configurable product: You can see the class Magento\ConfigurableProduct\Model\Product\Type\Configurable, it also has two functions:
 
/**
* Retrieve Required children ids
* Return grouped array, ex array(
*   group =&gt; array(ids)
* )
*
* @param  array|int $parentId
* @param  bool $required
* @return array
*/
public function getChildrenIds($parentId, $required = true)
{
   return $this-&gt;_catalogProductTypeConfigurable-&gt;getChildrenIds($parentId, $required);
}
 
/**
* Retrieve parent ids array by required child
*
* @param  int|array $childId
* @return array
*/
public function getParentIdsByChild($childId)
{
   return $this-&gt;_catalogProductTypeConfigurable-&gt;getParentIdsByChild($childId);
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="grouped-product">分组产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento\GroupedProduct\Model\Product\Type\Grouped 类：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>/**
* Retrieve Required children ids
* Return grouped array, ex array(
*   group =&gt; array(ids)
* )
*
* @param int $parentId
* @param bool $required
* @return array
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getChildrenIds($parentId, $required = true)
{
   return $this-&gt;productLinks-&gt;getChildrenIds(
       $parentId,
       \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED
   );
}
 
/**
* Retrieve parent ids array by requested child
*
* @param int|array $childId
* @return array
*/
public function getParentIdsByChild($childId)
{
   return $this-&gt;productLinks-&gt;getParentIdsByChild(
       $childId,
       \Magento\GroupedProduct\Model\ResourceModel\Product\Link::LINK_TYPE_GROUPED
   );
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您要在上面的类中引用的两个函数是<code>getChildrenIds</code>和<code>getParentIdsByChild</code>。这样，定义产品类型是前提，所以当然可以加载产品并声明函数，<code>getTypeInstance</code>如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$product-&gt;getTypeInstance()-&gt;getParentIdsByChild($child-&gt;getId());</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -174px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 10 Oct 2023 07:20:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中 Rest API 中的常见错误 HTTP 代码]]></title>
      <link>https://www.360magento.com/blog/common-error-http-codes-magento-rest-api/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>今天我将向您介绍<strong>Magento 2 Rest API 中的常见错误 HTTP 代码</strong>。首先你还需要知道什么是HTTP？HTTP代表超文本传输​​协议，是网站上的默认协议。在使用该协议的过程中，可能会出现一些常见的错误，这些错误称为HTTP错误代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>下面包含Magento 2 Rest API中的代码列表以及每个常见错误 HTTP 代码的含义，以便更好地理解。为了避免遇到这些错误，您需要首先充分理解每个错误。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-400">HTTP 错误 400</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>持续的：<code>Magento\Framework\Webapi\Exception::HTTP_BAD_REQUEST</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>信息含义： 请求数据无效。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-401">HTTP 错误 401</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_UNAUTHORIZED</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：授权失败。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-403">HTTP 错误 403</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_FORBIDDEN</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：访问被拒绝。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-404">HTTP 错误 404</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_NOT_FOUND</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：找不到资源。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-405">HTTP 错误 405</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_METHOD_NOT_ALLOWED</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：资源不支持方法。/ 资源方法尚未实现。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-406">HTTP 错误 406</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_NOT_ACCEPTABLE</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：所请求的资源不接受该请求。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="http-error-500">HTTP 错误 500</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>常量：Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述：资源内部错误。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>接下来，我将给您提供获取一些错误 HTTP 代码的示例。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您在 API 方法中运行异常：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>if (!$productId) {
 
throw new \Magento\Framework\Exception\NoSuchEntityException(__('Requested product doesn\'t exist'));
 
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>此时，响应中将显示 HTTP 错误 404。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>或者你可以使用Magento中提供的异常类<code>Magento\Framework\Exception</code>，或者使用通用异常类\Exception：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>if (!$productId) {
 
throw new \Exception(__('Requested product doesn\'t exist'));
 
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>确保错误代码始终为 500 (Magento\Framework\Webapi\Exception::HTTP_INTERNAL_ERROR)。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>您可能会收到此错误消息：出于安全原因，默认情况下禁用异常打印</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Mon, 09 Oct 2023 07:14:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更改 Magento 2 中的Block参数]]></title>
      <link>https://www.360magento.com/blog/change-block-arguments-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在这篇文章中，我将指导您如何<strong>更改 Magento 2 中的Block参数</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-change-block-arguments">如何更改块参数</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>首先，您需要修改要更改的目标块参数。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>对于要修改的块参数，<code>&lt;referenceBlock&gt;</code>使用该指令。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>下面是如何更改现有块参数值并添加新参数的示例。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>初始块声明：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;block class="Namespace_Module_Block_Type" name="block.example"&gt;
  &lt;arguments&gt;
    &lt;argument name="label" xsi:type="string"&gt;Block Label&lt;/argument&gt;
  &lt;/arguments&gt;
&lt;/block&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>扩展布局：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;referenceBlock name="block.example"&gt;
  &lt;arguments&gt;
    &lt;!-- Modified block argument --&gt;
    &lt;argument name="label" xsi:type="string"&gt;New Block Label&lt;/argument&gt;
    &lt;!- Newly added block argument --&gt;
    &lt;argument name="custom_label" xsi:type="string"&gt;Custom Block Label&lt;/argument&gt;
  &lt;/arguments&gt;
&lt;/referenceBlock&gt;</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -195px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 08 Oct 2023 07:09:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 布局中创建/引用容器]]></title>
      <link>https://www.360magento.com/blog/create-reference-container-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 中，布局、容器和块是页面设计的基本组成部分。或者 Magento 2 使用容器和块来构建页面布局。在这篇文章中，我将演示如何在 Magento 2 中创建/引用容器。为了帮助您更深入地理解，首先，我将说明和定义一些重要术语：</p>
<p><!-- /wp:paragraph --> <!-- wp:image {"id":4093,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-4093" src="http://kb.360magento.net/wp-content/uploads/2023/09/jL5gcLR.png" /><img src="https://www.360magento.com/media/wysiwyg/jL5gcLR.png" /> <!-- /wp:image --> <!-- wp:paragraph --></p>
<p>(1) 网页的结构由布局来表示。更具体地说，使用标识构成页面的所有容器和块的XML文件，提供网页的结构。稍后将描述布局 XML 文件的详细信息。(2) 网页结构中的占位符由容器表示。通过使用布局 XML 文件中的块标签将内容结构分配给页面。除了包含元素的内容外，没有额外的内容。<br />(3) 容器占位符内的 UI 控件或组件由块表示。通过在布局 XML 文件中使用块标签，可以呈现页面上的 UI 元素。块使用模板来生成 HTML 以插入其父结构块中。块的示例中包含类别列表、迷你购物车、产品列表和产品标签。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，我将向您展示<strong>在 Magento 2 中创建/引用容器的最简单方法。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>创建/引用容器</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>如何创建容器</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如何引用容器</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-create-a-container">如何创建容器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>为了创建容器，您可以使用以下示例：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;container name="some.container" as="someContainer" label="Some Container" htmlTag="div" htmlClass="some-container" /&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-reference-a-container">如何引用容器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>对于要更新的​​容器，请使用<code>&lt;referenceContainer&gt;</code>说明。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>以下是向页面监听器面板添加链接的示例：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;referenceContainer name="header.panel"&gt;
  &lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;
    &lt;arguments&gt;
      &lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;
    &lt;/arguments&gt;
  &lt;/block&gt;
&lt;/referenceContainer&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>如果您想使用容器来包装 div 或 block，请按以下步骤操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;container name="some.container" as="someContainer" label="Some Container" htmlTag="div" htmlClass="some-container"&gt;
  &lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;
    &lt;arguments&gt;
      &lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;
    &lt;/arguments&gt;
  &lt;/block&gt;
&lt;/container&gt;</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -20px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 07 Oct 2023 08:10:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加/删除静态文件 JS、CSS、字体]]></title>
      <link>https://www.360magento.com/blog/add-remove-static-files-js-css-fonts-magento/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在今天的文章中，我将指导您如何在 Magento 2 中<strong>添加和删除静态文件，包括 JS、CSS 和字体。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>通过这个易于理解的教程，添加或删除静态文件 JS、CSS、字体将变得很容易。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>让我们现在开始！</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>添加静态文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>删除静态文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="add">添加静态文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>通常，如果您想在 Magento 2 中使用外部库自定义页面，则需要添加 JavaScript 和 CSS 文件。JavaScript、CSS 和其他静态文件将添加到页面配置文件的 &lt;head&gt; 部分。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在页面配置文件中，该<code>&lt;head&gt;</code>部分包括各种静态资源，例如JavaScript、CSS。该文件定义了Magento 商店页面中<code>app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml</code>该部分的原始外观。<code>&lt;head&gt;</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>要添加 CSS 和 JavaScript，建议您在自定义主题中扩展该文件，然后在其中添加文件。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>以下是必须添加的文件示例：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;head&gt;
    &lt;!-- Add local resources --&gt;
    &lt;css src="css/my-styles.css"/&gt;
    &lt;!-- The following two ways to add local JavaScript files are equal --&gt;
    &lt;script src="Magento_Catalog::js/sample1.js"/&gt;
    &lt;link src="js/sample.js"/&gt;
    &lt;!-- Add external resources --&gt;
    &lt;css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" src_type="url" /&gt;
    &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" src_type="url" /&gt;
    &lt;link rel="stylesheet" type="text/css" src="http://fonts.googleapis.com/css?family=Montserrat" src_type="url" /&gt;
  &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>添加外部资源时，您必须指定<code>src_type="url"</code>参数值。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>或<code>&lt;link src="js/sample.js"/&gt;</code>指令<code>&lt;script src="js/sample.js"/&gt;</code>可用于将本地存储的 JavaScript 文件添加到您的主题中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>以下位置之一相对指定资产的路径：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><code>&lt;theme_dir&gt;/web-</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web-</code></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="add-conditional-comments">添加条件注释</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>条件注释用于为 Internet Explorer 提供特殊指令。在添加文件方面，可以为您添加 CSS 文件，以将其包含在 Internet Explorer 的特定版本中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>这是一个例子：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;head&gt;
    &lt;css src="css/ie-9.css" ie_condition="IE 9" /&gt;
  &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>这里，在生成的HTML中添加了一条IE条件注释，请查看以下示例：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;!--[if IE 9]&gt;
&lt;link rel="stylesheet" type="text/css" media="all" href="&lt;your_store_web_address&gt;/pub/static/frontend/OrangeCo/orange/en_US/css/ie-9.css" /&gt;
&lt;![endif]--&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在上面的示例中，<code>orange</code>是 OrangeCo 供应商创建的自定义主题。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="remove">删除静态文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>对于要删除的页面中链接的静态资源<code>&lt;head&gt;</code>，您可以在主题扩展中进行更改，<code>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml</code>如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;head&gt;
    &lt;!-- Remove local resources --&gt;
    &lt;remove src="css/styles-m.css" /&gt;
    &lt;remove src="my-js.js"/&gt;
    &lt;remove src="Magento_Catalog::js/compare.js" /&gt;
    &lt;!-- Remove external resources --&gt;
    &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"/&gt;
    &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"/&gt;
    &lt;remove src="http://fonts.googleapis.com/css?family=Montserrat" /&gt;
   &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您需要记住，如果在初始布局中添加或删除具有模块路径的静态资源，则需要指定模块路径，例如<code>Magento_Catalog::js/sample.js</code>.</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Fri, 06 Oct 2023 02:56:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中将元标签添加到head]]></title>
      <link>https://www.360magento.com/blog/add-meta-tags-header-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>您可能已经知道，页面的 HTML<code>&lt;head&gt;</code>部分包括不同的元标记、CSS、JS 文件定义、JS 代码片段等。通常，不需要复杂的逻辑来添加一些适当的内容。然而，在各种情况下，我们需要将几个取决于系统配置的元素插入到头部。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您一直使用Magento 1，您会发现使用head部分的内容很容易操作。然而，在最新的 Magento 版本中，<strong>向标头添加元标记</strong>对您来说可能有点棘手。因此，在今天的文章中，我将指导您如何添加块和模板，更具体地说，如何将<strong>元标签添加</strong>到 Magento 2 的头部部分。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="add-meta-tags-to-header">将元标签添加到标题</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>为了<code>&lt;meta&gt;</code>向布局<code>&lt;head&gt;</code>元素添加标签，您需要创建一个类似于以下内容的主题扩展文件：<code>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>默认情况下，是呈现标签<code>\Magento\Framework\View\Page\Config\Renderer</code>的类。<code>&lt;meta&gt;</code>有五种类型的元，并且此类呈现包罗万象的（默认）：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>og</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>charset</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>content_type</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>x_ua_compatible</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>media_type</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>&ldquo;default&rdquo; case</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>您可以使用以下内容作为示例来包含在布局主题中：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;head&gt;
    &lt;!-- This will create a tag like '&lt;meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&gt;' --&gt;
    &lt;meta name="x_ua_compatible" content="IE=edge,chrome=1"/&gt;
    &lt;!-- This will create a tag like '&lt;meta property="og:type" content="article"/&gt;'' --&gt;
    &lt;meta name="og:type" content="article"/&gt;
    &lt;!-- This will create a tag like '&lt;meta charset="UTF-8"&gt;' --&gt;
    &lt;meta name="charset" content="UTF-8"/&gt;
    &lt;!-- This will create a tag like '&lt;meta http-equiv="Content-Type" content="content-type-value"/&gt;' --&gt;
    &lt;meta name="content_type" content="content-type-value"/&gt;
    &lt;!-- This tag will not render (see \Magento\Framework\View\Page\Config\Renderer for details) --&gt;
    &lt;meta name="media_type" content="any-value"/&gt;
    &lt;!-- This will create a tag like '&lt;meta name="my_custom_type" content="my_custom_value"/&gt;' --&gt;
    &lt;meta name="my_custom_type" content="my_custom_value"/&gt;
   &lt;/head&gt;
&lt;/page&gt;</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -13px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 05 Oct 2023 07:49:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重写布局文件]]></title>
      <link>https://www.360magento.com/blog/overriding-native-layout-file-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>布局可以被视为核心组件之一，因为它使用 XML 文件来表示网页设计的结构，其中适当地显示了用户界面控件。当您想使用自定义扩展调整网页而不弄乱 Magento 核心文件中的内容时，在这种情况下覆盖本机布局文件将是您的最佳选择。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>此外，在Magento 2中，并非所有布局自定义都可以通过扩展布局来执行。如果定制量太大，最好使用覆盖。覆盖布局意味着将使用您在主题中创建的新文件，而不是基本布局文件的父主题布局文件中的布局文件。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在让我们详细了解如何在 Magento 2 中<strong>覆盖本机布局文件</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="magento-2-overriding-native-layout-file">Magento 2 覆盖本机布局文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>特别是，要覆盖 Magento 基本布局文件，您需要在下面提到的位置创建一个布局文件。<code>.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;theme_dir&gt;
  |__/&lt;Namespace_Module&gt;
    |__/layout
      |__/override
         |__/base
           |--&lt;layout1&gt;.xml
           |--&lt;layout2&gt;.xml
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>找到文件后，以下布局将被该文件覆盖：&nbsp;<code>&lt;module_dir&gt;/view/frontend/layout/&lt;layout1&gt;.xml</code>&nbsp;<code>&lt;module_dir&gt;/view/frontend/layout/&lt;layout2&gt;.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="magento-2-override-theme-layouts">Magento 2 覆盖主题布局</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>另一方面，要覆盖主题布局，您可以重复上述步骤。但是，这次您的新布局文件必须位于另一个位置，即：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;theme_dir&gt;
  |__/&lt;Namespace_Module&gt;
    |__/layout
      |__/override
         |__/theme
            |__/&lt;Parent_Vendor&gt;
               |__/&lt;parent_theme&gt;
                  |--&lt;layout1&gt;.xml
                  |--&lt;layout2&gt;.xml
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>以下文件将被覆盖：&nbsp;<code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout1&gt;.xml</code>&nbsp;<code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout2&gt;.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>请记住，您的新布局文件的名称需要与您要覆盖的文件的名称相同。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -86px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 04 Oct 2023 07:46:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 API：创建客户]]></title>
      <link>https://www.360magento.com/blog/create-customer-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>客户可以通过三种方式进行购买：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>购买前请先登录</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>下订单时登录或创建帐户</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>购买时不创建帐户</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>虽然顾客可以通过自己喜欢的方式进行购买，但很方便。如果客户没有在您的商店中创建帐户，您可能很难获取信息来建立客户群。但是，您可以代表他们创建客户帐户。通过这个易于理解的教程，这比您想象的要容易。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在本教程中，订单是由已登录的用户创建的。对于来宾用户，将提供额外的 REST 端点来处理它们。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>但在此之前，让我们按照以下步骤调用API<strong>创建客户。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>使用 Magento 2 API 分 3 个步骤创建客户：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建客户帐户</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：获取客户的访问令牌</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：验证此步骤</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-create-a-customer-account">第 1 步：创建客户帐户</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要创建客户帐户，需要管理员权限。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>注意</strong>：在此示例中，将显示创建客户帐户的简化方法。此处将指定不带密码参数的有效负载，而不是使用纯文本定义客户密码。在默认设置中，当呼叫成功时，将向客户发送一封<em>欢迎电子邮件，其中包含设置密码的请求。</em>此外，通过致电<code>PUT /V1/customers/password</code>，您可以发起密码重置电子邮件。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>POST &lt;host&gt;/rest/&lt;store_code&gt;/V1/customers</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="headers">Headers</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>Content-Type application/json</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>Authorization Bearer &lt;admin token&gt;</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>您应该用真实的电子邮件地址替换电子邮件参数的值。如果您这样做，您就可以收到所有通知。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>代码示例</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
    "customer": {
        "email": "jdoe@example.com",
        "firstname": "Jane",
        "lastname": "Doe",
        "addresses": [{
            "defaultShipping": true,
            "defaultBilling": true,
            "firstname": "Jane",
            "lastname": "Doe",
            "region": {
                "regionCode": "NY",
                "region": "New York",
        "regionId":43
            },
            "postcode": "10755",
            "street": ["123 Oak Ave"],
            "city": "Purchase",
            "telephone": "512-555-1111",
            "countryId": "US"
        }]
    },
  "password": "Password1"
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="response">Response</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>这个用户 ID 值 2 是由 Magento 分配的。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>代码示例</strong>'</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
  "id": 2,
  "group_id": 1,
  "default_billing": "2",
  "default_shipping": "2",
  "created_at": "2017-01-31 01:18:13",
  "updated_at": "2017-01-31 01:18:13",
  "created_in": "Default Store View",
  "email": "jdoe@example.com",
  "firstname": "Jane",
  "lastname": "Doe",
  "store_id": 1,
  "website_id": 1,
  "addresses": [
    {
      "id": 2,
      "customer_id": 2,
      "region": {
        "region_code": "NY",
        "region": "New York",
        "region_id": 43
      },
      "region_id": 43,
      "country_id": "US",
      "street": [
        "123 Oak Ave"
      ],
      "telephone": "512-555-1111",
      "postcode": "10755",
      "city": "Purchase",
      "firstname": "Jane",
      "lastname": "Doe",
      "default_shipping": true,
      "default_billing": true
    }
  ],
  "disable_auto_group_change": 0
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以使用用户名<code>jdoe@example.com</code>和密码<code>Password1</code>登录Luma商店</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-get-the-customers-access-token">第 2 步：获取客户的访问令牌</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>为了获取客户的访问令牌，必须在有效负载中指定客户的用户名和密码。不需要指定管理员授权令牌。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>默认情况下，客户令牌的有效时间为1小时。如果您想更改此值，请登录您的管理面板，然后转至<code>Stores &gt; Settings &gt; Configuration &gt; Services &gt; OAuth &gt; Access Token Expiration</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>POST &lt;host&gt;/rest/&lt;store_code&gt;/V1/integration/customer/token</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="headers-1">Headers</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>Content-Type application/json</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="payload-1">Payload</h3>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
"username": "jdoe@example.com",
"password": "Password1"
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="response-1">Response</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 返回客户的访问令牌。必须在客户代表自己进行的每次调用的授权标头中指定它。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>q0u66k8h42yaevtchv09uyy3y9gaj2ap</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-verify-this-step">第三步：验证此步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>使用邮箱<code>jdoe@example.com</code>和密码<code>Password1</code>登录Luma网站。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击右上角的帐户名称并选择<code>My Account</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要查看帐单和送货地址，请单击<code>Address Book</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Tue, 03 Oct 2023 07:51:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 API 获取所有产品、订单、类别]]></title>
      <link>https://www.360magento.com/blog/get-all-products-orders-categories-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在Magento 2中，您可以调用API轻松获取所有产品。多个 REST 调用会返回数千甚至数百个参数。解析所有这些数据有时可能很麻烦。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>此外，移动应用程序开发人员可能会发现处理不合理的请求需要带宽。为了处理这些问题，为 REST 请求提供了基于查询参数的语法，该语法返回部分响应。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>&lt;host&gt;/rest/&lt;store_code&gt;</code>可以替换为您的网站。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>查询<code>searchCriteria</code>参数使您能够搜索集合中的多个对象。fields 查询参数可以与 结合使用来<code>searchCriteria</code>限制输出。本文档中所有示例中字段前面的问号 (?) 将替换为与号 (&amp;)。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>获取所有产品、订单、类别</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>获取所有产品</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取具有类别的产品</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取所有订单</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>获取类别</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-all-products">获取所有产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>以下查询仅返回category_gear 属性包含值 86 的产品项目的 sku 和名称参数。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>GET &lt;host&gt;/rest/&lt;store_code&gt;/V1/products/?searchCriteria[filter_groups][0][filters][0][field]=category_gear&amp;searchCriteria[filter_groups][0][filters][0][value]=86&amp;searchCriteria[filter_groups][0][filters][0][condition_type]=finset&amp;fields=items[sku,name]</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
"items":
  {
    "sku": "24-MG04"
    "name": "Aim Analog Watch"
  }
  {
    "sku": "24-MG01"
    "name": "Endurance Watch"
  }
  {
    "sku": "24-MG03"
    "name": "Summit Watch"
  }
  {
    "sku": "24-MG05"
    "name": "Cruise Dual Analog Watch"
  }
  {
    "sku": "24-MG02"
    "name": "Dash Digital Watch"
  }
  {
    "sku": "24-WG09"
    "name": "Luma Analog Watch"
  }
  {
    "sku": "24-WG01"
    "name": "Bolo Sport Watch"
  }
  {
    "sku": "24-WG03"
      "name": "Clamber Watch"
  }
  {
    "sku": "24-WG02"
    "name": "Didi Sport Watch"
  }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>每页限制 20 项：<code>/V1/products?searchCriteria[pageSize]=20</code><a href="https://devdocs.magento.com/guides/v2.4/rest/modules/catalog.html"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-products-categories">获取具有类别的产品</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>GET &lt;host&gt;/rest/&lt;store_code&gt;/V1/products/MT12?fields=name,sku,extension_attributes[category_links,stock_item[item_id,qty]]</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
  "sku": "MT12"
  "name": "Cassius Sparring Tank"
  "extension_attributes": {
    "category_links": {
      "position": 1
      "category_id": "18"
    }
    "stock_item": {
      "item_id": 732
      "qty": 0
      }
  }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>上面的示例返回以下结果：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>产品<code>sku</code>的和<code>name</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>整个<code>category_links</code>物体。这是定义在<code>extension_attributes</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>对象<code>stock_item</code>和<code>item_id</code>字段<code>qty</code>。这些也定义在<code>extension_attributes</code></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-all-orders">获取所有订单</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>GET &lt;host&gt;/rest/&lt;store_code&gt;/V1/orders/2?fields=billing_address,customer_firstname,customer_lastname</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
  "customer_firstname": "Veronica"
  "customer_lastname": "Costello"
  "billing_address": {
    "address_type": "billing"
    "city": "Calder"
    "country_id": "US"
    "customer_address_id": 1
    "email": "roni_cost@example.com"
    "entity_id": 4
    "firstname": "Veronica"
    "lastname": "Costello"
    "parent_id": 2
    "postcode": "49628-7978"
    "region": "Michigan"
    "region_code": "MI"
    "region_id": 33
    "street": "6146 Honey Bluff Parkway"
    "telephone": "(555) 229-3326"
    }
  }
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>上面的示例返回客户的名字和姓氏以及<code>billing_address</code>指定订单的整个对象。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>当您希望返回对象的所有内容时，请勿在对象名称后添加括号[]。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-categories">获取类别</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>POST &lt;host&gt;/rest/&lt;store_code&gt;/V1/categories?fields=id,parent_id,name</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>Payload</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
  "category": {
    "name": "New Category",
    "is_active": true
  }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p><strong>Response</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{
  "id": 43,
  "parent_id": 2,
  "name": "New Category"
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>上述 POST 操作和有效负载用于创建名为 的目录类别<code>New Category</code>。这里仅返回<code>id</code>、<code>parent_id</code>和属性。<code>name</code></p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -133px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 02 Oct 2023 07:44:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 自定义产品价格添加购物车]]></title>
      <link>https://www.360magento.com/blog/add-product-to-cart-with-custom-price-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>通常，即使消费者从前端为所有或某些特定产品选择各种选项/附加产品，店主也准备设置固定的产品定价。我们不需要手动更改所有商店产品，而是需要手动编码以使用您首选的自定义价格覆盖所有商店产品价格。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在本文中，我将指导您在使用 Observe<strong>将产品添加到购物车时设置产品的自定义价格。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>让我们探讨下面两个简单的步骤！</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 Events/xml 文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：创建 CustomPrice.php 文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建 Events/xml 文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>首先，您需要<code>events/xml</code>在文件夹中创建<code>Webkul/Hello/etc/frontend</code>并使用事件<code>checkout_cart_product_add_after</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"&gt;
    &lt;event name="checkout_cart_product_add_after"&gt;
        &lt;observer name="customprice" instance="Webkul\Hello\Observer\CustomPrice" /&gt;
    &lt;/event&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">第 2 步：创建 CustomPrice.php 文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在，您必须创建<code>CustomPrice.php</code>覆盖文件夹中价格的文件<code>Observer</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

    namespace Webkul\Hello\Observer;
 
    use Magento\Framework\Event\ObserverInterface;
    use Magento\Framework\App\RequestInterface;
 
    class CustomPrice implements ObserverInterface
    {
        public function execute(\Magento\Framework\Event\Observer $observer) {
            $item = $observer-&gt;getEvent()-&gt;getData('quote_item');         
            $item = ( $item-&gt;getParentItem() ? $item-&gt;getParentItem() : $item );
            $price = 100; //set your price here
            $item-&gt;setCustomPrice($price);
            $item-&gt;setOriginalCustomPrice($price);
            $item-&gt;getProduct()-&gt;setIsSuperMode(true);
        }
 
    }
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>注意：根据您为一种或多种产品设置自定义价格的需要，您可以通过添加条件来操作。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sun, 01 Oct 2023 08:35:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 以编程方式获取最近查看的产品集合]]></title>
      <link>https://www.360magento.com/blog/get-recent-viewed-products-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 2 中显示最近查看的产品是在 Magento 2 商店中吸引客户购买您想要的产品的有效方法。它可以让顾客关注他们最近访问过的所有产品，这将有助于增强顾客的购物体验。对于他们来说，这可能是一个很好的建议，鼓励他们购买他们可能感兴趣的东西。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>为了在 Magento 2 站点上显示<strong>最近查看的产品集合</strong>，商店管理员将需要有关最近查看的产品集合的数据。然而，获取集合有时可能很复杂。因此，在今天的帖子中，我将向您提供<strong>在 Magento 2 中获取最近查看的产品集合的</strong>三个步骤。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-get-recent-viewed-products-collection-in-magento-2">如何在 Magento 2 中获取最近查看的产品集合</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>步骤1：创建RecentProducts区块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤2：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤3：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1">步骤1：创建RecentProducts区块</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获取最近查看的产品集合，首先，您需要创建一个<code>RecentProducts</code>块。为此，请按照路径&nbsp;<code>Example/Productslider/Block/RecentProducts.php</code>添加以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace Example\Productslider\Block;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Reports\Block\Product\Viewed as ReportProductViewed;
use Example\Productslider\Helper\Data;
/**
 * Class RecentProducts
 * @package Example\Productslider\Block
 */
class RecentProducts extends AbstractSlider
{
    /**
     * @var ReportProductViewed
     */
    protected $reportProductViewed;
    /**
     * RecentProducts constructor.
     * @param Context $context
     * @param CollectionFactory $productCollectionFactory
     * @param Visibility $catalogProductVisibility
     * @param DateTime $dateTime
     * @param Data $helperData
     * @param HttpContext $httpContext
     * @param ReportProductViewed $reportProductViewed
     * @param array $data
     */
    public function __construct(
        Context $context,
        CollectionFactory $productCollectionFactory,
        Visibility $catalogProductVisibility,
        DateTime $dateTime,
        Data $helperData,
        HttpContext $httpContext,
        ReportProductViewed $reportProductViewed,
        array $data = []
    ) {
        $this-&gt;reportProductViewed = $reportProductViewed;
        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);
    }
    /**
     * Get Collection Recently Viewed product
     * @return mixed
     */
    public function getProductCollection()
    {
        return $this-&gt;reportProductViewed-&gt;getItemsCollection()-&gt;setPageSize($this-&gt;getProductsCount());
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2">步骤2：插入phtml文件</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>将集合放入区块后，现在您可以按照此代码片段从区块中获取产品集合<code>Example/HelloWorld/view/frontend/templates/list.phtml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然后，请在 phtml 文件中插入以下代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -80px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 30 Sep 2023 08:28:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何获取愿望清单产品集合]]></title>
      <link>https://www.360magento.com/blog/get-wishlist-products-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>显示<strong>心愿单产品</strong>对鼓励客户从您的商店购买商品有积极的影响，因为它提醒客户他们有想要订购的首选产品。愿望清单也是您可以了解客户的购买兴趣和购物倾向的地方。因此，在 Magento 2 商店中处理此功能非常重要。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>为了在网站上显示<strong>愿望清单产品集合，商店管理员将需要有关愿望清单产品集合的数据。</strong>然而，获取集合并不是一项简单的任务，尽管有几篇文章写了有关此问题的解决方案，但没有一篇真正有效。因此，在今天的帖子中，我将为您提供在 Magento 2 中<strong>获取愿望清单产品集合的</strong>三个步骤。所有步骤都很容易遵循，我相信您将能够解决您商店的愿望清单产品集合当前的问题。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>3步获取心愿单产品系列</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 WishlistProducts 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建 WishlistProducts 块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获得愿望清单产品集合，首先，您需要创建一个<code>WishlistProducts</code>块。为此，请按照路径<code><span>Example</span>/Productslider/Block/WishlistProducts.php</code>添加以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\Productslider\Block;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Wishlist\Model\ResourceModel\Item\CollectionFactory as WishlistCollectionFactory;
use <span>Example</span>\Productslider\Helper\Data;
/**
 * Class FeaturedProducts
 * @package <span>Example</span>\Productslider\Block
 */
class WishlistProducts extends AbstractSlider
{
    /**
     * @var WishlistCollectionFactory
     */
    protected $_wishlistCollectionFactory;
    /**
     * WishlistProducts constructor.
     * @param Context $context
     * @param CollectionFactory $productCollectionFactory
     * @param Visibility $catalogProductVisibility
     * @param DateTime $dateTime
     * @param Data $helperData
     * @param HttpContext $httpContext
     * @param WishlistCollectionFactory $wishlistCollectionFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        CollectionFactory $productCollectionFactory,
        Visibility $catalogProductVisibility,
        DateTime $dateTime,
        Data $helperData,
        HttpContext $httpContext,
        WishlistCollectionFactory $wishlistCollectionFactory,
        array $data = []
    ) {
        $this-&gt;_wishlistCollectionFactory = $wishlistCollectionFactory;
        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);
    }
    /**
     * @inheritdoc
     */
    public function getProductCollection()
    {
        $collection = [];
        if ($this-&gt;_customer-&gt;isLoggedIn()) {
            $wishlist = $this-&gt;_wishlistCollectionFactory-&gt;create()
                -&gt;addCustomerIdFilter($this-&gt;_customer-&gt;getCustomerId());
            $productIds = null;
            foreach ($wishlist as $product) {
                $productIds[] = $product-&gt;getProductId();
            }
            $collection = $this-&gt;_productCollectionFactory-&gt;create()-&gt;addIdFilter($productIds);
            $collection = $this-&gt;_addProductAttributesAndPrices($collection)-&gt;addStoreFilter($this-&gt;getStoreId())-&gt;setPageSize($this-&gt;getProductsCount());
        }
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">步骤2：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>将集合放入区块后，现在您可以按照此代码片段从区块中获取产品集合<code><code>Example</code>/HelloWorld/view/frontend/templates/list.phtml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然后，请在 phtml 文件中插入以下代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -57px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 29 Sep 2023 08:31:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2如何获取特价产品集合]]></title>
      <link>https://www.360magento.com/blog/get-on-sale-products-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>为了在网站上显示<strong>促销产品系列，商店管理员将需要有关促销产品系列的数据。</strong>然而，获取集合并不是一件简单的任务，并且也没有太多文章来写这方面的解决方案。因此，在今天的帖子中，我将指导您如何在 Magento 2 中<strong>获得特价产品系列</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>3步获取特价产品系列</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 OnSaleProduct 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-create-onsaleproduct-block-">第 1 步：创建 OnSaleProduct 块 {}</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获得特价产品集合，首先，您需要创建一个<code>OnSaleProduct</code>块。为此，请按照路径&nbsp;<code>Mageplaza/Productslider/Block/OnSaleProduct.php</code>添加以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\Productslider\Block;
use Zend_Db_Expr;
/**
 * Class OnSaleProduct
 * @package <span>Example</span>\Productslider\Block
 */
class OnSaleProduct extends AbstractSlider
{
    /**
     * @inheritdoc
     */
    public function getProductCollection()
    {
        $visibleProducts = $this-&gt;_catalogProductVisibility-&gt;getVisibleInCatalogIds();
        $collection = $this-&gt;_productCollectionFactory-&gt;create()-&gt;setVisibility($visibleProducts);
        $collection = $this-&gt;_addProductAttributesAndPrices($collection)
            -&gt;addAttributeToFilter(
                'special_from_date',
                ['date' =&gt; true, 'to' =&gt; $this-&gt;getEndOfDayDate()],
                'left'
            )-&gt;addAttributeToFilter(
                'special_to_date',
                ['or' =&gt; [0 =&gt; ['date' =&gt; true,
                                                   'from' =&gt; $this-&gt;getStartOfDayDate()],
                                             1 =&gt; ['is' =&gt; new Zend_Db_Expr(
                                                 'null'
                                             )],]],
                'left'
            )-&gt;addAttributeToSort(
                'news_from_date',
                'desc'
            )-&gt;addStoreFilter($this-&gt;getStoreId())-&gt;setPageSize(
                $this-&gt;getProductsCount()
            );
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-insert-in-phtml-file-">第2步：插入phtml文件{}</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>将集合放入区块后，现在您可以按照此代码片段从区块中获取产品集合<code><code>Example</code>/HelloWorld/view/frontend/templates/list.phtml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然后，请在 phtml 文件中插入以下代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}

</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-flush-cache--test-result-">第 3 步：刷新缓存和测试结果{}</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -331px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 28 Sep 2023 07:59:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何获取浏览量最高的产品]]></title>
      <link>https://www.360magento.com/blog/get-most-viewed-product-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>展示浏览次数最多的产品通常用于吸引客户使用该产品，也可以作为对他们的推荐。这个浏览次数最多的产品系列对于对商店中销售的产品不太了解的首次访问用户特别有帮助。它可以帮助他们更轻松地选择最好的商品。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>浏览次数最多的产品</strong>在帮助您的商店提高销量方面发挥着重要作用。这是因为在您的网站上展示这些产品可以引导客户收集最有趣的产品，而不是让他们毫无方向地闲逛。但是，要显示浏览次数最多的产品，您需要获取浏览次数最多的产品集合。因此，在今天的文章中，我将指导您如何在 Magento 2 中<strong>获得浏览次数最多的产品集合</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>获取浏览次数最多的产品系列的 3 个步骤</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 MostViewedProducts 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建 MostViewedProducts 块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获得浏览次数最多的产品集合，首先，您需要创建一个<code>MostViewedProducts</code>块。为此，请按照路径<code>Example/Productslider/Block/MostViewedProducts.php</code>添加以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace Example\Productslider\Block;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Mageplaza\Productslider\Helper\Data;
use Example\Productslider\Model\ResourceModel\Report\Product\CollectionFactory as MostViewedCollectionFactory;
/**
 * Class MostViewedProducts
 * @package Mageplaza\Productslider\Block
 */
class MostViewedProducts extends AbstractSlider
{
    /**
     * @var MostViewedCollectionFactory
     */
    protected $_mostViewedProductsFactory;
    /**
     * MostViewedProducts constructor.
     * @param Context $context
     * @param CollectionFactory $productCollectionFactory
     * @param Visibility $catalogProductVisibility
     * @param DateTime $dateTime
     * @param Data $helperData
     * @param HttpContext $httpContext
     * @param MostViewedCollectionFactory $mostViewedProductsFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        CollectionFactory $productCollectionFactory,
        Visibility $catalogProductVisibility,
        DateTime $dateTime,
        Data $helperData,
        HttpContext $httpContext,
        MostViewedCollectionFactory $mostViewedProductsFactory,
        array $data = []
    ) {
        $this-&gt;_mostViewedProductsFactory = $mostViewedProductsFactory;
        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);
    }
    /**
     * Get Product Collection of MostViewed Products
     * @return mixed
     */
    public function getProductCollection()
    {
        $collection = $this-&gt;_mostViewedProductsFactory-&gt;create()
            -&gt;addAttributeToSelect('*')
            -&gt;setStoreId($this-&gt;getStoreId())-&gt;addViewsCount()
            -&gt;addStoreFilter($this-&gt;getStoreId())
            -&gt;setPageSize($this-&gt;getProductsCount());
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">第 2 步：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在块中拥有集合后，现在您可以按照此代码片段从块中获取产品集合<code>Example/HelloWorld/view/frontend/templates/list.phtml</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>接下来，请在phtml文件中插入以下代码</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Wed, 27 Sep 2023 07:20:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2编程方式获取特色产品]]></title>
      <link>https://www.360magento.com/blog/get-featured-product-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 商店中展示<strong>特色产品</strong>是交叉销售和追加销售产品的有效方式。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然而，为了展示特色产品，商店管理员需要获取特色产品集合，这对于新开发人员或非技术商店管理员来说可能并不容易。因此，在今天的文章中，我将向您展示在 Magento 2 中<strong>获取特色产品集合的</strong>三个步骤。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>在 Magento 2 中获取特色产品系列的 3 个步骤</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建特色产品块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建特色产品块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获取特征产品集合，首先需要创建一个<code>FeaturedProducts</code>块。为此，请按照路径<code>Example/Productslider/Block/FeaturedProducts.php</code>添加以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\Productslider\Block;
/**
 * Class FeaturedProducts
 * @package Example\Productslider\Block
 */
class FeaturedProducts extends AbstractSlider
{
    /**
     * get collection of feature products
     * @return mixed
     */
    public function getProductCollection()
    {
        $visibleProducts = $this-&gt;_catalogProductVisibility-&gt;getVisibleInCatalogIds();
        $collection = $this-&gt;_productCollectionFactory-&gt;create()-&gt;setVisibility($visibleProducts);
        $collection-&gt;addMinimalPrice()
            -&gt;addFinalPrice()
            -&gt;addTaxPercents()
            -&gt;addAttributeToSelect('*')
            -&gt;addStoreFilter($this-&gt;getStoreId())
            -&gt;setPageSize($this-&gt;getProductsCount())
            -&gt;addAttributeToFilter('is_featured', '1');
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">步骤2：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在块中拥有集合后，现在您可以按照此代码片段从块中获取产品集合<code><code>Example</code>/HelloWorld/view/frontend/templates/list.phtml</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>接下来，请将以下代码插入<code>phtml file</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，为了完成获取特色产品集合，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -135px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 26 Sep 2023 08:15:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 获得畅销产品集合]]></title>
      <link>https://www.360magento.com/blog/get-best-sellers-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在网上商店中，每种产品都会有不同的销售数量。有必要了解商店中所有产品的销售情况，看看哪种产品卖得最好，哪种产品卖得不好。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>当谈到畅销产品时，它通常被用作对客户，尤其是初次购买的客户的良好推荐。在商店中展示畅销产品以在购物旺季获得更多销售额也是一个明智的策略。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>要显示畅销产品，您将需要有关<strong>畅销产品集合的</strong>数据。因此，在今天的帖子中，我将为您提供三个阶段来帮助您<strong>获得 Magento 2 的畅销书收藏</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过三步获得畅销书系列</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 BestSellerProducts 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建 BestSellerProducts 块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获得畅销书系列，您要做的第一件事就是创建 BestSellerProducts 块。沿着这条路走<code>Example/Productslider/Block/BestSellerProducts.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\Productslider\Block;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\App\Http\Context as HttpContext;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\Sales\Model\ResourceModel\Report\Bestsellers\CollectionFactory as BestSellersCollectionFactory;
use <span>Example</span>\Productslider\Helper\Data;
/**
 * Class BestSellerProducts
 * @package <span>Example</span>\Productslider\Block
 */
class BestSellerProducts extends AbstractSlider
{
    /**
     * @var BestSellersCollectionFactory
     */
    protected $_bestSellersCollectionFactory;
    /**
     * BestSellerProducts constructor.
     * @param Context $context
     * @param CollectionFactory $productCollectionFactory
     * @param Visibility $catalogProductVisibility
     * @param DateTime $dateTime
     * @param Data $helperData
     * @param HttpContext $httpContext
     * @param BestSellersCollectionFactory $bestSellersCollectionFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        CollectionFactory $productCollectionFactory,
        Visibility $catalogProductVisibility,
        DateTime $dateTime,
        Data $helperData,
        HttpContext $httpContext,
        BestSellersCollectionFactory $bestSellersCollectionFactory,
        array $data = []
    ) {
        $this-&gt;_bestSellersCollectionFactory = $bestSellersCollectionFactory;
        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);
    }
    /**
     * get collection of best-seller products
     * @return mixed
     */
    public function getProductCollection()
    {
        $productIds = [];
        $bestSellers = $this-&gt;_bestSellersCollectionFactory-&gt;create()
            -&gt;setPeriod('month');
        foreach ($bestSellers as $product) {
            $productIds[] = $product-&gt;getProductId();
        }
        $collection = $this-&gt;_productCollectionFactory-&gt;create()-&gt;addIdFilter($productIds);
        $collection-&gt;addMinimalPrice()
            -&gt;addFinalPrice()
            -&gt;addTaxPercents()
            -&gt;addAttributeToSelect('*')
            -&gt;addStoreFilter($this-&gt;getStoreId())-&gt;setPageSize($this-&gt;getProductsCount());
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">步骤2：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在块中拥有集合后，现在您可以按照上面的代码片段从块中获取产品集合<code><span>Example</span>/HelloWorld/view/frontend/templates/list.phtml</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然后，在 phtml 文件中插入以下代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
$collection = $block-&gt;getProductCollection();
foreach ($collection as $_product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Mon, 25 Sep 2023 07:39:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2以编程方式 获取评论、评级的集合]]></title>
      <link>https://www.360magento.com/blog/get-review-rating-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>您可能已经知道，<strong>评论和评级</strong>在每个在线业务中都发挥着重要作用，尤其是在 Magento 2 平台上运行的业务，因为它直接关系到商店的声誉以及客户的购买决策。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>因此，在今天的帖子中，我将为您提供在 Magento 2 中<strong>获取评论和评级集合</strong>的最简单方法。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-get-review-rating-collection">如何获取评论、评分集合</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获得产品评论、评级集合，您需要创建一个<code>ProductReviews.php</code>文件。遵循这条路径<code>Example/HelloWorld/Model/ProductReviews.php</code>，以下是您将如何做到的。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\HelloWorld\Model;
use Magento\Framework\Model\AbstractModel;
class ProductReviews extends AbstractModel{

    protected $_ratingFactory;
    protected $_productFactory;
    protected $_ratingFactory;
    protected $_reviewFactory;

    public function __construct(
            \Magento\Store\Model\StoreManagerInterface $storeManager,
            \Magento\Catalog\Model\ProductFactory $productFactory,
            \Magento\Review\Model\RatingFactory $ratingFactory,
            \Magento\Review\Model\ResourceModel\Review\CollectionFactory $reviewFactory,
        ) {
            $this-&gt;_storeManager = $storeManager;
            $this-&gt;_productFactory = $productFactory;
            $this-&gt;_ratingFactory = $ratingFactory;
            $this-&gt;_reviewFactory = $reviewFactory;
        }

    public function getReviewCollection($productId){
        $collection = $this-&gt;_reviewFactory-&gt;create()
        -&gt;addStatusFilter(
            \Magento\Review\Model\Review::STATUS_APPROVED
        )-&gt;addEntityFilter(
            'product',
            $productId
        )-&gt;setDateOrder();

    }

    public function getRatingCollection(){
        $ratingCollection = $this-&gt;_ratingFactory-&gt;create()
        -&gt;getResourceCollection()
        -&gt;addEntityFilter(
            'product' 
        )-&gt;setPositionOrder()-&gt;setStoreFilter(
            $this-&gt;_storeManager-&gt;getStore()-&gt;getId()
        )-&gt;addRatingPerStoreName(
            $this-&gt;_storeManager-&gt;getStore()-&gt;getId()
        )-&gt;load();

        return $ratingCollection-&gt;getData();
    }

}</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -74px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 24 Sep 2023 07:52:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2根据产品可见性获取集合]]></title>
      <link>https://www.360magento.com/blog/get-product-collection-filter-visibility-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在今天的文章中，我将指导您如何在 Magento 2 中<strong>按可见性获取产品集合过滤器。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>可见性是产品属性，而不是类别属性。有时，店主会希望将产品的可见性限制在特定的客户群中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在本教程中，您将学习如何通过可见性通过 3 个步骤获取产品集合过滤器：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过可见性获取产品集合过滤器</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 Products.php 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建 Products.php 块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要按可见性获取产品集合过滤器，首先，您需要创建一个<code>Products.php</code>块。为了创建它，请遵循以下路径<code>Example/HelloWorld/Block/Products.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace <span>Example</span>\HelloWorld\Block;
class Products extends \Magento\Framework\View\Element\Template
{    
  
    protected $productCollectionFactory;
    protected $productVisibility;
    protected $productStatus;
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,        
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        \Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus,
        \Magento\Catalog\Model\Product\Visibility $productVisibility,
        array $data = []
    )
    {
        $this-&gt;productCollectionFactory = $productCollectionFactory;
        $this-&gt;productStatus = $productStatus;
        $this-&gt;productVisibility = $productVisibility;
        parent::__construct($context, $data);
    }
    public function getProductCollection()
    {
        $collection = $this-&gt;productCollectionFactory-&gt;create();
        $collection-&gt;addAttributeToFilter('status', ['in' =&gt; $this-&gt;productStatus-&gt;getVisibleStatusIds()]);
        $collection-&gt;setVisibility($this-&gt;productVisibility-&gt;getVisibleInSiteIds());
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">步骤2：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在您的块中已有集合后，现在按照以下代码片段从块中获取产品集合：<code><code>Example</code>/HelloWorld/view/frontend/templates/product-list.phtml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$collection = $block-&gt;getProductCollection;
foreach ($collectionas $_product) {
    echo $_product-&gt;getName() . ' - ' . $_product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，为了完成通过可见性获取产品集合过滤器，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sat, 23 Sep 2023 07:50:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 使用筛选获取所有订单集合]]></title>
      <link>https://www.360magento.com/blog/get-all-order-collection-filters-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在业务管理过程中，Magento 2商店可能需要过滤所有订单集合以进行进一步分析。在今天的文章中，我想向您展示如何通过按客户、日期、状态和付款方式<strong>进行筛选来获取所有订单集合</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何获取所有订单集合</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法1：通过过滤器获取所有订单集合</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法2：按客户ID获取所有订单集合</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法3：按日期获取订单集合</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法4：按状态获取订单集合</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法5：按付款方式获取订单集合</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-1-get-all-order-collection-with-filters">方法一：通过过滤器获取所有订单集合</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要获取带有过滤器的所有订单集合，请转到以下路径<code>Example/HelloWorld/Block/Orders.php</code>并创建一个<code>Orders.php</code>文件。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class Products extends \Magento\Framework\View\Element\Template
{    
  
     protected $_orderCollectionFactory;

    public function __construct(
        Magento\Framework\App\Action\Context $context,
        \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory 
    ) {
        $this-&gt;_orderCollectionFactory = $orderCollectionFactory;
        parent::__construct($context);

    }


   public function getOrderCollection()
   {
       $collection = $this-&gt;_orderCollectionFactory-&gt;create()
         -&gt;addAttributeToSelect('*')
         -&gt;addFieldToFilter($field, $condition); //Add condition if you wish
     
     return $collection;
     
    }


   public function getOrderCollectionByCustomerId($customerId)
   {
       $collection = $this-&gt;_orderCollectionFactory()-&gt;create($customerId)
         -&gt;addFieldToSelect('*')
         -&gt;addFieldToFilter('status',
                ['in' =&gt; $this-&gt;_orderConfig-&gt;getVisibleOnFrontStatuses()]
            )
         -&gt;setOrder(
                'created_at',
                'desc'
            );
 
     return $collection;

    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-2-get-all-order-collection-filter-by-customer">方法2：按客户获取所有订单集合过滤器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在前端开发 Magento 2 扩展（例如&ldquo;我的帐户&rdquo;）时，您可能需要在后端的网格中显示现有的客户订单。以下是我们如何按客户获取所有订单过滤器：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>   public function getOrderCollectionByCustomerId($customerId)
   {
       $collection = $this-&gt;_orderCollectionFactory()-&gt;create($customerId)
         -&gt;addFieldToSelect('*')
         -&gt;addFieldToFilter('status',
                ['in' =&gt; $this-&gt;_orderConfig-&gt;getVisibleOnFrontStatuses()]
            )
         -&gt;setOrder(
                'created_at',
                'desc'
            );
 
     return $collection;

    }

</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-3-get-order-collection-filter-by-date">方法3：按日期获取订单集合过滤器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>除了按客户获取订单收集过滤器之外，您还可以按日期获取订单收集过滤器。我们是这样做的：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code> public function getOrderCollectionByDate($from, $to)
   {
       $collection = $this-&gt;_orderCollectionFactory()-&gt;create($customerId)
         -&gt;addFieldToSelect('*')
         -&gt;addFieldToFilter('status',
                ['in' =&gt; $this-&gt;_orderConfig-&gt;getVisibleOnFrontStatuses()]
            )
         -&gt;setOrder(
                'created_at',
                'desc'
            );
 
     return $collection;

    }
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-4-get-order-collection-filter-by-status">方法4：按状态获取订单集合过滤器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>获取订单收集过滤器的第四种方法是按状态。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>public function getOrderCollectionByStatus($statuses = [])
   {
       $collection = $this-&gt;_orderCollectionFactory()-&gt;create($customerId)
         -&gt;addFieldToSelect('*')
         -&gt;addFieldToFilter('status',
                ['in' =&gt; $statuses]
            )
         ;
 
     return $collection;

    }
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-5-get-order-collection-filter-by-payment-method">方法5：按付款方式获取订单收集过滤器</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>除了上述解决方案可以帮助您获得订单收集过滤器之外，还有另一种方法。以下指南将向您展示如何按付款方式获取订单收集过滤器。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>public function getOrderCollectionPaymentMethod($paymentMethod)
   {
       $collection = $this-&gt;_orderCollectionFactory()-&gt;create($customerId)
         -&gt;addFieldToSelect('*')
         -&gt;addFieldToFilter('created_at',
                ['gteq' =&gt; $from]
            )
         -&gt;addFieldToFilter('created_at',
                ['lteq' =&gt; $to]
            );
 

     /* join with payment table */
    $collection-&gt;getSelect()
    -&gt;join(
        ["sop" =&gt; "sales_order_payment"],
        'main_table.entity_id = sop.parent_id',
        array('method')
    )
    -&gt;where('sop.method = ?',$paymentMethod); //E.g: ccsave

    $collection-&gt;setOrder(
        'created_at',
        'desc'
    );

     return $collection;

    }</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -189px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 22 Sep 2023 07:59:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中如何根据类别 ID 获取产品集合]]></title>
      <link>https://www.360magento.com/blog/get-product-collection-category-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>今天我们将介绍一个简短但有用的教程，介绍如何在 Magento 2 中通过类别 ID 获取产品集合。这是一种获取产品集合的快速方法，可以为商店管理员和客户节省大量配置时间。这就是为什么您可能会看到在线商店中的客户需要它。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>随着Magento的快速发展，产品集合变得越来越重要。这是因为，在不同的项目中，不同的过滤器和需求通常需要产品集合。现在让我们了解一下产品集合以及如何在 Magento 2 中通过类别 ID 获取它。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>**如何通过类别 ID 分 3 步获取产品集合：**</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建 Products.php 块</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：插入phtml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：刷新缓存和测试结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>现在请按照以下步骤及时完成工作。您不需要更改核心代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-create-productsphp-block">第 1 步：创建 Products.php 块</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>为了按类别 ID 获取产品集合，您要做的第一件事就是创建<code>Products.php</code>块。遵循以下路径：<code>Example/HelloWorld/Block/Products.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace <span>Example</span>\HelloWorld\Block;
class Products extends \Magento\Framework\View\Element\Template
{    
  
     /**
     * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
     */
    protected $_productCollectionFactory;
  
    public function __construct(
        \Magento\Backend\Block\Template\Context $context,        
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
    )
    {    
        $this-&gt;_productCollectionFactory = $productCollectionFactory;
        parent::__construct($context);
    }
    
    
    public function getProductCollectionByCategories($ids)
    {
        $collection = $this-&gt;_productCollectionFactory-&gt;create();
        $collection-&gt;addAttributeToSelect('*');
        $collection-&gt;addCategoriesFilter(['in' =&gt; ids]);
        return $collection;
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>这里，<code>$ids</code>是一个数组，其中包含类别 id。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>$_productCollectionFactory</code>是产品集合工厂的对象，用于获取产品模型的集合。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>addCategoriesFilter</code>应用类别过滤器的功能。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>$collection</code>返回分配给给定类别的产品集合。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-insert-in-phtml-file">步骤2：插入phtml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>完成上述步骤后，您的块中将有一个集合，现在要获取块中的 Product 集合，请按照以下代码片段操作：<code><span>Example</span>/HelloWorld/view/frontend/templates/list.phtml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$ids = [1,2,3];
$categoryProducts = $block-&gt;getProductCollectionByCategories($ids);
foreach ($categoryProducts as $product) {
    echo $product-&gt;getName() . ' - ' . $product-&gt;getProductUrl() . '&lt;br /&gt;';
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-flush-cache--test-result">第 3 步：刷新缓存和测试结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在，让我们刷新缓存并测试结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -15px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Thu, 21 Sep 2023 07:45:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中禁用付款方式]]></title>
      <link>https://www.360magento.com/blog/disable-payment-method-programmatically-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>支付系统管理可以被认为是 Magento 2 商店系统的核心之一，因为一个好的处理系统可以帮助您优化您的销售、利润以及您的努力。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>有时，您会希望根据客户组、产品/订单属性、运输参数等限制特定的<strong>付款方式</strong>。换句话说，您可以通过 Magento 2 后端配置以编程方式禁用付款方式。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在今天的文章中，我将向您展示<strong>在 Magento 2 中以编程方式禁用付款方式的</strong>2 个简单阶段。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>在 Magento 2 中以编程方式禁用付款方式的 2 个步骤：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>步骤1：编辑config.xml文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤2：编辑Observer.php文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">步骤1：编辑config.xml文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要以编程方式禁用付款方式，首先，您需要打开该<code>config.xml</code>文件，然后将以下代码添加到该文件中：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;global&gt;
&nbsp; &nbsp; ...
&nbsp; &nbsp; &lt;events&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;payment_method_is_active&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;observers&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;disable_paymentmethod&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;class&gt;Vendor_Extension_Model_Observer&lt;/class&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;method&gt;paymentMethodIsActive&lt;/method&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/disable_paymentmethod&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/observers&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/payment_method_is_active&gt;
&nbsp; &nbsp; &lt;/events&gt;
&nbsp; &nbsp; ...
&lt;/global&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">步骤2：编辑Observer.php文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>Observer.php</code>在此步骤中，应在文件中添加以下代码</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
class Vendor_Extension_Model_Observer {
&nbsp; &nbsp; public function paymentMethodIsActive(Varien_Event_Observer $observer) {
&nbsp; &nbsp; &nbsp; &nbsp; $method = $observer-&gt;getMethodInstance();
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; if ($method-&gt;getCode() == 'payment_method_code') {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (condition) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result = $observer-&gt;getResult();
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $result-&gt;isAvailable = false;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;
&nbsp; &nbsp; }
}</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Wed, 20 Sep 2023 07:44:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 的客户帐户中添加自定义选项卡]]></title>
      <link>https://www.360magento.com/blog/add-custom-tab-customer-account-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>关于 Magento 2 的默认设置，客户在注册或登录后将自动重定向到其<strong>帐户仪表板。在此仪表板中，有各种选项卡，例如&ldquo;我的帐户&rdquo;、&ldquo;我的订单&rdquo;、&ldquo;我的愿望清单&rdquo;。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>然而，在某些特定情况下，为了增强客户购物体验，需要在客户帐户仪表板中添加一些功能，例如检查演示产品、请求退款或其他<strong>自定义要求。</strong>遗憾的是，默认的 Magento 2 中并未提供这些功能。因此，在今天的帖子中，我将向您展示<strong>在客户帐户中添加自定义选项卡的 4 个简单阶段</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过 4 个步骤在客户帐户中添加自定义选项卡</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建客户帐户布局</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：创建索引布局</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：创建索引页</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第四步：创建模板文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：创建客户帐户布局</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>首先，您需要<code>customer_account.xml</code>在路径中创建文件<code><code>Example</code>/Module/view/frontend/layout</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
&lt;body&gt;
&lt;referenceBlock name="customer_account_navigation"&gt;
&lt;block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-custom"&gt;
&lt;arguments&gt;
&lt;argument name="path" xsi:type="string"&gt;routename/customer/index&lt;/argument&gt;
&lt;argument name="label" xsi:type="string"&gt;My Custom Tab&lt;/argument&gt;
&lt;/arguments&gt;
&lt;/block&gt;
&lt;/referenceBlock&gt;
&lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">第 2 步：创建索引布局</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>创建上述文件后，也在路径中<code><code>Example</code>/Module/view/frontend/layout</code>创建，<code>routename_customer_index.xml</code>其中包含以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"&gt; 
&lt;update handle="customer_account"/&gt; 
&lt;body&gt; 
&lt;referenceBlock name="page.main.title"&gt; 
&lt;action method="setPageTitle"&gt; 
&lt;argument translate="true" name="title" xsi:type="string"&gt;My Custom Tab&lt;/argument&gt; 
&lt;/action&gt; 
&lt;/referenceBlock&gt; 
&lt;referenceContainer name="content"&gt; 
&lt;block class="Magento\Framework\View\Element\Template" name="my_tab" template="Vendor_Module::mytab.phtml"&gt; 
&lt;/block&gt; 
&lt;/referenceContainer&gt; 
&lt;/body&gt; 
&lt;/page&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3">第 3 步：创建索引页</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>然后转到<code><code>Example</code>/Module/Controller/Customer</code>并创建<code>Index.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php 
namespace Example/Module\Controller\Customer;  
class Index extends \Magento\Framework\App\Action\Action { 
public function execute() { 
$this-&gt;_view-&gt;loadLayout(); 
$this-&gt;_view-&gt;renderLayout(); 
} 
} 
?&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-4">第四步：创建模板文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后，在客户帐户仪表板中添加自定义选项卡很容易，您只需遵循路径<code><code>Example</code>/Module/view/frontend/templates</code>并创建<code>mytab.phtml</code>.</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php 
// Add Some Code Here for design
?&gt;
&lt;span&gt; My Custom Tab.. &lt;/span&gt;</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Tue, 19 Sep 2023 08:28:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中编程方式获取客户集合]]></title>
      <link>https://www.360magento.com/blog/get-customer-collection-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>客户收集</strong>是为商店管理员提供了各种好处。但最显着的优点是它允许您按属性过滤商店的所有客户。因此，在本教程中，我将指导您<strong>如何在 Magento 2 中编程方式获取客户集合</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过两步获取客户集合：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：获取客户对象</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：获取客户详细信息</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-object">步骤1：获取客户对象</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 提供了各种方法来帮助您获取对象，例如从工厂、存储库、通过对象管理器获取或直接注入它。您可以使用任何您喜欢的方法，但是在使用对象管理器之前您应该仔细考虑，虽然它很简单，但它不是最好的方法。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>下面是可用于注入客户工厂和客户对象的行代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>class MyClass 
{
    protected $_customer;
    protected $_customerFactory;

    public function __construct(...
                                \Magento\Customer\Model\CustomerFactory $customerFactory,
                                \Magento\Customer\Model\Customer $customers
    )
    {
        ...
        $this-&gt;_customerFactory = $customerFactory;
        $this-&gt;_customer = $customers;
    }

    public function getCustomerCollection() {
        return $this-&gt;_customer-&gt;getCollection()
               -&gt;addAttributeToSelect("*")
               -&gt;load();
    }

    public function getFilteredCustomerCollection() {
        return $this-&gt;_customerFactory-&gt;create()-&gt;getCollection()
                -&gt;addAttributeToSelect("*")
                -&gt;addAttributeToFilter("firstname", array("eq" =&gt; "Max"))
                -load();
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>尽管同时注入客户对象和客户工厂可能毫无意义，但这将是一个很好的演示，供您在注入其他对象时参考。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>使用第一种方法<code>getCustomerCollection()</code>，返回所有客户的加载集合，包括所有属性。但是，如果由于内存限制而具有太多属性，则使用此方法并不是一个好主意。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>要从给定的客户工厂获取对象，<code>getFilteredCustomerCollection()</code>请应用第二种方法。使用这种方法，您只需要添加<code>create()</code>，您还可以添加过滤器来过滤您的集合。此时，您将收到所有具有名字的客户的集合，例如 Max。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="get-detail">第 2 步：获取客户详细信息</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>为了获取客户的详细信息，您将需要他们的 ID，因为客户集合需要按客户 ID 加载。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>为了更容易理解，假设客户 ID 为 10。您将通过运行以下命令获取客户详细信息：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$customerID = 10;
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$customerObj = $objectManager-&gt;create('Magento\Customer\Model\Customer')
-&gt;load($customerID);
$customerEmail = $customerObj-&gt;getEmail();</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -125px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 18 Sep 2023 07:49:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 编程方式获取所有付款方式]]></title>
      <link>https://www.360magento.com/blog/get-all-payment-methods-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在今天的帖子中，我将向您展示如何获取Magento 2 中的<strong>所有付款方式</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过两种方法检索Magento 2中的所有付款方式</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法 一：使用依赖注入</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法 二：使用对象管理器</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-1">方法一：使用依赖注入</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>使用该方法时，需要在<code>Block</code>类中编写以下代码。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>/**
 * Order Payment
 *
 * @var \Magento\Sales\Model\ResourceModel\Order\Payment\Collection
 */
protected $_orderPayment;
 
/**
 * Payment Helper Data
 *
 * @var \Magento\Payment\Helper\Data
 */
protected $_paymentHelper;
 
/**
 * Payment Model Config
 *
 * @var \Magento\Payment\Model\Config
 */
protected $_paymentConfig;
 
/**
 * @param \Magento\Backend\Block\Template\Context $context
 * @param \Magento\Sales\Model\ResourceModel\Order\Payment\Collection $orderPayment
 * @param \Magento\Payment\Helper\Data $paymentHelper
 * @param \Magento\Payment\Model\Config $paymentConfig
 * @param array $data
 */
public function __construct(
    \Magento\Backend\Block\Template\Context $context,
    \Magento\Sales\Model\ResourceModel\Order\Payment\Collection $orderPayment,
    \Magento\Payment\Helper\Data $paymentHelper,
    \Magento\Payment\Model\Config $paymentConfig,
    array $data = []
) {
    $this-&gt;_orderPayment = $orderPayment;
    $this-&gt;_paymentHelper = $paymentHelper;
    $this-&gt;_paymentConfig = $paymentConfig;
    parent::__construct($context, $data);
}
 
/**
 * Get all payment methods
 * 
 * @return array
 */ 
public function getAllPaymentMethods() 
{
    return $this-&gt;_paymentHelper-&gt;getPaymentMethods();
}
 
/**
 * Get key-value pair of all payment methods
 * key = method code &amp; value = method name
 * 
 * @return array
 */ 
public function getAllPaymentMethodsList() 
{
    return $this-&gt;_paymentHelper-&gt;getPaymentMethodList();
}
 
/**
 * Get active/enabled payment methods
 * 
 * @return array
 */ 
public function getActivePaymentMethods() 
{
    return $this-&gt;_paymentConfig-&gt;getActiveMethods();
}
 
/**
 * Get payment methods that have been used for orders
 * 
 * @return array
 */ 
public function getUsedPaymentMethods() 
{
    $collection = $this-&gt;_orderPayment;
    $collection-&gt;getSelect()-&gt;group('method');
    $paymentMethods[] = array('value' =&gt; '', 'label' =&gt; 'Any');
    foreach ($collection as $col) { 
        $paymentMethods[] = array('value' =&gt; $col-&gt;getMethod(), 'label' =&gt; $col-&gt;getAdditionalInformation()['method_title']);            
    }        
    return $paymentMethods;
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-2">方法 二：使用对象管理器</h2>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>$objectManager =  \Magento\Framework\App\ObjectManager::getInstance();        
 
$paymentHelper = $objectManager-&gt;get('Magento\Payment\Helper\Data');
$allPaymentMethods = $paymentHelper-&gt;getPaymentMethods();
$allPaymentMethodsArray = $paymentHelper-&gt;getPaymentMethodList();
 
var_dump($allPaymentMethodsArray);
var_dump($allPaymentMethods);
 
$paymentConfig = $objectManager-&gt;get('Magento\Payment\Model\Config');
$activePaymentMethods = $paymentConfig-&gt;getActiveMethods();
 
var_dump(array_keys($activePaymentMethods));
 
$orderPaymentCollection = $objectManager-&gt;get('\Magento\Sales\Model\ResourceModel\Order\Payment\Collection');
$orderPaymentCollection-&gt;getSelect()-&gt;group('method');
$paymentMethods[] = array('value' =&gt; '', 'label' =&gt; 'Any');
foreach ($orderPaymentCollection as $col) { 
    $paymentMethods[] = array('value' =&gt; $col-&gt;getMethod(), 'label' =&gt; $col-&gt;getAdditionalInformation()['method_title']);            
}        
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>这是<strong>getAllPaymentMethods()</strong>的 stample 输出</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>Array
(
    [free] =&gt; Array
        (
            [active] =&gt; 1
            [model] =&gt; Magento\Payment\Model\Method\Free
            [order_status] =&gt; pending
            [title] =&gt; No Payment Information Required
            [allowspecific] =&gt; 0
            [sort_order] =&gt; 1
            [group] =&gt; offline
        )
 
    [substitution] =&gt; Array
        (
            [active] =&gt; 0
            [model] =&gt; Magento\Payment\Model\Method\Substitution
            [allowspecific] =&gt; 0
        )
 
    [vault] =&gt; Array
        (
            [debug] =&gt; 1
            [model] =&gt; Magento\Vault\Model\VaultPaymentInterface
        )
 
    [checkmo] =&gt; Array
        (
            [active] =&gt; 1
            [model] =&gt; Magento\OfflinePayments\Model\Checkmo
            [order_status] =&gt; pending
            [title] =&gt; Check / Money order
            [allowspecific] =&gt; 0
            [group] =&gt; offline
        )
 
    [purchaseorder] =&gt; Array
        (
            [active] =&gt; 0
            [model] =&gt; Magento\OfflinePayments\Model\Purchaseorder
            [order_status] =&gt; pending
            [title] =&gt; Purchase Order
            [allowspecific] =&gt; 0
            [group] =&gt; offline
        )
 
    [banktransfer] =&gt; Array
        (
            [active] =&gt; 0
            [model] =&gt; Magento\OfflinePayments\Model\Banktransfer
            [order_status] =&gt; pending
            [title] =&gt; Bank Transfer Payment
            [allowspecific] =&gt; 0
            [group] =&gt; offline
        )
 
    [cashondelivery] =&gt; Array
        (
            [active] =&gt; 0
            [model] =&gt; Magento\OfflinePayments\Model\Cashondelivery
            [order_status] =&gt; pending
            [title] =&gt; Cash On Delivery
            [allowspecific] =&gt; 0
            [group] =&gt; offline
        )
 
    [paypal_express] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Express
            [title] =&gt; PayPal Express Checkout
            [payment_action] =&gt; Authorization
            [solution_type] =&gt; Mark
            [line_items_enabled] =&gt; 1
            [visible_on_cart] =&gt; 1
            [visible_on_product] =&gt; 1
            [allow_ba_signup] =&gt; never
            [group] =&gt; paypal
            [authorization_honor_period] =&gt; 3
            [order_valid_period] =&gt; 29
            [child_authorization_number] =&gt; 1
            [verify_peer] =&gt; 1
            [skip_order_review_step] =&gt; 1
        )
 
    [paypal_express_bml] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Bml
            [title] =&gt; PayPal Credit
            [group] =&gt; paypal
        )
 
    [payflow_express] =&gt; Array
        (
            [title] =&gt; PayPal Express Checkout Payflow Edition
            [payment_action] =&gt; Authorization
            [line_items_enabled] =&gt; 1
            [visible_on_cart] =&gt; 1
            [visible_on_product] =&gt; 1
            [group] =&gt; paypal
            [verify_peer] =&gt; 1
            [model] =&gt; Magento\Paypal\Model\PayflowExpress
        )
 
    [payflow_express_bml] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Payflow\Bml
            [title] =&gt; PayPal Credit
            [group] =&gt; paypal
        )
 
    [payflowpro] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Payflow\Transparent
            [title] =&gt; Credit Card
            [payment_action] =&gt; Authorization
            [cctypes] =&gt; AE,VI
            [useccv] =&gt; 1
            [tender] =&gt; C
            [verbosity] =&gt; MEDIUM
            [user] =&gt; 
            [pwd] =&gt; 
            [group] =&gt; paypal
            [verify_peer] =&gt; 1
            [date_delim] =&gt; 
            [ccfields] =&gt; csc,expdate,acct
            [place_order_url] =&gt; paypal/transparent/requestSecureToken
            [cgi_url_test_mode] =&gt; https://pilot-payflowlink.paypal.com
            [cgi_url] =&gt; https://payflowlink.paypal.com
            [transaction_url_test_mode] =&gt; https://pilot-payflowpro.paypal.com
            [transaction_url] =&gt; https://payflowpro.paypal.com
            [avs_street] =&gt; 0
            [avs_zip] =&gt; 0
            [avs_international] =&gt; 0
            [avs_security_code] =&gt; 1
            [cc_year_length] =&gt; 2
            [can_authorize_vault] =&gt; 1
            [can_capture_vault] =&gt; 1
        )
 
    [payflowpro_cc_vault] =&gt; Array
        (
            [model] =&gt; PayflowProCreditCardVaultFacade
            [title] =&gt; Stored Cards (Payflow Pro)
        )
 
    [paypal_billing_agreement] =&gt; Array
        (
            [active] =&gt; 1
            [allow_billing_agreement_wizard] =&gt; 1
            [model] =&gt; Magento\Paypal\Model\Method\Agreement
            [title] =&gt; PayPal Billing Agreement
            [group] =&gt; paypal
            [verify_peer] =&gt; 1
        )
 
    [payflow_link] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Payflowlink
            [payment_action] =&gt; Authorization
            [verbosity] =&gt; HIGH
            [user] =&gt; 
            [pwd] =&gt; 
            [group] =&gt; paypal
            [title] =&gt; Credit Card
            [partner] =&gt; PayPal
            [csc_required] =&gt; 1
            [csc_editable] =&gt; 1
            [url_method] =&gt; GET
            [email_confirmation] =&gt; 0
            [verify_peer] =&gt; 1
            [transaction_url_test_mode] =&gt; https://pilot-payflowpro.paypal.com
            [transaction_url] =&gt; https://payflowpro.paypal.com
            [cgi_url_test_mode] =&gt; https://pilot-payflowlink.paypal.com
            [cgi_url] =&gt; https://payflowlink.paypal.com
        )
 
    [payflow_advanced] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Payflowadvanced
            [payment_action] =&gt; Authorization
            [verbosity] =&gt; HIGH
            [user] =&gt; PayPal
            [pwd] =&gt; 
            [group] =&gt; paypal
            [title] =&gt; Credit Card
            [partner] =&gt; PayPal
            [vendor] =&gt; PayPal
            [csc_required] =&gt; 1
            [csc_editable] =&gt; 1
            [url_method] =&gt; GET
            [email_confirmation] =&gt; 0
            [verify_peer] =&gt; 1
            [transaction_url_test_mode] =&gt; https://pilot-payflowpro.paypal.com
            [transaction_url] =&gt; https://payflowpro.paypal.com
            [cgi_url_test_mode] =&gt; https://pilot-payflowlink.paypal.com
            [cgi_url] =&gt; https://payflowlink.paypal.com
        )
 
    [hosted_pro] =&gt; Array
        (
            [model] =&gt; Magento\Paypal\Model\Hostedpro
            [title] =&gt; Payment by cards or by PayPal account
            [payment_action] =&gt; Authorization
            [group] =&gt; paypal
            [display_ec] =&gt; 0
            [verify_peer] =&gt; 1
        )
 
    [authorizenet_directpost] =&gt; Array
        (
            [active] =&gt; 0
            [cctypes] =&gt; AE,VI,MC,DI
            [debug] =&gt; 0
            [email_customer] =&gt; 0
            [login] =&gt; 
            [merchant_email] =&gt; 
            [model] =&gt; Magento\Authorizenet\Model\Directpost
            [order_status] =&gt; processing
            [payment_action] =&gt; authorize
            [test] =&gt; 1
            [title] =&gt; Credit Card Direct Post (Authorize.net)
            [trans_key] =&gt; 
            [trans_md5] =&gt; 
            [allowspecific] =&gt; 0
            [currency] =&gt; USD
            [create_order_before] =&gt; 1
            [date_delim] =&gt; /
            [ccfields] =&gt; x_card_code,x_exp_date,x_card_num
            [place_order_url] =&gt; authorizenet/directpost_payment/place
            [cgi_url_test_mode] =&gt; https://test.authorize.net/gateway/transact.dll
            [cgi_url] =&gt; https://secure.authorize.net/gateway/transact.dll
            [cgi_url_td_test_mode] =&gt; https://apitest.authorize.net/xml/v1/request.api
            [cgi_url_td] =&gt; https://api2.authorize.net/xml/v1/request.api
        )
 
    [braintree] =&gt; Array
        (
            [model] =&gt; BraintreeFacade
            [title] =&gt; Credit Card (Braintree)
            [payment_action] =&gt; authorize
            [active] =&gt; 0
            [is_gateway] =&gt; 1
            [can_use_checkout] =&gt; 1
            [can_authorize] =&gt; 1
            [can_capture] =&gt; 1
            [can_capture_partial] =&gt; 1
            [can_authorize_vault] =&gt; 1
            [can_capture_vault] =&gt; 1
            [can_use_internal] =&gt; 1
            [can_refund_partial_per_invoice] =&gt; 1
            [can_refund] =&gt; 1
            [can_void] =&gt; 1
            [can_cancel] =&gt; 1
            [cctypes] =&gt; AE,VI,MC,DI,JCB,CUP,DN,MI
            [useccv] =&gt; 1
            [cctypes_braintree_mapper] =&gt; {"american-express":"AE","discover":"DI","jcb":"JCB","mastercard":"MC","master-card":"MC","visa":"VI","maestro":"MI","diners-club":"DN","unionpay":"CUP"}
            [order_status] =&gt; processing
            [environment] =&gt; sandbox
            [allowspecific] =&gt; 0
            [sdk_url] =&gt; https://js.braintreegateway.com/js/braintree-2.17.6.min.js
            [public_key] =&gt; 
            [private_key] =&gt; 
            [masked_fields] =&gt; cvv,number
            [privateInfoKeys] =&gt; avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision
            [paymentInfoKeys] =&gt; cc_type,cc_number,avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision
        )
 
    [braintree_paypal] =&gt; Array
        (
            [model] =&gt; BraintreePayPalFacade
            [title] =&gt; PayPal (Braintree)
            [active] =&gt; 0
            [payment_action] =&gt; authorize
            [allowspecific] =&gt; 0
            [require_billing_address] =&gt; 0
            [allow_shipping_address_override] =&gt; 1
            [display_on_shopping_cart] =&gt; 1
            [order_status] =&gt; processing
            [is_gateway] =&gt; 1
            [can_use_checkout] =&gt; 1
            [can_authorize] =&gt; 1
            [can_capture] =&gt; 1
            [can_capture_partial] =&gt; 1
            [can_refund] =&gt; 1
            [can_refund_partial_per_invoice] =&gt; 1
            [can_void] =&gt; 1
            [can_cancel] =&gt; 1
            [privateInfoKeys] =&gt; processorResponseCode,processorResponseText,paymentId
            [paymentInfoKeys] =&gt; processorResponseCode,processorResponseText,paymentId,payerEmail
        )
 
    [braintree_cc_vault] =&gt; Array
        (
            [model] =&gt; BraintreeCreditCardVaultFacade
            [title] =&gt; Stored Cards (Braintree)
        )</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -54px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 17 Sep 2023 07:25:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何在页面启用错误报告]]></title>
      <link>https://www.360magento.com/blog/display-error-enable-error-reporting-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 2 中，有时您会遇到这样的问题：出现黑色页面或纯白色页面，并显示错误号，例如错误日志记录号：568837792838 或任何损坏的内容错误。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在 Magento 2 的默认设置中，允许在前端显示错误的功能是禁用的。因此，在今天的帖子中，我将指导您如何在 Magento 2 上显示错误消息或启用错误报告。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何显示错误：启用错误报告</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法 1：重命名 pub/errors/local.xml.sample 文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法2：编辑.htaccess文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法3：编辑app/bootstrap.php文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-1">方法 1：重命名 pub/errors/local.xml.sample 文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要在浏览器上显示错误，您只需重命名一个 XML 文件即可。但是，如果您在生产环境中，则不建议使用此方法，因此您应该只考虑在开发环境中使用此方法。操作方法如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>首先，转到您的 Magento2 根目录。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>然后，打开<code>pub/errors</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开后，您将看到一个名为 的文件<code>local.xml.sample</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将其从<code>local.xml.sample</code>重命名为<code>local.xml</code>。换句话说，您<code>sample</code>从文件名中删除了 。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>最后，<code>System &gt; Tools &gt; Cache Management</code>从 Magento 管理员转到刷新缓存。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-2">方法2：编辑.htaccess文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>显示错误的第二种方法是编辑<code>.htaccess file</code>Magento 2 站点的 。编辑该文件时，您将能够启用 Magento 的开发模式以及 PHP 的错误显示设置。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>首先，打开文件<code>.htaccess</code>并在文件末尾写入以下代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php_value display_errors on ## enable PHP's error display settings
php_value error_reporting -1 ## set error display to E_ALL
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>添加代码后，打开终端/命令提示符并访问 Magento 的根目录。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>cd /path/to/your/magento/directory
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>现在，运行以下命令来激活开发者模式。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento deploy:mode:set developer
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>可以使用以下命令检查当前的部署模式：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento deploy:mode:show
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>最后，使用以下命令清除缓存：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento cache:clean
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>正确执行上述所有步骤后，当您浏览 Magento 网站时，您将看到浏览器本身显示错误。然而，就像第一种方法一样，这仅对开发环境有好处。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-3">方法3：编辑app/bootstrap.php文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>除了编辑<code>.htaccess file</code>（这是在 Magento 站点上启用错误显示的首选方式）之外，您还可以编辑 PHP 文件。要编辑该文件，请按照以下步骤操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>首先，访问 Magento 的根目录。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>然后，打开该文件<code>app/bootstrap.php</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在文件的开头，您将看到以下行代码：<code>#ini_set('display_errors', 1); </code>看到后，请将代码更新为：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>error_reporting(E_ALL); # Set Error Reporting as E_ALL (Report all PHP errors)
ini_set('display_errors', 1); # Un-commenting this line to enable PHP error display
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>更新代码后，打开终端/命令提示符，然后转到 Magento 的根目录。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>cd /path/to/your/magento/directory
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>然后，要启用开发者模式，需要运行以下命令</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento deploy:mode:set developer
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>如果您想检查当前的部署模式，可以使用以下行：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento deploy:mode:show
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>最后，清除缓存：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento cache:clean
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>就是这样。正确执行上述所有步骤后，您将能够在浏览器上看到错误显示。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sat, 16 Sep 2023 08:21:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 上的我的帐户中添加导航链接]]></title>
      <link>https://www.360magento.com/blog/add-navigation-link-my-account-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>我的帐户是一个重要的地方，可以帮助店主轻松管理客户、他们的信息、订单相关详细信息，甚至新闻通讯订阅。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在今天的帖子中，我将指导您如何向客户的帐户仪表板<strong>添加导航。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>如何通过两步在我的帐户中添加导航链接：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：在主题中创建一个文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：添加自定义链接</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1">第 1 步：在主题中创建一个文件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在进行任何自定义之前，您要做的第一件事就是<code>customer_account.xml</code>在主题中创建一个。请按照以下步骤操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>app/design/frontend/<span>Example</span>/_YOUR_THEME_/Magento_Customer/layout/customer_account.xml
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2">第 2 步：添加自定义链接</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在此步骤中，您唯一需要做的就是将此代码添加到您的布局 xml 文件中：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;referenceBlock name="customer_account_navigation"&gt;
    &lt;block class="Magento\Framework\View\Element\Html\Link\Current" name="customer-account-navigation-custom-link" after="-" &gt;
         &lt;arguments&gt;
             &lt;argument name="label" xsi:type="string" translate="true"&gt;Custom Link Label&lt;/argument&gt;
             &lt;argument name="path" xsi:type="string"&gt;custom-path&lt;/argument&gt;
         &lt;/arguments&gt;
    &lt;/block&gt;
&lt;/referenceBlock&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>这是关于在 Magento 2 的&ldquo;我的帐户&rdquo;中添加导航链接的说明。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Fri, 15 Sep 2023 07:29:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[启用/禁用 Magento 2 开发者模式]]></title>
      <link>https://www.360magento.com/blog/enable-disable-developer-mode-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>Magento 2平台为用户提供了三种模式：默认模式、<strong>开发者模式</strong>和生产模式。根据具体情况，商店管理员可以为其 Magento 商店应用不同的模式。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-enable-disable-developer-mode-in-magento-2">如何在 Magento 2 中启用/禁用开发者模式？</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>什么是开发者模式</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>Magento 2 检查开发者模式</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>启用 Magento 2 开发者模式</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>禁用 Magento 2 开发者模式</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="what-developer-mode">什么是开发者模式</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 的开发人员模式是当您需要自定义 Magento 2 或要安装扩展时将使用的模式。更具体地说，它将用于以下情况：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>将每个所需文件的符号链接发布到 pub/static 目录</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在浏览器中看到未捕获的异常</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>var/report 中的系统记录是口头的。将异常放入错误处理程序中</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如果无法强制执行事件订阅者，则生成异常。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>Magento 2 提供了 4 种不同的模式，包括 Default、Developer、Maintenance和 Production。其中，开发者模式是Magento 2开发者的最佳解决方案，因为它涵盖了Magento 2中开发者可用的所有类型的开发选项，包括：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>不缓存静态文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>自动编译代码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在屏幕上显示详细的错误日志</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>启用高级代码调试</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>慢慢地工作</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="check-current-mode">Magento 2 检查开发者模式</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要检查当前模式，需要以 Magento 文件系统所有者身份运行以下命令：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>bin/magento deploy:mode:show
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>如果您有共享托管，这将是您的提供商为您提供登录服务器的用户。相反，如果您的服务器是私有的，则它是 Magento 服务器上的本地用户帐户。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>运行上述命令后，将显示类似以下的消息：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>Current application mode: {mode}. 
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p><strong>注意</strong>：环境变量可能会覆盖该值。可以<code>{mode}</code>是<code>default</code>、<code>developer</code>、 或<code>production</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="enable-developer-mode">启用 Magento 2 开发者模式</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在启用开发者模式之前，您需要确保生成的类和对象管理器实体（例如代理）已经清晰。否则，可能会出现意外错误。清除它们后，您可以按照以下步骤开始将模式从生产模式更改为开发人员模式：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><strong>第 1 步</strong>：在第一步中，删除 generated/code 和 generated/metadata 目录的内容：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>rm -rf &lt;your Magento install dir&gt;/generated/metadata/* &lt;your Magento install dir&gt;/generated/code/*
</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><strong>第 2 步</strong>：接下来，您可以设置模式：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>bin/magento deploy:mode:set developer
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>设置模式后，您将看到以下消息：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>Enabled developer mode.
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="disable-developer-mode">禁用 Magento 2 开发者模式</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>上面我刚刚向您展示了启用开发者模式的方法。但是，在各种情况下，您需要将模式从开发人员更改回生产。这就是你如何做到的：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>将模式设置为生产。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>bin/magento deploy:mode:set production</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Thu, 14 Sep 2023 07:36:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[以编程方式清除缓存 Magento 2]]></title>
      <link>https://www.360magento.com/blog/clear-cache-programmically-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在开发的情况下，开发人员或商家的请求，他/她需要以编程方式清除/刷新缓存。如果您在 Magentoe 中以编程方式清除缓存时遇到问题，本文适合您。今天，我们将向您展示<strong>如何以编程方式清除缓存</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在开始说明之前，让我提醒您一些有关 Magento 2 缓存清除的基本知识。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="why-should-clear-cache-in-magento-2">为什么要清除 Magento 2 中的缓存？</h2>
<p><!-- /wp:heading --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="magento-2-cache-clean--cache-flush-the-differences">Magento 2 缓存清理和缓存刷新：差异</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 2 缓存清理/清除和 Magento 2 缓存刷新不一样。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>关于缓存清理/清除：</strong>&nbsp;Magento 2 缓存清理/清除是删除所有启用的 Magento 相关缓存的操作。它不会清除服务器中与 Magento 无关的其他部分。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>关于缓存刷新：</strong>&nbsp;Magento 2 缓存刷新是清理所有缓存存储的操作。与缓存清理/清除不同，此操​​作会对属于同一存储的其他存储部分产生影响。当新后端配置后缓存清理未反映前端的更改时，您可以刷新 Magento 2 中的缓存。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>区分这两个动作很简单。另外，记住这一点很重要，因为如果您错误执行这两个操作，可能会导致您的商店发生意外的变化。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在我们将了解如何在 Magento 2 中以编程方式清除/清理缓存。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-clear-cache-programmatically-in-magento-2">如何在 Magento 2 中以编程方式清除缓存</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在Helper中实现这几行代码：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
use Magento\Framework\App\PageCache\Version;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Cache\Frontend\Pool;
protected $cacheTypeList;
protected $cacheFrontendPool;
 
public function __construct(
    TypeListInterface $cacheTypeList, 
    Pool $cacheFrontendPool
){
    
    $this-&gt;cacheTypeList = $cacheTypeList;
    $this-&gt;cacheFrontendPool = $cacheFrontendPool;
 
}
 
public function flushCache(Version $subject)
{
  $_types = [
            'config',
            'layout',
            'block_html',
            'collections',
            'reflection',
            'db_ddl',
            'eav',
            'config_integration',
            'config_integration_api',
            'full_page',
            'translate',
            'config_webservice'
            ];
 
    foreach ($_types as $type) {
        $this-&gt;cacheTypeList-&gt;cleanType($type);
    }
    foreach ($this-&gt;cacheFrontendPool as $cacheFrontend) {
        $cacheFrontend-&gt;getBackend()-&gt;clean();
    }
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>现在调用控制器或模型<code>flushCache()</code>中的函数。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Wed, 13 Sep 2023 08:07:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 结帐页面添加自定义邮政编码验证器]]></title>
      <link>https://www.360magento.com/blog/add-custom-zipcode-validator-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在 Magento 2 中，自定义邮政编码验证和/或在结帐页面上添加自定义邮政编码验证器并不困难。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>Magento 使用正则表达式 (&nbsp;<code>re</code>) 检查输入的邮政编码是否正确。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在这篇文章中，我们将<code>add our own expression to validate the zipcode</code>.</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在 Magento 默认情况下，所有模式都在此文件中定义：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><code>vendor/magento/module-directory/etc/zip_codes.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>要添加您的模式，或在结帐页面上自定义邮政编码验证以适合特定国家/地区，请在您自己的模块<code>zip_codes.xml</code>中创建一个新模式<a href="https://www.mageplaza.com/magento-2-module-development/"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>这是一个例子：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>我选择 NL（荷兰语）并将其添加<code>zip_codes.xml</code>到<code>Example\HelloWorld\etc</code>文件夹</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Directory:etc/zip_codes.xsd"&gt;
    &lt;zip countryCode="NL"&gt;
            &lt;codes&gt;
                &lt;code id="pattern_1" active="true" example="1234 AB"&gt;^[0-9]{4}\s[a-zA-Z]{2}$&lt;/code&gt;
                &lt;code id="pattern_2" active="true" example="1234AB"&gt;^[0-9]{4}\s?[a-zA-Z]{2}$&lt;/code&gt;
            &lt;/codes&gt;
        &lt;/zip&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>Pattern_2与第一个非常相似，只是<strong>它</strong>允许用户输入空格字符。<br />我在那里留下了 2 个图案，以便您可以看到差异，当应用到您的商店时，您可以删除第一个图案，pattern_2 仍然覆盖 pattern_1 的情况。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在是时候刷新缓存并测试结果了</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -98px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 12 Sep 2023 08:05:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 工厂对象]]></title>
      <link>https://www.360magento.com/blog/factory-object-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在这一部分中，我们将讨论<strong>Magento 2 中模型的工厂对象</strong>。正如您在 OOP 中所知，工厂方法将用于实例化对象。在 Magento 2 中，<strong>Magento 2 工厂对象</strong>执行相同的操作。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>Factory<strong>类的名称</strong>是 Model 类的名称并附加单词<code>Factory</code>。因此，对于我们的示例，我们将有 TopicFactory 类。您不得创建此类。Magento 将为您创建它。每当 Magento 的对象管理器遇到以&ldquo;Factory&rdquo;结尾的类名时，如果该类尚不存在，它将自动在 var/ Generation 文件夹中生成 Factory 类。你会看到工厂类</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>var/generation/&lt;vendor_name&gt;/&lt;module_name&gt;/Model/ClassFactory.php
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>为了实例化模型对象，我们将使用自动构造函数依赖注入来注入工厂对象，然后使用工厂对象实例化模型对象。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，我们将调用模型来获取Block 中的数据。我们将创建一个主题块：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>Example\HelloWorld\Block\Topic.php
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>该文件的内容：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace Example\HelloWorld\Block;
class Topic extends \Magento\Framework\View\Element\Template
{
	protected $_topicFactory;
	public function _construct(
		\Magento\Framework\View\Element\Template\Context $context,
		\Example\HelloWorld\Model\TopicFactory $topicFactory
	){
		$this-&gt;_topicFactory = $topicFactory;
		parent::_construct($context);
	}

	public function _prepareLayout()
	{
		$topic = $this-&gt;_topicFactory-&gt;create();
		$collection = $topic-&gt;getCollection();
		foreach($collection as $item){
			var_dump($item-&gt;getData());
		}
		exit;
	}
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>正如您在此块中看到的，将在函数中创建 TopicFactory 对象<code>_construct()</code>。在<code>_prepareLayout()</code>函数中，我们用来<code>$topic = $this-&gt;_topicFactory-&gt;create();</code>创建模型对象。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -96px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 11 Sep 2023 07:44:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何创建和配置 Magento 2 Cron？]]></title>
      <link>https://www.360magento.com/blog/magento-2-create-cron-job/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>Magento 2 Create Cron Job</strong>正在按时设置自动计划，这在您运行Magento 2 商店时非常方便。为什么它是一个如此有用的功能？例如，网站统计或内容管理系统等软件可能需要在特定时间进行活动，但您无法手动处理。这就是在您的 Web 服务器上创建 Cron Job 变得很方便的时候。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>不用担心复杂的教程，因为我在这里是为了让您简单易懂。即使您不懂技术，您仍然可以轻松学习。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>Magento 2 以编程方式创建 Cron 作业</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>什么是 Cron 作业？</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如何在 Magento 2 中创建 Cron 作业<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>创建 crontab.xml</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>创建测试.php</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>Magento 2 中 Cron Job 的应用</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="what-is-a-cron-job">什么是 Cron 作业？</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><strong>Cron Job</strong>是 Linux（用户免费的操作系统）的一个很棒的功能。<strong>cron 作业</strong>将创建适合您想要执行的任务的命令或脚本。<strong>Cron Job 允许在准确的时间和日期自动运行</strong>，而不是手动工作。由于其自动化，<strong>Cron Jobs 是</strong>每天或每周重复项目的完美选择。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>笔记</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>Cron 配置在 Magento 中非常重要，它可以为许多系统活动设置时间表，例如重新索引、自动更新汇率、Magento 电子邮件等。只有当配置正确时，cron 作业才会激活。如果出现错误，这意味着 Magento 将无法按预期运行。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-create-cron-job-in-magento-2">如何在 Magento 2 中创建 Cron 作业</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>请按照指南按照您的意愿启动<strong>cron 作业程序：</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在&ldquo;Cron&rdquo;文件夹中创建一个类</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>使用 PHP 手动设置 cron 计划：<code>bin/magento cron:run</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>var/log/system.log</code>在 cron 作业运行后查找日志。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>登录到 Magento 2 管理面板，按照路径执行：<code>Stores &gt; Configuration &gt; Advanced &gt; System</code>，然后更改每个 cron 组的调度程序设置。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>最后，从命令行运行 cron：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p><code>magento cron:run [--group="&lt;cron group name&gt;"]</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，我们将在HelloWorld 模块中添加一个自定义 cron&nbsp;。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-crontabxml">创造<code>crontab.xml</code></h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/Example/HelloWorld/etc/crontab.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>内容将是</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" ?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd"&gt;
	&lt;group id="default"&gt;
		&lt;job instance="Example\HelloWorld\Cron\Test" method="execute" name="example_helloworld_cron"&gt;
			&lt;schedule&gt;* * * * *&lt;/schedule&gt;
		&lt;/job&gt;
	&lt;/group&gt;
&lt;/config&gt;

</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><code>group id</code>是你的 cron 组名称。您一次只能为单个组运行 cron。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>job instance</code>是要实例化的类（类路径）。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>job method</code>是要调用的方法<code>job instance</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>job name</code>是此 cron 作业的唯一 ID。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>schedule</code>是 cron 格式的计划。下图显示了它的组成部分：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>* * * * * command to be executed
| | | | |
| | | | +----- Day of week (0 - 7) (Sunday=0 or 7)
| | | +------- Month (1 - 12)
| | +--------- Day of month (1 - 31)
| +----------- Hour (0 - 23)
+------------- Minute (0 - 59)

</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在 中<code>crontab.xml</code>，我们定义<code>job instance</code>为<code>Example\HelloWorld\Cron\Test</code>。现在应该已经创建了。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-testphp">创建测试.php</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/Cron/Test.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>内容将是：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>
&lt;?php

namespace <span>Example</span>\HelloWorld\Cron;

class Test
{

	public function execute()
	{

		$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/cron.log');
		$logger = new \Zend\Log\Logger();
		$logger-&gt;addWriter($writer);
		$logger-&gt;info(__METHOD__);

		return $this;

	}
}

</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>全部完成，现在请刷新缓存并<code>magento cron:run --group="default"</code>从命令行运行。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>要检查 Cron 是否正常工作，请访问您的商店，您将看到其中的<code>var/log/cron.log</code>文本。<code><code>Example</code>\HelloWorld\Cron\Test::execute</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="applications-of-cron-job-for-magento-2">Magento 2 中 Cron Job 的应用</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 的多项功能至少需要一项 Cron Job，它安排未来发生的活动。这些活动的部分列表如下：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>目录价格规则</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>时事通讯</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>生成 Google 站点地图</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>客户警报/通知（产品价格变化、产品有货）</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>重新索引</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>私人销售（仅限 Magento Commerce）</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>自动更新货币汇率</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>所有 Magento 电子邮件（包括订单确认和交易电子邮件）</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>
<div id="gtx-trans" style="position: absolute; left: -165px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sun, 10 Sep 2023 07:25:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 使用示例创建 API - 代码片段]]></title>
      <link>https://www.360magento.com/blog/magento-2-create-api/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>Magento 2 创建 API</strong>意味着帮助在线零售商生成供自己使用的应用程序编程接口。API 是一组用于设计软件应用程序的例程、协议和其他工具。因此，如果您从其他网站请求任何程序或服务，API 是连接数据的必需元素。通过在 Magento 2 中创建 API，您可以轻松获得成功启动程序的所有构建块。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="what-is-api-in-magento-2">Magento 2 中的 API 是什么？</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>API 代表应用程序编程接口，允许您从应用程序访问数据。API可以作为程序员和应用程序之间的中间人来调用。当程序员通过中间人发出请求时，如果请求被批准，正确的数据就会被返回。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>作为基于 Magento 2 平台的电子商务商店，您应该关注两种架构类型的 Web API：<strong>REST</strong>（表述性状态传输）和<strong>SOAP</strong>（简单对象访问协议）。然而，在官方文档中，它们只附带原始的curl请求，没有任何示例。为了有效地连接和使用<strong>Magento 2 API</strong>，本主题将向您具体展示 PHP 示例。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="snippet-api">片段API</h2>
<p><!-- /wp:heading --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="file-etcwebapixml">文件：<code>etc/webapi.xml</code></h4>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" ?&gt;
&lt;routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd"&gt;
	&lt;route method="GET" url="/V1/example-helloworld/post"&gt;
		&lt;service class="Example\HelloWorld\Api\PostManagementInterface" method="getPost"/&gt;
		&lt;resources&gt;
			&lt;resource ref="anonymous"/&gt;
		&lt;/resources&gt;
	&lt;/route&gt;
&lt;/routes&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="file-etcdixml">文件：<code>etc/di.xml</code></h4>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" ?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"&gt;
	&lt;preference for="Example\HelloWorld\Api\PostManagementInterface" type="Example\HelloWorld\Model\PostManagement"/&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="file-modelpostmanagementphp">文件：<code>Model/PostManagement.php</code></h4>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php 
namespace Example\HelloWorld\Model;
 
 
class PostManagement {

	/**
	 * {@inheritdoc}
	 */
	public function getPost($param)
	{
		return 'api GET return the $param ' . $param;
	}
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="file-apipostmanagementinterfacephp">文件：<code>Api/PostManagementInterface.php</code></h4>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php 
namespace Example\HelloWorld\Api;
 
 
interface PostManagementInterface {


	/**
	 * GET for Post api
	 * @param string $param
	 * @return string
	 */
	
	public function getPost($param);
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>如果您想确保该过程顺利且成功，最好考虑 Magento API 集成服务。您将节省大量时间和精力，同时专注于其他重要的业务方面。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>通过使用 我们 的 Magento API 集成服务，您可以：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>将您的商店与其他第三方平台连接以简化流程</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>通过一个仪表板执行各种任务并共享数据</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>消除手动和繁琐的任务</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>改善客户体验</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>
<div id="gtx-trans" style="position: absolute; left: -61px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 09 Sep 2023 06:20:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 以编程方式添加类别属性]]></title>
      <link>https://www.360magento.com/blog/magento-2-category-attributes-programmatically/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>默认的 Magento 2 类别属性很好，但有时有必要添加新的属性。今天我们将向您展示如何以编程方式向 Magento 2 添加类别属性。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-add-category-attribute-programmatically-in-magento-2">如何在 Magento 2 中以编程方式添加类别属性</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>步骤1：创建文件InstallData.php</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 2：定义 install() 方法</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 3：创建类别属性</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第四步：显示类别属性</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-file-installdataphp">创建文件InstallData.php</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>我们将从位于<code>app/code/<code>Example</code>/HelloWorld/Setup/InstallData.php</code>.&nbsp;该文件的内容：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace <span>Example</span>\HelloWorld\Setup;

use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;

class InstallData implements InstallDataInterface
{
	private $eavSetupFactory;

	public function __construct(EavSetupFactory $eavSetupFactory)
	{
		$this-&gt;eavSetupFactory = $eavSetupFactory;
	}
	
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="define-the-install-method">定义 install() 方法</h3>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
	
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
	
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-category-attribute-programmatically">以编程方式创建类别属性</h3>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace <span>Example</span>\HelloWorld\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Setup\EavSetupFactory;

class InstallData implements InstallDataInterface
{

	private $eavSetupFactory;

	public function __construct(EavSetupFactory $eavSetupFactory)
	{
		$this-&gt;eavSetupFactory = $eavSetupFactory;
	}

	public function install(
		ModuleDataSetupInterface $setup,
		ModuleContextInterface $context
	)
	{
		$eavSetup = $this-&gt;eavSetupFactory-&gt;create(['setup' =&gt; $setup]);

		$eavSetup-&gt;addAttribute(
			\Magento\Catalog\Model\Category::ENTITY,
			'mp_new_attribute',
			[
				'type'         =&gt; 'varchar',
				'label'        =&gt; '<span>Example</span> Attribute',
				'input'        =&gt; 'text',
				'sort_order'   =&gt; 100,
				'source'       =&gt; '',
				'global'       =&gt; 1,
				'visible'      =&gt; true,
				'required'     =&gt; false,
				'user_defined' =&gt; false,
				'default'      =&gt; null,
				'group'        =&gt; '',
				'backend'      =&gt; ''
			]
		);
	}
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="display-the-category-attribute">显示类别属性</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>类别 UI 组件是使用<code>category_form.xml</code>文件中的配置呈现的。所有具有该名称的文件都会合并在一起。因此，我们将通过<code>category_form.xml</code>在<code>app/code/<code><code>Example</code></code>/HelloWorld/view/adminhtml/ui_component/</code>目录中创建文件来添加字段。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>这是在&ldquo;常规&rdquo;组下添加字段的完整示例。请务必注意，它<code>mp_new_attribute</code>应与您在安装脚本中创建的属性的 ID 相匹配。</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" ?&gt;
&lt;form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"&gt;
    &lt;fieldset name="general"&gt;
        &lt;field name="mp_new_attribute"&gt;
            &lt;argument name="data" xsi:type="array"&gt;
                &lt;item name="config" xsi:type="array"&gt;
                    &lt;item name="required" xsi:type="boolean"&gt;false&lt;/item&gt;
                    &lt;item name="validation" xsi:type="array"&gt;
                        &lt;item name="required-entry" xsi:type="boolean"&gt;false&lt;/item&gt;
                    &lt;/item&gt;
                    &lt;item name="sortOrder" xsi:type="number"&gt;333&lt;/item&gt;
                    &lt;item name="dataType" xsi:type="string"&gt;string&lt;/item&gt;
                    &lt;item name="formElement" xsi:type="string"&gt;input&lt;/item&gt;
                    &lt;item name="label" translate="true" xsi:type="string"&gt;<span>Example</span> new attribute&lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/field&gt;
    &lt;/fieldset&gt;
&lt;/form&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>全部完成，请运行升级，刷新缓存，并检查结果。</p>
<p><!-- /wp:paragraph --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>刷新缓存 在此处运行刷新缓存</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>运行升级命令行：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>然后去<code>Product &gt; Categories</code>管理员那里查看结果。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -113px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 08 Sep 2023 08:47:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 创建事件 - Magento 2 中的观察者]]></title>
      <link>https://www.360magento.com/blog/magento-2-create-events/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在此示例中，我们将向您展示<strong>如何在 Magento 2 中创建事件</strong><code>Example</code><code>&nbsp;- Event</code>，我们仅捕获该事件以在前端显示，因此我们应该<code>events.xml</code>在文件夹中创建一个文件<code>etc/frontend</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="overview-of-creating-events-in-magento-2">在 Magento 2 中创建事件的概述</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：调度事件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：创建事件文件：events.xml</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：创建观察者类</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 4 步：刷新缓存并检查结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="understand-catching-and-handling-a-event">了解捕获和处理事件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>Magento 使用区域定义来管理商店。我们将有一个前端区域和管理区域。通过配置文件，它们可以放在3个地方：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>文件夹下<code>etc/</code>是可在管理和前端中使用的配置。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>etc/frontend</code>文件夹将用于前端区域。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>etc/adminhtml</code>文件夹将用于管理区域。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>与事件配置文件相同。您可以为每个区域创建事件配置文件，如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>管理区域：<code>app/code/<code>Example</code>/HelloWorld/etc/adminhtml/events.xml</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>前端区域：<code>app/code/<code>Example</code>/HelloWorld/etc/frontend/events.xml</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>全局区域：<code>app/code/<code>Example</code>/HelloWorld/etc/events.xml</code></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-1-dispatch-event">第 1 步：调度事件</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在我们想要调度一个magento 2 事件列表，它允许其他模块可以更改显示的单词。我们将像这样更改控制器：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/Controller/Index/Test.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>内容将是：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\HelloWorld\Controller\Index;

class Test extends \Magento\Framework\App\Action\Action
{

	public function execute()
	{
		$textDisplay = new \Magento\Framework\DataObject(array('text' =&gt; '<span>Example</span>'));
		$this-&gt;_eventManager-&gt;dispatch('example_helloworld_display_text', ['mp_text' =&gt; $textDisplay]);
		echo $textDisplay-&gt;getText();
		exit;
	}
}

</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>调度方法将接收 2 个参数：一个唯一的事件名称和一个数组数据。在此示例中，我们将数据对象添加到事件中并回调它以显示文本。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-2-create-a-event-file-eventsxml">步骤2：创建事件文件：events.xml</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/etc/frontend/events.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"&gt;
    &lt;event name="example_helloworld_display_text"&gt;
        &lt;observer name="mp_display_text" instance="<span>Example</span>\HelloWorld\Observer\ChangeDisplayText" /&gt;
    &lt;/event&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在此文件中的 config 元素下，我们定义一个事件元素，其名称是上面调度的事件名称。将执行此事件的类将通过实例属性在观察者元素中定义。观察者的名称用于与该事件的其他观察者进行识别。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>使用此文件，只要在前端区域调用此事件的调度方法，<code>events.xml</code>Magento 就会执行类。<code><code>Example</code>\HelloWorld\Observer\ChangeDisplayText</code>请注意，我们放置<code>events.xml</code>在前端区域，因此如果您在管理区域（如管理控制器）调度该事件，它将不会运行。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-3-create-observer-class">第三步：创建观察者类</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在我们将创建一个类来执行上述事件。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/Observer/ChangeDisplayText.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php

namespace <span>Example</span>\HelloWorld\Observer;

class ChangeDisplayText implements \Magento\Framework\Event\ObserverInterface
{
	public function execute(\Magento\Framework\Event\Observer $observer)
	{
		$displayText = $observer-&gt;getData('mp_text');
		echo $displayText-&gt;getText() . " - Event &lt;/br&gt;";
		$displayText-&gt;setText('Execute event successfully.');

		return $this;
	}
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>该类将实现<code>ObserverInterface</code>并声明执行方法。您可以看看这个简单的方法来了解它是如何工作的。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="step-4-flush-cache-and-check-the-result">步骤 4：刷新缓存并检查结果</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>最后刷新缓存并查看结果。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Thu, 07 Sep 2023 08:36:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 缓存和页面缓存概述]]></title>
      <link>https://www.360magento.com/blog/cache-overview-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>除了Magento\Cache库之外，Magento 还使用Zend_Cache与缓存存储交互。在今天的文章中，让我们一起探讨 Magento 2 中的缓存和页面缓存。我希望您在以下信息中找到有用的信息。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="cache-overview">缓存概述</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>当您首次安装 Magento 商店时，默认情况下会启用文件系统缓存。<br />要更改它，您可以编辑<code>env.php</code>在<code>app/etc</code>文件夹。找到<code>cache_types</code>并更改 array_key 值（1 或 0）。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>设置应该如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>'cache_types' =&gt;
    array (
        'config' =&gt; 1,
        'layout' =&gt; 1,
        'block_html' =&gt; 1,
        'collections' =&gt; 1,
        'db_ddl' =&gt; 1,
        'eav' =&gt; 1,
        'full_page' =&gt; 0,
        'translate' =&gt; 1,
        'config_integration' =&gt; 1,
        'config_webservice' =&gt; 1,
        'config_integration_api' =&gt; 1,
    ),
); 
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="page-cache-overview">页面缓存概述</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在 Magento 中，&ldquo;页面缓存&rdquo;意味着缓存整个页面。<br />您可以使用<code>Default Cache</code>将缓存文件存储在<code>File system</code>、<code>Database</code>或 上<code>Redis</code>。<br />另一种选择是使用Magento 推荐的Varnish 。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="cacheable-and-uncacheable-pages">可缓存和不可缓存的页面</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>默认情况下，所有页面都是可缓存的。<br />如果您不希望缓存页面。您可以将其添加<code>cacheable="false"</code>到布局中的任何块中。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -99px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 06 Sep 2023 08:22:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 索引和重新索引]]></title>
      <link>https://www.360magento.com/blog/magento-2-indexing/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>如何<strong>在 Magento 2 中创建索引器重新索引</strong>。<strong>索引器是Magento 2 索引</strong>中的一个重要功能。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>我们将使用示例模块 Example_HelloWorld 进行此练习。请查看我们之前的文章，了解如何在 Magento 2 中创建示例模块。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>索引是 Magento 转换产品、类别等数据以提高店面性能的方式。当数据发生变化时，必须更新转换后的数据或重新索引。Magento 具有非常复杂的架构，在许多数据库表中存储大量商家数据（包括目录数据、价格、用户、商店等）。为了优化店面性能，Magento 使用索引器将数据累积到特殊表中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，假设您将商品的价格从 8.99 美元更改为 6.99 美元。Magento<strong>必须重新索引</strong>价格变化才能将其显示在您的店面上。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果没有索引，Magento 就必须动态计算每种产品的价格&mdash;&mdash;考虑到购物车价格规则、捆绑定价、折扣、分级定价等。加载产品价格需要很长时间，可能会导致购物车放弃。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>创建索引器概述</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="lets-start-to-create-a-custom-indexer">让我们开始创建一个自定义索引器：</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：创建索引器配置文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：创建Mview配置文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：创建索引器类</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 4 步：运行测试</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-indexer-configuration-file">创建索引器配置文件</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>该配置文件将定义索引器。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件<code>app/code/Example/HelloWorld/etc/indexer.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Indexer/etc/indexer.xsd"&gt;
    &lt;indexer id="example_helloworld_indexer" view_id="example_helloworld_indexer" class="<span>Example</span>\HelloWorld\Model\Indexer\Test"&gt;
        &lt;title translate="true"&gt;<span>Example</span> HelloWorld Indexer&lt;/title&gt;
        &lt;description translate="true"&gt;HelloWorld of custom indexer&lt;/description&gt;
    &lt;/indexer&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在此文件中，我们使用以下属性声明一个新的索引器进程：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>id 属性用于标识该索引器。当您想通过命令行检查状态、模式或重新索引该索引器时，可以调用它。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>这<code>view_id</code>是将在配置文件中定义的视图元素的 id&nbsp;<code>mview</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>class 属性是我们处理索引器方法的类的名称。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>简单的<strong>Magento 2 索引</strong>将有一些子元素：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>title 元素用于定义在索引器网格中显示时的标题。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>描述元素用于定义在索引器网格中显示时的描述。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-mview-configuration-file">创建Mview配置文件</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>该<code>mview.xml</code>文件用于跟踪某个实体的数据库更改并运行更改句柄（execute() 方法）。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/etc/mview.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Mview/etc/mview.xsd"&gt;
    &lt;view id="example_helloworld_indexer" class="<span>Example</span>\HelloWorld\Model\Indexer\Test" group="indexer"&gt;
        &lt;subscriptions&gt;
            &lt;table name="catalog_product_entity" entity_column="entity_id" /&gt;
        &lt;/subscriptions&gt;
    &lt;/view&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在此文件中，我们定义一个视图元素，该元素具有要从索引器调用的 id 属性和包含该方法的类<code>execute()</code>。当订阅中的表发生更改时，将运行此方法。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>为了声明表，我们使用表名和该表的列，它们将被发送到该<code>execute()</code>方法。在此示例中，我们声明了 table&nbsp;<code>catalog_product_entity</code>。因此，每当保存一个或多个产品时，类中的execute()方法<code><code>Example</code>\HelloWorld\Model\Indexer\Test</code>就会被调用。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="create-indexer-class">创建索引器类</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>按照上面的内容<code>indexer.xml</code>，<code>mview.xml</code>我们将为它们定义一个 Indexer 类：<code><code>Example</code>\HelloWorld\Model\Indexer\Test</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/Model/Indexer/Test.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?php
namespace <span>Example</span>\HelloWorld\Model\Indexer;

class Test implements \Magento\Framework\Indexer\ActionInterface, \Magento\Framework\Mview\ActionInterface
{
	/*
	 * Used by mview, allows process indexer in the "Update on schedule" mode
	 */
	public function execute($ids){

		//code here!
	}

	/*
	 * Will take all of the data and reindex
	 * Will run when reindex via command line
	 */
	public function executeFull(){
		//code here!
	}
   
   
	/*
	 * Works with a set of entity changed (may be massaction)
	 */
	public function executeList(array $ids){
		//code here!
	}
   
   
	/*
	 * Works in runtime for a single entity using plugins
	 */
	public function executeRow($id){
		//code here!
	}
}
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>您可以在 Indexer 类的方法中编写代码以将数据添加到索引器表中。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>之后，请刷新缓存并<code>System &gt; Index Management</code>从后端查看结果。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="run-reindex-by-command">通过命令运行重建索引</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>通过命令行运行重新索引<a href="https://www.mageplaza.com/devdocs/magento-2-command-line-interface-cli.html"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento indexer:reindex
</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Tue, 05 Sep 2023 07:21:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 路由开发]]></title>
      <link>https://www.360magento.com/blog/magento-2-routings/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在这篇文章中，我们将讨论<strong>Magento 2 路由</strong>中的一个重要部分。路由将定义模块的名称，我们可以在 url 中使用该名称来查找模块并执行控制器操作<strong>。</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p><strong>目录</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>Magento 2 请求流程</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在前端/管理上创建自定义路由<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>前端路线<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>routes.xml</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>管理路线</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>使用route重写controller</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="magento-2-request-flow">Magento 2 请求流程</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在Magento 2中，请求 url 将如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>http://example.com/index.php/front_name/controller/action
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>在该 url 中，您将看到<code>front_name</code>用于查找模块的 。<strong>路由器</strong>通过在<strong>routes.xml</strong>中定义为每个模块定义这个名称，我们将在下面看到更多细节。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>当您在 Magento 2 中发出请求时，它将按照以下流程查找<code>controller/action</code>：&nbsp;<code>index.php &rarr; HTTP app &rarr; FrontController &rarr; Routing &rarr; Controller processing &rarr; etc</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>将<code>FrontController</code>在 Http 类中调用来路由将找到<code>controller/action</code>匹配项的请求。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>vendor/magento/framework/App/FrontController.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>public function dispatch(RequestInterface $request)
{
   \Magento\Framework\Profiler::start('routers_match');
   $routingCycleCounter = 0;
   $result = null;
   while (!$request-&gt;isDispatched() &amp;&amp; $routingCycleCounter++ &lt; 100) {
       /** @var \Magento\Framework\App\RouterInterface $router */
       foreach ($this-&gt;_routerList as $router) {
           try {
               $actionInstance = $router-&gt;match($request);
               if ($actionInstance) {
                   $request-&gt;setDispatched(true);
                   $this-&gt;response-&gt;setNoCacheHeaders();
                   if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
                       $result = $actionInstance-&gt;dispatch($request);
                   } else {
                       $result = $actionInstance-&gt;execute();
                   }
                   break;
               }
           } catch (\Magento\Framework\Exception\NotFoundException $e) {
               $request-&gt;initForward();
               $request-&gt;setActionName('noroute');
               $request-&gt;setDispatched(false);
               break;
           }
       }
   }
   \Magento\Framework\Profiler::stop('routers_match');
   if ($routingCycleCounter &gt; 100) {
       throw new \LogicException('Front controller reached 100 router match iterations');
   }
   return $result;
}

</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>正如您在此方法中看到的<code>dispatch()</code>，路由器列表将循环查找与此请求匹配的路由器。如果它找到此请求的控制器操作，则将调用并执行该操作。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="create-custom-route-on-frontendadmin">在前端/管理上创建自定义路由</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>我们将了解如何创建前端路由、管理路由以及如何使用路由重写控制器。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="frontend-route">前端路线</h3>
<p><!-- /wp:heading --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="routesxml">路由.xml</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>要注册前端路由，我们必须创建一个<strong>routes.xml</strong>文件：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/Example/HelloWorld/etc/frontend/routes.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0" ?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
    &lt;!--Use router 'standard' for frontend route--&gt;
    &lt;router id="standard"&gt;
        &lt;!--Define a custom route with id and frontName--&gt;
        &lt;route frontName="helloworld" id="helloworld"&gt;
            &lt;!--The module which this route match to--&gt;
            &lt;module name="<span>Example</span>_HelloWorld"/&gt;
        &lt;/route&gt;
    &lt;/router&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>请看一下代码，你会发现注册<strong>路由</strong>非常简单。您必须使用标准路由器作为前端。该路由将有一个为其定义模块的子路由和 2 个属性：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>id 属性是一个唯一的字符串，用于标识该路由。您将使用此字符串来声明此模块操作的布局句柄</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>frontName 属性也是一个唯一的字符串，将显示在 url 请求上。例如，如果您声明这样的路线：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code> &lt;route frontName="helloworld" id="helloworld"&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>该模块的 url 应该是：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>http://example.com/index.php/helloworld/controller/action
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>此操作的布局句柄为：<code>helloworld_controller_action.xml</code>&nbsp;因此，对于此示例路径，您必须在此文件夹中创建操作类：<code>{namespace}/{module}/Controller/{Controller}/{Action}.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="admin-route">管理路线</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>该路由与前端路由相同，但您必须在 adminhtml 文件夹中声明它，路由器 id 为<code>admin</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/<code>Example</code>/HelloWorld/etc/adminhtml/routes.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
    &lt;!--Use router 'admin' for admin route --&gt;
    &lt;router id="admin"&gt;
        &lt;!--Define a custom route with id and frontName --&gt;
        &lt;route id="<span>example</span>_helloworld" frontName="<span>example</span>_helloworld"&gt;
            &lt;!--The module which this route match to--&gt;
            &lt;module name="<span>Example</span>_HelloWorld"/&gt;
        &lt;/route&gt;
    &lt;/router&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>管理页面的 url 与前端页面的结构相同，但<code>admin_area</code>前面会添加名称<code>route_frontName</code>以识别这是管理路由器。例如，管理 cms 页面的 url ：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>http://example.com/index.php/admin/<span>example</span>_helloworld/controller/action
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>管理页面的控制器操作将添加到文件夹内<code>Controller/Adminhtml</code>。例如上面的网址：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>{namespace}/{module}/Controller/Adminhtml/{Controller}/{Action}.php
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="use-route-to-rewrite-controller">使用route重写controller</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在此路径中，我们将看到如何使用路由器重写控制器。如上路径，可以看到每条路由都会有一个id属性来标识。那么如果我们定义 2 个具有相同 id 属性的路由会发生什么呢？</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>答案是控制器操作将在这两个模块中找到。Magento 系统提供before/after 属性来配置模块排序顺序，定义首先找到哪个模块控制器。这是控制器重写的逻辑。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，如果我们想重写控制器<code>customer/account/login</code>，我们将在<strong>route.xml</strong>中定义更多路由，如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>文件：<code>app/code/Example/HelloWorld/etc/frontend/routes.xml</code></p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
   &lt;!--Use router 'standard' for frontend route--&gt;
   &lt;router id="standard"&gt;
        &lt;!--Define a custom route with id and frontName--&gt;
        &lt;route frontName="helloworld" id="helloworld"&gt;
            &lt;!--The module which this route match to--&gt;
            &lt;module name="<span>Example</span>_HelloWorld"/&gt;
        &lt;/route&gt;
       &lt;route id="customer"&gt;
           &lt;module name="<span>Example</span>_HelloWorld" before="Magento_Customer" /&gt;
       &lt;/route&gt;
   &lt;/router&gt;
&lt;/config&gt;
</code></pre>
<p><!-- /wp:code --> <!-- wp:paragraph --></p>
<p>和控制器文件：<code>app/code/<code>Example</code>/HelloWorld/Controller/Account/Login.php</code></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>所以 frontController 会首先在我们的模块中查找Login 操作，如果找到，它将运行，而 Login 操作<code>Magento_Customer</code>将不会运行。我们成功重写了控制器。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>您还可以使用它来拥有与另一个模块具有相同路由器的第二个模块。例如，通过上述声明，您可以将路由&ldquo;customer&rdquo;用于控制器操作。如果您有控制器&ldquo;Blog&rdquo;和操作&ldquo;Index.php&rdquo;，您可以使用以下网址：</p>
<p><!-- /wp:paragraph --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>http://example.com/customer/blog/index</code></pre>
<p><!-- /wp:code --></p>
<div id="gtx-trans" style="position: absolute; left: -37px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 04 Sep 2023 03:29:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中的订单状态工作流程]]></title>
      <link>https://www.360magento.com/blog/order-status-workflow-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>遵循<strong>订单状态工作流程</strong>将帮助您了解客户下订单时的订购流程。否则，订单状态工作流程将向商店管理员显示每个订单状态都对应于一个 state。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，新订单的第一阶段未付款和交付，Magento 2系统会自动将其设置为&ldquo;待处理&rdquo;。完成发票或更新发货后，状态将更改为&ldquo;处理中&rdquo;，当您生成发票并发货订单时，状态将更改为&ldquo;完成&rdquo;。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>让我们通过下图详细了解订单状态工作流程。</p>
<p><!-- /wp:paragraph --> <!-- wp:image {"id":3894,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3894" src="http://kb.360magento.net/wp-content/uploads/2023/08/order-status-workflow-magento-2.png" /><img src="https://www.360magento.com/media/wysiwyg/order-status-workflow-magento-2.png" /> <!-- /wp:image --> <!-- wp:paragraph --></p>
<p>Magento 2 创建预定义状态，例如：新建、待付款、处理、完成、关闭、取消、暂停、付款审核。一些预定义状态包括正在处理、待付款、待付款 Paypal、暂停、涉嫌欺诈、待处理、完成、已关闭、已取消、付款审核。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>下面我们就为大家解释一下工作流程中的术语：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><strong>新：</strong>当客户刚刚创建订单且尚未付款时</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>待处理：</strong>当发票和发货尚未创建时</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>处理中：</strong>订单已开票或已交付</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>完成：</strong>当订单已开具发票并发货时</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>暂停：</strong>管理员可以手动分配暂停状态</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>已取消：</strong>当订单尚未支付时，商店管理员或支付网关将决定放置此状态。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>已关闭：</strong>已包含贷项凭证且已退款。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Sun, 03 Sep 2023 07:47:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ 如何在 Magento 2 中配置运输策略]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-shipping-policy-magento-2/</link>
      <description><![CDATA[<p><span><span>店主应在结帐时向顾客阐明运输政策。</span><span>每个商店的运输政策都会有所不同，因此店主有必要核实客户是否准确了解您的运输政策。</span></span></p>
<p>Magento 2<span>支持您配置显示或不显示的运输政策，您可以通过在配置中完成运输政策参数来轻松编辑您的运输政策。</span></p>
<p><span>按照下面给出的指南在 Magento 2 中配置运输政策</span></p>
<h2 id="configure-your-shipping-policy-in-magento-2"><span>在 Magento 2 中配置您的运输政策</span></h2>
<ul>
<li><span>在管理面板上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>在&ldquo;&nbsp;</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>&rdquo;部分中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span><span>在左侧面板中</span><span>选择</span></span><code class="language-plaintext highlighter-rouge">Shipping Settings</code><span>下</span><code class="language-plaintext highlighter-rouge">Sales</code><span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Shipping Policy Parameters</code><span>部分，然后继续执行以下操作：</span>
<ul>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Apply Custom Shipping Policy</code><span>字段中，选择</span><code class="language-plaintext highlighter-rouge">Yes</code><span>启用应用</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Shipping Policy</code><span>字段的文本框中输入您的运输政策。</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。<br /><img src="https://www.360magento.com/media/wysiwyg/xcfI7eX.png" /><br /></span></li>
</ul>]]></description>
      <pubDate>Sat, 02 Sep 2023 07:40:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置多个地址运送]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-multiple-addresses-shipping-magento-2/</link>
      <description><![CDATA[<p><span><span>在本主题中，我将介绍一种最简单的方法来帮助您配置多个地址运送，从而允许客户在结帐页面将其订单运送到多个地址。</span><span>在某些情况下，当客户想要订购多种产品并将其运送到多个送货地址时，此功能是必要的。</span></span></p>
<p><span><span>商店所有者无需集成更多 Multiple Shipping Magento 扩展</span><span>即可</span></span>让客户满意。<span><span>跳出率将会降低，销量也会相应提高。</span><span>请按照下面给出的简单指南来配置多地址运送。</span></span></p>
<h2 class="active" id="4-steps-to-configure-multiple-address-shipping-in-magento-2"><span>在 Magento 2 中配置多个地址运送的 4 个步骤</span></h2>
<ol>
<li><span>在管理面板上，单击</span>&ldquo;商店&rdquo;<span><span>。</span><span>在</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>&ldquo;部分&rdquo;中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code></li>
<li><span><span>在左侧面板中</span><span>选择</span></span><code class="language-plaintext highlighter-rouge">Multishipping Settings</code><span>下</span><code class="language-plaintext highlighter-rouge">Sales</code><span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Options</code><span>部分，然后继续执行以下操作：<br /><img src="https://www.360magento.com/media/wysiwyg/I6CWSs3.png" /><br /></span></li>
</ol><ol>
<li>
<ul>
<li><span>在&ldquo;允许运送到</span>多个地址&rdquo;<span>字段中，选择</span><code class="language-plaintext highlighter-rouge">Yes</code><span>是否允许</span></li>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Maximum Qty Allowed for Shipping to Multiple Addresses</code><span>字段中输入您允许的最大送货地址数量</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。</span></li>
</ol>
<h2 class="active" id="benefits-of-multiple-addresses-shipping-in-magento-2"><span>Magento 2 中多个地址运送的好处</span></h2>
<p><span>Magento 2 中的多个地址运输可以为您带来惊人的好处，例如：</span></p>
<ul>
<li><span>鼓励赠送节日礼物：</span><span><span>在节日期间，顾客往往会购买礼物并同时发送给不同地址的很多人。</span><span>此功能使送礼变得比以往更容易。</span></span></li>
<li><span>支持企业礼品：</span><span>现在很容易获得想要为员工或商业伙伴购买礼品的公司的大订单。</span></li>
<li><span>降低跳出率：</span><span><span>通常，由于地址不同，购物者必须一次订购一份订单。</span><span>每当顾客完成结账时，商店就不得不面临可能推迟下次购买的风险。</span><span>不过，现在客户只需下单一次，因此跳出率将大大降低。</span></span></li>
<li></li>
</ul>]]></description>
      <pubDate>Fri, 01 Sep 2023 07:17:08 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置免费送货方式]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-free-shipping-method-magento-2/</link>
      <description><![CDATA[<h2 class="active" id="configure-free-shipping-method-in-magento-2"><span>在 Magento 2 中配置免费送货方式</span></h2>
<ul>
<li>配置免费送货方式设置</li>
<li>在承运商配置中显示免费送货</li>
</ul>
<h3 id="complete-free-shipping-method-settings"><span>在 Magento 2 中配置免费送货方法的步骤</span></h3>
<ul>
<li><span>在管理面板上，</span><code class="language-plaintext highlighter-rouge">Stores &gt; Settings &gt; Configuration</code><span>.</span></li>
<li><span>在左侧面板的 下</span><code class="language-plaintext highlighter-rouge">Sales</code><span>，选择 选项</span><code class="language-plaintext highlighter-rouge">Shipping Methods</code><span>卡。</span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Free Shipping</code><span>部分，</span>
<ul>
<li><code class="language-plaintext highlighter-rouge">Enable</code><span></span><span>选择是的</span><span><span>运输方式</span><span>。</span></span></li>
<li><span>在结账页面设置</span><code class="language-plaintext highlighter-rouge">Title</code><span>免运费。</span></li>
<li><span>在字段中创建有关运输方式的描述</span><code class="language-plaintext highlighter-rouge">Method Name</code><span>。</span></li>
<li><span>提供</span><code class="language-plaintext highlighter-rouge">Minimum Order Amount</code><span>运费。</span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Displayed Error Message</code><span><span>如果免费送货不可用，</span><span>请在出现的框中输入错误消息。</span></span></li>
<li><span>设置</span><code class="language-plaintext highlighter-rouge">Ship to Applicable Countries</code><span>为两个选项之一：</span>
<ul>
<li><span>所有允许的国家/地区：每个国家/地区均支持免费送货。</span></li>
<li><span>特定国家/地区：仅特定国家/地区支持免费送货。</span></li>
</ul>
</li>
<li><span></span><code class="language-plaintext highlighter-rouge">Show Method if Not Applicable</code><span><span>如果您想始终显示免费送货，</span><span>请设置为&ldquo;是&rdquo;。</span></span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Sort Order</code><span><span>在结帐页面的运输方式上</span><span>设置。</span></span></li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">Save Config</code><span>完成。</span></li>
</ul>
<h3 id="display-free-shipping-in-carrier-configuration"><span>在运营商配置中激活免费送货</span></h3>
<ul>
<li><span>从运输方式配置中，打开该</span><code class="language-plaintext highlighter-rouge">UPS</code><span>部分。</span></li>
<li><span>将&ldquo;自由方法&rdquo;设置为&ldquo;接地&rdquo;。</span></li>
<li><span>启用</span><code class="language-plaintext highlighter-rouge">Free Shipping with Minimum Order Amount</code><span>并设置现场应用免费送货的最小订单数量</span><code class="language-plaintext highlighter-rouge">Minimum Order Amount for Free Shipping</code><span>。</span></li>
<li><code class="language-plaintext highlighter-rouge">Save Config</code><span>完成。</span></li>
</ul>]]></description>
      <pubDate>Thu, 31 Aug 2023 07:11:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置统一费率运送方式]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-flat-rate-shipping-method-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>统一费率送货方式是在您的商店配置送货方式的简单解决方案。对于不同尺寸或重量或任何送货地址的任何订单，它收取固定的运费。由于统一费率运输易于配置和应用，因此受到许多运营商的欢迎。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>掌握在 Magento 2 中配置统一费率、免费和表费率运输方式的艺术，以有效地应用不同的费用。立即增强您的运输流程，实现最大程度的优化！</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="4-steps-to-configure-flat-rate-shipping-method-in-magento-2">在 Magento 2 中配置统一费率运送方式的 4 个步骤：</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Settings &gt; Configuration</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板的 下<code>Sales</code>，选择<code>Shipping Methods</code>选项卡。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Flat Rate</code>部分，
<ul>
<li><code>Enable</code><strong>选择是的</strong>运输方式。届时，购物车的&ldquo;预估运费和税费&rdquo;部分以及结账时的&ldquo;运费&rdquo;部分中均提供统一费率。</li>
<li>在结帐页面上设置<code>Title</code>统一运费。</li>
<li><code>Method Name</code>在购物车中显示计算运费的字段中描述方法。方法名称默认为&ldquo;Fixed&rdquo;。</li>
<li>要阐明应用统一费率送货方式的条款，请将 设为<code>Type</code>以下选项之一：</li>
</ul>
<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>无：此类型的运费为零，类似于免费送货方式。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>每个订单：设置整个订单的统一运费</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>每件商品：设置每件商品的统一运费。费率乘以购物车中的商品数量，无论是否有多个相同或不同的商品。* 提供<code>Price</code>您想要收取统一运费的费用。* 如果您要求收取额外的手续费，请设置<code>Calculate Handling Fee</code>为&ldquo;固定&rdquo;或&ldquo;百分比&rdquo;，然后在字段中输入您要设置的数字<code>Handling Fee</code>。<code>Displayed Error Message</code>*如果无法使用统一费率送货，请输入简短的文本。* 设置<code>Ship to Applicable Countries</code>为以下两个选项之一：</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>所有允许的国家/地区：每个国家/地区均支持免费送货。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>特定国家/地区：仅特定国家/地区支持统一费率运送。*<code>Sort Order</code>在结账页面的运输方式上设置。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Config</code>去完成。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3873,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3873" src="http://kb.360magento.net/wp-content/uploads/2023/08/how-to-configure-flat-rate-shipping-method-magento-2-flat-rate-shipping-configuration-1-1.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-configure-flat-rate-shipping-method-magento-2-flat-rate-shipping-configuration_1_.png" /> <!-- /wp:image --></p>]]></description>
      <pubDate>Wed, 30 Aug 2023 07:36:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用或禁用重新排序]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-disable-reorders-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>在 Magento 2 中启用重新订购</strong>可帮助客户在完成购买后重新订购。如果每个细节保持不变，客户不再需要再次填写所有信息，此功能简化了流程。借助它，您可以增强客户体验并快速提高销售额。客户可以立即从他们的帐户重新订购或要求管理员在后端重新订购。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您不想允许客户重新订购，您应该考虑这一点，因为默认情况下启用重新订购功能。现在，让我们跳转到在 Magento 2 中启用或禁用重新排序的步骤：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="steps-to-enable-or-disable-customer-reorder-in-magento-2">在 Magento 2 中启用或禁用客户重新订购的步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Sales</code>下<code>Sales</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Reorder</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3870,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3870" src="http://kb.360magento.net/wp-content/uploads/2023/08/QsQomlu-1024x477.png" /><img src="https://www.360magento.com/media/wysiwyg/QsQomlu.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Allow Reorder</code>字段中，选择<code>Yes</code>允许重新订购并选择<code>No</code>禁用重新订购。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>完成后，单击<code>Save</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Tue, 29 Aug 2023 07:29:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加、管理、导出订阅者]]></title>
      <link>https://www.360magento.com/blog/how-to-add-manage-export-subscribers-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在Magento 2中，您可以有效地管理订阅列表。您可以查看所有订阅者，采取更改状态以取消订阅的操作，甚至在必要时删除标记的订阅者。每当客户要求取消订阅您的电子邮件时，您应该在短时间内采取行动来满足他们，否则可能会让您的客户不高兴并对您的网站产生负面看法。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="to-add-manage-export-subscribers-in-magento-2">在 Magento 2 中添加、管理、导出订阅者</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>如何取消订阅</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如何导出订阅者列表</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="how-to-cancel-a-subscription">如何取消订阅</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，单击<code>Marketing</code>。在&ldquo;&nbsp;<code>Communications</code>&rdquo;部分中，选择<code>Newsletter Subscribers</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Status</code>列中，找到<code>subscriber</code>列表中的 。之后，标记第一列中的复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将<code>Action</code>控件更改为<code>Unsubscribe</code>.&nbsp;然后，单击<code>Submit</code>。标记记录的状态将更改为<code>Unsubscribed</code>。</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/G8SCRPP.png" /><!-- /wp:list --> <!-- wp:image {"id":3866,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3866" src="http://kb.360magento.net/wp-content/uploads/2023/08/G8SCRPP.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="how-export-list-subcribers">导出订阅者列表</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在该<code>Status</code>列中，使用筛选器控件筛选适合相应网站、商店或商店视图的所有已订阅状态。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择您想要导出到的文件，<code>CSV</code>或者<code>XML</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>然后，单击<code>Export</code>并保存文件</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/TaJPtjN.png" /><!-- /wp:list --> <!-- wp:image {"id":3867,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3867" src="http://kb.360magento.net/wp-content/uploads/2023/08/TaJPtjN.png" /> <!-- /wp:image --></p>]]></description>
      <pubDate>Mon, 28 Aug 2023 07:11:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改 PDF 发票徽标、发货徽标]]></title>
      <link>https://www.360magento.com/blog/how-to-change-pdf-invoice-logo-shippment-logo-magento-2/</link>
      <description><![CDATA[<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-change-pdf-invoice-logo-shippment-logo-in-magento-2">如何在 Magento 2 中更改 PDF 发票徽标、发货徽标</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>设置发票和装箱单</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>替换图像</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>请按照简单的方法来执行此操作：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="setup-invoices-packing-slips">设置发票和装箱单的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理侧栏上，单击<code>Stores &gt; Settings &gt; Configuration</code>。然后，查看左侧面板的 下<code>Sales</code>，单击<code>Sales</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开发票和装箱单设计部分。然后，执行以下操作：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3863,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3863" src="http://kb.360magento.net/wp-content/uploads/2023/08/qc54tz8.png" /><img src="https://www.360magento.com/media/wysiwyg/qc54tz8.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>要上传<code>Logo for PDF Print-outs</code>，请单击<code>Choose File</code>。选择徽标，然后单击<code>Open</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要上传<code>Logo for HTML Print View</code>，请单击<code>Choose File</code>。选择徽标，然后单击<code>Open</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>填写您的地址以显示在发票和装箱单上。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。注意：即使缩略图出现扭曲，发票上的徽标比例也是正确的。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="replace-image">替换图像的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>单击<code>Choose File</code>并根据需要选择其他徽标文件。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>标记<code>Delete Image</code>您要替换的图像的复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Sun, 27 Aug 2023 07:09:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改发票、发货、贷项凭证 PDF 中的客户地址模板]]></title>
      <link>https://www.360magento.com/blog/how-change-customer-address-template-in-invoices-shipments-credit-memo-pdf-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>按照这篇文章了解<strong>如何在 Magento 2 中更改发票、发货、贷项凭证 PDF 中的客户地址模板</strong>。地址模板将确定客户地址的格式，包括客户帐户中显示的帐单地址、送货地址和客户地址信息。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>这里给大家介绍一下简单的方法：</p>
<p><!-- /wp:paragraph --> <!-- wp:image {"id":3854,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3854" src="http://kb.360magento.net/wp-content/uploads/2023/08/JAMNc9H-1024x645.png" /><img src="https://www.360magento.com/media/wysiwyg/JAMNc9H.png" /> <!-- /wp:image --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-change-customer-address-template-in-invoices-shipments-credit-memo-pdf-in-magento-2">如何在 Magento 2 中更改发票、发货、贷项凭证 PDF 中的客户地址模板</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>示例 1：文本模板 用于文本、一行文本、HTML 和 PDF 地址模板</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>
{{depend address attribute code}} a space, a character, or UI label
{{/depend}};
{{if address attribute code}}{{var address attribute code}} a space,
a character, or UI label
{{/if}}

</code></pre>
<p><!-- /wp:code --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>示例 2：JavaScript 模板 对于 JavaScript 地址模板</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>
#{address attribute code} or User Interface label #{address
attribute code}
</code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Sat, 26 Aug 2023 08:30:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中的电子邮件模板列表]]></title>
      <link>https://www.360magento.com/blog/email-template-list-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>电子邮件模板列表</strong>包括各种可自定义的模板，每个模板对应于不同的活动，例如客户帐户、客户活动、新闻通讯、促销等。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>电子邮件模板可用作系统对客户在您网站上的活动的响应，同时支持正文内容的默认模板，并将其与已完成电子邮件的页眉和页脚模板相关联。最值得注意的是，由于内容的格式是 HTML 和 CSS，因此可以灵活地自定义电子邮件模板以适合每个网站或每个商店视图。为了确保它发送到收件箱，您应该启用SMTP。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>按照下面的模板列表了解您可以自由编辑的电子邮件模板是什么：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><strong>客户账户</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>新账户</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>新帐户确认密钥</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>新账户已确认</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>新账户无密码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>忘记密码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>提醒密码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>重设密码</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>客户活动</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>联系表</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>发送产品链接给朋友</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>愿望清单分享</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>时事通讯</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>订阅确认</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>订阅成功</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>退订成功</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>产品提醒</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>克朗错误警告</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>价格提醒</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>库存提醒</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>促销活动</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>促销通知/提醒</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>管理员活动</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>忘记管理员密码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>重设密码</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>电子邮件模板</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>电子邮件 - 页脚</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>电子邮件 - 标题</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>导出失败</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>导入失败</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如何在 Magento 2 中自定义电子邮件模板</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>产品提醒</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>产品警报Cron 错误</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>产品价格提醒</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>产品库存提醒</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>命令</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>新订单/宾客新订单</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>订单更新/宾客订单更新</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>支付失败</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>发票</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>新发票/客人新发票</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>发票更新/客人发票更新</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>运输</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>新货/宾客新货</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>货件更新/访客货​​件更新</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>贷项凭证</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>贷项凭证更新</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>宾客贷项凭证更新</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>新贷项凭证</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>宾客新贷项凭证</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>系统通知</strong><!-- wp:list -->
<ul><!-- wp:list-item -->
<li>站点地图生成警告</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>货币更新警告</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Fri, 25 Aug 2023 07:42:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置付款失败电子邮件]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-payment-failed-email-magento-2/</link>
      <description><![CDATA[<h2 class="active" id="configure-the-payment-failed-email"><span>配置支付失败邮件</span></h2>
<ul>
<li>刷新电子邮件模板</li>
<li>配置支付失败邮件</li>
</ul>
<h3 id="refresh-email-template"><span>刷新电子邮件模板</span></h3>
<p><span>确保您已更新每个电子邮件模板以反映</span>您的品牌<span>。</span></p>
<h3 id="configure-payment-failed-emails"><span>配置付款失败电子邮件的步骤</span></h3>
<ol>
<li><span>在管理面板上，</span><code class="language-plaintext highlighter-rouge">Stores &gt; Settings &gt; Configurations</code><span>.</span></li>
<li><span>在左侧面板的</span><code class="language-plaintext highlighter-rouge">Sales</code><span>选项卡下，单击</span><code class="language-plaintext highlighter-rouge">Checkout</code><span>子选项卡。</span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Payment Failed Emails</code><span>部分</span>
<ul>
<li><span>在字段中选择电子邮件的商店联系人作为消息的接收者</span><code class="language-plaintext highlighter-rouge">Payment Failed Email Receiver</code><span>。</span></li>
<li><span>在字段中选择电子邮件的商店联系人作为消息的发件人</span><code class="language-plaintext highlighter-rouge">Payment Failed Email Sender</code><span>。</span></li>
<li><span>选择发送给现场注册客户的所需电子邮件模板</span><code class="language-plaintext highlighter-rouge">Payment Failed Template</code><span>。</span></li>
<li><span>要同时向多人发送付款失败电子邮件，请在字段中输入电子邮件地址</span><code class="language-plaintext highlighter-rouge">Send Payment Failed Email Copy To&nbsp;</code><span>，每个电子邮件地址均以逗号分隔。</span></li>
<li><span>在以下选项中选择一种发送电子邮件的方法</span><code class="language-plaintext highlighter-rouge">Payment Failed Copy Method</code><span>：</span></li>
</ul>
<ul>
<li><span><span>密件抄送：通过将收件人包含在发送给客户的同一电子邮件的标题中来发送&ldquo;密送副本&rdquo;。</span><span>客户看不到密件抄送收件人，并且他/她不知道副本已发送到多个地址。</span></span></li>
<li><span>单独的电子邮件：将电子邮件副本作为单独的电子邮件发送。</span></li>
</ul>
</li>
<li><code class="language-plaintext highlighter-rouge">Save Config</code><span>完成支付失败邮件配置。</span></li>
</ol>]]></description>
      <pubDate>Thu, 24 Aug 2023 07:01:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改电子邮件徽标]]></title>
      <link>https://www.360magento.com/blog/how-to-change-email-logo-magento-2/</link>
      <description><![CDATA[<h2 class="active" id="3-steps-to-change-email-logo-in-magento-2"><span>在 Magento 2 中更改电子邮件徽标的 3 个步骤</span></h2>
<p><span>以下步骤将帮助您了解如何更改 Magento 2 中的电子邮件徽标：</span></p>
<ul>
<li>第 1 步：上传您的徽标</li>
<li>第 2 步：选择页眉和页脚模板</li>
<li>第 3 步：保存配置和设计</li>
</ul>
<h3 id="upload-logo"><span>第 1 步：上传您的徽标</span></h3>
<p><span><span>首先，您必须选择您的徽标并将其上传到 Magento 平台。</span><span>我将向您展示如何在 MAgento 2.0 和 2.1 或更高版本中执行此操作：</span></span></p>
<h4 id="change-email-logo-in-magento-20"><span>在 Magento 2.0 中更改电子邮件徽标</span></h4>
<ul>
<li><span>在管理侧栏上，</span><code class="language-plaintext highlighter-rouge">Stores &gt; Settings &gt; Configuration</code><span>.</span></li>
</ul>
<h4 id="change-email-logo-in-magento-21-or-above"><span>在 Magento 2.1 或更高版本中更改电子邮件徽标</span></h4>
<ul>
<li>
<p><span>在管理侧栏上，</span><code class="language-plaintext highlighter-rouge">Content &gt; Design &gt; Configuration &gt; Select your current theme &gt;&nbsp;</code><span>.</span></p>
</li>
<li><span>您可以在管理表中看到现有的设计配置，然后单击</span><code class="language-plaintext highlighter-rouge">Edit</code><span>下的</span><code class="language-plaintext highlighter-rouge">Action</code><span>。</span></li>
<li><span>在工作场所，请向下滚动到</span><span>其他设置</span><span>，打开</span><code class="language-plaintext highlighter-rouge">Transactional Email</code><span>选项，</span>
<ul>
<li><span>要更改您的徽标电子邮件，请单击</span><code class="language-plaintext highlighter-rouge">Upload</code><span>选择您想要用于徽标的图像文件之一。</span></li>
<li><span>输入标识 的替代文本</span><code class="language-plaintext highlighter-rouge">Logo Image Alt</code><span>。</span></li>
<li><span>要求</span><code class="language-plaintext highlighter-rouge">Logo Width</code><span>和</span><code class="language-plaintext highlighter-rouge">Logo Height</code><span><span>以像素为单位。</span><span>只需输入不包含&ldquo;px&rdquo;符号的数字即可。</span><span>标题中电子邮件徽标的外观取决于提供的值大小，而不是徽标的实际大小。</span></span></li>
</ul>
</li>
</ul>
<h3 id="select-header-footer-templates"><span>第 2 步：选择页眉和页脚模板</span></h3>
<p><span>如果您想要修改页眉和页脚模板，或者如果您经营多个商店，您可以为每个商店分配一个特定的模板，该模板将显示在交易电子邮件中。</span></p>
<ul>
<li><span><span>根据需要从可用列表中</span><span>选择 和</span></span><code class="language-plaintext highlighter-rouge">Header Template</code><span>。</span><code class="language-plaintext highlighter-rouge">Footer Template</code><span></span></li>
</ul>
<h3 id="save-config-design"><span>第 3 步：保存配置和设计</span></h3>
<p><code class="language-plaintext highlighter-rouge">Save Config</code><span>完成并且电子邮件的设计处于活动状态。</span></p>]]></description>
      <pubDate>Wed, 23 Aug 2023 07:58:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用管理员登录验证码]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-admin-login-captcha-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>将验证码要求添加到管理员登录和忘记密码页面有助于将您的商店安全性提高到一个新的水平。当用户点击该图标时，验证码将可以无限地重新加载<code>Reload</code>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="4-steps-to-enable-an-admin-captcha-in-magento-2">在 Magento 2 中启用管理员验证码的 4 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Admin</code>下<code>Advanced</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>CAPTCHA</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ol>
<p><img src="https://www.360magento.com/media/wysiwyg/Zir5S5l_1.png" /><!-- /wp:list --> <!-- wp:image {"id":3821,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3821" src="http://kb.360magento.net/wp-content/uploads/2023/08/Zir5S5l.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Enable CAPTCHA on Frontend</code>字段中，选择&ldquo;是&rdquo;以在前端启用验证码</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Font</code>字段中，选择用于验证码的字体名称。默认为 LinLibertine。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Forms</code>字段中，选择以下要使用 CAPTCHA 的表单之一<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>管理员登录</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>管理员忘记密码</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 中<code>Displaying Mode</code>，选择以下选项之一<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>总是</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>尝试登录次数后</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Number of Unsuccessful Attempts to Login</code>字段中，输入验证码出现之前尝试登录失败的次数。如果您输入零，验证码将始终可用</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>CAPTCHA Timeout (minutes)</code>字段中输入验证码到期前的分钟数。当验证码过期时，用户必须重新加载页面以生成新的验证码。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Number of Symbols</code>字段中输入验证码将更改的符号范围数，例如：3-7。符号的最大数量为八个。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在该<code>Symbols Used in CAPTCHA</code>字段中，指定可在验证码中使用的符号。仅在框中输入字母（az 和 AZ）或数字 (0-9)。不允许使用空格或其他字符，并且默认情况下不使用类似的符号。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Case Sensitive</code>字段中，选择<code>Yes</code>是否要求用户完全按照所示输入大写和小写字符<!-- wp:list {"ordered":true} --><ol><!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code></li>
<!-- /wp:list-item --></ol><!-- /wp:list --></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Tue, 22 Aug 2023 07:40:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何配置 Magento 2 管理操作日志？]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-action-log-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>Magento 2 支持您<strong>配置管理操作日志</strong>，它将帮助您管理和跟踪管理员的所有活动。您可以在网格上查看日志历史记录，了解商店管理面板中执行的操作以及执行者。此外，您还可以在操作日志上查看 IP 和日期。该功能对于帮助您有效管理系统非常重要，特别是当您的商店有多个管理员时。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在请按照下面给出的简单指南来配置操作日志：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-configure-the-action-log-in-magento-2">如何在 Magento 2 中配置操作日志</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击Store。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Admin</code>下<code>Advanced</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Admin Actions Logging</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3818,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3818" src="http://kb.360magento.net/wp-content/uploads/2023/08/8xmQ5tx.png" /><img src="https://www.360magento.com/media/wysiwyg/8xmQ5tx_1.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>要启用管理日志记录，请选中该复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要禁用管理日志记录，请清除该复选框。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>
<div id="gtx-trans" style="position: absolute; left: -112px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 21 Aug 2023 07:02:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用模板路径提示]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-template-path-hints-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>您是否正在寻找<strong>如何在 Magento 2 教程中启用模板路径提示</strong>？所以你来对地方了。在这篇文章中，我们将帮助您从 Magento 管理面板启用前端和管理的模板路径提示。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>例如，Magento 2 中的模板路径提示可帮助您定义与商店的特定页面区域之一相对应的 .php 块类。由于每个路径模板中添加了符号，您还可以更轻松地找到 .phtml 文件，当然也可以更快地编辑它们。该代码可以在 Magento 文件结构的前端和后端找到。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="to-enable-template-path-hints-in-magento-2">在 Magento 2 中启用模板路径提示</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>我们将教程分为两个主要部分，如下所示：</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理配置中启用模板路径提示</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>启用模板路径提示命令行</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="enable-template-path-hints-in-admin-configuration">在管理配置中启用模板路径提示</h3>
<p><!-- /wp:heading --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="to-enable-template-path-hints-for-storefront">为店面启用模板路径提示</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><em>在 Magento 2 中启用模板路径提示的 3 个步骤</em></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第1步：进入管理面板</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：选择<code>Store &gt; Configuration &gt; Advanced &gt; Developer &gt; Debug &gt; Enabled Template Path Hints for Storefront</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：单击<code>Yes</code>启用模板路径提示</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3814,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3814" src="http://kb.360magento.net/wp-content/uploads/2023/08/IxPjmbA.png" /><img src="https://www.360magento.com/media/wysiwyg/IxPjmbA.png" /> <!-- /wp:image --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="enabled-template-path-hints-for-admin">为管理员启用模板路径提示</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>进入管理面板：Store &gt; Configuration &gt; Advanced &gt; Developer &gt; Debug &gt; Enabled Template Path Hints for Admin &gt; Yes</p>
<h3 class="wp-block-heading" id="enable-template-path-hints-command-line">启用模板路径提示命令行</h3>
<p><!-- /wp:heading --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="82016">8/2016</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>此时，可能没有命令行可以通过命令行（默认 Magento 2 命令行）启用或禁用模板路径提示。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>让我们等待下一次 Magento 更新或外部模块。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="updated-12018">2018 年 1 月更新</h4>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在您可以<strong>通过命令行启用或禁用模板路径提示</strong>&nbsp;转到 Magento 2 根文件夹并运行以下命令：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":5} --></p>
<h5 class="wp-block-heading" id="enable">使能够</h5>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento dev:template-hints:enable 
</code></pre>
<p><!-- /wp:code --> <!-- wp:heading {"level":5} --></p>
<h5 class="wp-block-heading" id="disable">禁用</h5>
<p><!-- /wp:heading --> <!-- wp:code --></p>
<pre class="wp-block-code"><code>php bin/magento dev:template-hints:disable </code></pre>
<p><!-- /wp:code --></p>]]></description>
      <pubDate>Sun, 20 Aug 2023 07:06:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中导入所有带有图像的产品]]></title>
      <link>https://www.360magento.com/blog/how-to-import-all-products-with-images-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在主题<strong>如何在 Magento 2 中导入带有图像的所有产品中</strong>，有指向产品图像文件的路径的&ldquo;图像文件目录&rdquo;字段。为了解释图像文件目录字段的存在，Magento 有自己的产品图像目录结构，该结构按字母顺序组织，并且特定图像的路径包含在导入产品文件中。实际上，您可以在使用具有管理服务器上 Magento 文件夹权限的正确凭据登录后，将图像文件上传到 Magento 服务器或外部服务器上。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>导入产品图片是管理员的常见任务；然而，如果你逐一手动进行，那就会浪费时间和精力。这就是为什么您需要有关如何批量导入图像的指南。很容易看出，<strong>导入所有带有图像的产品</strong>有两个步骤，我还将向您演示两种导入产品图像的方法：使用<strong>本地服务器</strong>和使用<strong>外部服务器</strong>。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="2-steps-to-import-all-products-with-images-in-magento-2">在 Magento 2 中导入所有带有图像的产品的 2 个步骤：</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第1步：将产品图片文件上传到本地服务器</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>步骤 2：使用 CSV 文件导入产品图像</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p><strong>2 上传产品图片的方法</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法一：从本地服务器导入产品图片</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法二：从外部服务器导入产品图片</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-1-import-image-from-local-server">方法一：从本地服务器导入图片</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>在此方法中，您将使用本地服务器批量上传 Magento 2 产品图像。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="upload-the-images-file-on-server">第一步：将图片文件上传到服务器</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在 Magento 服务器上，将图像文件上传到用于导入产品图像的默认文件夹：<code>pub/media/import</code>。您也可以在 Magento 服务器上使用不同的文件夹，只要在导入过程中指定该文件夹的路径即可。}</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="import-product-images-with-csv-file">步骤 2：使用 CSV 文件导入产品图像</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在 CSV 数据中，根据图像类型 (&nbsp;<code>base_image, small_image, thumbnail_image, or additional_images</code>) 在正确的行、按 SKU 和正确的列中输入要导入的每个图像文件的名称。确保每个文件名之前都包含导入目录的相对路径。例如：<code>/pub/media/import/image.jpg</code>.&nbsp;CSV 文件只需包含 SKU 列和相关图像列。如果要为单个 SKU 导入多个图像，请在 SKU 下方插入一个空白行，然后在相应的列中输入其他图像文件名。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>按照导入产品中的说明进行操作，直至填写<strong>&ldquo;图像文件目录&rdquo;</strong>字段。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>在图像文件目录</strong>字段中输入您最初上传图像的文件夹路径，然后继续导入产品。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3811,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3811" src="http://kb.360magento.net/wp-content/uploads/2023/08/Oxi0HyZ.png" /><img src="https://www.360magento.com/media/wysiwyg/Oxi0HyZ.png" /> <!-- /wp:image --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="method-2-import-images-from-external-server">方法二：从外部服务器导入图片</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果您想使用远程服务器为您的 Magento 2 商店导入图像，您可以使用此方法。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-upload-the-image-files-on-external-server">第 1 步：将图像文件上传到外部服务器</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>将要导入的图像上传到外部服务器上选定的文件夹。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 CSV 数据中，按图像类型 ( ) 在正确的列中输入每个图像文件的完整 URL&nbsp;<code>base_image, small_image, thumbnail_image, or additional_images</code>。例如：<code>http://example.com/images/image.jpg</code>.</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2-import-bulk-product-images">第2步：导入批量产品图片</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>过程与第一种方法的步骤2相同。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sat, 19 Aug 2023 07:52:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中导出产品所有数据、过滤和排除属性]]></title>
      <link>https://www.360magento.com/blog/export-products-all-data-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>如果您还没有习惯 Magento 的数据库，我建议您导出<strong>产品</strong>并打开 CSV 文件来熟悉结构。显然，当您熟悉数据库的结构时，您可以有效地管理您的信息。此外，导出产品数据不仅是为了帮助您熟悉数据库，它还可以用作备份您的产品数据或保存数据以用于其他目的（例如在其他站点上导入数据）的另一种工具。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>此外，如果您想在 Magento 2 中过滤和排除属性，您完全可以这样做。在今天的教程中，我将向您展示如何批量导出所有或筛选的产品数据。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="export-products-all-data-filter-and-exclude-attributes-in-magento-2">在 Magento 2 中导出产品所有数据、筛选和排除属性</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：开始导出产品数据</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：配置导出数据的类型</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：导出数据并打开 CSV 文件进行查看</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-start-export-product-data">第1步：开始导出产品数据</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理侧栏上，单击<code>System &gt; Data Transfer &gt; Export</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在&ldquo;<strong>导出设置&rdquo;</strong>部分中，将&ldquo;<strong>实体类型</strong>&rdquo;字段设置为&ldquo;<strong>产品</strong>&rdquo;以开始导出产品数据。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>保留默认的<strong>导出文件格式</strong>&ldquo;&nbsp;<strong>CSV</strong>&nbsp;&rdquo;。<br /><img src="https://www.360magento.com/media/wysiwyg/qFVyjlg.png" /></li>
</ul>
<h3 class="wp-block-heading" id="step-2-configure-type-of-export-data">第 2 步：配置导出数据的类型</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>现在，您可以过滤和排除某些属性。如果您只想批量导出部分数据，此设置很有用。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在步骤 1 中选择实体类型后，将出现&ldquo;实体属性&rdquo;部分，其中按字母顺序列出了所有可用属性。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要根据产品标签或产品代码搜索产品，请在<strong>属性标签</strong>/<strong>属性代码</strong>中输入标签/代码，然后单击<code>Search</code>按钮。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>要仅导出具有特定属性值的记录，请在&ldquo;过滤器</strong>&rdquo;列中输入所需的值。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要从导出中省略属性，请标记行开头的&nbsp;<strong>排除复选框。</strong></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3806,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3806" src="http://kb.360magento.net/wp-content/uploads/2023/08/goi350q-1024x296.png" /><img src="https://www.360magento.com/media/wysiwyg/goi350q.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-3-export-your-data-and-open-csv-file-to-view">第 3 步：导出数据并打开 CSV 文件进行查看</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>向下滚动并单击<code>Continue</code>页面右下角以启动导出操作。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>出现提示时，单击<code>Save</code>保存导出文件。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开 CSV 文件以查看或编辑导入的数据。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Fri, 18 Aug 2023 08:03:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建用户角色]]></title>
      <link>https://www.360magento.com/blog/how-to-create-user-role-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>在本主题中，我们将向您展示<strong>如何在 Magento 2 中创建用户角色</strong>。我们将指导您如何添加新的用户规则并将现有用户帐户分配给上述角色。让我们检查以下步骤：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="to-define-a-role-in-magento-2">在 Magento 2 中定义角色</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，单击<code>System</code>。在&ldquo;&nbsp;<code>Permissions</code>&rdquo;部分中，选择<code>User Roles</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在右上角，单击<code>Add New Role</code>按钮</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/l9jB1KK.png" /><!-- /wp:list --> <!-- wp:image {"id":3762,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3762" src="http://kb.360magento.net/wp-content/uploads/2023/08/l9jB1KK.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Role Information</code>字段中，输入描述性角色名称。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中，选择<code>Role Resources</code>。</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/KLOieO7.png" /><!-- /wp:list --> <!-- wp:image {"id":3763,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3763" src="http://kb.360magento.net/wp-content/uploads/2023/08/KLOieO7.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Resource Access</code>现场，执行以下操作<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>设置为<code>Custom</code>，然后勾选该角色有权访问的每个网站和视图的复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>All</code>如果要标记所有复选框，请设置为</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>完成后，单击<code>Save Role</code>。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Thu, 17 Aug 2023 08:04:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何备份 Magento 2 商店]]></title>
      <link>https://www.360magento.com/blog/how-to-create-backups-magento/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>目录</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>创建 Magento 2 备份<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>系统备份</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>数据库和媒体备份</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>数据库备份</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p><strong>为您的 Magento 2 创建备份</strong>是如此紧迫和必要，如果网站上有任何更改或中断，您可以通过备份管理保护所有数据免遭丢失。特别是，这些数据库将自动恢复到需要的正确位置。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>备份管理归档的系统部分还有文件系统、数据库、媒体文件等。同时，数据库备份文件采用.gz格式压缩。对于系统备份以及数据库和媒体备份，使用 .tgz 格式。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，我们将更深入地挖掘该指令，为像您这样的 Magento 2 网站创建完美的备份。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="create-magento-2-backup">创建 Magento 2 备份</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，单击<code>System</code>。在&ldquo;&nbsp;<code>Tools</code>&rdquo;部分中，选择<code>Backups</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在右上角，点击您要创建的备份类型的按钮：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3758,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3758" src="http://kb.360magento.net/wp-content/uploads/2023/08/ZZbkuUH.png" /><img src="https://www.360magento.com/media/wysiwyg/ZZbkuUH.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="system-backup">系统备份</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>创建数据库和文件系统的完整备份。<code>Include Media folder to System Backup</code>在此过程中，您可以通过标记复选框来选择将媒体文件夹包含在备份中</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="datebase-and-media-backup">数据库和媒体备份</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>创建数据库和媒体文件夹的备份。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="database-backup">数据库备份</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>创建数据库的备份。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/qhvxLFu.png" /><!-- /wp:paragraph --> <!-- wp:image {"id":3759,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3759" src="http://kb.360magento.net/wp-content/uploads/2023/08/qhvxLFu.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>完成后，单击<code>OK</code>按钮</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Wed, 16 Aug 2023 08:01:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建新税率]]></title>
      <link>https://www.360magento.com/blog/how-to-create-a-new-tax-rate-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>使用 Magento 2，您可以根据不同的地理区域（州或国家）<strong>创建许多新的税率。</strong>添加税率是在&ldquo;税区和税率&rdquo;工具的控制下，将多种税收定向到特定区域。所有订单信息填写完毕后，系统会根据门店的税费设置，正确计算客户订单的税费。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>税率是制定税收规则的重要要素之一。让我们根据我们的指南尽力而为。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="create-a-new-tax-rate-in-magento-2">在 Magento 2 中创建新税率</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在 Magento 2 中设置新的税率</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>更改 Magento 2 中的现有税率</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="setup-new-tax-rate">在 Magento 2 中设置新税率</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Taxes &gt; Tax Zones and Rates</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击右上角<code>Add New Tax Rate</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>设置<code>Tax Identifier</code>为新税率。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>插入<code>Zip/Post Code</code>来指定新的税率。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>星号通配符 (&nbsp;<em>) 可用于匹配代码中最多十个字符。例如，90</em>代表从 90000 到 90999 的所有邮政编码。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要将税率分配给邮政编码范围，需要执行以下操作：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>勾选<code>Zip/Post is Range</code>复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>输入该范围内的第一个邮政编码。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>输入该范围内的最后一个邮政编码。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择税率适用的地方<code>State</code>。<code>Country</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>设置<code>Rate Percent</code>计算税率。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Save Rate</code>完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3755,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3755" src="http://kb.360magento.net/wp-content/uploads/2023/08/how-to-create-a-new-tax-rate-magento-2-add-new-tax-rate-1024x589.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-create-a-new-tax-rate-magento-2-add-new-tax-rate.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="change-existing-rate">更改 Magento 2 中的现有税率</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，转到<code>Stores &gt; Taxes &gt; Tax Zones and Rates</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在税区和税率网格中查找需要编辑的税率。如果网格中有很多费率，则使用过滤器查找。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>根据需要修改任何信息，然后单击<code>Save Rate</code>完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Tue, 15 Aug 2023 07:29:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置增值税 (VAT)]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-value-added-tax-vat-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>从 Magento 2 后端配置增值税 (VAT)</strong>是一个很好的解决方案，可以解决不同增值税计算的冲突，即商店位于不同的地区，您提供的商品类型是产品、材料或服务。通过增值税功能，您可以创建包含您所在国家/地区、增值税税率、客户类型等的数据管理表。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在 Magento 2 中配置增值税可以让您遵守现有规则、更好地管理成本并变得更加专业。因此，今天，我想向您展示在 Magento 2 商店上快速配置和应用增值税的所有步骤。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="configure-value-added-tax-vat-in-magento-2">在 Magento 2 中配置增值税 (VAT)：</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>配置客户税级</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>配置产品税级</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>配置税区和税率</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>配置税务规则</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>加上产品的税级</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-configure-customer-tax-classes">配置客户税级</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Taxes &gt; Tax Zones and Rates</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>确保客户税级可用于增值税，例如零售客户。如果您尚未创建，请点击<code>Add New</code>添加它。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2-configure-product-tax-classes">在 Magento 2 中配置产品税级</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Tax &gt; Product Tax Classes</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Add New</code>按钮并创建三个新类：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>增值税标准</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>增值税减免</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>增值税零</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Save Class</code>您添加的每个新课程的按钮。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-3-configure-tax-zones-rates">设置税区和税率</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理菜单上，<code>Stores &gt; Tax &gt; Manage Tax Zones &amp; Rates</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Add New Tax Rate</code>按钮并根据需要填写所有必要的信息。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Rate</code>应用新的费率。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-4-configure-tax-rules">配置税务规则</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>税收规则是客户税级、产品税级和税率的组合。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Tax &gt; Manage Tax Rules</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>根据新税务规则的需要，填写所有必填信息。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Rule</code>应用新规则。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-5-plus-tax-classes-to-products">加上产品的税级</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Products &gt; Products &gt; Catalog</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在产品列表中找到所需的产品并以编辑模式打开。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板的 下<code>General</code>，选择<code>General</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将增值税类别设置<code>Tax Class</code>为适用于产品的增值税类别。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Save</code>完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>增值税是开展任何类型业务时的重要组成部分，并且可能因地点或产品类型而异。但是，您可以按照上述指南轻松在 Magento 2 中配置增值税。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Mon, 14 Aug 2023 07:23:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中将产品翻译成其他语言]]></title>
      <link>https://www.360magento.com/blog/how-to-translate-products-into-other-language-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>在全球业务中，将产品信息翻译成其他语言</strong>是必须的。Magento 2 支持多商店和多语言，这使您的商店对来自不同国家的任何受众更加友好。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>现在，在每个商店视图上，产品信息都已准备好相关语言。您可以维护一些产品数据，例如 SKU、价格，而您只需根据每种语言的需要翻译产品名称、描述字段和元数据。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="translate-products-into-other-language-in-magento-2">在 Magento 2 中将产品翻译成其他语言</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：翻译产品字段</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：翻译字段标签</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：翻译所有类别</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-1-translate-product-fields">第 1 步：翻译产品字段</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Products &gt; Inventory &gt; Catalog</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>找到需要翻译的产品，并以编辑模式打开它。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左上角选择<code>Store View</code>翻译显示</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>OK</code>确认。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在编辑模式下，您需要：
<ul>
<li>取消选中<code>Use Default Value</code>该字段右侧的复选框。在字段中输入翻译后的文本。</li>
</ul>
确保所有必要的文本字段都得到良好翻译，包括图像标签和替代文本、搜索引擎优化字段和任何自定义选项信息。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Save</code>完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-2-translate-field-labels">第 2 步：翻译字段标签</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Attributes &gt; Product</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>找到需要翻译的属性，并在编辑模式下打开它。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板上，选择<code>Manage Labels</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 下<code>Manage Title</code>，为每个商店视图设置翻译标签。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3743,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3743" src="http://kb.360magento.net/wp-content/uploads/2023/08/how-to-transalte-products-into-other-language-magento-2-enter-translated-labels-1024x284.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-transalte-products-into-other-language-magento-2-enter-translated-labels.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>单击<code>Save Attribute</code>完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="step-3-translate-all-categories">第 3 步：翻译所有类别</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，转到<code>Product &gt; Inventory &gt; Categories</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左上角选择<code>Store View</code>翻译显示</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>OK</code>确认。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在类别树中找到需要翻译的类别，并以编辑模式打开。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在该<code>General Information</code>部分中，将必填字段翻译为名称、描述、页面标题、元关键字和元描述。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>允许翻译<code>URL Key</code>如下：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>取消选中<code>Use Default Value</code>该字段右侧的复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>输入翻译后的文本。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选中<code>Create Permanent Redirect for old URL</code>复选框。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Save Category</code>完成。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如果您想翻译其他内容，请逐步按照指南进行操作。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3744,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3744" src="http://kb.360magento.net/wp-content/uploads/2023/08/how-to-transalte-products-into-other-language-magento-2-translate-url-key.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-transalte-products-into-other-language-magento-2-translate-url-key.png" /> <!-- /wp:image --></p>]]></description>
      <pubDate>Sun, 13 Aug 2023 07:20:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中翻译 CMS 页面]]></title>
      <link>https://www.360magento.com/blog/how-to-translate-cms-pages-magento-2/</link>
      <description><![CDATA[<p><span>翻译 CMS 页面</span><span><span>是在全球范围内发展业务的支持方式之一。</span><span>这意味着您可以创建翻译后的网站，然后将其显示在</span><span>客户的</span></span>特定商店视图中。<span>要设置翻译的内容页面，您必须</span>创建一个具有相同 URL 的新页面<span><span>以将其分配给商店。</span><span>配置后，您将使用翻译后的文本更新特定视图的 CMS 页面。</span></span></p>
<h2 class="active" id="6-steps-to-translate-cms-page-in-magento-2"><span>在 Magento 2 中翻译 CMS 页面的 6 个步骤：</span></h2>
<ol>
<li><span>在管理面板上，</span><code class="language-plaintext highlighter-rouge">Content &gt; Elements &gt; Pages</code><span>.</span></li>
<li><span>找到需要翻译的页面，并以编辑模式打开它。</span></li>
<li><span>将其复制</span><code class="language-plaintext highlighter-rouge">URL Key</code><span><span>到剪贴板。</span><span>然后，点击</span></span><code class="language-plaintext highlighter-rouge">Back</code><span>按钮返回页面网格。</span></li>
<li><span>点击</span><code class="language-plaintext highlighter-rouge">Add New Page</code><span>，您需要：</span>
<ul>
<li><span>翻译</span><code class="language-plaintext highlighter-rouge">Page Title</code><span>.</span></li>
<li><span>粘贴</span><code class="language-plaintext highlighter-rouge">URL Key</code><span>之前复制的内容</span></li>
<li><span>在左上角选择</span><code class="language-plaintext highlighter-rouge">Store View</code><span>翻译显示</span></li>
<li><span>在左侧面板的 下</span><code class="language-plaintext highlighter-rouge">Page Information</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Content</code><span>，然后插入页面的翻译文本。</span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Layout</code><span><span>为选项卡中的页面</span><span>创建</span></span><code class="language-plaintext highlighter-rouge">Design</code><span>。</span></li>
<li><span><span>完成选项卡</span><span>中</span></span><code class="language-plaintext highlighter-rouge">Keywords</code><span><span>和 的</span><span>翻译</span></span><code class="language-plaintext highlighter-rouge">Description</code><span></span><code class="language-plaintext highlighter-rouge">Meta Data</code><span></span></li>
</ul>
</li>
<li><span>单击</span><code class="language-plaintext highlighter-rouge">Save Page</code><span>以完成，并在出现提示时</span>刷新缓存<span>。</span></li>
<li><span>前往店面并使用</span>语言选择器在<span></span>商店视图<span><span>中检查翻译</span><span>。</span><span>公司页脚链接块和</span></span>欢迎消息<span>等一些元素也需要翻译。</span></li>
</ol>]]></description>
      <pubDate>Sat, 12 Aug 2023 08:23:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中为客户设置密码选项]]></title>
      <link>https://www.360magento.com/blog/how-to-set-password-options-for-customers-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>密码是客户访问其商店</strong>帐户时必须使用的唯一密钥，但他们可能会忘记注册密码。通过Magento 2 平台，您可以为这些客户设置密码选项，以帮助他们轻松找回密码。这种策略简化了问题解决过程，可以改善他们的体验并降低跳出率。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>从后端，您将设置电子邮件模板，包括忘记的电子邮件和带有密码恢复链接的提醒电子邮件。您还可以配置管理员或客户可以重置密码。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>请按照以下说明了解您需要做什么。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="steps-to-set-password-options-for-customers-in-magento-2">在 Magento 2 中为客户设置密码选项的步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在 Magento 管理面板上，<code>Stores &gt; Settings &gt; Configuration</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板的<code>Customers</code>选项卡下，选择<code>Customer Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开<strong>密码选项</strong>部分，<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>选择<code>Forgot Email Template</code>在客户忘记密码时发送给客户的信息。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择包含要发送给客户的密码提示的提醒电子邮件模板。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择<code>Reset Password Template</code>发送给客户的，并附有重置密码的链接。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择密码电子邮件发件人，其名称将显示在忘记和提醒电子邮件通知上。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在字段中设置密码恢复链接的到期时间<code>Recovery Link Expiration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><strong>选择&ldquo;是&rdquo;</strong>选项时，仅允许商店管理员更改客户密码<code>Require admin user to change user password</code>。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Config</code>去完成。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3702,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3702" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-set-password-options-for-customers-password-options.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-set-password-options-for-customers-password-options.png" /> <!-- /wp:image --></p>]]></description>
      <pubDate>Fri, 11 Aug 2023 07:14:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[登录 Magento 2 后如何重定向到客户仪表板]]></title>
      <link>https://www.360magento.com/blog/how-to-rediect-to-customer-dashboard-after-loggin-in-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>使用Magento 2，您可以启用或禁用在客户登录后将客户重定向到客户仪表板。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>事实上，吸引客户访问您的网站是一回事，但让他们在您的网站停留更长时间则是另一回事。因此，此功能是利用当前流量并获得更高转化率的好方法。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>如果您想让客户留在当前页面或继续购物，您应该考虑禁用该功能，因为默认情况下会启用重定向功能。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="steps-to-configure-redirect-customer-after-login-in-magento-2">在 Magento 2 中登录后配置重定向客户的步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Customer Configuration</code>下<code>Customers</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Login Options</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3699,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3699" src="http://kb.360magento.net/wp-content/uploads/2023/07/BbOaGmk.png" /><img src="https://www.360magento.com/media/wysiwyg/BbOaGmk.png" /> <!-- /wp:image --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在<code>Set Redirect Customer to Account Dashboard after Logging in</code>字段中，选择以下选项之一：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>选择<code>Yes</code>：允许在客户登录其帐户时显示客户帐户仪表板。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择<code>No</code>：当客户登录其帐户时，不重定向到客户帐户仪表板。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Thu, 10 Aug 2023 07:10:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中插入图像]]></title>
      <link>https://www.360magento.com/blog/how-to-insert-images-in-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>除了了解如何优化图像之外，在商店中创建新页面时<strong>插入图像也是一项重要任务。</strong>它使您能够美化您的页面并更轻松地展示您的产品。当客户能够更清晰地想象时，他们往往会停留更长时间来探索。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>Magento 2 提供了所见即所得编辑器工具，它允许您在&ldquo;所见即所得&rdquo;的内容视图中工作。在所见即所得栏上，您可以看到<strong>&ldquo;插入图片&rdquo;图标，只需点击它即可在</strong>CMS 页面上添加您需要的任何图片。此外，您可以使用的另一种方式是媒体存储提供的。所以在本教程中，我们将指导您如何通过两种方式插入图像。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-insert-images-in-magento-2">如何在 Magento 2 中插入图像</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>方法 1：插入媒体存储中的图像</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>方法 2：插入来自另一台服务器的图像</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="insert-image-from-media-storage">方法 1：插入媒体存储中的图像</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果您在媒体存储中准备好了图像，则此方法适用：</p>
<p><!-- /wp:paragraph --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li><code>Show/Hide Editor</code>如果您想直接使用代码，请单击该按钮。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将光标置于要插入图像的位置。然后，单击&nbsp;&ldquo;插入图像&rdquo;。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>从弹出框中显示的文件列表中，选择要使用的项目并单击按钮<code>Insert File</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>要以所见即所得模式查看图像，请&nbsp;<code>Show / Hide Editor</code>&nbsp;再次点击。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="insert-image-from-another-server">方法 2：插入来自另一台服务器的图像</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>如果图像在线并且包含在另一台服务器中，则可以使用此方法。插入图像时需要提供图像的完整 URL。</p>
<p><!-- /wp:paragraph --> <!-- wp:image {"id":3690,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3690" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-insert-images-in-magento-2-WYSIWYG-editor.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-insert-images-in-magento-2-WYSIWYG-editor.png" /> <!-- /wp:image --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li><code>Show/Hide Editor</code>如果您想直接使用代码，请单击按钮。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将光标置于要插入图像的位置。然后，单击&nbsp;插入图像图标。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>从弹出框中显示的文件列表中，选择要使用的项目并单击按钮<code>Insert File</code>。<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>在字段中输入图像的完整 URL&nbsp;<code>Image URL</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>输入该<code>Image Description</code>字段的一些描述。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>输入字段的标题<code>Image Title</code>。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Insert</code>以完成插入过程。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Wed, 09 Aug 2023 07:14:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用合并 CSS、JavaScript]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-merge-css-javascript-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>所有分离的<strong>CSS 文件以及 CSS 文件和 JavaScript 文件</strong>都可以合并为一个或压缩文件，这有助于优化您的网站并减少页面加载时间。合并后，合并后的CSS文件或脚本文件将显示无换行符，并且不允许编辑该文件。要在 Magento 2 中启用合并 CSS、JavaScript，您可以按照下面给出的一些简单步骤操作。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-enable-merge-css-javascript-in-magento-2">如何在 Magento 2 中启用合并 CSS、JavaScript</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>您需要了解的页面加载速度事实</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 Magento 2 中合并 CSS 文件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 Magento 2 中合并 JavaScript 文件</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="facts-of-page-loading-speed-that-you-need-to-know">您需要了解的页面加载速度事实</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>如果超过 45% 的访问者遇到电子商务网站加载速度比预期慢 (&nbsp;Unbounce&nbsp;)，他们将不会购买该产品。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>53% 的移动网站访问者倾向于在等待超过三秒时离开页面 (&nbsp;Akamai&nbsp;)。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>页面加载时间减少 0.1 秒可以将零售客户参与度提高 5.2%（Unbounce&nbsp;Google、55-5 和 Deloitte）。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>因此，您的页面以最佳速度运行至关重要。在 Magento 2 中启用合并 CSS、JavaScript 可以是此网站优化过程的第一步。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="merge-css-file-magento-2">在 Magento 2 中合并 CSS 文件</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Developer</code>下<code>Advanced</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>CSS Settings</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3686,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3686" src="http://kb.360magento.net/wp-content/uploads/2023/07/a4uXRkg.png" /><img src="https://www.360magento.com/media/wysiwyg/a4uXRkg.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Merge CSS&nbsp;Files</code>字段中，选择<code>Yes</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="merge-javascript-files-magento-2">在 Magento 2 中合并 JavaScript 文件</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。在&ldquo;&nbsp;<code>Settings</code>&rdquo;部分中，选择<code>Configuration</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板中选择<code>Developer</code>下<code>Advanced</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>JavaScript Settings</code>部分，然后继续执行以下操作：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3687,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3687" src="http://kb.360magento.net/wp-content/uploads/2023/07/85fMSFG.png" /><img src="https://www.360magento.com/media/wysiwyg/85fMSFG.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<code>Merge JavaScript Files</code>字段中，选择<code>Yes</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>提高网站加载速度是提高转化率和促进销售的第一步，可以通过<strong>在 Magento 2 中启用合并 CSS、JavaScript</strong>来完成。</p>
<p><!-- /wp:paragraph --></p>
<div id="gtx-trans" style="position: absolute; left: -126px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Tue, 08 Aug 2023 07:09:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加新的 CMS 块]]></title>
      <link>https://www.360magento.com/blog/how-to-add-new-cms-blocks-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>从<strong>Magento 管理面板</strong>可以轻松地<strong>在 Magento 2 中添加新的 CMS 块</strong>。您可以设置显示块的位置，可以是一页、一组页面或任何页面。创建块标题和标识符以确定块并易于管理。块的内容将使用编辑器方便地创建，该编辑器允许您设置文本格式、创建链接和表格、图像、视频和音频。此外，如果您更喜欢使用 HTML 代码，只需单击&ldquo;显示/隐藏编辑器&rdquo;按钮即可。<strong><a href="https://www.mageplaza.com/magento-2-module-development/create-admin-menu-magento-2.html"></a></strong><a href="https://www.mageplaza.com/kb/how-to-insert-images-in-magento-2.html"></a><a href="https://www.mageplaza.com/kb/how-to-upload-product-videos-in-magento-2.html"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>CMS 块将您的网站变成一个有吸引力且引人入胜的页面，以吸引更多流量。要在 Magento 2 中添加新的 CMS 块，您可以按照下面给出的简单步骤操作。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="8-steps-to-add-new-cms-blocks-in-magento-2">在 Magento 2 中添加新 CMS 块的 步骤</h2>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><strong><em>通过以下步骤在 Magento 2 中添加新的 CMS 块：</em></strong></p>
<p><!-- /wp:paragraph --></p>
<p><img src="https://www.360magento.com/media/wysiwyg/b6tJiNX.png" /></p>
<p><!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击内容。在&ldquo;&nbsp;<code>Elements</code>&rdquo;部分中，选择<code>Blocks</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Add New Block</code>右上角的按钮并继续。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Block Title</code>字段中输入新块的名称标题</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>
<p><img src="https://www.360magento.com/media/wysiwyg/sK750OU.png" /></p>
<p><!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在<code>Identifier</code>字段中，选择块的唯一标识符。请记住，使用全部小写字符并使用下划线而不是空格。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在&ldquo;商店视图&rdquo;字段中，选择块可用的商店视图</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Status</code>字段中设置为<code>Enable</code>以使该块在商店中可见</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Content</code>字段中，填写块的内容</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>完成后，单击<code>Save Block</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Mon, 07 Aug 2023 07:07:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置默认​​页面]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-the-default-page-magento-2/</link>
      <description><![CDATA[<p><span>在本主题中，我将介绍</span><span>如何配置默认CMS页面</span><span><span>。</span><span>默认页面是当您单击基本 URL 时将出现的页面。</span><span>通常主页被配置为默认页面。</span><span>此外，当发生&ldquo;找不到页面&rdquo;错误时，将显示默认页面。</span></span></p>
<h2 class="active" id="configure-the-default-pages-in-magento-2"><span>在 Magento 2 中配置默认​​页面</span></h2>
<p><em>按照简单指南在 Magento 2 中配置默认​​页面：</em></p>
<ul>
<li><span>在管理面板上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>在&ldquo;&nbsp;</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>&rdquo;部分中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span><span>在左侧面板中</span><span>选择</span></span><code class="language-plaintext highlighter-rouge">Web</code><span>下</span><code class="language-plaintext highlighter-rouge">General</code><span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Default Pages</code><span>部分，然后继续执行以下操作：</span>
<ul>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Default Web URL</code><span>字段中，默认值</span><code class="language-plaintext highlighter-rouge">cms</code><span>或根据需要输入其他值</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">CMS Home Page</code><span>字段中，选择您想要成为主页的页面，您应该选择&ldquo;主页&rdquo;</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Default No-route URL</code><span><span>字段中，默认值为&ldquo;cms/index/noRoute&rdquo;。</span><span>或根据需要输入其他值</span></span></li>
<li><span>在</span><code class="language-plaintext highlighter-rouge">CMS No Route Page</code><span><span>字段中，选择</span><span>出现</span><span>404 Not Found</span></span><code class="language-plaintext highlighter-rouge">404 Page Not Found</code><span>错误时显示 CMS 页面的值</span><a href="https://www.mageplaza.com/kb/magento-2-404-page-not-found.html"><span></span></a><span></span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">CMS No Cookies Page</code><span>字段中，选择</span><code class="language-plaintext highlighter-rouge">Enable Cookies</code><span>当浏览器中禁用 cookie 时显示 CMS 页面的值</span></li>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Show Breadcrumbs for CMS Pages</code><span>字段中，设置</span><code class="language-plaintext highlighter-rouge">Yes</code><span>是否要在所有 CMS 页面的顶部显示面包屑路径</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。<br /><img src="https://www.360magento.com/media/wysiwyg/f1llfjO.png" /><br /></span></li>
</ul>]]></description>
      <pubDate>Sun, 06 Aug 2023 07:41:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置 Robots.txt]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-robots-txt-magento-2/</link>
      <description><![CDATA[<p></p>
<h2 class="active" id="what-is-robotstxt-in-magento-2">Magento 2 中的 Robots.txt 是什么？</h2>
<p>robots.txt 文件指示网络爬虫了解在何处为您的网站建立索引以及在何处跳过。定义网站机器人与网站爬虫的关系将帮助您优化网站的排名。有时您需要它来识别并避免对特定部分建立索引，这可以通过配置来完成。您可以决定使用默认设置还是为每个搜索引擎设置自定义说明。</p>
<h2 class="active" id="steps-to-configure-magento-2-robotstxt-file">配置 Magento 2 robots.txt 文件的步骤</h2>
<p>请按照此分步指南在 Magento 2 中配置 robots.txt 文件：</p>
<ul>
<li>在管理面板上，单击<code class="language-plaintext highlighter-rouge">Stores</code>。在&ldquo;&nbsp;<code class="language-plaintext highlighter-rouge">Settings</code>&rdquo;部分中，选择<code class="language-plaintext highlighter-rouge">Configuration</code>。</li>
<li>在左侧面板中选择<code class="language-plaintext highlighter-rouge">Design</code>下<code class="language-plaintext highlighter-rouge">General</code></li>
<li>打开该<code class="language-plaintext highlighter-rouge">Search Engine Robots</code>部分，然后继续执行以下操作：
<ul>
<li>在 中<code class="language-plaintext highlighter-rouge">Default Robots</code>，选择以下选项之一：
<ul>
<li>索引、关注</li>
<li>NOINDEX，关注</li>
<li>索引、不关注</li>
<li>NOINDEX、NOFOLLOW</li>
</ul>
</li>
<li>如果需要，请在<code class="language-plaintext highlighter-rouge">Edit Custom instruction of robots.txt File</code>字段中输入自定义说明。</li>
<li>如果您需要恢复默认说明，请在该<code class="language-plaintext highlighter-rouge">Reset to Defaults</code>字段中单击按钮。<code class="language-plaintext highlighter-rouge">Reset to Default</code></li>
</ul>
</li>
<li>完成后，单击<code class="language-plaintext highlighter-rouge">Save Config</code>。</li>
</ul>
<h2 class="active"><span><img src="https://www.360magento.com/media/wysiwyg/orT3LMl.png" /></span></h2>
<h2 class="active" id="magento-2-robotstxt-examples"><span>Magento 2 Robots.txt 示例</span></h2>
<p><span>您还可以通过设置自定义说明来隐藏您的页面，使其不被网站抓取工具发现，如下所示：</span></p>
<ul>
<li><span>允许完全访问</span></li>
</ul>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent:*<span></span>
Disallow:<span></span>
</code></pre>
</div>
</div>
<ul>
<li><span>禁止访问所有文件夹</span></li>
</ul>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent:*<span></span>
Disallow: /<span></span>
</code></pre>
</div>
</div>
<h2 class="active" id="magento-2-default-robotstxt"><span>Magento 2 默认 Robots.txt</span></h2>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>Disallow: /lib/<span></span>
Disallow: /*.php$<span></span>
Disallow: /pkginfo/<span></span>
Disallow: /report/<span></span>
Disallow: /var/<span></span>
Disallow: /catalog/<span></span>
Disallow: /customer/<span></span>
Disallow: /sendfriend/<span></span>
Disallow: /review/<span></span>
Disallow: /*SID=<span></span>
Disallow: /*?<span></span>
<span></span>
# Disable checkout &amp; customer account<span></span>
Disallow: /checkout/<span></span>
Disallow: /onestepcheckout/<span></span>
Disallow: /customer/<span></span>
Disallow: /customer/account/<span></span>
Disallow: /customer/account/login/<span></span>
<span></span>
# Disable Search pages<span></span>
Disallow: /catalogsearch/<span></span>
Disallow: /catalog/product_compare/<span></span>
Disallow: /catalog/category/view/<span></span>
Disallow: /catalog/product/view/<span></span>
<span></span>
# Disable common folders<span></span>
Disallow: /app/<span></span>
Disallow: /bin/<span></span>
Disallow: /dev/<span></span>
Disallow: /lib/<span></span>
Disallow: /phpserver/<span></span>
Disallow: /pub/<span></span>
<span></span>
# Disable Tag &amp; Review (Avoid duplicate content)<span></span>
<span></span>
Disallow: /tag/<span></span>
Disallow: /review/<span></span>
<span></span>
# Common files<span></span>
Disallow: /composer.json<span></span>
Disallow: /composer.lock<span></span>
Disallow: /CONTRIBUTING.md<span></span>
Disallow: /CONTRIBUTOR_LICENSE_AGREEMENT.html<span></span>
Disallow: /COPYING.txt<span></span>
Disallow: /Gruntfile.js<span></span>
Disallow: /LICENSE.txt<span></span>
Disallow: /LICENSE_AFL.txt<span></span>
Disallow: /nginx.conf.sample<span></span>
Disallow: /package.json<span></span>
Disallow: /php.ini.sample<span></span>
Disallow: /RELEASE_NOTES.txt<span></span>
<span></span>
# Disable sorting (Avoid duplicate content)<span></span>
Disallow: /*?*product_list_mode=<span></span>
Disallow: /*?*product_list_order=<span></span>
Disallow: /*?*product_list_limit=<span></span>
Disallow: /*?*product_list_dir=<span></span>
<span></span>
# Disable version control folders and others<span></span>
Disallow: /*.git<span></span>
Disallow: /*.CVS<span></span>
Disallow: /*.Zip$<span></span>
Disallow: /*.Svn$<span></span>
Disallow: /*.Idea$<span></span>
Disallow: /*.Sql$<span></span>
Disallow: /*.Tgz$<span></span>
<span></span>
</code></pre>
</div>
</div>
<h2 class="active" id="more-robotstxt-examples"><span>更多 Robots.txt 示例</span></h2>
<h3 id="block-google-bot-from-a-folder"><span>阻止 Google 机器人访问文件夹</span></h3>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot <span></span>
Disallow: /subfolder/<span></span>
</code></pre>
</div>
</div>
<h3 id="block-google-bot-from-a-page"><span>阻止 Google 机器人访问某个页面</span></h3>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot <span></span>
Disallow: /subfolder/page-url.html<span></span>
</code></pre>
</div>
</div>
<h2 class="active" id="common-web-crawlers-bots"><span>常见的网络爬虫（Bot）</span></h2>
<p><span>以下是互联网上一些常见的机器人。</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot<span></span>
User-agent: Googlebot-Image/1.0<span></span>
User-agent: Googlebot-Video/1.0<span></span>
User-agent: Bingbot<span></span>
User-agent: Slurp		# Yahoo<span></span>
User-agent: DuckDuckBot<span></span>
User-agent: Baiduspider<span></span>
User-agent: YandexBot<span></span>
User-agent: facebot		# Facebook<span></span>
User-agent: ia_archiver		# Alexa</code></pre>
</div>
</div>]]></description>
      <pubDate>Sat, 05 Aug 2023 07:35:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用站点地图并将其提交到搜索引擎]]></title>
      <link>https://www.360magento.com/blog/how-to-enable-submit-sitemap-to-search-engines-magento-2/</link>
      <description><![CDATA[<h2 id="enable-and-submit-sitemap-to-search-engines-in-magento-2"><span>在 Magento 2 中启用站点地图并将其提交到搜索引擎</span></h2>
<ul>
<li>第 1 步：设置并启用站点地图</li>
<li>第 2 步：设置并启用robots.txt</li>
<li>第 3 步：向搜索引擎提交站点地图</li>
<li>第 4 步：恢复之前的机器人指令（可选）</li>
</ul>
<h3 id="setting-enable-sitemap"><span>第 1 步：设置并启用站点地图</span></h3>
<p><span>启用并完成所有</span>XML 站点地图<span>配置，以确定站点地图文件的限制以及站点地图的更新频率。</span></p>
<h3 id="setting-enable-robot-txt"><span>第 2 步：设置并启用 robots.txt（可选）</span></h3>
<p><span><span>启用并完成搜索引擎机器人配置，并使用指导搜索引擎抓取您希望将其编入索引的网站部分的说明。</span><span>此任务是可选的。</span></span></p>
<h3 id="submit-sitemap-search-engines"><span>第 3 步：向搜索引擎提交站点地图</span></h3>
<p><span>您可以通过向不同的搜索引擎发送指向 Magento 安装根目录中的 sitemap.xml 文件的链接来将站点地图提交到不同的搜索引擎。</span></p>
<h3 id="restore-previous-robot-instructions"><span>第 4 步：恢复之前的机器人指令</span></h3>
<p><span>如果需要，您可以恢复到原始或默认限制。</span></p>]]></description>
      <pubDate>Fri, 04 Aug 2023 07:24:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建产品 URL 重写]]></title>
      <link>https://www.360magento.com/blog/how-to-create-product-url-rewrites-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>创建产品 URL 重写</strong>意味着您可以更改产品链接以实现更好的 SEO并使您的网站对访问者更加友好。但是，在重写过程中，您应该知道Target Path和Request Path是什么。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>目标<strong>路径</strong>包含系统使用的内部 URL 以及产品 ID。它会自动输入，并呈灰色显示。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>尽管<strong>请求路径</strong>最初显示当前 URL，但它是您正在请求的路径。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>由于性能优化，Magento 2 删除了 URL 重写自动重新生成的功能。因此，您必须按照以下 3 个步骤自行创建它：</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="3-steps-to-create-product-url-rewrite-in-magento-2">在 Magento 2 中创建产品 URL 重写的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：添加产品 URL 重写</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：更新 URL 索引</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：测试产品 URL 重写结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="add-rewrite">第 1 步：添加重写</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Marketing &gt; SEO &amp; Search &gt; URL Rewrites</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击右上角的按钮<code>Add URL Rewrites</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>从创建 URL 重写的下拉列表中，选择&ldquo;针对产品&rdquo;选项。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在立即出现的产品列表中，点击需要重定向编辑的产品。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Skip Category Selection</code>按钮，然后导航至该<code>URL Rewrite Information</code>部分。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>此处，当前产品 URL 包含在 中，<code>Request Path</code>并且<code>Target Path</code>显示系统使用的内部 URL。它呈灰色且不可编辑。</p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>如有必要，请设置<code>Store</code>以应用重写。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Request Path</code>字段中，插入产品的新 URL 键和后缀。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>转换<code>Redirect</code>为<strong>临时 (302)</strong>或<strong>永久 (301)</strong>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>留下一些重写的​​描述。</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/how-to-create-product-url-rewrites-magento-2-url-rewrite-information.png" /><!-- /wp:list --> <!-- wp:image {"id":3663,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3663" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-create-product-url-rewrites-magento-2-url-rewrite-information-1024x589.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li><code>Save</code>去完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>现在，您可以在列表顶部看到新产品重写。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="update-index">第 2 步：更新索引</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>System &gt; Tools &gt; Index Management</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>标记<code>Catalog URL Rewrites</code>复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择为<strong>重新索引数据</strong><code>Action</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Submit</code>更新索引。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="test-results">第 3 步：检查结果</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>仔细检查重写以确保其完美运行。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Thu, 03 Aug 2023 07:38:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建 CMS 页面重写]]></title>
      <link>https://www.360magento.com/blog/how-to-create-cms-page-rewrites-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>除了&ldquo;产品&rdquo;和&ldquo;类别&rdquo;之外，CMS 页面是三个元素之一，如果 CMS 页面上有任何更改，商店管理员可以将访问者重定向到另一个链接。使用 Magento 2 的 URL Rewrtie 工具，可以设置内容页面或其他页面的 URL 进行重写。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>在本主题中，我们将学习如何在 Magento 配置中创建 CMS 页面重写。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="3-steps-to-create-cms-page-rewrites-in-magento-2">在 Magento 2 中创建 CMS 页面重写的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：添加 CMS 页面重写</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：更新 CMS 页面索引</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：测试 CMS 页面结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="add-rewrite">第 1 步：添加重写</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Marketing &gt; SEO &amp; Search &gt; URL Rewrites</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在右上角，单击<code>Add URL Rewrites</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>从下拉列表中<code>Create URL Rewrites</code>，选择&ldquo;对于类别&rdquo;选项。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在立即出现的页面列表中，点击需要重定向的页面进行编辑。</li>
<!-- /wp:list-item --></ul>
<p><img src="https://www.360magento.com/media/wysiwyg/how-to-create-cms-page-rewrites-magento-2-cms-page-rewrites.png" /><!-- /wp:list --> <!-- wp:image {"id":3659,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3659" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-create-cms-page-rewrites-magento-2-cms-page-rewrites-1024x574.png" /> <!-- /wp:image --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在<strong>URL 重写信息</strong>页面上，<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>如有必要，请设置<code>Store</code>以应用重写。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Request Path</code>字段中，插入 CMS 页面的新 URL 键 和 。<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>如果您想要重定向到站点中的另一个 CMS 页面，请插入不带前导斜杠的相关补丁。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如果您想要重定向到不同站点上的另一个 CMS 页面，请输入目标的完全限定 URL。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>转换<code>Redirect</code>为<strong>临时 (302)</strong>或<strong>永久 (301)</strong>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>留下一些重写的​​描述。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3660,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3660" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-create-cms-page-rewrites-magento-2-url-information-rewrites-1024x576.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-create-cms-page-rewrites-magento-2-url-information-rewrites.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="update-index">第 2 步：更新索引</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>System &gt; Tools &gt; Index Management</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>标记<code>Catalog URL Rewrites</code>复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>选择为<strong>重新索引数据</strong><code>Action</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Submit</code>更新索引。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="test-results">第 3 步：检查结果</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p>仔细检查重写以确保其完美运行。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Wed, 02 Aug 2023 07:34:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中自动产品重定向]]></title>
      <link>https://www.360magento.com/blog/how-to-automatic-product-redirects-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>每当产品的 URL 键发生更改时，商店管理员都可以从 Magento 2 后端自动生成永久产品重定向。要应用 URL 重定向，请标记&ldquo;搜索引擎优化&rdquo;部分下方显示<strong>的&ldquo;为旧 URL 创建永久重定向&rdquo;</strong>复选框。届时，您的商店已准备好设置自动产品重定向并更新 URL 键。<a href="https://www.mageplaza.com/blog/what-seo.html"></a></p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="how-to-automatic-product-redirects-in-magento-2">如何在 Magento 2 中自动产品重定向</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>配置自动重定向</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>自动重定向目录 URL</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="configure-automatic-redirects">配置自动重定向</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Stores &gt; Settings &gt; Configurations</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在左侧面板的 下<code>Catalog</code>，选择<code>Catalog</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Search Engine Optimzation</code>部分。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>为字段选择<strong>是。</strong><code>Create Permanent Redirect for URLs if URL Key Changed</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Config</code>去完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3643,"sizeSlug":"full","linkDestination":"none"} --> <img alt="" class="wp-image-3643" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-automatic-product-redirects-magento-2-search-engine-optimization.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-automatic-product-redirects-magento-2-search-engine-optimization.png" /> <!-- /wp:image --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="auto-redirect-catalog-urls">自动重定向目录 URL</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理面板上，<code>Products &gt; Inventory &gt; Catalog</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开库存列表中所需产品的编辑模式。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>URL key</code>现场，执行以下后续步骤：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>确保您标记了该<code>Create Permanent Redirect for old URL</code>复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>根据需要编辑<code>URL Key</code>所有小写字符和连字符（空格除外）。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save</code>去完成。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>按照<code>Cache Management</code>系统消息中的链接刷新缓存和索引。之后，将为产品和任何关联的类别 URL 启用永久重定向。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Tue, 01 Aug 2023 07:19:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加搜索词]]></title>
      <link>https://www.360magento.com/blog/how-to-add-search-terms-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p><strong>目录</strong></p>
<p><!-- /wp:paragraph --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>如何在 Magento 2 中添加搜索词</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>修改搜索词信息</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>删除 Magento 2 中的搜索词</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="add-new-search-term">如何在 Magento 2 中添加搜索词</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，<code>Marketing &gt; SEO &amp; Search &gt; Search Terms</code>.</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Add New Search Term</code>按钮，设置常规信息：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>在<code>Search Query</code>字段中输入新搜索词。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Store</code>如果您支持多个商店，请从字段的下拉列表中选择商店视图。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Synonym For</code>如果该术语是另一个搜索术语的同义词，请提供该字段。您可以填写其他术语，任何对同义词的搜索都会自动导航到该搜索术语的页面。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Redirect URL</code>字段中插入所需页面的 URL，以将搜索结果重定向到该页面。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>将此搜索词作为任何没有结果的搜索的建议，请在字段中选择<strong>是</strong><code>Display in Suggested Terms</code>。</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Search</code>去完成。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --> <!-- wp:image {"id":3639,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3639" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-add-search-terms-magento-2-general-information-1024x579.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-add-search-terms-magento-2-general-information.png" /> <!-- /wp:image --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="modify-search-term-information">修改搜索词信息</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>从包含所有现有搜索词的管理网格中，单击所需术语的行以打开编辑模式。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>根据需要对搜索词进行任何更改。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li><code>Save Search</code>去完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="remove-search-term">删除 Magento 2 中的搜索词</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在搜索词的管理网格上，勾选要删除的词的复选框。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Action</code>框中，选择<strong>删除</strong>选项。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>点击<code>Submit</code>即可完成。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:image {"id":3640,"sizeSlug":"large","linkDestination":"none"} --> <img alt="" class="wp-image-3640" src="http://kb.360magento.net/wp-content/uploads/2023/07/how-to-add-search-terms-magento-2-remove-search-terms-1024x515.png" /><img src="https://www.360magento.com/media/wysiwyg/how-to-add-search-terms-magento-2-remove-search-terms.png" /> <!-- /wp:image --></p>]]></description>
      <pubDate>Mon, 31 Jul 2023 07:37:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置分页控件]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-the-pagination-controls-magento-2/</link>
      <description><![CDATA[<p><!-- wp:paragraph --></p>
<p>分页控件提供了另一种显示产品列表的方式。您可以设置控件中显示的链接数量，并配置&ldquo;下一个&rdquo;和&ldquo;上一个&rdquo;链接。当需要显示的产品数量大于产品列表设置中允许的数量时，需要显示分页链接。</p>
<p><!-- /wp:paragraph --> <!-- wp:paragraph --></p>
<p>设置分页控件后，您的客户可以在产品列表的顶部和底部获得该控件。因此，<strong>配置分页控件</strong>是使站点性能更加专业的明智方法之一。此外，如果客户不想继续滚动浏览商品，这肯定会改善他们的体验。</p>
<p><!-- /wp:paragraph --></p>
<p><img src="https://www.360magento.com/media/wysiwyg/how-to-configure-the-pagination-controls-magento-2-pagination-controls.png" /></p>
<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="3-steps-to-set-up-the-pagination-controls-in-magento-2">在 Magento 2 中设置分页控件的 3 个步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>第 1 步：登录您的 Magento 2 后端</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 2 步：设置分页控件</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>第 3 步：保存配置并在店面查看结果</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="login-magento-2-backend">第 1 步：登录您的 Magento 2 后端</h3>
<p><!-- /wp:heading --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="magento-20">Magento 2.0</h4>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理侧栏上，&nbsp;Stores&nbsp;&gt; Settings &gt; Configuration.</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":4} --></p>
<h4 class="wp-block-heading" id="magento-21-or-above">Magento 2.1 或更高版本</h4>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在管理侧栏上，<code>Content &gt; Design &gt; Configuration &gt; Select your current theme &gt;&nbsp;</code>.</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="setup-pagination-controls">第 2 步：设置分页控件</h3>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在左侧面板的 下<code>General</code>，选择<code>Design</code>。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Pagination</code>部分，然后执行以下操作：</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --></p>
<p><img src="https://www.360magento.com/media/wysiwyg/how-to-configure-the-pagination-controls-magento-2-pagination-configurations.png" /></p>
<p><!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>在字段中，输入将在分页控件<code>Pagination Frame</code>中显示的链接数。<a href="https://www.mageplaza.com/kb/how-to-configure-the-pagination-controls-magento-2.html"></a></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Pagination Frame Skip</code>字段中，输入在分页控件中显示下一组链接之前向前跳过的链接数。例如，在此字段中插入数字 4，则上一组链接的最后一个链接是下一组链接的第一个链接。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Anchor Text for Previous</code>字段中，写入将与上一个链接一起显示的文本。如果该字段为空，则应用默认箭头。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在&ldquo;下一个锚文本&rdquo;字段中，写入将与&ldquo;下一个&rdquo;链接一起显示的文本。如果该字段为空，则应用默认箭头。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:heading {"level":3} --></p>
<h3 class="wp-block-heading" id="save-configurations-check-storefront">第三步：保存配置并在店面查看结果</h3>
<p><!-- /wp:heading --> <!-- wp:paragraph --></p>
<p><code>Save Config</code>去完成。</p>
<p><!-- /wp:paragraph --> <!-- wp:heading --></p>
<h2 class="wp-block-heading" id="benefits-of-pagination-controls">分页控件的好处</h2>
<p><!-- /wp:heading --> <!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>清晰的定位：顾客可以轻松记住他们找到的物品的位置，因此他们更有可能在需要时返回该物品。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>良好的转化：他们可以轻松跳转到合适的结果，因此往往会停留更长时间。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>减少挫败感：无限滚动对于访问者来说可能看起来太多了，因为他们会觉得有些长的项目列表永远都是这样。</li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:paragraph --></p>
<p>由于这些惊人的好处，客户可以更好地估计他们需要花费多长时间来滚动整个列表。此外，在线商店能够有效地创建搜索结果列表，为购物者提供更清晰的指导。</p>
<p><!-- /wp:paragraph --></p>]]></description>
      <pubDate>Sun, 30 Jul 2023 07:42:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置搜索目录搜索]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-search-catalog-search-magento-2/</link>
      <description><![CDATA[<h2 id="5-steps-to-configure-catalog-search-in-magento-2"><span>在 Magento 2 中配置目录搜索的 5 个步骤</span></h2>
<p><span>要在 Magento 2 中配置目录搜索，请按照以下步骤操作：*</span></p>
<ol>
<li><span>在管理面板上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>在&ldquo;&nbsp;</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>&rdquo;部分中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span><span>在左侧面板中</span><span>选择</span></span><code class="language-plaintext highlighter-rouge">Catalog</code><span>下</span><code class="language-plaintext highlighter-rouge">Catalog</code><span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Catalog Search</code><span>部分，然后继续执行以下操作：</span>
<ul>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Minimal Query Length</code><span>字段中输入数字以设置可以在查询中提交的最少字符</span></li>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Maximum Query Length</code><span>字段中输入数字以设置可在查询中提交的最大字符数</span></li>
</ul>
</li>
<li><span>要限制搜索查询文本的长度和字数，请执行以下操作：</span>
<ul>
<li><span>将最小查询长度设置为查询中可以提交的最小字符数。</span></li>
<li><span>将最大查询长度设置为查询中可以提交的最大字符数。</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><img src="https://www.360magento.com/media/wysiwyg/bwdIUVa.png" /></li>
</ol>]]></description>
      <pubDate>Sat, 29 Jul 2023 08:01:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置产品列表]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-product-listings-magento-2/</link>
      <description><![CDATA[<p><!-- wp:heading --></p>
<h2 class="wp-block-heading" id="steps-to-configure-product-listings-in-magento-2">在 Magento 2 中配置产品列表的步骤</h2>
<p><!-- /wp:heading --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>在管理面板上，单击<code>Stores</code>。<code>Configuration</code>在该<code>Settings</code>部分下选择</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>单击<code>Catalog</code>lept 面板中的 ，然后选择<code>Catalog</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>打开该<code>Storefront</code>部分，然后执行以下步骤：</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>
<p><img src="https://www.360magento.com/media/wysiwyg/NA1qfyb.png" /></p>
<p><!-- wp:list --></p>
<ul><!-- wp:list-item -->
<li>通过选择以下列表之一来选择默认列表模式<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>仅网格</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>仅列出</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>网格（默认）/列表</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>列表（默认/网格</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Products per page on Grid Allowed Values</code>字段中，根据需要输入网格上每页显示的产品数量。如果您想设置值列表，请用逗号分隔每个数字。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Products per Page on Grid Default Value</code>字段中，输入您要为网格上每页显示的产品设置默认值的数字。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Products per Page on List Allowed Values</code>字段中，根据需要输入列表中每页显示的产品数量。如果您想设置值列表，请用逗号分隔每个数字。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Products per page on List Default Value</code>字段中，输入您要为列表中每页显示的产品设置默认值的编号。</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Allow All Products on Page</code>字段中，选择<code>Yes</code>允许客户显示所有产品的列表</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在<code>Product Listing Sort by</code>字段中，设置默认属性以对产品进行排序，以下列表之一：<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>位置</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>姓名</li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>价格</li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如果您使用平面目录，请执行以下操作<!-- wp:list -->
<ul><!-- wp:list-item -->
<li>在 中<code>Use Flat Catalog Category</code>，选择<code>Yes</code></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>在 中<code>Use Flat Catalog Product</code>，设置为<code>Yes</code></li>
<!-- /wp:list-item --></ul>
<!-- /wp:list --></li>
<!-- /wp:list-item --> <!-- wp:list-item -->
<li>如果您希望允许动态引用类别和产品 URL 中的媒体资产，请在<code>Allow Dynamic Media URLs in Products and Categories</code>字段中设置为<code>Yes</code></li>
<!-- /wp:list-item --></ul>
<p><!-- /wp:list --> <!-- wp:list {"ordered":true} --></p>
<ol><!-- wp:list-item -->
<li>完成后，单击<code>Save Config</code>。</li>
<!-- /wp:list-item --></ol>
<p><!-- /wp:list --></p>]]></description>
      <pubDate>Fri, 28 Jul 2023 07:28:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中设置订单确认电子邮件]]></title>
      <link>https://www.360magento.com/blog/configure-sales-email-order-confirmation-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Set_up_Order_Confirmation_Email_in_Magento_2">在 Magento 2 中设置订单确认电子邮件的步骤</span></h2>
<ul>
<li><span>转到</span><span>Magento 2 后端面板中的<span>Stores &gt; Configuration &gt; Sales &gt; Sales Email</span></span><span>。</span><span><span></span></span></li>
<li><span><span>从给定的选项中探索订单部分。<br /><img src="https://www.360magento.com/media/wysiwyg/order-confirmationemail-magento-2.png" /></span></span>
<p><span>已启用</span><span>：设置&ldquo;是&rdquo;以启用销售电子邮件选项。</span></p>
<p><span>新订单确认电子邮件发件人：</span><span>选择要发送电子邮件的商店代表，该代表将被表示为电子邮件的发件人。</span></p>
<p><span><span><span>新</span></span><span><span>订单确认模板</span></span><span><span>：</span></span></span><span>选择发送电子邮件的模板。</span></p>
<p><span>访客新订单确认模板</span><span>：选择访客用户的模板。</span></p>
<p><span>发送订单电子邮件副本至</span><span>此处添加您的测试电子邮件 ID。</span></p>
<p><span>发送订单电子邮件副本方法</span><span>：在此处添加发送电子邮件副本的方法。</span></p>
<ul>
<li><span>然后，浏览订单评论、发票、发货和贷项凭证部分，并根据订单填写所有适当的详细信息。</span></li>
<li><span>单击</span><span>保存配置</span><span>以完成销售电子邮件配置过程。</span></li>
</ul>
<p><span>完成上述步骤后，您将可以轻松地向客户发送有关客户或用户执行的任何特定操作的电子邮件。</span></p>
</li>
</ul>
<p><a href="https://magecomp.com/blog/wp-content/uploads/2020/05/order-confirmationemail-magento-2.png" data-wpel-link="internal"></a></p>]]></description>
      <pubDate>Thu, 27 Jul 2023 07:20:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：如何在主页上插入产品]]></title>
      <link>https://www.360magento.com/blog/how-to-insert-products-on-homepage-magento-2/</link>
      <description><![CDATA[<p><span><span><span>登陆页面可以被认为是每个网站最重要的部分。</span><span>客户在选择购物之前会首先看到您的着陆页，因此您的责任是使着陆页真正吸引客户。</span><span>如果没有，他们会立即离开您的网站。</span><span>也许吸引客户的最理想方法是将项目嵌入到您的目标网页上。</span><span>因为当他们访问您的网站时，他们会更轻松地看到吸引他们的商品，并有动力购买它们。</span><span>您还可以在登陆页面上嵌入标记/标记，请阅读本指南。</span></span></span></p>
<h2><span id="How_to_Insert_Products_on_Homepage_in_Magento_2">如何在 Magento 2 主页上插入产品：</span></h2>
<p><span>第 1 步</span><span>&ndash; 选择内容菜单和其中的页面</span></p>
<p><span><span>首先，您需要打开 Magento 2 管理面板，然后通过菜单单击内容菜单。</span><span>此处将显示页面，您将看到商店的所有页面。</span><span>您将看到以下屏幕。</span></span></p>
<p><span><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/2.1-1.png" /></span></span></p>
<p><span><span><span>第 2 步</span><span>&ndash; 选择&ldquo;操作&rdquo;菜单下的&ldquo;编辑&rdquo;</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/2.3.png" /></span></span></span></p>
<p><span>现在单击内容部分并继续插入小部件选项。</span></p>
<p><span>步骤 3 &ndash;</span><span>从选项中选择目录产品列表</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/2.4.png" /></span></p>
<p><span><span>现在您将看到&ldquo;插入小部件&rdquo;页面，现在为小部件类型选择&ldquo;目录产品列表&rdquo;选项。</span><span>MageComp可以帮助您轻松在首页列出特色商品、畅销商品、新品、每日优惠等，让我们看看它是如何做到的。</span></span></p>
<p><span><span>&nbsp;</span></span><span>第 4 步 &ndash;</span><span>选择分类并单击&ldquo;插入小部件&rdquo;按钮</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/vishal-bc.png" /></span></p>
<p><span>紧接着，在下一页上，您将看到有一个&ldquo;条件&rdquo;属性。因此，现在从选项中选择&ldquo;类别&rdquo;，然后选择您想要在商店主页上展示的类别。</span><span>现在轻松单击&ldquo;插入小部件&rdquo;。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/4th-edit.png" /></span></p>
<p><span>最后，返回&ldquo;内容&rdquo;选项卡，您将在内容框中看到&ldquo;产品&rdquo;符号。</span><span>单击&ldquo;保存页面&rdquo;按钮即可完成页面的更改。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/a.png" /></span></p>]]></description>
      <pubDate>Wed, 26 Jul 2023 07:15:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中所有页面的前端添加 JS 文件]]></title>
      <link>https://www.360magento.com/blog/add-js-file-frontend-pages-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_JS_File_in_Frontend_for_All_Pages_in_Magento_2">在 Magento 2 中所有页面的前端添加 JS 文件的步骤：</span></h2>
<p><span><span>第一步：创建一个文件 default.xml 在此路径下 app\code\[Vendor]\[Module]\view\frontend\layout\default.xml</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/QQ20230719-141237_2x.png" /></span></span></p>
<p></p>
<p><span>第二步：在此路径下创建JS文件 app\code\[Vendor]\[Module]\view\frontend\web\js\js_fileName.js</span></p>
<p>第三步：执行 setup Upgrade 命令和 setup:static-content:deploy 命令，为 Magento 2 商店的所有页面实施 JS 文件</p>]]></description>
      <pubDate>Tue, 25 Jul 2023 07:09:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用持久购物车]]></title>
      <link>https://www.360magento.com/blog/enable-persistent-shopping-cart-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Enable_Persistent_Shopping_Cart_in_Magento_2">在 Magento 2 中配置启用持久购物车的步骤：</span></h2>
<p><span>要在 Magento 2 商店中启用持久购物车，您需要执行以下操作：</span></p>
<p><span>第 1 步</span><span>：导航到</span><span>管理</span><span>并转到商店&gt;配置&gt;客户&gt;持久购物车</span></p>
<p><span>步骤 2&nbsp;</span><span>：</span><span>禁用</span><span>&ldquo;使用系统值&rdquo;复选框并设置</span><span>&ldquo;是&rdquo;</span><span>选项。</span></p>
<p><span>步骤 3&nbsp;</span><span>：根据您的选择设置时间，默认值为</span><span>31,536,000</span><span>秒。</span></p>
<p><span>步骤4&nbsp;</span><span>：</span><span>启用</span><span>记住我保存购物车信息的选项。</span></p>
<p><span>步骤 5&nbsp;</span><span>：设置</span><span>&ldquo;否&rdquo;&nbsp;</span><span>，以便在用户退出时保存购物车信息。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Enable-Persistent-Shopping-Cart-in-Magento-2.png" /></span></p>
<p><span>步骤 6：最后，</span><span>保存配置</span><span>以应用持久购物车。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Mon, 24 Jul 2023 08:16:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置操作日志]]></title>
      <link>https://www.360magento.com/blog/configure-action-log-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Action_Log_in_Magento_2">在 Magento 2 中配置操作日志的步骤：</span></h2>
<p><span>步骤1：</span></p>
<p><span>导航到</span><span>商店&gt;设置&gt;配置&gt;高级&gt;管理操作日志记录部分</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Admin.png" /></span></p>
<p><span>用于启用管理日志记录以标记复选框&nbsp;</span></p>
<p><span>要禁用管理日志记录，请取消选中该复选框&nbsp;</span></p>
<p><span>步骤 2：保存配置</span></p>
<p><span>最后的话：</span></p>
<p><span><span><span>希望通过上述解决方案，所有人都能够在 Magento 2 中配置操作日志。如果您在上述解决方案中发现任何困难，那么我会在下面的评论部分中倾听。</span><span>另外，通过社交媒体与您的 Magento 朋友分享本文，并帮助他们在 Magento 2 中配置操作日志。直到保持安全。</span></span></span></p>]]></description>
      <pubDate>Sun, 23 Jul 2023 08:09:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加新的 CMS 页面]]></title>
      <link>https://www.360magento.com/blog/add-new-cms-page-magento/</link>
      <description><![CDATA[<h2><span id="How_to_add_a_New_CMS_Page_in_Magento_2">如何在 Magento 2 中添加新的 CMS 页面：</span></h2>
<h3><span id="Step_1_Firstly_you_need_to_Add_a_New_Page"><span><span>第1步：首先您需要</span></span><span><span><span>添加一个新页面</span></span></span></span></h3>
<p><span>导航到</span><span>内容 &gt; 元素 &gt; 页面</span><span>，然后点击</span><span>添加新页面</span><span>：</span></p>
<p><span>页面标题：</span><span>根据您的要求添加适当的页面标题。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add-a-New-CMS-Page-in-Magento-2.png" /></span></p>
<p><span><span>探索</span><span>搜索引擎优化</span><span>选项</span></span></p>
<p></p>
<p><img src="https://www.360magento.com/media/wysiwyg/Search-Engine-Optimization-option.png" /></p>
<p><span>URL 键：</span><span>添加页面在线地址的 URL。</span></p>
<p><span>元标题：</span><span>在此处添加您的元标题。</span></p>
<p><span>元关键字：</span><span>在此处添加元关键字。</span></p>
<p><span>元描述：</span><span>添加适当的元描述</span></p>
<p><span><span>浏览网站</span><span>选项</span></span><span>中的页面</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Page-in-Website-option.png" /></span></p>
<p><span>商店视图：</span><span>选择显示页面的商店视图。</span></p>
<p><span>探索</span><span>设计</span><span>选项</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Explore-Design-Option.png" /></span></p>
<p><span>布局：</span><span>从下拉列表中选择您想要的布局</span></p>
<p><span>探索</span><span>自定义设计更新</span><span>选项</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Custom-Design-Update-option.png" /></span></p>
<p><span>用于自定义页面的设计和主题。</span></p>
<p><span>探索</span><span>内容</span><span>选项</span></p>
<p><span>内容标题：</span><span>管理员需要添加显示在页面顶部的主标题。</span></p>
<p><span>显示/隐藏编辑器：</span><span>用于探索所见即所得编辑器。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/exploring-WYSIWYG-editor.png" /></span></p>]]></description>
      <pubDate>Sat, 22 Jul 2023 07:39:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示/删除 CMS 页面的面包屑]]></title>
      <link>https://www.360magento.com/blog/show-remove-breadcrumbs-cms-pages-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Show_Remove_Breadcrumbs_to_CMS_Pages_in_Magento_2">在 Magento 2 中显示/删除 CMS 页面面包屑的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至</span><span>&ldquo;商店&rdquo;&gt;&ldquo;配置&rdquo;&gt;&ldquo;常规&rdquo;&gt;&ldquo;Web&rdquo;</span></p>
<p><span>并探索</span><span>&ldquo;默认页面&rdquo;选项</span><span>。</span></p>
<p><span><span></span></span><span>如果想在 Magento 2 中显示面包屑，请将</span><span>CMS 页面的显示面包屑</span><span>更改</span><span>为&ldquo;</span><span>是&rdquo;</span><span><span></span></span></p>
<p><span><span></span></span><span>如果要在 Magento 2 中删除面包屑，请将</span><span>CMS 页面的显示面包屑</span><span>更改</span><span>为&ldquo;</span><span>否&rdquo;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Show-Remove-Breadcrumbs-to-CMS-Pages-in-Magento-2-1.png" /></span></p>]]></description>
      <pubDate>Fri, 21 Jul 2023 07:47:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置分页控件]]></title>
      <link>https://www.360magento.com/blog/configure-pagination-controls-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_the_Pagination_Controls_in_Magento_2">在 Magento 2 中配置分页控件的步骤：</span></h2>
<p><span>第1步：</span><span>导航到</span><span>内容&gt;设计&gt;配置&gt;选择当前主题&gt;&nbsp;</span><span>。</span></p>
<p><span>向下滚动并浏览</span><span>分页</span><span>部分。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/How-to-Configure-the-Pagination-Controls-in-Magento-2-1.png" /></p>
<p><span>分页框架：</span><span>输入您想要在分页控件中显示的链接数量。</span></p>
<p><span>分页帧跳过：</span><span>添加在分页控件中显示下一个链接时跳过的所需数量。</span></p>
<p><span>上一个锚文本：</span><span>添加所需的文本以与上一个链接一起显示。</span></p>
<p><span>下一个锚文本：</span><span>添加将与下一个链接一起显示的所需文本。</span></p>
<p><span>第 2 步：</span><span>保存配置</span></p>
<p><span>就是这样。</span></p>]]></description>
      <pubDate>Thu, 20 Jul 2023 08:43:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建新的商店视图]]></title>
      <link>https://www.360magento.com/blog/create-new-store-view-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_a_New_Store_View_in_Magento_2">在 Magento 2 中创建新商店视图的步骤</span></h2>
<p><span>第 1 步：</span><span>登录管理并从仪表板导航至</span><span>商店 &gt; 设置 &gt; 所有商店</span></p>
<p><span>第 2 步：</span><span>现在，单击</span><span>&ldquo;创建商店视图&rdquo;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/New-Store-View-in-Magento-2.png" /></span></p>
<p><span>第三步：</span><span>输入店铺查看信息</span></p>
<p><span>商店：</span><span>选择该商店视图的主要商店。</span></p>
<p><span>名称：</span><span>插入该商店视图的名称。</span></p>
<p><span>代码：</span><span>输入您正在创建的商店视图的代码。</span></p>
<p><span>状态：</span><span><span>选择启用以配置商店视图。</span><span>稍后，如果有需要，您可以通过选择状态为禁用来禁用商店视图。</span></span></p>
<p><span>排序顺序：</span><span>输入商店视图的序列号，该序列号将按照该顺序与其他商店视图一起显示。</span></p>
<p><span>第四步：</span><span>输入所有信息后，点击</span><span>&ldquo;保存商店视图&rdquo;</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Save-Store-View..png" /></span></p>
<p><span><span>就是这样。</span><span>在 Magento 2 中配置新的商店视图后，您可以在前端商店中找到它。</span></span></p>]]></description>
      <pubDate>Wed, 19 Jul 2023 08:39:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中取消发货]]></title>
      <link>https://www.360magento.com/blog/cancel-shipment-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Cancel_A_Shipment_In_Magento_2">在 Magento 2 中取消发货的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至&ldquo;销售&rdquo;&gt;&ldquo;订单&rdquo;</span></p>
<p><span></span><span>步骤2：</span><span>选择您需要取消的订单</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Choose-the-order-you-require-to-cancel.png" /></span></p>
<p><span>第三步：</span><span>查看已取消订单的发货情况</span></p>
<p><span>如果没有显示取消按钮，则无法取消该货件。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/The-Shipments-Of-Canceled-Order.png" /></span></p>
<p><span>第 4 步：</span><span>很可能会显示取消按钮，因此单击取消按钮即可取消该订单。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Click-on-the-Cancel-Button.png" /></span></p>]]></description>
      <pubDate>Tue, 18 Jul 2023 07:33:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置重新排序]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-reorder-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_enable_or_disable_reorder_in_Magento_2">在 Magento 2 中启用或禁用重新排序的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至</span><span>商店&gt;配置&gt;销售&gt;销售</span><span>并探索</span><span>重新订购</span><span>选项</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Configure-Reorder-in-Magento-2.png" /></span></p>
<p><span>允许重新排序：</span><span>设置&ldquo;&nbsp;</span><span>YES&nbsp;</span><span>&rdquo;允许重新排序，设置&ldquo;&nbsp;</span><span>NO&nbsp;</span><span>&rdquo;则禁用重新排序。</span></p>
<p><span>步骤 2：</span><span>保存</span><span>配置</span></p>
<p><span>就这样，您已经在 Magento 2 商店中成功实施了重新排序配置。</span></p>]]></description>
      <pubDate>Mon, 17 Jul 2023 08:31:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加条款和条件复选框]]></title>
      <link>https://www.360magento.com/blog/add-terms-and-conditions-checkbox-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Terms_And_Conditions_Checkbox_in_Magento_2">在 Magento 2 中添加条款和条件复选框☑️的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至商店 &gt; 配置 &gt; 销售 &gt; 结帐并浏览结帐选项。</span></p>
<p><span>启用单页结帐：</span><span>选择</span><span>&ldquo;是&rdquo;</span><span>选项以启用一步结帐。</span></p>
<p><span>启用条款和条件：</span><span>选择</span><span>&ldquo;是&rdquo;</span><span>选项以启用条款和条件。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add-Terms-And-Conditions-Checkbox.png" /></span></p>
<p><span>第 2 步：</span><span>现在，导航至</span><span>&ldquo;商店&rdquo;&gt;&ldquo;条款和条件&rdquo;</span></p>
<p><span>然后点击</span><span>&ldquo;添加新条件&rdquo;</span><span>选项。</span></p>
<p><span>填写以下所有信息：</span></p>
<p><span>条件名称：</span><span>添加条件名称以供您个人参考。</span></p>
<p><span>状态：</span><span>将状态更改为&ldquo;已启用&rdquo;</span></p>
<p><span>将内容显示为：</span><span>选择所需的选项（文本或 HTML）以在前端显示内容。</span></p>
<p><span>应用：</span><span>自动或手动选择您所需的选项来应用条款和条件。</span></p>
<p><span>商店视图：</span><span>选择您的商店视图以了解将使用的条款和条件。</span></p>
<p><span>复选框文本：</span><span>添加将在条款和条件链接中显示的所需文本</span></p>
<p><span>内容：</span><span>添加商店的全部条款和条件。</span></p>
<p><span>内容高度 (CSS)：</span><span>添加内容高度，以决定结账时显示条款和条件的文本框的高度（以像素为单位）。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add-New-Condition.png" /></span></p>
<p><span>第三步：</span><span>保存</span><span>配置。</span></p>
<p><span>第 4 步：</span><span>执行上述步骤后，您将能够在商店的结账页面（前端）查看条款和条件</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Save-the-Config.png" /></span></p>]]></description>
      <pubDate>Sun, 16 Jul 2023 07:28:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置免费送货]]></title>
      <link>https://www.360magento.com/blog/setup-free-shipping-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Setup_Free_Shipping_in_Magento_2">在 Magento 2 中设置免费送货的步骤：</span></h2>
<p><span>步骤 1：</span><span>登录 Admin Dashboard 并导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span>从左侧面板导航至</span><span>&ldquo;销售&rdquo;&gt;&ldquo;送货方式&rdquo;&nbsp;</span><span>，然后展开</span><span>&ldquo;免费送货&rdquo;</span><span>部分。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/free-shipping-configuration.png" /></span></p>
<p><span>已启用：</span><span>选择&ldquo;是&rdquo;以启用免费送货。</span><br /><span>标题：</span><span>在结账页面提及免运费的标题。</span><br /><span>方法名称：</span><span>添加方法名称，以消除运输方面的混乱。</span><br /><span>最低订单金额：</span><span>添加最低订单金额以获得免费送货服务。</span><br /><span>显示的错误消息：</span><span>如果不提供免费送货，请添加所需的错误消息。</span><br /><span>运送到适用的国家/地区：</span><span>根据您的要求选择所有国家/地区或特定国家/地区以启用免费送货。</span><br /><span>运送到特定国家/地区：</span><span>如果您只想运送到特定国家/地区，请选择国家/地区。</span><br /><span>如果不适用则显示方法：</span><span>根据您的要求选择。</span><br /><span>排序：</span><span>在结账页面设置运送方式的排序顺序。</span></p>
<p><span>第 3 步：</span><span>现在，展开</span><span>UPS</span><span>部分以激活免费送货</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/free-shipping-activate.png" /></span></p>
<p><span>自由方法：</span><span>将此字段设置为 UPS 接地。</span><br /><span>启用免费送货阈值：</span><span>将此选项设置为启用。</span><br /><span>免费送货金额阈值：</span><span>根据您的要求添加提供免费送货的最低金额阈值。</span></p>
<p><span>步骤 4：</span><span>单击</span><span>&ldquo;保存配置&rdquo;。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Sat, 15 Jul 2023 07:25:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更改 Magento 2 中的默认语言]]></title>
      <link>https://www.360magento.com/blog/change-default-language-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_Default_Language_in_Magento_2">更改 Magento 2 中默认语言的步骤：</span></h2>
<p><span>&nbsp;</span><span>第一步：</span><span><span>后台</span><span>登录店铺</span></span><span>管理员账号</span><span></span></p>
<p><span>第2步：</span><span>导航到以下路径</span></p>
<p><span>商店 -&gt; 配置</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Change-Default-Language-in-Magento-2.png" /></span></p>
<p><span>步骤 3：</span><span>选择以下选项</span></p>
<p><span>常规 -&gt; 区域设置选项</span></p>
<p><span></span><span>并从区域</span><span><span>设置字段下拉菜单中选择所需的语言</span><span>。</span></span></p>
<p><span>注意</span><span><span>&ndash;</span><span>如果您有多个商店视图，请选择要更改语言的</span></span><span>商店视图。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Store-View.png" /></span></p>
<p><span><span>步骤 4：</span><span>按</span><span>&ldquo;保存配置&rdquo;</span><span>按钮。</span></span></p>]]></description>
      <pubDate>Fri, 14 Jul 2023 07:19:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置高级定价]]></title>
      <link>https://www.360magento.com/blog/setup-advanced-pricing-in-magento/</link>
      <description><![CDATA[<h1><span id="Steps_to_Setup_Advanced_Pricing_in_Magento_2">在 Magento 2 中设置高级定价的步骤：</span></h1>
<p><span>第 1 步：</span><span>导航至</span><span>目录 &gt; 产品</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Setup-Advanced-Pricing-in-Magento-2.png" /></span></p>
<p><span>步骤 2：</span><span>然后选择您需要应用高级定价设置的产品</span></p>
<p><span>步骤 3：</span><span>然后，选择</span><span>高级定价</span><span>选项。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/special-price-tier-price.png" /></span></p>
<p><span><span>第 4 步：现在填写</span><span><span><span>特价</span></span><span><span>和</span></span><span><span>客户团体价格</span></span></span><span>的详细信息</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/advanced-pricing-1.png" /></span></span></p>]]></description>
      <pubDate>Thu, 13 Jul 2023 07:17:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中翻译 CMS 页面]]></title>
      <link>https://www.360magento.com/blog/translate-cms-pages-in-magento/</link>
      <description><![CDATA[<p>如何在 Magento 2 中翻译 CMS 页面：<br />第 1 步：首先导航到内容&gt;元素&gt;页面</p>
<p>选择您需要翻译的页面并通过单击编辑模式进行探索：</p>
<p>只需复制 URL 密钥并返回按钮到页面网格，然后点击添加新页面按钮：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/Translate-CMS-Pages-in-Magento-2.png" /></p>
<p><span>第二步：填写相应信息。</span></p>
<p><span>启用页面为&ldquo;是&rdquo;</span></p>
<p><span>页面标题：</span><span>在此处添加翻译后的标题。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add-the-translated-title.png" /></span></p>
<p><span>URL 键：</span><span>添加您之前复制的 URL。</span></p>
<p><span>元标题：</span><span>添加翻译页面的标题</span></p>
<p><span>元关键字：</span><span>为翻译页面添加关键字。</span></p>
<p><span>元描述：</span><span>添加翻译页面的元描述。</span></p>
<p><span><span>商店视图：</span><span>相应地选择以显示翻译。</span></span></p>
<p></p>
<p><img src="https://www.360magento.com/media/wysiwyg/Select-store-view-for-CMS-page-in-Magento-2.png" /></p>
<p><span>内容</span><span>：浏览内容部分并添加翻译的内容。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/CMS-page-in-Magento-2.png" /></span></p>]]></description>
      <pubDate>Wed, 12 Jul 2023 07:59:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中禁用或允许访客结帐]]></title>
      <link>https://www.360magento.com/blog/disable-or-allow-guest-checkout-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Disable_or_Allow_Guest_Checkout_in_Magento_2">在 Magento 2 中禁用或允许访客结账的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理员帐户转到</span><span>商店 &gt; 设置 &gt; 配置</span></p>
<p><span>步骤 2：</span><span>从左侧面板中，展开</span><span>&ldquo;销售&rdquo;</span><span>并选择</span><span>&ldquo;结帐&rdquo;</span></p>
<p><span>步骤 3：</span><span>放大</span><span>&ldquo;结帐选项&rdquo;选项</span><span><span><span>卡。</span><span>要限制访客结帐，请取消选中&ldquo;使用系统值&rdquo;复选框，然后</span></span></span><span><span><span>在</span></span><span><span>&ldquo;允许访客结帐&rdquo;字段中选择</span></span></span><span>&ldquo;否&rdquo;选项</span><span>。</span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/QQ20230629-151238_2x.png" /></span></p>
<p><span>如果您希望在 Magento 2 中进行访客结帐，请将&ldquo;允许访客结帐&rdquo;字段</span><span>设置</span><span>为</span><span>&ldquo;是&rdquo;</span><span>或选中&ldquo;使用系统值&rdquo;复选框。</span></p>
<p><span>步骤 4：</span><span>单击</span><span>&ldquo;保存配置&rdquo;</span><span>按钮。</span></p>]]></description>
      <pubDate>Tue, 11 Jul 2023 07:11:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建 301 重定向]]></title>
      <link>https://www.360magento.com/blog/create-301-redirect-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_301_Redirect_in_Magento_2">在 Magento 2 中创建 301 重定向的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至</span><span>管理面板 &gt; 营销 &gt; SEO 和搜索 &gt; URL 重写</span></p>
<p><span>第 2 步：</span><span>现在按</span><span>以下屏幕截图中的</span><span>&ldquo;添加 URL 重写&rdquo;选项。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_1_1.png" /></span></p>
<p><span>步骤 3：</span><span>在相应字段中输入信息。</span></p>
<p><span>创建 URL 重定向：</span><span>从下拉列表中选择自定义选项。</span></p>
<p><span>商店：</span><span>选择您需要实现 URL 重写的商店视图</span></p>
<p><span>请求路径：</span><span>输入您需要重定向的路径</span></p>
<p><span>目标路径：</span><span>输入您需要将过去的 URL 重定向到的路径。</span></p>
<p><span>重定向类型：</span><span>从下拉列表中选择永久 (301)。</span></p>
<p><span>描述：</span><span>添加此 301 重定向的描述或原因。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_2.png" /></span></p>]]></description>
      <pubDate>Mon, 10 Jul 2023 07:00:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何通过命令行安装 Magento 2.4]]></title>
      <link>https://www.360magento.com/blog/install-magento-2-4-via-command-line/</link>
      <description><![CDATA[<p>通过命令行安装 Magento 2.4 并受益于最新 Magento 2.4 版本的增强功能，例如：</p>
<p>通过店内提货为购物者带来新的满足感<br />通过卖家辅助购物以客户为导向的服务<br />性能提高 10 倍并简化资产管理<br />Magento 2 管理面板的 2FA 安全性<br />使用审批工作流程的 B2B 采购<br />简单的无头商务和 PWA 开发。<br />升级的平台安全性、质量和性能。<br />我想现在我们已经迫不及待地想安装 Magento 2.4 了。如果您想安装 Magento 2.4，请按照以下步骤操作：</p>
<p>要通过命令行安装 Magento 2.4，有一个命令行界面可以执行安装和配置任务：&lt;magento_root&gt;/bin/magento</p>
<h2><span id="Steps_to_Install_Magento_24_via_Command_Line">通过命令行安装 Magento 2.4 的步骤：</span></h2>
<p><span>在命令行中运行以下命令：</span></p>
<pre>php bin/magento setup:install --base-url="http://127.0.0.1/m240/" --db-host="localhost" --db-name="m240" --db-user="root" --db-password="root@123" --admin-firstname="admin" --admin-lastname="admin" --admin-email="admin@admin.com" --admin-user="admin" --admin-password="admin@123" --language="en_US" --currency="USD" --timezone="America/Chicago" --use-rewrites="1" --backend-frontname="admin"
</pre>]]></description>
      <pubDate>Sun, 09 Jul 2023 07:49:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更改 Magento 2 中的版权声明]]></title>
      <link>https://www.360magento.com/blog/change-copyright-notice-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_change_copyright_notice_in_Magento_2">在 Magento 2 中更改版权声明的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航到内容&gt;配置，</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_1-3.png" /></span></p>
<p><span><span>步骤 2：</span><span>点击 编辑您需要更改版权声明的位置</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/Config_2-3.png" /></span></span></p>
<p><span>第 3 步：</span><span>现在，探索页脚部分，</span></p>
<p><span>版权所有：</span><span>根据您的要求更新文本。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_3-1.png" /></span></p>
<p><span><span>保存配置。</span></span></p>]]></description>
      <pubDate>Fri, 07 Jul 2023 21:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中批量更新产品属性]]></title>
      <link>https://www.360magento.com/blog/update-product-attributes-in-bulk-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Update_Product_Attribute_in_Bulk_in_Magento_2">在 Magento 2 中批量更新产品属性的步骤：</span></h2>
<p><span>转到</span><span>目录&gt;产品</span><span>并选择多个产品来赋予您想要更新的值。</span></p>
<p><span><span></span></span><span><span><span>现在，从批量操作选项中</span></span><span><span>选择</span></span></span><span>&ldquo;更新属性&rdquo; 。</span><span><span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/QQ20230628-143955_2x.png" /></span></p>
<p><span>&nbsp;</span><span>向下滚动并点击</span><span>&ldquo;更改&rdquo;</span><span>以更改产品属性的值。</span></p>
<p><span><span>保存</span><span>配置。</span></span></p>]]></description>
      <pubDate>Fri, 07 Jul 2023 00:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建新的 CMS 块]]></title>
      <link>https://www.360magento.com/blog/create-new-cms-block-in/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_New_CMS_Block_in_Magento_2">在 Magento 2 中创建新 CMS 块的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航到</span><span>内容&gt;元素&gt;块</span></p>
<p><span>点击添加新块，如下图所示。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add_new_block_1.png" /></span></p>
<p><span>步骤2：</span><span>按照以下说明进行配置。</span></p>
<p><span>块标题：</span><span>根据您的需要添加新块的标题。&nbsp;</span></p>
<p><span>标识符：</span><span>选择一个唯一的标识符，并确保使用小写字符和下划线而不是空格。</span></p>
<p><span>商店视图：</span><span>选择您需要显示块的商店视图。</span></p>
<p><span>状态：</span><span>启用该按钮以在 Magento 2 商店中显示该块。</span></p>
<p><span>内容：</span><span>根据您的愿望和要求添加内容。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_1.png" /></span></p>]]></description>
      <pubDate>Thu, 06 Jul 2023 02:35:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置产品列表]]></title>
      <link>https://www.360magento.com/blog/how-to-configure-product-listings-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Product_Listings_in_Magento_2">在 Magento 2 中配置产品列表的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航至</span><span>&ldquo;商店&rdquo;&gt;&ldquo;配置&rdquo;&gt;&ldquo;目录&rdquo;&gt;&ldquo;目录&rdquo;</span><span>并探索</span><span>&ldquo;店面&rdquo;</span><span>选项</span></p>
<p><span>步骤 2：</span><span>现在根据您的要求进行以下配置。</span></p>
<p><span>列表模式：</span><span>根据您的要求从下面的下拉列表中选择&nbsp;</span></p>
<p><span>仅网格</span><br /><span>网格（默认）/列表</span><br /><span>仅</span><br /><span>列表 列表（默认/网格</span></p>
<p><span>网格上每页的产品允许值：</span><span><span><span>根据您的要求添加将在网格上显示的产品数量。</span><span>如果您想设置值列表，请使用逗号添加数字。</span></span></span></p>
<p><span>网格上每页的产品默认值：</span><span>添加您需要设置为网格上每页产品显示默认值的数量。</span></p>
<p><span>列表中每页的产品允许值：</span><span><span><span>根据您的需要添加每页显示的数量。</span><span>如果您想设置值列表，请使用逗号添加数字。</span></span></span></p>
<p><span>列表中每页的产品默认值：</span><span>添加您想要设置为列表中每页显示的产品的默认数量。</span></p>
<p><span>产品列表排序方式：</span><span>根据您的需要进行选择，根据位置、产品名称和价格对产品进行排序。</span></p>
<p><span>允许每页显示所有产品：</span><span>选择&ldquo;是&rdquo;可向用户显示所有产品的列表。</span></p>
<p><span>记住类别分页：</span><span>设置&ldquo;是&rdquo;以保留基于客户搜索和目录列表的分页设置。</span></p>
<p><span>使用平面目录类别：</span><span>要使用平面目录类别，请</span><span>在此选项中设置</span><span>&ldquo;是&rdquo; 。</span><span><span></span></span></p>
<p><span>使用平面目录产品：</span><span>要使用平面目录产品，请</span><span>在此选项中设置</span><span>&ldquo;是&rdquo; 。</span><span><span></span></span></p>
<p><span>每个产品的色板：</span><span>根据您的要求添加数字以显示每个产品的色板。</span></p>
<p><span>在产品列表中显示色板：</span><span>如果您希望在产品列表中显示色板，</span><span>请设置</span><span>&ldquo;是&rdquo; 。</span><span><span></span></span></p>
<p><span>显示样本工具提示：</span><span>如果您希望在产品列表中显示样本工具提示，</span><span>请设置</span><span>&ldquo;是&rdquo; 。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_storefront.png" /></span></p>]]></description>
      <pubDate>Wed, 05 Jul 2023 06:33:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加订单和退货小部件]]></title>
      <link>https://www.360magento.com/blog/how-to-add-orders-and-returns-widget-in-magento/</link>
      <description><![CDATA[<h2><span id="Step_to_add_the_orders_and_returns_widget_in_Magento_2">在 Magento 2 中添加订单和退货小部件的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航到</span><span>内容&gt;元素&gt;小部件&nbsp;</span></p>
<p><span>点击</span><span>小工具按钮</span></p>
<p><span>第 2 步：</span><span>现在，在</span><span>店面属性中</span><span>进行如下配置。</span></p>
<p><span>类型：</span><span>管理员必须选择订单和退货选项。</span></p>
<p><span>设计包/主题：</span><span>选择商店内使用的主题。</span></p>
<p><span>小部件标题：</span><span>用于描述您的小部件，仅管理员可见。</span></p>
<p><span>分配到商店视图：</span><span>相应地选择您的商店视图。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add_widget.png" /></span></p>
<p><span>第 3 步：</span><span>现在，点击&ldquo;布局更新&rdquo;并进行相应配置。</span></p>
<p><span>显示于：</span><span>选择需要显示小部件的页面类型。</span></p>
<p><span>完成布局更新中的更多详细信息以在页面上显示小部件。</span></p>
<p><span></span></p>
<p><span>第四步：</span><span>保存配置</span></p>
<p><span>要在 Magento 2 中使用订单和退货小部件，您必须在订单 ID、帐单姓氏、电子邮件地址或邮政编码字段中添加详细信息，然后点击搜索按钮来搜索您的订单。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Tue, 04 Jul 2023 06:30:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何删除 Magento 2 中的货币切换器]]></title>
      <link>https://www.360magento.com/blog/remove-currency-switcher-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Remove_Currency_Switcher_in_Magento_2">在 Magento 2 中删除货币切换器的步骤：</span></h2>
<p><span>第1步：</span><span>转到以下路径</span></p>
<p><span>app/design/frontend/Themes/Yourtheme/Magento_Theme/layout/default.xml</span></p>
<p><span><span>并添加以下代码：</span></span></p>
<p>&lt;?xml version="1.0"?&gt;</p>
<p>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;body&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="currency" remove="true" /&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceBlock name="store.settings.currency" remove="true" /&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;/body&gt;</p>
<p>&lt;/page&gt;</p>
<p></p>
<p><span>注意：</span><span>如果您已经有名为&ldquo;default.xml&rdquo;的文件，您只需在 &lt;/body&gt; 标记结束前添加以下两行。</span></p>
<p><span></span></p>
<p><span><span>第 2 步：</span><span>运行以下命令刷新缓存。</span></span></p>
<p><span>php bin/magento cache:flush</span></p>]]></description>
      <pubDate>Mon, 03 Jul 2023 08:36:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中向类别页面添加静态块的指南]]></title>
      <link>https://www.360magento.com/blog/add-static-block-to-category-page-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Static_Block_to_Category_Page_in_Magento_2">在 Magento 2 中将静态块添加到类别页面的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理仪表板导航到</span><span>内容 &gt; 类别</span></p>
<p><span>第 2 步：</span><span>选择</span><span>要添加静态块的</span><span>类别。</span><span><span></span></span></p>
<p><span>第 3 步：</span><span>放大</span><span>内容部分，并从下拉列表中选择您要在</span><span><span>添加 CMS 块字段</span></span><span>中添加的块</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_1-2_1_.png" /></span></p>
<p><span><span>第 4 步：</span><span>现在，展开</span><span>显示设置</span><span>部分并将</span><span>显示模式设置</span><span>为静态块和产品。</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/Config_2-2_1_.png" /></span></span></p>
<p></p>
<p><span>第 5 步：</span><span>点击</span><span>保存</span><span>，在店面勾选分类。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_3.jpg" /></span></p>]]></description>
      <pubDate>Sun, 02 Jul 2023 08:30:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置默认​​页面]]></title>
      <link>https://www.360magento.com/blog/configure-default-page-in-magento-2/</link>
      <description><![CDATA[<p>基本上，每个在线商店的默认页面都可以在商店的基本 URL 的帮助下访问。当任何用户访问您的商店时，将直接显示默认页面，而不是您网站上的任何其他页面。主要是，当出现诸如&ldquo;找不到页面&rdquo;之类的错误时，将显示默认页面。也可以将主页保留为默认页面。</p>
<p>在 Magento 2 中配置默认​​页面的步骤：<br />第 1 步：导航至Stores&gt;Configuration并选择General选项下方的WEB 。</p>
<p>探索默认页面选项卡并继续进行以下配置：</p>
<p>默认 Web URL：添加默认值 cms 或根据您的要求添加其他值。</p>
<p>CMS主页：管理员必须选择您需要的页面成为您的主页，您应该选择&ldquo;主页&rdquo;</p>
<p>默认无路由 URL：管理员可以设置默认值，即&ldquo;cms/index/noRoute&rdquo;，或者您可以根据需要添加。</p>
<p>CMS No Route Page：选择 404 Page Not Found 值，在显示 404 pages not found 错误时显示 CMS 页面。</p>
<p>CMS 无 Cookie 页面：当浏览器中未启用 cookie 时，管理员需要从下拉列表中选择启用 Cookie 以显示 CMS 页面。</p>
<p>显示 CMS 页面的面包屑：如果管理员需要在所有 CMS 页面的顶部显示面包屑，则需要选择&ldquo;是&rdquo;。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/Default_pages.png" /></p>
<p></p>]]></description>
      <pubDate>Sat, 01 Jul 2023 08:26:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建新的 CMS 块]]></title>
      <link>https://www.360magento.com/blog/create-new-cms-block-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_New_CMS_Block_in_Magento_2">在 Magento 2 中创建新 CMS 块的步骤：</span></h2>
<p><span>第 1 步：</span><span>导航到</span><span>内容&gt;元素&gt;块</span></p>
<p><span>按照下面的屏幕截图点击添加新块。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add_new_block.png" /></span></p>
<p><span>第 2 步：</span><span>根据以下说明进行配置。</span></p>
<p><span>块标题：</span><span>根据需要为新块添加标题。&nbsp;</span></p>
<p><span>标识符：</span><span>选择一个唯一的标识符，并确保使用小写字符和下划线而不是空格。</span></p>
<p><span>Store View：</span><span>选择您需要显示的区块所在的Store View。</span></p>
<p><span>状态：</span><span>启用按钮以在您的 Magento 2 商店中显示块。</span></p>
<p><span>内容：</span><span>根据您的愿望和要求添加内容。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config.png" /></span></p>]]></description>
      <pubDate>Fri, 30 Jun 2023 08:21:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中将产品属性添加到销售规则条件]]></title>
      <link>https://www.360magento.com/blog/how-to-add-product-attribute-to-sales-rules-conditions-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Product_Attribute_to_Sales_Rules_Conditions_in_Magento_2">在 Magento 2 中将产品属性添加到销售规则条件的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录管理面板并转到</span><span>Stores &gt; Attributes &gt; Product</span></p>
<p><span>第 2 步：</span><span>选择您想要的产品属性。</span><span><span><span>然后，从左侧面板</span></span><span><span>转到</span></span></span><span>Storefront Properties并将</span><span><span><span>Yes设置</span></span><span><span>为</span></span><span><span>Use for Promo Rule Conditions&nbsp;</span></span><span><span>。</span></span><span><span>最后，</span></span><span><span>保存属性</span></span><span><span>。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span><span><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/Config_1-2.png" /></span></span></span></p>
<p><span>第 3 步：</span><span>现在，导航至</span><span>&ldquo;营销&rdquo;&gt;&ldquo;促销&rdquo;&gt;&ldquo;购物车价格规则&rdquo;</span></p>
<p><span>第 4 步：</span><span><span><span>选择您想要的购物车价格规则。</span><span>展开</span></span></span><span>条件</span><span><span><span>选项。</span><span>现在，根据要求添加条件并单击保存。</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/Config_2-2.png" /></span></span></span></p>]]></description>
      <pubDate>Thu, 29 Jun 2023 08:18:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中上传产品图片占位符]]></title>
      <link>https://www.360magento.com/blog/how-to-upload-product-image-placeholder-in-magento/</link>
      <description><![CDATA[<p><span><span><span>Magento 2 中的产品图片占位符是实际图片的临时图片。</span><span>它用于短时间显示产品图像，直到显示该产品的实际图像。</span></span></span></p>
<p><span><span><span>默认情况下，Magento 会显示其徽标，但我们也可以上传自定义产品图片占位符。</span><span>Magento 占位符图像显示如下：</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_image.png" /></span></p>
<p><span>要在 Magento 2 中上传产品图片占位符，请按照以下步骤操作。</span></p>
<h2><span id="Steps_to_Upload_Product_Image_Placeholder_in_Magento_2">在 Magento 2 中上传产品图片占位符的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理面板转到</span><span>商店 &gt; 设置 &gt; 配置</span></p>
<p><span>第 2 步：</span><span>现在，从左侧面板中选择</span><span>目录 &gt; 目录</span><span>。</span></p>
<p><span>第 3 步：</span><span>然后，展开</span><span>产品图片占位符</span><span><span><span>部分。</span><span>单击</span></span></span><span>选择文件</span><span>为每个图像角色上传产品图像占位符 - 基本、小、色板和缩略图。</span></p>
<p><span>&nbsp;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Frontend_page.png" /></span></p>]]></description>
      <pubDate>Wed, 28 Jun 2023 08:15:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中为产品图片添加水印]]></title>
      <link>https://www.360magento.com/blog/add-watermarks-to-product-images-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Watermarks_to_Product_Images_in_Magento_2">在 Magento 2 中为产品图片添加水印的步骤：</span></h2>
<p><span>第 1 步：</span><span>从</span><span>Admin Dashboard</span><span>导航到</span><span>Content &gt; Design &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：选择您想要的主题并在</span><span><span>编辑模式</span></span><span>下打开它</span><span>。</span><span><span></span></span><span><span></span></span></p>
<p><span>第 3 步：</span><span>展开</span><span>产品图片水印</span><span>选项。</span></p>
<p><span>第 4 步：</span><span>完成基本图像的以下选项</span></p>
<ul>
<li><span>图像</span><span>&ndash; 上传要显示为水印的图像。</span></li>
<li><span>图像不透明度</span><span>&ndash; 以百分比形式设置图像的不透明度。</span></li>
<li><span>图像大小</span><span>&ndash; 以像素为单位设置图像的大小。</span></li>
<li><span>图像位置</span><span>&ndash; 从可用选项中选择水印图像的位置。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/watermark_base_magento_2.png" /></span></p>
<p></p>
<p><span>完成缩略图图像的配置。</span></p>
<p><span></span></p>
<p><span><span>第 5 步：</span><span>完成后，点击</span><span>保存配置</span><span><span><span>。</span><span>转到缓存管理并</span></span></span><span>刷新缓存</span><span>。</span></span></p>]]></description>
      <pubDate>Tue, 27 Jun 2023 08:10:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中将自定义通知添加到页面顶部]]></title>
      <link>https://www.360magento.com/blog/add-custom-notice-to-page-top-in-magento/</link>
      <description><![CDATA[<p><span><span><span>Magento 店主一直在寻找吸引顾客注意力的方法。</span><span>最好的方法之一是在您网站的每个页面的顶部显示一个通知栏。</span><span>商店商家用它来显示优惠、折扣、新产品发布等。顶部的通知栏可以轻松吸引访问您商店的任何人的注意力。</span></span></span></p>
<p><span><span><span>Magento 提供在网站页面顶部显示自定义通知栏的功能。</span><span>店主可以完全控制自定义通知的外观。</span><span>这有助于在不影响用户体验的情况下提高商店收入。</span><span>让我们看看如何在 Magento 2 中将自定义通知添加到页面顶部的步骤。&nbsp;</span></span></span></p>
<h2><span id="Steps_to_Add_Custom_Notice_to_Page_Top_in_Magento_2">在 Magento 2 中将自定义通知添加到页面顶部的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录 Admin Dashboard 并导航至</span><span>Content &gt; Elements &gt; Blocks&nbsp;</span><span>，然后单击</span><span>Add New Block&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span>填写新区块的信息</span></p>
<p><span>块标题</span><span>- 输入块的标题。</span><br /><span>标识符</span><span>&mdash;&mdash;输入用于识别块的值。</span><br /><span>商店视图</span><span>&mdash;&mdash;选择块的商店视图。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/add_new_block_magento_2.png" /></span></p>
<p><span>在编辑器中输入下面提到的代码，以在 Magento 2 的页面顶部显示自定义通知。但是，您可以根据需要更改代码。</span></p>
<p>&lt;div class="main"&gt;</p>
<p>&lt;div class="demonotice" style="text-align: center; background: orange; padding: 10px; font-size: 20px; font-family: forte;"&gt;&amp;nbsp;New Year Sale Live Now! Get upto 60% Discount&lt;/div&gt;</p>
<p>&lt;/div&gt;</p>
<p></p>
<p><span>最后，点击</span><span>保存</span><span>。</span></p>
<p><span>第 3 步：</span><span>导航到</span><span>&ldquo;内容&rdquo;&gt;&ldquo;元素&rdquo;&gt;&ldquo;小部件&rdquo;&nbsp;</span><span>，然后单击</span><span>&ldquo;添加小部件&rdquo;&nbsp;</span><span>。</span></p>
<p><span>第 4 步：</span><span><span><span>在</span></span><span><span>类型字段中</span></span></span><span>选择</span><span>CMS 静态块</span><span><span><span>。</span></span><span><span>选择</span></span><span><span>设计主题</span></span><span><span>为</span></span><span><span>Magento Luma&nbsp;</span></span><span><span>。</span></span><span><span>然后点击</span></span><span><span>继续</span></span><span><span>。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/add_widget_magento_2.png" /></span></p>
<p><span>第 5 步：</span><span>填写店面属性部分中的信息</span></p>
<p><span>小部件标题</span><span>- 输入小部件的标题。</span><br /><span>分配给商店视图</span><span>&ndash; 选择商店视图以显示小部件。</span><br /><span>排序顺序</span><span>&ndash; 输入小部件的排序顺序值。</span></p>
<p><span>&nbsp;</span><img src="https://www.360magento.com/media/wysiwyg/widget_settings_magento_2.png" /></p>
<p><span>第 6 步：</span><span>然后在 Layout Updates 部分中，选择</span><span>Add Layout Update&nbsp;</span><span>。</span><span><span><span>在</span></span><span><span>Display On字段中</span></span><span><span>选择</span></span></span><span>All Pages</span><span><span><span>和</span></span><span><span>Page Top&nbsp;</span></span><span><span>as&nbsp;</span></span><span><span>Container&nbsp;</span></span><span><span>。</span></span><span><span>然后点击</span></span><span><span>保存</span></span><span><span>。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/layout_update_magento_2.png" /></span></p>
<p><span>第 7 步：</span><span>在 Widget Options 中，选择</span><span><span>您创建的</span></span><span>Block ，然后单击</span><span><span><span>Save&nbsp;</span></span><span><span>。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/widget_options_magento_2.png" /></span></p>
<p><span>就是这样！</span><span>在 Magento 2 Frontend 中检查结果。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/cutom_notice_frontend_magento_2.png" /></span></p>]]></description>
      <pubDate>Mon, 26 Jun 2023 08:03:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 的登录页面添加自定义消息]]></title>
      <link>https://www.360magento.com/blog/add-custom-message-to-login-page-in-magento/</link>
      <description><![CDATA[<p><span>在 Magento 2 中将自定义消息添加到登录页面的步骤：</span></p>
<p><span>第 1 步：</span><span>从 Admin Dashboard 转到</span><span>Content &gt; Elements &gt; Blocks&nbsp;</span><span><span><span>。</span><span>单击</span></span></span><span>添加新块</span><span>。</span></p>
<p><span>第 2 步：</span><span>填写详细信息</span></p>
<p><span>块标题</span><span>- 输入块的标题&nbsp;</span></p>
<p><span>标识符</span><span>&mdash;&mdash;提及块的标识符</span></p>
<p><span>商店视图</span><span>&mdash;&mdash;选择商店视图以显示块</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Custom-Message-to-Login-Page-in-Magento-2.png" /></span></p>
<p></p>
<p><span>输入以下代码。</span><span>您可以根据需要更改代码。</span></p>
<p><span><span class="crayon-o">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"message info"</span><span class="crayon-o">&gt;</span></span></p>
<p><span><span class="crayon-o"></span></span><span class="crayon-o">&lt;</span><span class="crayon-v">p</span><span class="crayon-o">&gt;</span><span class="crayon-o">&lt;</span><span class="crayon-v">strong</span><span class="crayon-o">&gt;</span><span class="crayon-e">Welcome </span><span class="crayon-st">to</span><span class="crayon-h"> </span><span class="crayon-v">MageComp</span><span class="crayon-o">!</span><span class="crayon-h"> </span><span class="crayon-e">Please </span><span class="crayon-e">login </span><span class="crayon-st">to</span><span class="crayon-h"> </span><span class="crayon-st">continue</span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">strong</span><span class="crayon-o">&gt;</span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">p</span><span class="crayon-o">&gt;</span></p>
<div class="crayon-line" id="urvanov-syntax-highlighter-6484c5c196370065414572-5"><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">div</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line"><span class="crayon-o"></span></div>
<div class="crayon-line">
<p><span>最后，点击</span><span>保存</span><span>。</span></p>
<p><span>第 3 步：</span><span>现在，导航至</span><span>Content &gt; Elements &gt; Widgets&nbsp;</span><span><span><span>。</span><span>单击</span></span></span><span>添加小部件</span><span>。</span></p>
<p><span>第 4 步：</span><span>&nbsp;填写详细信息</span></p>
<p><span>类型</span><span>&mdash;&mdash;选择 CMS 静态块</span></p>
<p><span>设计主题</span><span>&mdash;&mdash;选择Magento Luma</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Select-Magento-Luma.png" /></span></p>
<p></p>
<p><span>然后点击</span><span>继续</span></p>
<p><span>第 5 步：</span><span>在店面属性部分下填写详细信息</span></p>
<p><span>小部件标题</span><span>- 给出小部件的标题</span></p>
<p><span>分配给商店视图</span><span>&mdash;&mdash;选择商店视图</span></p>
<p><span>排序顺序</span><span>&mdash;&mdash;设置小部件的顺序</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Set-the-order-of-the-widget.png" /></span></p>
<p></p>
<p><span>第 6 步：</span>&nbsp;<span>填写布局更新部分下的详细信息，</span><span>&nbsp;</span><span><span></span></span></p>
<p><span>显示在</span><span>&ndash; 选择指定页面选项</span></p>
<p><span>页面</span><span>- 选择自定义帐户登录表单</span></p>
<p><span>容器</span><span>&ndash; 根据您的要求设置</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Set-as-per-your-requirement.png" /></span></p>
<p></p>
<p><span>第 7 步：</span><span>从 Widget Options 选项卡中，选择</span><span>您之前创建的</span><span>Block 。</span><span><span></span></span></p>
<p><span>最后，点击</span><span>保存</span><span>。</span></p>
<p><span><span><span>就是这样！</span><span>开始了 -</span></span></span><span>&nbsp;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Output.png" /></span></p>
</div>]]></description>
      <pubDate>Sun, 25 Jun 2023 08:58:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用/禁用演示商店通知]]></title>
      <link>https://www.360magento.com/blog/enable-disable-demo-store-notice-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_EnableDisable_Demo_Store_Notice_in_Magento_2">在 Magento 2 中启用/禁用演示商店通知的步骤：</span></h2>
<p><span>第 1 步：</span><span>从</span><span>Admin Dashboard</span><span>转到</span><span>Content &gt; Configuration &gt; Design&nbsp;</span><span>。</span></p>
<p><span>第二步：找到要配置的store view，在</span><span><span>Edit模式</span></span><span>下打开</span><span>。</span><span><span></span></span><span><span></span></span></p>
<p><span>第 3 步：在</span><span><span>Other Settings选项</span></span><span>下</span><span><span><span>，展开</span></span><span><span>HTML Head&nbsp;</span></span><span><span>。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第 4 步：</span><span>找到</span><span>Display Demo Store Notice</span><span>字段并将其设置为</span><span>Yes&nbsp;</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/demo-store-notice-config.png" /></span></p>
<p></p>
<p><span>然后单击</span><span>保存配置</span><span><span><span>并清除 Magento 缓存。</span><span>现在，检查商店前端，演示通知将显示如下：</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/demo-store-notice-1.png" /></span></p>]]></description>
      <pubDate>Sat, 24 Jun 2023 07:56:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中为客户设置密码选项]]></title>
      <link>https://www.360magento.com/blog/set-password-options-for-customers-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Set_Password_Options_for_Customers_in_Magento_2">在 Magento 2 中为客户设置密码选项的步骤：</span></h2>
<p><span>导航到</span><span>Stores &gt; Settings &gt; Configuration ，然后在</span><span><span>Customers 选项</span></span><span>下</span><span><span><span>选择</span></span><span><span>Customer Configuration</span></span><span><span>选项。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>探索</span><span>密码选项选项</span><span>卡，</span></p>
<p><span>忘记电子邮件模板：</span><span>根据您希望发送给客户的模板选择模板，以防他们忘记帐户密码。</span></p>
<p><span>提醒电子邮件模板：</span><span>选择用于将其帐户密码的密码提示共享给您的客户的模板。</span></p>
<p><span>重置密码模板：</span><span>根据您向商店客户发送的愿望选择模板，其中包含重置密码的链接。</span></p>
<p><span>密码模板 电子邮件发件人：</span><span>选择发送忘记和提醒电子邮件通知时将显示的电子邮件发件人姓名。</span></p>
<p><span>恢复链接有效期（小时）：</span><span>管理员可以从这里轻松设置密码恢复/重置链接的有效期。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Config_reset_password.png" /></span></p>]]></description>
      <pubDate>Fri, 23 Jun 2023 07:54:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加搜索词]]></title>
      <link>https://www.360magento.com/blog/add-search-terms-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Search_Terms_in_Magento_2">在 Magento 2 中添加搜索词的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到管理员帐户，然后导航至</span><span>营销 &gt; 搜索引擎优化和搜索 &gt; 搜索词</span><span>。</span></p>
<p><span>第 2 步：</span><span>现在，单击</span><span>&ldquo;添加新搜索词&rdquo;</span><span>并添加详细信息</span></p>
<ul>
<li><span>搜索查询</span><span>&ndash; 输入要添加到列表中的搜索查询词。</span></li>
<li><span>商店</span><span>&ndash; 如果您有多家商店，请选择商店以添加搜索词。</span></li>
<li><span>重定向 URL&nbsp;</span><span>&ndash; 当用户输入搜索查询时，输入 URL 以将客户重定向到登陆页面或产品页面，或任何类别页面。</span></li>
<li><span>在建议的术语中显示</span><span>- 当任何搜索未返回结果时，选择是将其设置为建议的术语。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/search-term.png" /></span></p>
<p></p>
<p><span>第 3 步：</span><span>最后，点击</span><span>保存搜索</span><span>。</span></p>
<h2><span id="How_to_Edit_Search_Term_in_Magento_2">如何在 Magento 2 中编辑搜索词？</span></h2>
<ul>
<li><span>从搜索词网格中，选择您要修改的词并在</span><span>编辑</span><span>模式下将其打开。</span></li>
<li><span>进行适当的更改。</span></li>
<li><span>最后，</span><span>保存搜索</span><span>。</span></li>
</ul>
<h2><span id="How_to_Delete_Search_Term_in_Magento_2">如何删除 Magento 2 中的搜索词？</span></h2>
<ul>
<li><span>从搜索词网格中，选择要删除的词。</span></li>
<li><span>从</span><span>&ldquo;操作&rdquo;</span><span>选项卡中选择</span><span>&ldquo;删除&rdquo;&nbsp;</span><span>。</span></li>
<li><span>最后，</span><span>提交</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/delete-search-term.png" /></span></p>]]></description>
      <pubDate>Thu, 22 Jun 2023 07:52:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[加速您的 Magento 2 商店的 7 个行之有效的步骤]]></title>
      <link>https://www.360magento.com/blog/speed-up-your-magento-2-store/</link>
      <description><![CDATA[<h2><span id="7_Proven_Steps_to_Speed_up_Your_Magento_2_Store">加速您的 Magento 2 商店的 7 个行之有效的步骤</span></h2>
<h3><span id="1_Install_CDN_Content_Delivery_Network"><span><span><span>1.安装CDN（内容分发网络）</span></span></span><span></span></span></h3>
<p><span><span><span>内容交付网络是一种允许存储文件和页面的程序。</span><span>使用CDN，可以大大提高页面加载速度。</span><span>通过为您的 Magento 2 商店设置 CDN，CSS 文件、图像、Javascripts 文件可以更快地交付给用户。</span></span></span></p>
<p><span><span><span>由于 Magento 默认支持 CDN，因此您无需为其安装任何第三方扩展。</span><span>以下是为 Magento 2 商店设置 CDN 的步骤。</span></span></span></p>
<ul>
<li><span>从 Magento 管理面板，转到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>接下来，展开</span><span>General</span><span>选项卡并选择</span><span>Web&nbsp;</span><span>。</span></li>
<li><span>现在，扩大</span><span>Base URLs (Secure)</span><span>选项并配置 URL 详细信息。</span></li>
</ul>
<h3><span id="2_Enable_Varnish_Cache"><span><span><span>2.启用Varnish&nbsp;缓存</span></span></span><span></span></span></h3>
<p><span><span><span>最小化服务器负载有助于提高网站速度。</span><span>缓存可以帮助您实现这一点。</span><span>启用清漆缓存可以使您的 Magento 2 存储速度更快。</span></span></span></p>
<p><span>以下是为 Magento 2 商店启用 Varnish Cache 的步骤。</span></p>
<ul>
<li><span>从 Magento 管理面板，转到</span><span>System &gt; Tools &gt; Cache Management&nbsp;</span><span>。</span></li>
<li><span>选择所有</span><span>字段并</span><span>提交</span><span>。</span></li>
</ul>
<h3><span id="3_Merge_and_Minify_JSCSS"><span><span><span>3. 合并和缩小 JS/CSS</span></span></span><span></span></span></h3>
<p><span><span><span>JavaScript 和 CSS 文件是导致 Magento 2 商店加载速度慢的另一个原因。</span><span>Magento 2 提供合并和缩小 JS 和 CSS 文件以增强您的 Magento 商店性能。</span></span></span></p>
<p><span>合并和缩小 JS：</span></p>
<ul>
<li><span>在管理面板中，转到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>展开</span><span>高级</span><span>并选择</span><span>开发人员</span><span>。</span></li>
<li><span>现在，扩大</span><span>JavaScript 设置</span><span>选项。</span></li>
<li><span>启用</span><span>合并 JavaScript 文件</span><span>和</span><span>缩小 JavaScript 文件</span><span>。</span></li>
</ul>
<p><span>合并和缩小 CSS：</span></p>
<ul>
<li><span>在管理面板中，转到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>展开</span><span>高级</span><span>并选择</span><span>开发人员</span><span>。</span></li>
<li><span>现在，扩大</span><span>CSS 设置</span><span>选项。</span></li>
<li><span>启用</span><span>合并 CSS 文件</span><span>和</span><span>缩小 CSS 文件</span><span>。</span></li>
</ul>
<p></p>
<p>4.升级到最新版本的Magento 2<br />不可忽视的方法之一是优化您的 Magento 2 存储速度，即更新到最新版本。高级功能和增强的安全性可以加快 Magento 2 商店的性能。强烈建议升级到最新的 Magento 2 版本以提高商店的速度。利用Magento 年度升级服务，让您的 Magento 2 商店升级过程毫无压力。</p>
<p></p>
<p>5.启用平面类别和产品<br />您的商店中有大量产品，数据库需要很长时间才能读取。这会减慢您的 Magento 2 存储速度。要解决此问题，您可以启用 Flat Category and Product 选项。</p>
<p>以下是启用平面类别和产品的步骤</p>
<p>在管理面板中，转到Stores &gt; Settings &gt; Configuration 。<br />展开目录并选择目录。<br />放大店面选项。<br />启用使用平面目录类别和使用平面目录产品字段。</p>
<p>6. 禁用 JavaScript 捆绑<br />如果启用了 HTTP/2，JavaScript 捆绑就没有用了。JS 捆绑的规模很大，可能会对您的 Magento 2 商店的速度产生不利影响。以下是禁用 JavaScript 捆绑的步骤。</p>
<p>在管理面板中，转到Stores &gt; Settings &gt; Configuration 。<br />展开高级并选择开发人员。<br />现在，扩大JavaScript 设置选项。<br />将Enable JavaScript Bundling字段设置为No 。</p>
<p></p>
<p>7.优化图片<br />很明显，您的网站上有很多产品图片。大尺寸图像需要更长的时间来加载，从而降低网站性能。因此，有必要对图像进行适当的优化。压缩图像将有助于提高 Magento 2 商店的速度。在将图像上传到您的站点之前，使用优化工具压缩图像。</p>]]></description>
      <pubDate>Wed, 21 Jun 2023 06:42:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 HTML 标签中添加自定义代码]]></title>
      <link>https://www.360magento.com/blog/add-custom-code-in-magento-2-head-html/</link>
      <description><![CDATA[<p><span><span><span>在 Magento 2 &lt;head&gt; HTML 标签中添加自定义代码的</span></span><span><span>步骤：</span></span></span><span><span></span></span></p>
<p><span>第 1 步：</span><span>转到 Magento 管理面板并导航到内容 &gt; 设计 &gt; 配置。</span></p>
<p><span>第 2 步：</span><span>选择商店视图以更改标题标签或选择全局以更改每个商店视图的标题标签。</span></p>
<p><span>第 3 步：</span><span>放大</span><span>HTML 标题</span><span><span><span>部分。</span><span>将您的自定义代码添加到</span></span></span><span>脚本和样式表</span><span>字段。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Add-Code-in-Head-Tag.png" /></span></p>
<p><span><span>第 4 步：</span><span>最后，</span><span>保存配置</span><span><span><span>。</span><span>转到缓存管理和</span></span></span><span>刷新 Magento 缓存</span><span>。</span></span></p>]]></description>
      <pubDate>Tue, 20 Jun 2023 08:39:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中以编程方式创建可配置产品]]></title>
      <link>https://www.360magento.com/blog/create-configurable-product-programmatically-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_create_configurable_product_programmatically_in_Magento_2">在 Magento 2 中以编程方式创建可配置产品的步骤：</span></h2>
<p><span><span><span><span>第一步：</span></span></span><span><span>首先在Magento根目录下创建一个</span></span><span><span><span>configurable_product.php</span></span></span><span><span>文件，添加如下代码</span></span></span></p>
<p></p>
<pre>&lt;?php
use Magento\Framework\AppInterface;
try {
    require_once __DIR__ . '/app/bootstrap.php';
} catch (\Exception $e) {
    echo 'Autoload error: ' . $e-&gt;getMessage();
    exit(1);
}
try {
    $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
    $objectManager = $bootstrap-&gt;getObjectManager();
    $appState = $objectManager-&gt;get('Magento\Framework\App\State');
    $appState-&gt;setAreaCode('frontend');

    $configurableproduct = $objectManager-&gt;create('Magento\Catalog\Model\Product');
    $configurableproduct-&gt;setSku("configurable_sku"); // set Your SKU
    $configurableproduct-&gt;setName("Configurable Name"); // set Your Configurable Name
    $configurableproduct-&gt;setAttributeSetId(4); // set attribute id
    $configurableproduct-&gt;setStatus(1); // status enabled/disabled 1/0
    $configurableproduct-&gt;setTypeId('configurable'); // type of product (simple/virtual/downloadable/configurable)
    $configurableproduct-&gt;setVisibility(4);  // visibility of product (Not Visible Individually (1) / Catalog (2)/ Search (3)/ Catalog, Search(4))
    $configurableproduct-&gt;setPrice(0);
    $configurableproduct-&gt;setTaxClassId(0); // Tax class ID
    $configurableproduct-&gt;setWebsiteIds(array(1)); // set website Id
    $category_id = array(2, 3);
    $configurableproduct-&gt;setCategoryIds($category_id);
    $configurableproduct-&gt;setStockData(array(
            'use_config_manage_stock' =&gt; 0,
            'manage_stock' =&gt; 1,
            'is_in_stock' =&gt; 1,
        )
    );
    $configurableattributesdata = $configurableproduct-&gt;getTypeInstance()-&gt;getConfigurableAttributesAsArray($configurableproduct);
    $configurableproduct-&gt;setCanSaveConfigurableAttributes(true);
    $configurableproduct-&gt;setConfigurableAttributesData($configurableattributesdata);
    $configurableproductsdata = array();
    $configurableproduct-&gt;setConfigurableProductsData($configurableproductsdata);
    try {
        $configurableproduct-&gt;save();
    } catch (Exception $ex) {
        echo '</pre>
<pre>';
        print_r($ex-&gt;getMessage());
        exit(1);
    }
    $product_id = $configurableproduct-&gt;getId();
    $associatedproductids = array(1,9);
    try {
        $configurableproduct_load = $objectManager-&gt;create('Magento\Catalog\Model\Product')-&gt;load($product_id);
        $configurableproduct_load-&gt;setAssociatedProductIds($associatedproductids);
        $configurableproduct_load-&gt;setCanSaveConfigurableAttributes(true);
        $configurableproduct_load-&gt;save();
        echo "configurable product save successfully";
    } catch (Exception $e) {
        echo "</pre>
<pre>";
        print_r($e-&gt;getMessage());
        exit(1);
    }
}catch (Exception $e) {
    echo "</pre>
<pre>";
    print_r($e-&gt;getMessage());
    exit(1);
}
</pre>
<pre><span>第 2 步：</span><span>完成上述步骤后，您需要运行下面给出的 URL 来创建可配置的产品。</span><br />https://yourdomain.com/configurable_product.php</pre>]]></description>
      <pubDate>Mon, 19 Jun 2023 07:36:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中以编程方式创建简单产品]]></title>
      <link>https://www.360magento.com/blog/create-simple-product-programmatically-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_Simple_Product_Programmatically_in_Magento_2">在 Magento 2 中以编程方式创建简单产品的步骤：</span></h2>
<p><span>第 1 步：首先，</span><span>在 Magento 根目录中</span><span>创建一个</span><span>simple_product.php文件并添加以下给定代码。</span></p>
<pre>&lt;?php

use Magento\Framework\AppInterface;

try {

&nbsp;&nbsp;&nbsp;&nbsp;require_once __DIR__ . '/app/bootstrap.php';

} catch (\Exception $e) {

&nbsp;&nbsp;&nbsp;&nbsp;echo 'Autoload error: ' . $e-&gt;getMessage();

&nbsp;&nbsp;&nbsp;&nbsp;exit(1);

}

try{

$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);

$objectManager = $bootstrap-&gt;getObjectManager();


$appState = $objectManager-&gt;get('Magento\Framework\App\State');

$appState-&gt;setAreaCode('frontend');


$product = $objectManager-&gt;create('Magento\Catalog\Model\Product');

$sku = 'your_sku';&nbsp; // set your sku

$product-&gt;setSku($sku);

$product-&gt;setName('Simple Product Name'); // set your Product Name of Product

$product-&gt;setAttributeSetId(4); // set attribute id

$product-&gt;setStatus(1); // status enabled/disabled 1/0

$product-&gt;setWeight(1); // set weight of product

$product-&gt;setVisibility(4); // visibility of product (Not Visible Individually (1) / Catalog (2)/ Search (3)/ Catalog, Search(4))

$product-&gt;setWebsiteIds(array(1));

$product-&gt;setTaxClassId(0); // Tax class ID

$product-&gt;setTypeId('simple'); // type of product (simple/virtual/downloadable/configurable)

$product-&gt;setPrice(100); // set price of product

$product-&gt;setStockData(

      array(

      'use_config_manage_stock' =&gt; 0,

      'manage_stock' =&gt; 1,

      'is_in_stock' =&gt; 1,

      'qty' =&gt; 100
      )
    );

$product-&gt;save();

$categoryIds = array('2','3'); // assign your product to category using Category Id

&nbsp;&nbsp;&nbsp;&nbsp;$category = $objectManager-&gt;get('Magento\Catalog\Api\CategoryLinkManagementInterface');

$category-&gt;assignProductToCategories($sku, $categoryIds);

echo "$sku Product Created Successfully ";

}

catch(\Exception $e){

print_r($e-&gt;getMessage());

}<br /><br /><br /></pre>
<p>第 2 步：完成上述步骤后，您需要运行下面给出的 URL 来创建一个简单的产品。</p>
<p>https://yourdomain.com/simple_product.php</p>]]></description>
      <pubDate>Sun, 18 Jun 2023 07:32:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中导入和导出客户]]></title>
      <link>https://www.360magento.com/blog/how-to-import-and-export-customers-in-magento/</link>
      <description><![CDATA[<p><span>大多数情况下，对于所有在线商店所有者而言，客户详细信息管理是管理所有订单和改进其商店营销策略的最关键任务之一。&nbsp;</span></p>
<p><span><span><span>如果您正在在线转变您的业务，那么您将需要将所有常规客户的数据导入您的商店。</span><span>为此，Magento 提供了通过将 CSV 文件上传到您的商店来导入数据的选项。&nbsp;</span></span></span></p>
<p><span><span><span>同样，如果您需要检查商店列表或需要新客户列表，那么您只需将其以 excel 文件的形式从您的 Magento 2 商店中导出即可。</span><span>为此，让我们学习如何在 Magento 2 中导入和导出客户</span></span></span></p>
<h2><span id="Steps_to_Import_and_Export_Customers_in_Magento_2">在 Magento 2 中导入和导出客户的步骤：</span></h2>
<h3><span id="Export_Customers_in_Magento_2">在 Magento 2 中导出客户：</span></h3>
<p><span>转到</span><span>系统 &gt; 数据传输 &gt; 导出</span><span>并在</span><span>导出设置下方</span><span>选择</span><span>实体类型中的</span><span>客户主文件</span><span><span></span></span></p>
<p><span>默认情况下，</span><span>导出文件的格式</span><span>为</span><span>CSV&nbsp;</span><span>。</span></p>
<p><span>在</span><span>实体属性中，单击选择您希望从要</span><span><span>导出的</span></span><span>CSV 文件中删除的属性</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/export.png" /></span></p>
<p><span>然后点击</span><span>继续</span><span>按钮。</span></p>
<p><span>您将获得</span><span>包含所有客户信息的</span><span>CSV 文件。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/csv-file.png" /></span></p>
<p></p>
<h3><span id="Import_Customers_in_Magento_2">在 Magento 2 中导入客户：</span></h3>
<p><span><span></span></span><span><span><span>首先，从管理面板侧栏</span></span><span><span>转到</span></span></span><span>系统 &gt; 数据传输 &gt; 导入，然后在实体类型下方选择</span><span><span>客户主文件。</span></span><span><span></span></span><span><span></span></span></p>
<p><span>在行为中选择</span><span>添加/更新复杂数据</span><span>选项&nbsp;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/import.png" /></span></p>
<p><span><span>导航至</span><span>选择要导入的文件</span><span>并上传您的文件。</span></span></p>]]></description>
      <pubDate>Sat, 17 Jun 2023 06:30:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中扩展布局]]></title>
      <link>https://www.360magento.com/blog/extend-a-layout-in-magento/</link>
      <description><![CDATA[<p><span>在这个 Magento 教程中，我将解释如何在 Magento 2 中扩展布局。</span></p>
<p><span><span><span>布局表示网页的结构。</span><span>建议不要更改 Magento 模块和主题布局，以确保稳定性和保护您的自定义设置，以免它们在升级过程中被删除。</span><span>要进行更改，您可以在 Magento 2 的自定义主题中扩展布局文件。与其复制大量页面布局或页面配置代码而不是进行更改，扩展布局文件是一个不错的选择。</span></span></span></p>
<p><span></span></p>
<h2><span id="Steps_to_Extend_a_Layout_in_Magento_2">在 Magento 2 中扩展布局的步骤：</span></h2>
<p><span>第一步：</span><span>创建主题扩展文件&nbsp;</span></p>
<p><span>app/design/frontend/Themes/Yourtheme/Magento_Catalog/layout/catalog_product_view.xml</span></p>
<p><span>到&nbsp;</span></p>
<p><span><span>vendor</span>/magento/module-catalog/view/frontend/layout/catalog_product_view.xml</span></p>
<p><span><span>Example :</span></span></p>
<p></p>
<p><img src="https://www.360magento.com/media/wysiwyg/as42826_2x.png" /></p>]]></description>
      <pubDate>Fri, 16 Jun 2023 06:27:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：如何从命令行刷新缓存和重新索引]]></title>
      <link>https://www.360magento.com/blog/magento-2-flush-cache-and-reindex-from-command-line/</link>
      <description><![CDATA[<h2><span id="How_to_Flush_the_Cache_and_Reindex_from_Command_Line_in_Magento_2">如何从 Magento 2 中的命令行刷新缓存和重新索引？</span></h2>
<p><span>运行以下命令刷新 Magento 缓存存储：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-mac print-yes notranslate" id="urvanov-syntax-highlighter-64865e806160c870635293" data-settings=" minimize scroll-mouseover">
<div class="crayon-toolbar" data-settings=" mouseover overlay hide delay">
<div class="crayon-tools">
<div class="crayon-button urvanov-syntax-highlighter-popup-button" title="Open Code In New Window">
<div class="urvanov-syntax-highlighter-button-icon"></div>
</div>
</div>
</div>
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-64865e806160c870635293-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-64865e806160c870635293-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">cache</span><span class="crayon-o">:</span><span class="crayon-v">clean</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行以下命令刷新 Magento 缓存：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-mac print-yes notranslate" id="urvanov-syntax-highlighter-64865e8061614311524119" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-64865e8061614311524119-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-64865e8061614311524119-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">cache</span><span class="crayon-o">:</span><span class="crayon-v">flush</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行以下命令重新索引 Magento 站点：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-mac print-yes notranslate" id="urvanov-syntax-highlighter-64865e8061616313747032" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-64865e8061616313747032-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-64865e8061616313747032-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-v">reindex</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>运行以下命令以重新索引特定 ID：</span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-mac print-yes notranslate" id="urvanov-syntax-highlighter-64865e8061617231190475" data-settings=" minimize scroll-mouseover">
<div class="urvanov-syntax-highlighter-plain-wrap"></div>
<div class="urvanov-syntax-highlighter-main">
<table class="crayon-table">
<tbody>
<tr class="urvanov-syntax-highlighter-row">
<td class="crayon-nums " data-settings="show">
<div class="urvanov-syntax-highlighter-nums-content">
<div class="crayon-num" data-line="urvanov-syntax-highlighter-64865e8061617231190475-1">1</div>
</div>
</td>
<td class="urvanov-syntax-highlighter-code">
<div class="crayon-pre">
<div class="crayon-line" id="urvanov-syntax-highlighter-64865e8061617231190475-1"><span class="crayon-e">php </span><span class="crayon-v">bin</span><span class="crayon-o">/</span><span class="crayon-e">magento </span><span class="crayon-v">indexer</span><span class="crayon-o">:</span><span class="crayon-e">reindex </span><span class="crayon-v">catalog_category_product</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>]]></description>
      <pubDate>Thu, 15 Jun 2023 06:24:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加顶部链接]]></title>
      <link>https://www.360magento.com/blog/add-top-link-in-magento/</link>
      <description><![CDATA[<p><span>今天的学习模块将学习如何在 Magento 2 中显示模板 phtml 文件中的 Cms 静态块。所以，不浪费时间，让我们开始吧。</span></p>
<p><span><span><span>您网站的页眉可能是显示重要链接和页面的最佳位置。</span><span>一些链接已经存储在 Magento 2 中，但在您的 Magento 2 网站的首页添加顶部链接会显示一些有用的链接。</span><span>标题链接和顶部链接之间的主要区别在于，</span></span></span></p>
<p><span><span><span>&nbsp;Magento 2 标题链接显示访客和登录客户。</span><span>但顶部链接仅显示已登录的客户。</span></span></span></p>
<p><span>建立顶级链接还有助于鼓励客户购买越来越多的愿望。</span></p>
<p></p>
<h2><span id="How_to_Add_Top_Link_in_Magento_2">如何在 Magento 2 中添加顶部链接</span></h2>
<p><span>第一步：</span><span>在路径下&nbsp;</span><span>创建</span><span>default.xml文件。</span><span><span></span></span></p>
<p><span>app\code\Vendor\Extension\view\frontend\layout\default.xml</span></p>
<p><span>并粘贴下面的代码&nbsp;&nbsp;</span></p>
<p>&lt;?xml version="1.0"?&gt;<br />&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;<br />&lt;body&gt;<br />&lt;referenceBlock name="header.links"&gt;<br />&lt;block class="Magento\Framework\View\Element\Html\Link" name="custom-top-link"&gt;<br /> &lt;arguments&gt;<br /> &lt;argument name="label" xsi:type="string" translate="true"&gt;Custom Top Link Label&lt;/argument&gt;<br /> &lt;argument name="path" xsi:type="string" translate="true"&gt;custom_path&lt;/argument&gt;<br /> &lt;/arguments&gt;<br /> &lt;/block&gt;<br /> &lt;/referenceBlock&gt;<br />&lt;/body&gt;<br />&lt;/page&gt;</p>
<p></p>]]></description>
      <pubDate>Wed, 14 Jun 2023 07:23:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示来自模板 phtml 文件的 Cms 静态块]]></title>
      <link>https://www.360magento.com/blog/cms-static-block-from-template-phtml-file-in-magento/</link>
      <description><![CDATA[<p><span><span><span>CMS 静态块是向消费者显示各种信息的绝佳方式。</span><span>CMS 静态块有助于吸引更多消费者对特定产品的关注，并使您的 Magento 2 商店或网站更具吸引力。</span><span>您几乎可以在 Magento 2 网站和 Magento 2 商店的每个页面上显示 CMS 静态块。</span></span></span></p>
<p><span><span><span>如果您不想在配置 CMS 静态块上花费太多时间，那么您可以在 phtml 中或使用 XML 文件布局调用 CMS 静态块。</span><span>让我们一步一步来</span></span></span><span>。</span></p>
<h2><span id="Steps_to_Show_Cms_Static_Block_From_Template_phtml_File_in_Magento_2"><span><span><span>在 Magento 2 中从模板 phtml 文件显示 Cms 静态块的</span></span><span><span>步骤</span></span></span><span><span></span></span></span></h2>
<p><span><span><span><span>第 1 步：</span></span></span><span><span>在显示静态块时在 phtml 文件中添加以下代码</span></span></span></p>
<pre>        
 echo $this---&gt;getLayout()
        -&gt;createBlock(\Magento\Cms\Block\Block::class)
        -&gt;setBlockId('block_identifier_here')
	-&gt;toHtml();
	//change  block_identifier_here with Your CMS Block Identifier</pre>
<pre><br /><br /><span>第 2 步</span><span>：在您的 CMS 页面中添加以下代码 CMS 静态块。</span><br /><br /></pre>]]></description>
      <pubDate>Tue, 13 Jun 2023 07:20:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用 Canonical 元标记]]></title>
      <link>https://www.360magento.com/blog/enable-canonical-meta-tag-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Enable_Canonical_Meta_Tag_in_Magento_2">在 Magento 2 中启用规范元标记的步骤</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>管理面板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航到</span><span>商店 &gt;</span>&nbsp;<span>设置 &gt; 配置。</span></p>
<p><span>第 3 步：</span><span>单击</span><span><span><span>位于左侧面板中</span></span><span><span>目录部分</span></span><span><span>下的</span></span></span><span>目录。</span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第 4 步：</span><span>展开</span><span>搜索引擎优化</span><span>部分并执行以下操作。</span></p>
<p><a href="https://magecomp.com/blog/wp-content/uploads/2021/06/canonical-tag-configuration-1.png" data-wpel-link="internal"></a></p>
<p><img src="https://www.360magento.com/media/wysiwyg/canonical-tag-configuration-1.png" /></p>
<p></p>
<p><span>现在，看一下最后 2 个字段并根据您的要求从下面提到的执行操作。</span></p>
<ul>
<li><span><span></span></span><span><span><span>如果您希望搜索引擎只记录类别页面而不记录产品页面，请在类别下拉菜单</span></span><span><span>中</span></span><span><span>选择</span></span><span><span>是</span></span><span><span>选项，在</span></span><span><span>产品</span></span><span><span>下拉</span></span></span><span>菜单</span><span>中选择否。</span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></li>
<li><span><span></span></span><span>如果您希望搜索引擎只记录产品页面而不记录类别页面，请在类别下拉菜单中选择否选项并</span><span>在</span><span>产品</span><span>下拉</span><span>菜单</span><span><span><span>中</span></span><span><span>选择</span></span><span><span>是</span></span></span><span>。</span><span><span></span></span><span><span></span></span><span><span></span></span></li>
<li><span>如果您希望类别和产品页面都记录在搜索引擎中，请</span><span>在两个字段中选择</span><span>是。</span><span><span></span></span></li>
</ul>
<p><span>第 5 步：</span><span>完成所需的选择后，单击</span><span>&ldquo;保存配置&rdquo;&nbsp;</span><span>。</span></p>]]></description>
      <pubDate>Mon, 12 Jun 2023 08:10:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 优惠券代码生成指南]]></title>
      <link>https://www.360magento.com/blog/create-coupon-codes-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Methods_to_Create_Coupon_Codes_in_Magento_2">在 Magento 2 中创建优惠券代码的方法：</span></h2>
<h3><span id="Method_1_Create_a_Specific_Coupon">方法 1：创建特定优惠券</span></h3>
<ul>
<li>创建购物车价格规则</li>
<li><span>接下来，转到</span><span>营销 &gt; 促销 &gt; 购物车价格规则</span></li>
<li><span><span></span></span><span>在Rule Information</span><span>下</span><span>，您将看到</span><span>Coupon</span><span>字段，将其设置为</span><span>Specific Coupon&nbsp;</span><span>。</span></li>
<li><span>输入</span><span>优惠券代码</span><span>。</span></li>
<li><span>要设置优惠券使用次数限制，请将其输入</span><span>Uses Per Coupon</span><span>和</span><span>Uses Per Customer&nbsp;</span><span><span><span>。</span><span>为了不受限制地使用，请将这些字段留空。</span></span></span></li>
<li><span><span></span></span><span>在从</span><span>和</span><span>到字段</span><span>中输入优惠券的使用期限</span><span>。</span></li>
<li><span>单击</span><span>保存</span><span>并在前端检查优惠券的工作情况。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/specific-coupon.png" /></span></p>
<p></p>
<h3><span id="Method_2_Create_Bulk_Coupons">方法 2：创建批量优惠券</span></h3>
<ul>
<li>创建购物车价格规则</li>
<li><span>接下来，转到</span><span>营销 &gt; 促销 &gt; 购物车价格规则</span></li>
<li><span>在</span><span>Rule Information下</span><span>，滚动到</span><span>Coupon Code</span><span>字段并勾选</span><span>Use Auto Generation</span><span>复选框。</span></li>
<li><span>要设置优惠券使用次数限制，请将其输入</span><span>Uses Per Customer&nbsp;</span><span><span><span>。</span><span>要无限使用，请将此字段留空。<br /><img src="https://www.360magento.com/media/wysiwyg/auto-generation.png" /><br /></span></span></span></li>
</ul>
<ul>
<li><span>现在，放大</span><span>&ldquo;管理优惠券代码&rdquo;</span><span>选项卡。</span></li>
<li><span>在</span><span>优惠券数量</span><span>字段中，输入要生成的优惠券总数。</span></li>
<li><span>输入</span><span>代码长度</span><span><span><span>。</span><span>它不包括前缀、后缀和分隔符。</span></span></span></li>
<li><span><span></span></span><span>将代码格式</span><span>设置</span><span>为字母数字、字母或数字。</span></li>
<li><span>输入</span><span>添加在代码开头的</span><span>代码前缀。</span><span>该字段是可选的。</span></li>
<li><span>输入</span><span>添加在代码末尾的代码</span><span>后缀。</span><span>该字段是可选的。</span></li>
<li><span>在</span><span>Dash Every X Characters</span><span><span><span>字段中，输入破折号将作为分隔符出现在代码中的数字。</span><span>它使代码更易于阅读。</span><span>例如，如果设置为 4，代码可能看起来像 XXXX-XXXX-XXXX。&nbsp;</span></span></span></li>
<li><span>最后点击</span><span>生成</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/manage-coupon-codes-1_1_.png" /></span></p>]]></description>
      <pubDate>Sun, 11 Jun 2023 08:06:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改域名 ]]></title>
      <link>https://www.360magento.com/blog/change-domain-name-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_Domain_Name_in_Magento_2">在 Magento 2 中更改域名的步骤&nbsp;</span></h2>
<p><span>第 1 步：</span><span><span><span><span>登录</span></span></span><span><span>到您的 Magento 2 网站的管理面板。</span></span></span></p>
<p><span>第 2 步：</span><span>单击</span><span>管理侧栏中的</span><span>Stores &gt; Configuration 。</span></p>
<p><span>第 3 步：</span><span>然后，从导航菜单中转到</span><span>&ldquo;常规&rdquo;&gt;&ldquo;Web&rdquo;</span><span>选项卡。</span></p>
<p><span>第 4 步：</span><span>扩展</span><span>基本 URL</span><span>部分。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Base-URL-2.png" /></span></p>
<p><span>第 5 步：</span><span><span><span>在</span></span><span><span><span>基本 URL</span></span></span><span><span>字段中，将您的新 URL 替换为当前 URL。</span><span>例如，如果您当前的 Magento 2 商店域是 auroracreation.com，并且您希望将其更改为 xyz.com，那么您可以从此处进行更改。</span></span></span></p>
<p><span>第 6 步：</span><span>以同样的方式，扩展</span><span>Base URLs (Secure)部分并更改</span><span><span>Secure Base URL字段</span></span><span>中的域名</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Base-URL-Secure-1-1.png" /></span></p>]]></description>
      <pubDate>Sat, 10 Jun 2023 08:04:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何禁用 Magento 2 的比较产品]]></title>
      <link>https://www.360magento.com/blog/how-to-disable-compare-products-for-magento/</link>
      <description><![CDATA[<h2><span id="What_are_Compare_Products">什么是比较产品？</span></h2>
<p><span><span><span>比较产品功能使我们能够向用户显示类别和特性相似的两种或多种产品的详细信息。</span><span>两个或多个产品彼此相邻放置，以向最终用户展示它们之间的明确隔离。</span><span>这种比较产品的功能是内置的。&nbsp;</span></span></span></p>
<p><span><span><span>因此，如果您有一家销售电器、软件或机器的商店，那么这可能非常适合您的业务，因为客户需要比较两种产品的功能和价格范围。</span><span>另一方面，如果您的商店经营服装和配饰，那么您可能不需要此功能，因为购买主要取决于个人的喜好和尺码的可用性。</span></span></span></p>
<p><span>让我们进入在 Magento 2 中禁用比较产品的方法</span></p>
<h2><span id="Method_to_Disable_Compare_Products_for_Magento_2">禁用 Magento 2 比较产品的方法</span></h2>
<p><span><span></span></span><span><span><span>在下面给定的路径中</span></span><span><span>创建一个</span></span></span><span>default.xml文件：</span><span><span></span></span></p>
<p><span>app\design\frontend\Themes\Yourtheme\Magento_Catalog\layout\</span></p>
<p><span>现在，添加下面给出的代码：</span></p>
<p>&lt;referenceBlock name="catalog.compare.link" remove="true" /&gt;</p>
<p>&lt;referenceBlock name="catalog.compare.sidebar" remove="true"/&gt;</p>
<p>&lt;referenceBlock name="catalogsearch.product.addto.compare" remove="true"/&gt;</p>
<p>&lt;referenceBlock name="category.product.addto.compare" remove="true"/&gt;</p>
<p>&lt;referenceBlock name="crosssell.product.addto.compare" remove="true" /&gt;</p>
<p>&lt;referenceBlock name="related.product.addto.compare" remove="true" /&gt;</p>
<p>&lt;referenceBlock name="upsell.product.addto.compare" remove="true" /&gt;</p>
<p>&lt;referenceBlock name="view.addto.compare" remove="true" /&gt;</p>]]></description>
      <pubDate>Fri, 09 Jun 2023 09:01:08 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何检查 Magento 2 中是否存在具有 SKU 的产品]]></title>
      <link>https://www.360magento.com/blog/check-if-product-with-sku-exists-magento/</link>
      <description><![CDATA[<p>第 1 步：在下面给定的路径中创建一个名为Data.php的文件。</p>
<p><span>app\code\Vendor\Extension\Helper\</span></p>
<pre>&lt;?php

namespace Vendor\Extension\Helper;

use Magento\Framework\App\Helper\Context;

use Magento\Catalog\Model\Product;

use Magento\Framework\App\Helper\AbstractHelper;

class Data extends AbstractHelper

{

&nbsp;&nbsp;&nbsp;&nbsp;protected $product;

&nbsp;&nbsp;&nbsp;&nbsp;public function __construct(Context $context,Product $product)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;product = $product;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parent::__construct($context);

&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;public function Checkproductexist($product_sku)

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ($this-&gt;product-&gt;getIdBySku($product_sku))

&nbsp; &nbsp; &nbsp; $this-&gt;_logger-&gt;info('Product is Exist');

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else

&nbsp; $this-&gt;_logger-&gt;info('Product is not Exist');

&nbsp;&nbsp;&nbsp;&nbsp;}

}
</pre>
<p>第 2 步：接下来，在模块 phtml文件中添加以下代码：</p>
<p>&lt;?php</p>
<p>$helper = $this-&gt;helper('Vendor\Extension\Helper\Data');</p>
<p>$product_sku = "product_sku"; // add your sku here</p>
<p>$helper-&gt;Checkproductexist($product_sku);</p>
<p>?&gt;<br /><span>添加以上代码后，在system.log（var/log/system.log）文件</span><span><span>中查看产品是否存在</span></span><span>。</span></p>]]></description>
      <pubDate>Thu, 08 Jun 2023 07:58:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置分级价格]]></title>
      <link>https://www.360magento.com/blog/setup-tier-price-magento-2/</link>
      <description><![CDATA[<p><span><span><span>分级价格意味着它允许您以最优惠的价格以折扣价提供所有或特定产品。</span><span>可以在目录或产品页面上将此折扣视为一条短消息。</span><span>例如，&ldquo;以每件 5.00 美元的价格购买 20 件并节省 29%&rdquo;。</span></span></span></p>
<p><span><span><span>Magento 2 中的层级价格基本上是根据购买产品的数量设置的折扣价。</span><span>达到每个级别后，买家可以使用新的更好的价格。</span></span></span></p>
<p><span><span><span>设置分级价格是一种非常有效的促销策略，可以逐步推动您商店中的更多购买。</span><span>根据您的商店计划，在特定商店视图、客户组或共享目录上设置等级价格条件，让客户在结账时获得折扣。</span></span></span></p>
<h2><span id="Steps_to_Setup_Tier_Price_in_Magento_2"><span><span><span>在 Magento 2 中设置分级价格的步骤</span></span></span><span></span></span></h2>
<ul>
<li><span>登录到 Magento 管理面板并转到</span><span>目录 &gt; 产品。<br /></span>在这里，从产品列表中选择要添加等级价格的所需产品，然后单击编辑。</li>
<li>在价格字段中，单击&ldquo;高级定价&rdquo;按钮。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/setup-tier-price-3.png" /></p>
<ul>
<li><span>在高级定价窗口中，单击&ldquo;客户组价格&rdquo;字段中的</span><span>&ldquo;添加&rdquo;</span><span>以添加分级价格并设置价格条件。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/setup-tier-price-4.png" /><br /></span></p>
<p><span>网站：</span><span>选择您希望为其开放层级价格的网站。</span></p>
<p><span>客户组：</span><span><span><span>选择您希望折扣价适用的一组客户。</span><span>您也可以选择所有组。</span></span></span></p>
<p><span>数量：</span><span>在此字段中，输入申请折扣的产品数量。</span></p>
<p><span>价格：</span><span>在此字段中，输入降低后的产品价格。</span></p>
<p><span><span><span>您可以根据需要为所有产品自由设置任意数量的分级价格条件。</span><span>例如，购买 2 件商品的一个折扣价和购买 3 件商品的另一个分级价格。</span></span></span></p>
<ul>
<li><span>设置所有配置后，按</span><span>完成</span><span>并</span><span>保存</span><span>更改。</span></li>
<li><span>清除缓存并重新索引 Magento 数据</span></li>
</ul>]]></description>
      <pubDate>Wed, 07 Jun 2023 07:55:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置 Robots.txt？]]></title>
      <link>https://www.360magento.com/blog/configure-robots-txt/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Robotstxt_in_Magento_2">在 Magento 2 中配置 Robots.txt 的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理面板转到</span><span>内容 &gt; 设计配置</span><span>，然后选择您想要的</span><span>商店</span><span>。</span></p>
<p><span>第 2 步：</span><span>展开</span><span>搜索引擎机器人</span><span>部分。&nbsp;</span></p>
<p><span>&nbsp;</span><img src="https://www.360magento.com/media/wysiwyg/robots-configuration.png" /></p>
<p></p>
<ul>
<li><span>选择默认机器人字段</span><span>的选项</span><span><span><span>。</span><span>有几个选项可用，</span></span></span></li>
<li><span><span><span><span>INDEX, FOLLOW</span></span></span><span><span>&nbsp;&ndash; 网络爬虫索引页面并跟随页面上的链接。</span></span><br /><span><span><span>NOINDEX, FOLLOW</span></span></span><span><span>&nbsp;&ndash; 网络爬虫不索引页面但跟随页面上的链接。</span></span><br /><span><span><span>INDEX, NOFOLLOW</span></span></span><span><span>&nbsp;&ndash; 网络爬虫索引页面但不跟踪链接。</span></span><br /><span><span><span>NOINDEX, NOFOLLOW</span></span></span><span><span>&nbsp;&ndash; 网络爬虫既不索引页面也不跟随页面上的链接。</span></span><br /></span></li>
<li><span>在</span><span>编辑 robots.txt 文件的自定义指令</span><span>字段中，输入网络爬虫的自定义指令（如果有）。</span></li>
<li><span>重置为默认值</span><span>按钮会清除您所有的 robots.txt 设置并重置为默认值。</span></li>
</ul>
<p><span>单击</span><span>保存配置</span><span>并刷新缓存以反映更改。</span></p>
<p></p>]]></description>
      <pubDate>Mon, 05 Jun 2023 19:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中生成订单报告的分步指南]]></title>
      <link>https://www.360magento.com/blog/generate-order-report-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Generate_Order_Report_in_Magento_2">在 Magento 2 中生成订单报告的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录管理面板并导航至</span><span>&ldquo;报告&rdquo;&gt;&ldquo;销售&rdquo;&gt;&ldquo;订单&rdquo;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/order-report-configuration.png" /></span></p>
<p></p>
<p><span>第二步：</span><span>进行如下配置设置：</span></p>
<ul>
<li><span>使用日期</span><span>&mdash;&mdash;您在这里有两个选项，订单创建或订单更新。</span></li>
<li><span>期间</span><span>&ndash; 根据您需要的报告类型将其设置为日、月或年。</span></li>
<li><span>发件人</span><span>&ndash; 在创建订单时设置此字段。</span></li>
<li><span>To&nbsp;</span><span>&ndash; 将此字段设置为直到订单有效。</span></li>
<li><span>Order Status&nbsp;</span><span><span><span>&ndash; 它定义要生成的订单状态的报告。</span><span>Option Any 包括所有类型的订单，不包括已取消的订单。</span><span>选择指定选项可提供更多选项以从列表中选择特定订单状态。</span></span></span></li>
<li><span>空行</span><span>&mdash;&mdash;将其设置为否将排除报告中的空行。</span></li>
<li><span>显示实际值</span><span>&mdash;&mdash;将其设置为否将不会在报告中提及产品的实际值。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/order-report-filter.png" /></span></p>]]></description>
      <pubDate>Mon, 05 Jun 2023 06:03:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中创建管理菜单的步骤]]></title>
      <link>https://www.360magento.com/blog/create-admin-menu-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Create_Admin_Menu_in_Magento_2">在 Magento 2 中创建管理菜单的步骤：</span></h2>
<p><span>第一步：</span><span><span><span>在以下路径创建一个名为</span></span><span><span>menu.xml</span></span></span><span>文件的管理菜单文件</span><span><span></span></span><span><span></span></span></p>
<p><span>app\code\Vendor\Extension\etc\adminhtml\menu.xml</span></p>
<p><span>现在添加以下代码</span></p>
<p><span></span></p>
<p>&lt;?xml version="1.0"?&gt;<br />&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Backend:etc/menu.xsd"&gt;<br /> &lt;menu&gt;<br /> &lt;add id="Vendor_Extension::custom_menu" title="Custom Menu" module="Vendor_Extension" sortOrder="50" resource="Vendor_Extension::custom_menu"/&gt;<br /> &lt;add id="Vendor_Extension::notifications" title="Notifications" module="Vendor_Extension" sortOrder="10" action="vendorextension/notifications" resource="Vendor_Extension::notifications" parent="Vendor_Extension::custom_menu"/&gt;<br /> &lt;add id="Vendor_Extension::configuration" title="Configurations" module="Vendor_Extension" sortOrder="100" parent="Vendor_Extension::custom_menu" action="adminhtml/system_config/edit/section/custom_menu" resource="Vendor_Extension::configuration"/&gt;<br /> &lt;/menu&gt;<br />&lt;/config&gt;</p>
<p><span>从您的 Magento 管理员处结帐。</span><span>将创建一个自定义菜单，如下图所示。</span></p>
<p><span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/admin-menu.png" /></span></p>
<p></p>]]></description>
      <pubDate>Sun, 04 Jun 2023 07:59:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中自定义联系我们表单]]></title>
      <link>https://www.360magento.com/blog/customize-contact-us-form-magento2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Customize_Contact_Us_Form_in_Magento_2">在 Magento 2 中自定义联系我们表单的步骤：</span></h2>
<p><span>您必须覆盖 Magento 联系表单文件。</span></p>
<p><span>从路径</span><br /><span>vendor/magento/module-contact/view/frontend/templates复制 form.phtml</span></p>
<p><span>并将其粘贴到</span><br /><span>app/code/Vendor/Extension/view/frontend/templates</span></p>
<p><span>第 1 步：</span><span>文件路径：</span><span>app\code\Vendor\Extension\view\frontend\templates\form.phtml</span></p>
<p><span class="crayon-o">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"field custom required"</span><span class="crayon-o">&gt;</span></p>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-2"><span class="crayon-h"> </span><span class="crayon-o">&lt;</span><span class="crayon-e">label </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"label"</span><span class="crayon-h"> </span><span class="crayon-st">for</span><span class="crayon-o">=</span><span class="crayon-s">"custom"</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-3"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">&lt;</span><span class="crayon-e">span</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-4"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-ta">&lt;?php</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-k ">echo</span><span class="crayon-h"> </span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Custom Field'</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-5"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">span</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-6"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">label</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-7">&nbsp;</div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-8"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"control"</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-9"><span class="crayon-h"> &nbsp;&nbsp; </span><span class="crayon-o">&lt;</span><span class="crayon-e">input </span><span class="crayon-v">name</span><span class="crayon-o">=</span><span class="crayon-s">"custom"</span><span class="crayon-h"> </span><span class="crayon-v">id</span><span class="crayon-o">=</span><span class="crayon-s">"custom"</span><span class="crayon-h"> </span><span class="crayon-v">title</span><span class="crayon-o">=</span><span class="crayon-s">"</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-10"><span class="crayon-s">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="crayon-ta">&lt;?php</span><span class="crayon-h"> </span><span class="crayon-o">/</span><span class="crayon-h"> </span><span class="crayon-sy">@</span><span class="crayon-i">escapeNotVerified</span><span class="crayon-h"> </span><span class="crayon-o">*</span><span class="crayon-o">/</span><span class="crayon-h"> </span><span class="crayon-k ">echo</span><span class="crayon-h"> </span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Custom Field'</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span><span class="crayon-h"> </span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-11"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-v">value</span><span class="crayon-o">=</span><span class="crayon-s">""</span><span class="crayon-h"> </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"input-text"</span><span class="crayon-h"> </span><span class="crayon-v">type</span><span class="crayon-o">=</span><span class="crayon-s">"text"</span><span class="crayon-h"> </span><span class="crayon-v">data</span><span class="crayon-o">-</span><span class="crayon-v">validate</span><span class="crayon-o">=</span><span class="crayon-s">"{required:true}"</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-12"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">div</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line" id="urvanov-syntax-highlighter-6479aec5dd8ae539189198-13"><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">div</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line"></div>
<div class="crayon-line"></div>
<div class="crayon-line"><span>第二步：</span><span>在以下文件路径中添加以下代码：</span><span>app\code\Vendor\Extension\view\frontend\layout\contact_index_index.xml</span></div>
<div class="crayon-line"></div>
<div class="crayon-line"></div>
<div class="crayon-line"></div>
<div class="crayon-line">
<p>&lt;?xml version="1.0"?&gt;</p>
<p>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;</p>
<p>&lt;body&gt;</p>
<p>&lt;referenceBlock name="contactForm" remove="true"/&gt;</p>
<p>&lt;referenceContainer name="content"&gt;</p>
<p>&lt;block class="Magento\Contact\Block\ContactForm" name="customContactForm" template="Vendor_Extension::form.phtml" /&gt;</p>
<p>&lt;/referenceContainer&gt;</p>
<p>&lt;/body&gt;</p>
<p>&lt;/page&gt;</p>
</div>]]></description>
      <pubDate>Sat, 03 Jun 2023 02:55:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中应用默认主题的简单方法]]></title>
      <link>https://www.360magento.com/blog/apply-default-theme-magento/</link>
      <description><![CDATA[<h2><span id="How_to_Filter_the_Theme_Grid_in_Magento_2">如何过滤 Magento 2 中的主题网格？</span></h2>
<ul>
<li><span>从 Magento 管理面板，导航到</span><span>Content &gt; Design &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>现在，点击</span><span>过滤器</span><span>。</span></li>
<li><span>输入网站、商店、商店视图或主题名称。</span></li>
<li><span>然后点击</span><span>应用过滤器</span><span>。</span></li>
<li><span>主题列表将被更新。&nbsp;</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/filter-theme-grid.png" /></span></p>
<p></p>
<h2><span id="How_to_View_Current_Themes_in_Magento_2">如何在 Magento 2 中查看当前主题？</span></h2>
<ul>
<li><span>从 Magento 管理面板，导航到</span><span>Content &gt; Design &gt; Themes&nbsp;</span><span>。</span></li>
<li><span>您将获得所有主题的列表。</span></li>
</ul>
<p><span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/view-theme.png" /></span></p>
<p></p>
<ul>
<li><span>单击主题设置的视图。</span></li>
<li><span>您可以预览主题的示例页面。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/theme-settings.png" /></span></p>
<p></p>
<p></p>
<h2><span id="How_to_Apply_The_Default_Theme_In_Magento_2">如何在 Magento 2 中应用默认主题？</span></h2>
<ul>
<li><span>从 Magento 管理面板，导航到</span><span>Content &gt; Design &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>确定要为其更新主题的商店视图，然后单击</span><span>操作列中的</span><span>编辑。</span><span><span></span></span></li>
<li><span>在 Default Theme 选项卡下，</span><span>根据您的选择设置</span><span>Applied Theme 。</span><span><span></span></span></li>
<li><span>最后点击</span><span>保存配置</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/applied-theme.png" /></span></p>
<p></p>
<h2><span id="How_to_Add_User_Agent_Rule_for_Themes_in_Magento_2">如何在 Magento 2 中为主题添加用户代理规则？</span></h2>
<p><span>用户代理规则用于根据设备更改主题。&nbsp;</span></p>
<ul>
<li><span>从 Magento 管理面板，导航到</span><span>Content &gt; Design &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>确定要为其更新主题的商店视图，然后单击</span><span>操作列中的</span><span>编辑。</span><span><span></span></span></li>
<li><span>在 Design Rule 选项卡下，单击</span><span>Add New User Agent Rule&nbsp;</span><span>。</span></li>
<li><span><span></span></span><span>在搜索字符串</span><span>中输入特定设备的浏览器 ID&nbsp;</span><span>，然后选择</span><span>该设备的</span><span>主题名称。</span><span><span></span></span></li>
<li><span>重复相同的过程以添加其他设备。</span></li>
<li><span>您还可以从操作列中删除用户代理规则。</span></li>
<li><span>最后点击</span><span>保存配置</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/user-agent-rule.png" /></span></p>]]></description>
      <pubDate>Sat, 27 May 2023 06:45:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中禁用 AJAX 添加到购物车]]></title>
      <link>https://www.360magento.com/blog/disable-ajax-add-to-cart-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Disable_AJAX_Add_to_Cart_in_Magento_2">在 Magento 2 中禁用 AJAX 添加到购物车的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理面板导航到</span><span>商店 &gt; 设置 &gt; 配置</span></p>
<p><span>第 2 步：</span><span>在左侧窗格中，展开</span><span>销售</span><span>并选择</span><span>结帐</span></p>
<p><span>第 3 步：</span><span>放大</span><span>购物车</span><span>选项</span></p>
<p><span>第 4 步：将</span><span><span>添加产品后重定向到购物车选项</span></span><span>设置</span><span><span><span>为是，以便在产品添加到购物车后将客户重定向到购物车。</span></span><span><span>这意味着 AJAX 被禁用。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/disable-ajax.png" /></span></p>]]></description>
      <pubDate>Fri, 26 May 2023 08:49:49 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用管理员帐户共享？]]></title>
      <link>https://www.360magento.com/blog/magento-2-admin-account-sharing/</link>
      <description><![CDATA[<h2><span id="Steps_to_Enable_Admin_Account_Sharing_in_Magento_2">在 Magento 2 中启用管理员帐户共享的步骤</span></h2>
<ul>
<li><span>登录到 Magento 2 商店后端。</span></li>
<li><span>导航到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>在左侧面板中，导航至</span><span>Advanced &gt; Admin&nbsp;</span><span>。</span></li>
<li><span>展开</span><span>安全</span><span>部分</span></li>
<li><span><span></span></span><span><span><span>根据您的选择</span></span><span><span>启用或禁用</span></span></span><span>管理员帐户共享为是或否。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/enable-admin-account-sharing-in-magento-2-2.png" /></span></p>]]></description>
      <pubDate>Wed, 24 May 2023 20:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中为特定国家/地区添加新区域]]></title>
      <link>https://www.360magento.com/blog/magento-2-add-new-region-for-specific-country/</link>
      <description><![CDATA[<h2><span id="How_to_Add_New_Region_For_Specific_Country_in_Magento_2">如何在 Magento 2 中为特定国家/地区添加新区域：</span></h2>
<p><span>您需要运行以下</span><span>SQL 查询：</span></p>
<p><span>句法：</span></p>
<p>INSERT INTO &lsquo;directory_country_region&rsquo; (&lsquo;country_id&rsquo;, &lsquo;code&rsquo;, &lsquo;default_name&rsquo;, &lsquo;state_code&rsquo;) VALUES ('country id', 'region code', 'region name&rsquo;, 'state code&rsquo;);<br /><br /></p>
<p><span>示例 1：</span></p>
<p>INSERT INTO `directory_country_region` (`country_id`, `code`, `default_name`, `state_code`) VALUES ('IN', 'IS', 'Indian State', '46');</p>
<p><img src="https://www.360magento.com/media/wysiwyg/indian-state.png" /></p>
<div id="gtx-trans" style="position: absolute; left: -33px; top: 166.375px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Wed, 24 May 2023 07:40:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中自定义联系我们表单]]></title>
      <link>https://www.360magento.com/blog/customize-contact-us-form-magento/</link>
      <description><![CDATA[<p>联系我们表格通常包括姓名、图像和消息。但是，您可以根据您的业务需要自定义&ldquo;联系我们&rdquo;表单。查看Magento 2 的快速联系表单扩展，它有助于在您网站的所有页面上嵌入联系按钮。</p>
<h2><span id="Steps_to_Customize_Contact_Us_Form_in_Magento_2">在 Magento 2 中自定义联系我们表单的步骤：</span></h2>
<p><span>您必须覆盖 Magento 联系表单文件。</span></p>
<p><span>从路径</span><br /><span>vendor/magento/module-contact/view/frontend/templates复制 form.phtml</span></p>
<p><span>并将其粘贴到</span><br /><span>app/code/Vendor/Extension/view/frontend/templates</span></p>
<p><span>第 1 步：</span><span>文件路径：</span><span>app\code\Vendor\Extension\view\frontend\templates\form.phtml</span></p>
<p>&lt;div class="field custom required"&gt;<br /> &lt;label class="label" for="custom"&gt;<br /> &lt;span&gt;<br /> &lt;?php /* @escapeNotVerified */ echo __('Custom Field') ?&gt;<br /> &lt;/span&gt;<br /> &lt;/label&gt;</p>
<p>&lt;div class="control"&gt;<br /> &lt;input name="custom" id="custom" title="<br /> &lt;?php / @escapeNotVerified */ echo __('Custom Field') ?&gt;" <br /> value="" class="input-text" type="text" data-validate="{required:true}"<br /> &lt;/div&gt;<br />&lt;/div&gt;</p>
<p></p>
<p><span>第二步：</span><span>在以下文件路径中添加以下代码：</span><span>app\code\Vendor\Extension\view\frontend\layout\contact_index_index.xml</span></p>
<p><span></span></p>
<p><span><span class="crayon-o">&lt;</span><span class="crayon-e">referenceBlock </span><span class="crayon-v">name</span><span class="crayon-o">=</span><span class="crayon-s">"contactForm"</span><span class="crayon-h"> </span><span class="crayon-v">remove</span><span class="crayon-o">=</span><span class="crayon-s">"true"</span><span class="crayon-o">/</span><span class="crayon-o">&gt;</span><span class="crayon-h">&nbsp;&nbsp;</span></span></p>
<p><span><span class="crayon-h"></span></span><span class="crayon-h">&nbsp; &nbsp; &nbsp; &nbsp;</span><span class="crayon-o">&lt;</span><span class="crayon-e">referenceContainer </span><span class="crayon-v">name</span><span class="crayon-o">=</span><span class="crayon-s">"content"</span><span class="crayon-o">&gt;</span>&nbsp;</p>
<div class="crayon-line" id="urvanov-syntax-highlighter-64667c7ccfec1193072053-11"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">&lt;</span><span class="crayon-e">block </span><span class="crayon-t">class</span><span class="crayon-o">=</span><span class="crayon-s">"Magento\Contact\Block\ContactForm"</span><span class="crayon-h"> </span><span class="crayon-v">name</span><span class="crayon-o">=</span><span class="crayon-s">"customContactForm"</span><span class="crayon-h"> </span><span class="crayon-v">template</span><span class="crayon-o">=</span><span class="crayon-s">"Vendor_Extension::form.phtml"</span><span class="crayon-h"> </span><span class="crayon-o">/</span><span class="crayon-o">&gt;</span></div>
<div class="crayon-line crayon-striped-line" id="urvanov-syntax-highlighter-64667c7ccfec1193072053-12">&nbsp;</div>
<div class="crayon-line" id="urvanov-syntax-highlighter-64667c7ccfec1193072053-13"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-o">&lt;</span><span class="crayon-o">/</span><span class="crayon-v">referenceContainer</span><span class="crayon-o">&gt;</span></div>
<p></p>]]></description>
      <pubDate>Tue, 23 May 2023 06:34:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更改 Magento 2 中的管理员启动页面]]></title>
      <link>https://www.360magento.com/blog/change-admin-startup-page-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_the_Admin_Startup_Page_in_Magento_2">在 Magento 2 中更改管理员启动页面的步骤</span></h2>
<p><span>第 1 步：</span><span>登录到您的 Magento 商店管理后端并导航到</span><span>商店 &gt; 配置</span><span>部分。</span></p>
<p><span>第 2 步：</span><span>在左侧面板中，转到</span><span>&ldquo;高级&rdquo;</span><span>选项并选择</span><span>&ldquo;管理&rdquo;</span><span><span><span>选项。</span><span>在 Advance 菜单中展开</span></span></span><span>Startup Page</span><span>选项。</span></p>
<p><span>第 3 步：取消选中</span><span><span><span>Startup Page</span></span></span><span><span><span>字段的 Use System Value 框</span><span>，然后从下拉菜单中选择要在启动页显示的页面。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/admin-startup-page-setup.png" /></span></p>]]></description>
      <pubDate>Mon, 22 May 2023 08:51:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置密码重置请求之间的最短时间？]]></title>
      <link>https://www.360magento.com/blog/set-min-time-between-password-reset-requests-in-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_set_Min_Time_Between_Password_Reset_Requests_in_Magento_2_store_for_Admin"><span>在 Magento 2 商店中为管理员设置密码重置请求之间的最短时间的步骤</span></span></h2>
<p><span>第 1 步：</span><span>登录到 Magento 管理面板并导航到</span><span>Store &gt; Settings &gt; Configuration</span></p>
<p><span>从侧边栏。</span></p>
<p><span>第 2 步：</span><span>在配置中，展开</span><span>Advance</span><span>选项并选择</span><span>Admin</span><span>菜单。</span></p>
<p><span>第 3 步：</span><span>现在展开</span><span>&ldquo;安全&rdquo;</span><span>菜单并进一步处理。</span><br /><br /><img src="https://www.360magento.com/media/wysiwyg/admin-side_1_.png" /></p>
<p><span>密码重置请求之间的最短时间：</span><span>取消选中该框并在&ldquo;密码重置请求之间的最短时间&rdquo;字段中输入密码重置请求之间必须经过的最短分钟数。</span></p>
<p><span>第 3 步：</span><span>要应用您的更改，请点击</span><span>保存配置</span><span>按钮。</span></p>
<h2><span id="Steps_To_Set_Min_Time_Between_Password_Reset_Requests_In_Magento_2_Store_For_Customer"><span>在 Magento 2 Store 中为客户设置密码重置请求之间的最短时间的步骤</span></span></h2>
<p><span>第 1 步：</span><span>导航到</span><span>管理主页，然后</span><span>从边栏中</span><span>选择</span><span>商店。</span><span>然后，在&ldquo;设置&rdquo;下，选择</span><span>&ldquo;配置&rdquo;&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span><span><span>从</span></span><span><span>左侧的</span></span><span><span>客户面板中</span></span></span><span>选择</span><span>客户配置。</span><span><span><span>之后，展开</span></span><span><span>密码选项</span></span><span><span>部分。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/customer-side.png" /></span></p>
<p><span>密码重置请求之间的最短时间：</span><span>取消选中该复选框并在&ldquo;密码重置请求之间的最短时间&rdquo;字段中添加密码重置请求之间必须经过的分钟数。</span></p>
<p><span>第 3 步：</span><span>单击</span><span>右上角的</span><span>&ldquo;保存配置&rdquo;按钮以保存您的更改。</span></p>
<p><span></span></p>]]></description>
      <pubDate>Sun, 21 May 2023 07:58:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中隐藏或删除 Minicart]]></title>
      <link>https://www.360magento.com/blog/hide-or-remove-minicart-magento/</link>
      <description><![CDATA[<h2><span id="How_To_Remove_Minicart_In_Magento_2">如何删除 Magento 2 中的 Minicart？</span></h2>
<p><span><img src="https://www.360magento.com/media/wysiwyg/How-to-Hide-or-Remove-Minicart-in-Magento-2.png" /></span></p>
<ol>
<li><span><span><span>从 Magento 管理面板</span></span><span><span>导航到</span></span></span><span>Stores &gt; Settings &gt; Configuration 。</span><span><span></span></span></li>
<li><span><span></span></span><span><span><span>从</span></span><span><span>左侧的</span></span><span><span>销售标题中</span></span><span><span>选择</span></span></span><span>结帐选项。</span><span><span></span></span><span><span></span></span><span><span></span></span></li>
<li><span>放大</span><span>Mini Cart</span><span>标题。</span></li>
<li><span>取消选中 Display Mini Cart 字段中的 Use System Value 选项。</span></li>
<li><span>将</span><span>Display Mini Cart</span><span>字段设置为</span><span>No&nbsp;</span><span>。</span></li>
<li><span>保存配置</span><span>。</span></li>
</ol>]]></description>
      <pubDate>Sat, 20 May 2023 07:56:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置零小计结帐]]></title>
      <link>https://www.360magento.com/blog/configure-zero-subtotal-checkout-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Zero_Subtotal_Checkout_in_Magento_2">在 Magento 2 中配置零小计结帐的步骤</span></h2>
<p><span><span><span><span>第 1 步：</span></span></span><span><span>从 Magento 管理面板转到</span></span></span><span>Stores -&gt; Configuration&nbsp;</span><span>。</span></p>
<p><span><span><span><span>第 2 步：</span></span></span><span></span></span><span>在&ldquo;销售&rdquo;部分</span><span>下</span><span>，选择</span><span>&ldquo;付款方式&rdquo;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/configuration_2.png" /></span></p>
<p><span><span><span><span>第 3 步：</span></span></span><span><span>从各个选项卡展开</span></span></span><span>零小计结帐</span><span>选项卡。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/zero-subtotal-checkout.png" /></p>
<p><span>已启用：</span><span>将此字段设置为是以启动零小计结帐。</span></p>
<p><span>标题：</span><span>在这里设置标题，显示给客户。&nbsp;</span></p>
<p><span>新订单状态：</span><span>从下拉菜单的 3 个选项中，根据您的要求选择任何一个。</span></p>
<ul>
<li><span>待定：</span><span>如果订单等待批准，请选择此选项。</span></li>
<li><span>处理：</span><span>如果交易正在处理，请设置此选项。</span></li>
<li><span>涉嫌欺诈：</span><span>如果订单涉嫌欺诈，请设置此选项。</span></li>
</ul>
<p><span>来自适用国家/地区的付款：</span><span>如果您希望向所有国家/地区提供零小计结账，请从下拉菜单中选择所有允许的国家/地区，如果您希望仅向指定国家/地区提供该功能，请选择特定国家/地区选项。</span></p>
<p><span>来自特定国家/地区的付款：</span><span>在此字段中，选择您希望允许付款的国家/地区。&nbsp;</span></p>
<p><span>排序顺序：</span><span>输入您希望定义零小计结帐位置的顺序。</span></p>
<p><span><span><span><span>第 4 步：</span></span></span><span><span>最后，</span></span></span><span>保存配置</span><span>。</span></p>]]></description>
      <pubDate>Fri, 19 May 2023 07:54:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置结帐总计排序顺序]]></title>
      <link>https://www.360magento.com/blog/configure-checkout-totals-sort-order-magento/</link>
      <description><![CDATA[<h2><span id="How_To_Configure_Checkout_Totals_Sort_Order_In_Magento_2">如何在 Magento 2 中配置结帐总计排序顺序</span></h2>
<p><img src="https://www.360magento.com/media/wysiwyg/checkout-totals-sort-order.png" /></p>
<p><span>第 1 步 &ndash;</span><span>在 Magento 管理员中，前往</span><span>Stores &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步 &ndash;</span><span>之后，选择</span><span>销售 &gt; 销售</span><span>。</span></p>
<p><span>第 3 步 &ndash;</span><span>放大</span><span>Checkout Totals Sort Order</span><span>部分。</span></p>
<p><span>第 4 步 &ndash;</span><span><span><span>为每个字段分配值。</span><span>订单金额将按从低到高的顺序显示。</span><span>编号最低的字段将被评为较高的位置。&nbsp;</span></span></span></p>
<p><span>第 5 步 &ndash;</span><span>完成后，点击</span><span>保存配置</span><span>！</span></p>]]></description>
      <pubDate>Thu, 18 May 2023 07:50:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何打印 Magento 2的日志]]></title>
      <link>https://www.360magento.com/blog/print-log-in-magento-2/</link>
      <description><![CDATA[<p><span><span><span>日志是系统信息的记录，可以在将来检查。</span><span>错误日志是此类事件的重要实例之一。&nbsp;</span></span></span></p>
<p><span><span><span>开发人员熟悉错误带来的痛苦以及交付功能解决方案所涉及的步骤。</span><span>自定义日志可以使他们更容易调试。</span><span>它使识别错误和问题原因变得简单。</span><span>日志有助于深入了解 Magento 2 系统进程。</span></span></span></p>
<p><span><span><span>&nbsp;</span></span></span></p>
<h2><span id="Steps_To_Print_Log_In_Magento_2"><span><span><span>打印登录 Magento 2 的步骤</span></span></span><span>&nbsp;</span></span></h2>
<p>在我们执行这些方法之前，请确保您的 Magento 商店处于开发人员模式。检查您的商店是否处于生产模式，然后执行此命令。</p>
<p><span>php bin/magento config:set dev/debug/debug_logging 1</span></p>
<p><span>可以通过三种方式打印您在 Magento 商店中的日志。</span></p>
<h3><span id="Method_1_To_print_temporary_logs_with_a_new_file">方法 1：使用新文件打印临时日志</span></h3>
<p><span>将此代码添加到任何文件夹或 sun 目录中的任何新 PHP 文件。</span></p>
<pre>    $writer = new \Zend\Log\Writer\Stream(BP . '/var/log/mylogfile.log');
    $logger = new \Zend\Log\Logger();
    $logger---&gt;addWriter($writer);
    $logger-&gt;info('This Is Simple Text Log'); //To print simple text log
    $logger-&gt;info(print_r($myarray, true)); //To print array log

</pre>
<p>方法二：使用Logger接口 在以下路径创建一个文件 app\code\Vendor\Extension\Block\Printlog.php 现在，添加以下代码。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/php-log.png" /></p>
<pre>方法 3：使用 ObjectManager
将此代码添加到任何文件夹或 sun 目录中的任何新 PHP 文件。</pre>
<pre>    $objectmanager = \Magento\Framework\App\ObjectManager::getInstance();
    $objectmanager---&gt;get('Psr\Log\LoggerInterface')-&gt;info('Testing Log'); //Print log in var/log/system.log
    $objectmanager-&gt;get('Psr\Log\LoggerInterface')-&gt;debug('Testing Log'); //Print log in var/log/debug.log

</pre>]]></description>
      <pubDate>Wed, 17 May 2023 07:00:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中为新客户帐户设置默认组]]></title>
      <link>https://www.360magento.com/blog/set-default-group-for-new-customer-magento/</link>
      <description><![CDATA[<h2><span id="What_are_customer_groups_in_Magento_2">Magento 2 中的客户群是什么？</span></h2>
<p><span><span><span>默认的 Magento 提供自定义商店和改善用户体验的功能。</span><span>在线零售商有能力根据他们拥有的类别将他们的客户分成不同的组。</span></span></span></p>
<p><span>当您想要区分 B2C 和 B2B 客户时，可以使用此功能。</span></p>
<h2><span id="How_to_Set_Default_Group_for_New_Customer_Account_in_Magento_2">如何在 Magento 2 中为新客户帐户设置默认组</span></h2>
<p><span>Magento 2 中可以有四种不同的客户群：</span></p>
<ul>
<li><span>一般的</span></li>
<li><span>未登录</span></li>
<li><span>零售商</span></li>
<li><span>批发的</span></li>
</ul>
<p><span><span><span>在这 4 个中，一个新帐户自动归入常规类别。</span><span>要更改新注册的默认类别，请从 Magento 2 管理员帐户执行以下操作。</span></span></span></p>
<ul>
<li><span>转到</span><span>商店 &rarr; 配置 &rarr; 客户 &rarr; 客户配置</span><span>。</span></li>
<li><span>展开</span><span>创建新帐户选项选项</span><span>卡。</span></li>
<li><span>将启用</span><span>自动分配给客户组分配</span><span>为是。</span></li>
<li><span>更改</span><span>默认组</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/customer-group-configuration.png" /><br /></span></p>
<p><span><span>此外，您还可以创建自己的自定义组，这非常容易配置。</span><span>让我们看看如何！</span></span></p>
<p></p>
<p><img src="https://www.360magento.com/media/wysiwyg/add-new-customer-group-1.png" /></p>
<p></p>
<ul>
<li><span>转到</span><span>客户 &rarr; 客户组</span><span>。</span></li>
</ul>
<p><span>在那里您将看到四种可编辑或可删除的客户组变体。&nbsp;</span></p>
<ul>
<li><span>单击</span><span>添加新客户组</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/new-customer-group-configuration-1_1_.png" /></span></p>
<p></p>
<ul>
<li><span>输入</span><span>组名称</span><span>并</span><span>为其分配</span><span>税级。</span><span><span></span></span></li>
<li><span>并</span><span>保存客户群</span><span>。</span></li>
</ul>]]></description>
      <pubDate>Tue, 16 May 2023 08:31:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中禁用管理员密码过期]]></title>
      <link>https://www.360magento.com/blog/disable-admin-password-expiration-magento/</link>
      <description><![CDATA[<h2><span id="How_to_Disable_Admin_Password_Expiration_in_Magento_2">如何在 Magento 2 中禁用管理员密码过期？</span></h2>
<ul>
<li><span>在 Magento 管理员中，转到</span><span>Stores &rarr; Settings &rarr; Configuration&nbsp;</span><span>。</span></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/admin-security-1.png" /></p>
<ul>
<li><span>然后，转到</span><span>高级 &rarr; 管理</span></li>
<li><span><span></span></span><span>我们将在安全部分</span><span>工作</span><span>。</span></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/password-lifetime.png" /></p>
<ul>
<li><span>请参阅</span><span>密码有效期（天）</span><span><span><span>字段。</span><span>您可以在此处输入密码保持合法的天数。</span><span>如果该值保持为空，则该功能将被禁用。&nbsp;</span></span></span></li>
<li><span>密码更改</span><span>下拉列表可以具有</span><span>推荐值</span><span>或</span><span>强制</span><span>值。&nbsp;</span></li>
<li><span>强制</span><span>值要求管理员在设置帐户后更改密码。</span></li>
<li><span>建议</span><span>值敦促管理员在设置帐户后更改密码。</span></li>
<li><span>保存配置。</span></li>
</ul>]]></description>
      <pubDate>Mon, 15 May 2023 07:29:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：允许客人写评论]]></title>
      <link>https://www.360magento.com/blog/magento-2-allow-guests-to-write-reviews/</link>
      <description><![CDATA[<h2><span id="How_to_Allow_Guests_to_Write_Reviews_in_Magento_2">如何允许客人在 Magento 2 中撰写评论？</span></h2>
<p><span>第 1 步：常规设置&nbsp;</span></p>
<ul>
<li><span>登录到 Magento 管理员帐户。</span></li>
<li><span>导航到</span><span>商店 &rarr; 配置</span><span>。</span></li>
</ul>
<p><span>第 2 步：允许客人撰写评论</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/product-reviews.png" /></span></p>
<ul>
<li><span>转到</span><span>目录 &rarr; 目录。</span></li>
<li><span><span></span></span><span>我们将在产品评论部分</span><span>工作</span><span>。</span></li>
<li><span><span></span></span><span>将Allow Guests to Write Reviews字段</span><span>设置</span><span>为</span><span>Yes&nbsp;</span><span>。</span></li>
<li><span>保存配置</span><span>。</span></li>
</ul>]]></description>
      <pubDate>Sun, 14 May 2023 06:27:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建新的属性集]]></title>
      <link>https://www.360magento.com/blog/create-new-attribute-sets-magento/</link>
      <description><![CDATA[<h2><span id="How_to_Create_New_Attribute_Sets_in_Magento_2">如何在 Magento 2 中创建新的属性集？</span></h2>
<ul>
<li><span>登录到 Magento 管理员。</span></li>
<li><span>转到</span><span>商店 &rarr; 属性 &rarr; 属性集</span><br /><br /><img src="https://www.360magento.com/media/wysiwyg/new-attribute-configuration.png" /><br /><br />
<ul>
<li><span>单击</span><span>添加属性集</span><span>。</span><img src="https://www.360magento.com/media/wysiwyg/add-attribute-set.png" /></li>
<li>
<p><span>输入询问的信息。</span></p>
<ul>
<li><span>名称：</span><span><span><span>为属性命名。</span><span>这是要求内部使用的。</span></span></span></li>
<li><span>基于：</span><span>选择将用作模板的属性集。</span></li>
<li><span>点击</span><span>保存</span><span>按钮。</span><br /><br /><img src="https://www.360magento.com/media/wysiwyg/attribute-set-information.png" /><br />
<ul>
<li><span>下一页将如下所示。</span></li>
</ul>
</li>
<li>
<ul>
<li><span>要更改属性集，只需将项目</span><span>从未分配的属性拖动</span><span>到</span><span>组</span><span>列。</span></li>
<li><span>完成后</span><span>保存<br /><img src="https://www.360magento.com/media/wysiwyg/edit-attribute-set.png" /><br /></span></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>]]></description>
      <pubDate>Fri, 12 May 2023 17:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中启用管理仪表板图表]]></title>
      <link>https://www.360magento.com/blog/enable-admin-dashboard-charts-magento/</link>
      <description><![CDATA[<h2><span id="How_To_Enable_Admin_Dashboard_Charts_In_Magento_2">如何在 Magento 2 中启用管理仪表板图表？</span></h2>
<p><span><img src="https://www.360magento.com/media/wysiwyg/admin-charts-1.png" /></span></p>
<ul>
<li><span>登录到 Magento 管理员。</span></li>
<li><span>前往</span><span>商店 &rarr; 设置 &rarr; 配置</span><span>。</span></li>
<li><span>之后，</span><span>Advanced &rarr; Admin&nbsp;</span><span>。</span></li>
<li><span><span></span></span><span>我们将在仪表板区域</span><span>工作</span><span>。</span></li>
<li><span><span></span></span><span>将启用图表选项</span><span>设置</span><span>为</span><span>是</span><span>。</span></li>
<li><span>保存配置</span><span>。</span></li>
</ul>]]></description>
      <pubDate>Fri, 12 May 2023 06:25:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置默认​​页面布局]]></title>
      <link>https://www.360magento.com/blog/configure-default-page-layout-magento/</link>
      <description><![CDATA[<h2><span id="How_To_Configure_Default_Page_Layout_In_Magento_2">如何在 Magento 2 中配置默认​​页面布局？</span></h2>
<p><img src="https://www.360magento.com/media/wysiwyg/default-layout_1_.png" /></p>
<p></p>
<ul>
<li><span>登录到 Magento 管理员。</span></li>
<li><span>前往</span><span>商店 &rarr; 设置 &rarr; 配置。</span></li>
<li><span>转到</span><span>Web &rarr; 默认布局</span></li>
<li><span>您可以在此处从下拉菜单中更改默认产品布局和类别布局。</span></li>
<li><span>选择您选择的页面布局以显示在前端。</span></li>
<li><span>保存配置。</span></li>
</ul>]]></description>
      <pubDate>Thu, 11 May 2023 07:19:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置商店信息]]></title>
      <link>https://www.360magento.com/blog/setup-store-information-magento/</link>
      <description><![CDATA[<h2><span id="How_to_Setup_Store_Information_in_Magento_2">如何在 Magento 2 中设置商店信息？</span></h2>
<ul>
<li><span>登录到 Magento 管理员。</span></li>
<li><span>前往</span><span>商店 &rarr; 设置 &rarr; 配置</span><span>。</span></li>
<li><span>之后，转到</span><span>General &rarr; Store Information&nbsp;</span><span>。<br /><img src="https://www.360magento.com/media/wysiwyg/configuration_1.png" /><br /><br /></span></li>
<li><span>放大商店信息部分。填写所有商店详细信息。<br /><img src="https://www.360magento.com/media/wysiwyg/store-information.png" /><br /></span></li>
</ul>]]></description>
      <pubDate>Wed, 10 May 2023 06:14:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改街道地址的行数]]></title>
      <link>https://www.360magento.com/blog/change-number-of-lines-in-street-address-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_Number_of_Lines_in_a_Street_Address_in_Magento_2">在 Magento 2 中更改街道地址行数的步骤：</span></h2>
<ul>
<li><span>登录到</span><span>Magento 管理仪表板</span><span>。</span></li>
<li><span>导航到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>从左侧菜单展开</span><span>CUSTOMERS</span><span>并选择</span><span>Customer Configuration&nbsp;</span><span>。</span></li>
<li><span>移动到</span><span>名称和地址选项</span><span>部分。</span></li>
<li><span><span></span></span><span>在街道地址字段中的行数</span><span>中设置数字</span><span><span><span>。</span><span>默认值为 3，范围为 1-4。<br /><img src="https://www.360magento.com/media/wysiwyg/number-of-lines-in-address-magento-2.png" /><br /></span></span></span></li>
</ul>]]></description>
      <pubDate>Tue, 09 May 2023 09:54:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 的注册表中启用中间名]]></title>
      <link>https://www.360magento.com/blog/enable-middle-name-in-registration-form-magento/</link>
      <description><![CDATA[<h2><span id="Steps_To_Enable_Middle_Name_In_Registration_Form_In_Magento_2">在 Magento 2 的注册表中启用中间名的步骤：</span></h2>
<ul>
<li><span>登录到您的</span><span>Magento 2 管理</span><span>仪表板。</span></li>
<li><span>从左侧菜单中选择</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span><span></span></span><span><span><span>从左侧面板</span></span><span><span>展开</span></span></span><span>CUSTOMERS选项。</span><span><span></span></span></li>
<li><span>选择</span><span>客户配置</span><span>。</span></li>
<li><span>现在，扩大</span><span>名称和地址选项</span><span>部分。</span></li>
<li><span>移至</span><span>Show Middle Name (initial)</span><span>字段并取消选中 Use system value 复选框。</span></li>
<li><span><span></span></span><span><span><span>从下拉列表中</span></span><span><span>选择</span></span></span><span>是。</span><span><span><span>但是，可以启用中间名字段，但永远不能将其设为必需。</span><span>它将保留为可选字段。</span></span></span><br /><img src="https://www.360magento.com/media/wysiwyg/middle-name.png" /></li>
</ul>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
<p><span>结果：</span></p>
<p><span><span><span>现在，您可以在 Magento 2 店面进行验证。</span><span>中间名字段已添加到客户帐户。</span></span></span></p>
<p><span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/middle-name-frontend.png" /></span></p>]]></description>
      <pubDate>Mon, 08 May 2023 08:51:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示传真字段]]></title>
      <link>https://www.360magento.com/blog/show-fax-field-magento-2/</link>
      <description><![CDATA[<p><span><span><span>传真是发送和接收文件的快速替代方法。</span><span>它用作冗长订单、签署文件或其他信息的通信工具。</span><span>尽管随着计算机和互联网的出现，传真已经是一种过时的通讯方式，但一些公司仍然使用传真来传递信息。</span></span></span></p>
<p><span><span><span>在 Magento 2 中，默认的客户注册表不包含传真字段，因为它在后端被禁用。</span><span>但是，如果您需要来自客户的传真信息，您可以轻松启用它</span></span></span></p>
<h2><span id="Steps_To_Show_Fax_Field_In_Magento_2">在 Magento 2 中显示传真字段的步骤：</span></h2>
<ul>
<li><span>登录到您的</span><span>Magento 2 管理</span><span>仪表板。</span></li>
<li><span>打开&nbsp;&nbsp;</span><span>Stores</span><span>菜单并选择</span><span>Settings 部分下的</span><span>Configuration 。</span><span><span></span></span></li>
<li><span>查看屏幕左侧并扩展</span><span>CUSTOMERS&nbsp;</span><span>。</span></li>
<li><span>从选项中选择</span><span>客户配置</span><span>。</span></li>
<li><span>放大</span><span>名称和地址选项选项</span><span>卡。<br /><br /></span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/fax-configuration.png" /></span></p>
<p></p>
<ul>
<li><span>移动到</span><span>显示传真</span><span>字段并取消选中使用系统值复选框。</span></li>
<li><span>选择适当的选项作为</span><span>Optional 或 Required&nbsp;</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/enable-fax.png" /></span></p>
<p></p>
<ul>
<li><span>然后</span><span>保存配置</span><span>。</span></li>
</ul>]]></description>
      <pubDate>Sun, 07 May 2023 08:48:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[修复：Magento 2 中的 PHP 致命错误“Allowed Memory Size”]]></title>
      <link>https://www.360magento.com/blog/fixed-php-fatal-error-allowed-memory-size-magento/</link>
      <description><![CDATA[<h2><span id="Steps_to_Fix_PHP_Fatal_Error_8220Allowed_Memory_Size8221_in_Magento_2">修复 Magento 2 中 PHP 致命错误&ldquo;允许的内存大小&rdquo;的步骤：</span></h2>
<p><span>第一步：</span><span><span><span>&nbsp; 首先，您需要定位到php.ini目录所在的目录。</span><span>这通常是&nbsp;&nbsp;</span></span></span></p>
<p><span>/etc/php/版本（例如 7.4）/apache2</span></p>
<p><span>第 2 步：接下来，找到</span><span><span>&ldquo;memory_limt =&rdquo;</span></span><span>这一行</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/memory-limit-find.png" /></span></p>
<p></p>
<p><span>第三步：</span><span>最后，你可以相应地调整值并保存</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/QQ20230506-150120_2x.png" /></span></p>
<p><span>第 4 步：</span><span><span><span>修改 php.ini 文件后，您需要重新启动 apache 服务器。</span><span>使用以下命令</span></span></span></p>
<div class="urvanov-syntax-highlighter-syntax crayon-theme-classic urvanov-syntax-highlighter-font-monaco urvanov-syntax-highlighter-os-mac print-yes notranslate" id="urvanov-syntax-highlighter-64534ef74f2bc756858361" data-settings=" minimize scroll-mouseover">
<div class="crayon-toolbar" data-settings=" mouseover overlay hide delay"><span class="crayon-title"></span>
<div class="crayon-tools">
<div class="crayon-button urvanov-syntax-highlighter-nums-button crayon-pressed" title="Toggle Line Numbers">
<div class="urvanov-syntax-highlighter-button-icon">systemctl restart apache2</div>
</div>
</div>
</div>
</div>
<div id="gtx-trans" style="position: absolute; left: -43px; top: 1839.38px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Sat, 06 May 2023 08:53:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：如何更改订单摘要中显示的最大项目数]]></title>
      <link>https://www.360magento.com/blog/magento-2-change-maximum-number/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_Maximum_Number_Of_Items_To_Display_In_Order_Summary_in_Magento_2">更改 Magento 2 中订单摘要中显示的最大项目数的步骤：</span></h2>
<ul>
<li><span>登录到您的 Magento 2 商店</span><span>管理仪表板</span><span>。</span></li>
<li><span>在侧面菜单中，转到</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></li>
<li><span>展开</span><span>左侧菜单中的</span><span>SALES菜单并选择</span><span><span><span>Checkout&nbsp;</span></span><span><span>。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></li>
<li><span>现在，放大</span><span>Checkout Options</span><span>部分。</span></li>
<li><span><span></span></span><span>在要在订单摘要中显示的最大项目数字段</span><span>中输入您想要的值</span><span><span><span>。</span><span>默认值为 10。</span></span></span></li>
</ul>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/Maximum-Number-Of-Items-To-Display-In-Order-Summary.png" /></span></span></span></p>]]></description>
      <pubDate>Fri, 05 May 2023 09:26:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置报价生命周期]]></title>
      <link>https://www.360magento.com/blog/configure-quote-lifetime-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Quote_Lifetime_in_Magento_2">在 Magento 2 中配置报价生命周期的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>Magento 2 管理仪表板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>展开</span><span>左侧面板中的</span><span>SALES菜单并选择</span><span><span><span>Checkout&nbsp;</span></span><span><span>。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第 4 步：</span><span>现在放大</span><span>购物车</span><span>选项并在</span><span>报价生命周期</span><span><span><span>字段中设置所需天数。</span><span>默认值为 30 天。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/quote-lifetime-magento-2.png" /></span></p>]]></description>
      <pubDate>Thu, 04 May 2023 09:22:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置分层导航]]></title>
      <link>https://www.360magento.com/blog/configure-layered-navigation-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_To_Configure_Layered_Navigation_In_Magento_2">在 Magento 2 中配置分层导航的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的 Magento 2 商店的</span><span>管理面板</span><span>。</span></p>
<p><span>第 2 步：</span><span>移至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>展开</span><span>目录</span><span>并选择</span><span>目录</span><span>选项。</span></p>
<p><span>第 4 步：</span><span>现在放大</span><span>分层导航</span><span>部分。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/layered-navigation-configuration.png" /></span></p>
<p><span>显示产品数量：</span><span>如果要在分层导航中显示产品数量，请设置是。</span></p>
<p><span>价格导航步骤计算：</span><span><span><span>设置分层价格导航的方法。</span><span>它有 3 个下拉选项</span></span></span><span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/price-navigation-step-calculation.png" /></span></p>
<p><span>1. Automatic (equalize price ranges) &ndash;</span><span>根据价格范围自动计算价格导航步长</span></p>
<p><span>2. 自动（均衡产品数量）&mdash;&mdash;</span><span>根据产品数量自动计算价格导航步骤。</span></p>
<p><span>选择此选项后，它将生成新字段：</span></p>
<ul>
<li><span>Display Price Interval as One Price：</span><span>设置是否要在特定价格区间内的所有价格都相等时显示价格区间。</span></li>
<li><span>Interval Division Limit：</span><span>设置不分区间的产品个数。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Automatic-equalize-product-counts.png" /></span></p>
<p><span>3. Manual&mdash;&mdash;</span><span>手动设置分层导航价格。</span></p>
<p><span>选择此选项后，它将生成新字段：</span></p>
<ul>
<li><span>默认价格导航步骤：</span><span>指定每个步骤中包含的产品数量。</span></li>
<li><span>价格区间的最大数量：</span><span>定义价格步长的最大数量。</span></li>
<li><span></span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/manual.png" /></span></p>
<p><span> 显示类别过滤器：</span><span>如果要显示类别过滤器，请设置是。</span></p>
<p><span>第五步：</span><span>最后点击</span><span>保存配置</span><span>按钮。</span></p>
<p><span><span><span>&nbsp;</span></span></span></p>]]></description>
      <pubDate>Wed, 03 May 2023 09:18:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中为管理员设置密码重置保护类型]]></title>
      <link>https://www.360magento.com/blog/set-password-reset-protection-type-for-admin/</link>
      <description><![CDATA[<h1><span id="Steps_to_Set_Password_Reset_Protection_Type_for_Admin_in_Magento_2">在 Magento 2 中为管理员设置密码重置保护类型的步骤：</span></h1>
<p><span>第 1 步：</span><span>登录到</span><span>Magento 2 管理仪表板</span><span>。</span></p>
<p><span>第 2 步：</span><span>移至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>从左侧菜单中，展开</span><span>&ldquo;高级&rdquo;</span><span>并选择</span><span>&ldquo;管理&rdquo;&nbsp;</span><span>。</span></p>
<p><span>第 4 步：</span><span>现在展开</span><span>安全</span><span>选项。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Screenshot_1.png" /></span></p>
<p><a href="https://magecomp.com/blog/wp-content/uploads/2022/09/Screenshot_1.png" data-wpel-link="internal"></a></p>
<p><span>第 5 步：在</span><span><span>密码重置保护类型字段</span></span><span>中选择您想要的选项</span><span>。</span><span><span></span></span><span><span></span></span></p>
<ul>
<li><span>通过IP和Email：</span><span>在收到与admin账户关联的邮箱的通知响应后，可以在线重置admin密码。</span></li>
<li><span>通过IP：</span><span>无需任何确认即可在线重置管理员密码。</span></li>
<li><span>通过电子邮件：</span><span>可以通过回复与管理员帐户关联的电子邮件通知来重置管理员密码。</span></li>
<li><span>无：</span><span>只有管理员可以重置密码。</span></li>
</ul>
<p><span>第 6 步：</span><span>最后单击</span><span>Save Config</span><span>以应用更改。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Tue, 02 May 2023 08:19:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置发货起点]]></title>
      <link>https://www.360magento.com/blog/set-shipping-point-of-origin-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Set_Shipping_Point_of_Origin_in_Magento_2">在 Magento 2 中设置发货起点的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>Magento 2 管理面板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>现在从左侧窗格中展开</span><span>SALES</span><span>并选择</span><span>Shipping Settings&nbsp;</span><span>。</span></p>
<p><span>第 4 步：</span><span>展开</span><span>来源</span><span>选项并输入国家、地区/州、邮政编码、城市、街道地址和街道地址第 2 行。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/shipping-point-of-origin-configuration.png" /></span></p>]]></description>
      <pubDate>Mon, 01 May 2023 08:13:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置结帐选项]]></title>
      <link>https://www.360magento.com/blog/configure-checkout-options-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Checkout_Options_in_Magento_2">在 Magento 2 中配置结帐选项的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>Magento 2 管理</span><span>仪表板。</span></p>
<p><span>第 2 步：</span><span>转到</span><span>商店 &gt; 设置 &gt; 配置</span><span>。</span></p>
<p><span>第 3 步：</span><span>展开</span><span>SALES</span><span>并选择</span><span>Checkout&nbsp;</span><span>。</span></p>
<p><span>第 4 步：</span><span>现在放大</span><span>Checkout Options&nbsp;</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/checkout-options.png" /></span></p>
<ul>
<li><span>Enable Onepage Checkout &ndash;</span><span>设置 Yes 以允许客户快速完成结帐。</span></li>
<li><span>Allow Guest Checkout &ndash;</span><span>设置 Yes 以允许访客用户在不注册您的 Magento 2 商店帐户的情况下结账。</span><a href="https://magecomp.com/blog/guest-checkout-magento-2/" data-wpel-link="internal"><span><br /></span></a></li>
<li><span>显示帐单地址 &ndash;</span><span>选择在付款方式或付款页面上显示帐单地址的位置。</span></li>
<li><span>启用条款和条件 &ndash;</span><span>如果需要客户同意条款和条件，则设置。</span></li>
<li><span>订单摘要中要显示的最大项目数 -</span><span><span><span>输入一个数字，表示结账时要在订单摘要中显示的项目数。</span><span>默认值为 10。</span></span></span></li>
</ul>]]></description>
      <pubDate>Sun, 30 Apr 2023 09:11:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[将您的 IP 地址添加到 Magento 2 中的白名单]]></title>
      <link>https://www.360magento.com/blog/add-your-ip-address-to-whitelist-magento-2/</link>
      <description><![CDATA[<p>如何在 Magento 2 中将您的 IP 地址添加到白名单。</p>
<p>当您想要启用 Template Path Hints时，您必须将您的 IP 添加到允许列表中，以避免破坏客户的购物体验。您可以从&ldquo;开发人员客户端限制&rdquo;选项将您的 IP 地址添加到允许列表。</p>
<h2><span id="Steps_to_Add_your_IP_Address_to_Whitelist_in_Magento_2">在 Magento 2 中将您的 IP 地址添加到白名单的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到</span><span>Magento 2 管理仪表板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>在左侧面板中，放大</span><span>ADVANCED</span><span>选项并选择</span><span>Developer&nbsp;</span><span>。</span></p>
<p><span>第 4 步：</span><span>现在展开</span><span>Developer Client Restrictions</span><span>部分。</span></p>
<p><span>第 5 步：</span><span>在</span><span>允许的 IP</span><span><span><span>字段中，输入您的 IP 地址。</span><span>如果您有多个 IP，您可以添加所有 IP，并用逗号分隔。</span></span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/IP-address-allow-list.png" /></p>]]></description>
      <pubDate>Sat, 29 Apr 2023 08:08:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：在目录上显示含税和不含税的产品价格]]></title>
      <link>https://www.360magento.com/blog/magento-2-display-product-price-including/</link>
      <description><![CDATA[<h2><span id="Steps_to_Display_Product_Price_Including_Excluding_Tax_on_Catalog_in_Magento_2">在 Magento 2 的目录中显示产品价格（含税和不含税）的步骤：</span></h2>
<p><span>第 1 步：</span><span>从管理面板侧边栏移至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span>展开</span><span>左侧窗格中的</span><span>&ldquo;销售&rdquo;菜单并选择</span><span><span><span>&ldquo;税收&rdquo;</span></span><span><span>选项。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第3步：</span><span>现在放大</span><span>价格显示设置</span><span>选项</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/price-incl-excl-tax-magento-2.png" /></span></p>
<p><span>第 4 步：</span><span>为给定的字段选择合适的。</span></p>
<p><span>在目录中显示产品价格</span></p>
<ul>
<li><span>不含税 &ndash; 它将在目录中显示不含税率的产品价格。</span></li>
<li><span>含税 &ndash; 它将在目录上显示产品价格和税率。</span></li>
<li><span>含税和不含税&mdash;&mdash;它会在目录中显示含税和不含税的产品价格。</span></li>
</ul>
<p><span>显示运费</span></p>
<ul>
<li><span>不含税 - 它将显示不含税率的运费。</span></li>
<li><span>含税 - 它将显示含税率的运费。</span></li>
<li><span>含税和不含税&mdash;&mdash;它将显示含税和不含税的运费。</span></li>
</ul>
<p><span>第 5 步：</span><span>最后，单击</span><span>保存配置</span><span>按钮以应用更改。</span></p>]]></description>
      <pubDate>Fri, 28 Apr 2023 09:07:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中配置订单、发票、贷记凭证显示设置]]></title>
      <link>https://www.360magento.com/blog/rder-invoice-credit-memo-display-settings-in-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Configure_Order_Invoice_Credit_Memo_Display_Settings_in_Magento_2">在 Magento 2 中配置订单、发票、贷记凭证显示设置的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>管理仪表板</span><span>并导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：现在，</span><span>从左侧菜单面板中</span><span>放大</span><span>SALES ，然后选择</span><span><span><span>Tax</span></span><span><span>选项。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第 3 步：</span><span>展开</span><span>订单、发票、贷记凭证显示设置</span><span>选项。</span></p>
<p><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/price-display-settings-magento-2.png" /></span></p>
<p><span>第 4 步：</span><span>应用所需的设置</span></p>
<ul>
<li><span>显示价格 &ndash;</span><span>确定如何显示价格 &ndash; 不含税、含税或含税和不含税。</span></li>
<li><span>显示小计 &ndash;</span><span>确定如何显示小计 &ndash; 不含税、含税或含税和不含税。</span></li>
<li><span>显示运费 &ndash;</span><span>确定如何显示运费 &ndash; 不含税、含税或含税和不含税。</span></li>
<li><span>另外显示不含税的订单总计&mdash;&mdash;</span><span>确定订单总计是否必须显示为含税或不含税。</span></li>
<li><span>显示完整的税务摘要&mdash;&mdash;</span><span>确定是否必须显示完整的税务摘要。</span></li>
<li><span>显示零税小计 &ndash;</span><span>确定是否必须显示零税小计。</span></li>
</ul>
<p><span>第 5 步：</span><span>完成后，点击</span><span>&ldquo;保存配置&rdquo;</span><span>按钮。</span></p>
<p><span>&nbsp;</span></p>
<p><span></span></p>]]></description>
      <pubDate>Thu, 27 Apr 2023 08:04:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 中启用自动备份]]></title>
      <link>https://www.360magento.com/blog/automatic-backup-magento-2/</link>
      <description><![CDATA[<h2><span>Magento 2 在管理配置中提供了设置自动备份的选项。管理员可以备份数据库、系统文件、媒体文件等。Magento 使用 GZ 格式压缩数据库备份，使用 TGZ 格式压缩系统备份和数据库和媒体备份。</span></h2>
<h2><span id="Steps_to_Enable_Automatic_Backup_in_Magento_2">在 Magento 2 中启用自动备份的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>Magento 管理仪表板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>Stores &gt; Settings Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>放大</span><span>高级</span><span>菜单并选择</span><span>系统</span><span>。</span></p>
<p><span>第 4 步：</span><span>现在展开</span><span>备份设置</span><span>部分并将</span><span>启用备份</span><span>字段设置为是。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/automatic-backup-configuration.png" /></p>
<p>第 5 步：现在，还将启用计划备份字段设置为是。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/enable-scheduled-backup.png" /><br />第 6 步：现在在 Magento 2 中应用自动备份所需的设置。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/scheduled-backup-settings.png" /><br />计划的备份类型 -从可用的下拉选项中选择备份类型。它有 4 个选项：数据库、数据库和媒体、系统和系统（不包括媒体）。<br />开始时间 &ndash;以 hh:mm:ss 格式设置备份时间。<br />频率 &ndash;将备份频率设置为每日、每周或每月。<br />维护模式&mdash;&mdash;如果要在备份时启用维护模式，选择是；否则，将其设置为否。<br />第 7 步：最后，点击屏幕右上角的&ldquo;保存配置&rdquo;按钮。</p>]]></description>
      <pubDate>Wed, 26 Apr 2023 09:00:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中更改索引模式]]></title>
      <link>https://www.360magento.com/blog/change-index-mode-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Change_Index_Mode_in_Magento_2">在 Magento 2 中更改索引模式的步骤：</span></h2>
<p><span>第 1 步：</span><span>要更改 Magento 2 中的索引模式，请首先登录到您的 Magento 2 管理面板。</span></p>
<p><span>第 2 步：</span><span>从屏幕左侧的菜单面板中，选择</span><span>系统 &gt; 工具 &gt; 索引管理</span><span>。</span></p>
<p><span>第 3 步：</span><span>现在选择要更改模式的索引器。</span></p>
<p><span>第 4 步：</span><span>从</span><span>&ldquo;操作&rdquo;</span><span>下拉列表中选择所需的选项。</span></p>
<ul>
<li><span>保存时更新&mdash;&mdash;</span><span><span><span>这是索引的默认操作。</span><span>使用保存时更新模式，索引会在管理面板中发生任何更改后更新。</span></span></span></li>
<li><span>按计划更新 &ndash;</span><span><span><span>这是索引的推荐操作。</span><span>使用按计划更新，索引根据 cron 作业进行更新。</span></span></span></li>
</ul>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/index-management.png" /></span></span></span></p>
<p><span><span>第 5 步：</span><span>选择操作后，单击</span><span>提交</span><span>按钮应用更改。</span></span></p>]]></description>
      <pubDate>Tue, 25 Apr 2023 08:16:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[启用区分大小写的管理员登录]]></title>
      <link>https://www.360magento.com/blog/magento-2-enable-case-sensitive-admin-login/</link>
      <description><![CDATA[<h2><span id="Steps_to_Enable_Case_Sensitive_Admin_Login_in_Magento_2">在 Magento 2 中启用区分大小写的管理员登录的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的 Magento 2 管理面板。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>现在，放大</span><span>ADVANCED</span><span>选项并选择</span><span>Admin&nbsp;</span><span>。</span></p>
<p><span>第四步：</span><span>然后，展开</span><span>安全</span><span>选项。</span></p>
<p><span>第 5 步：将</span><span><span>登录区分大小写字段</span></span><span>设置</span><span>为是。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/case-sensitive-admin-login.png" /></span></p>]]></description>
      <pubDate>Mon, 24 Apr 2023 08:15:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中查看导入历史]]></title>
      <link>https://www.360magento.com/blog/import-history-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_View_the_Import_History_in_Magento_2">在 Magento 2 中查看导入历史记录的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到</span><span>Magento 2 管理面板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>系统 &gt; 数据传输 &gt; 导入历史记录</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/import-history-magento-2.png" /></span></p>
<p><span><span>第 3 步：</span><span>您可以查看有关导入历史记录的详细信息。</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/import-history-details.png" /></span></span></p>
<p></p>
<ul>
<li><span>ID &ndash;</span><span>特定导入的 ID。</span></li>
<li><span>开始日期和时间 &ndash;</span><span>导入发生的日期和时间。</span></li>
<li><span>用户 &ndash;</span><span>进行导入的用户。</span></li>
<li><span>导入的文件&mdash;&mdash;</span><span>从这里下载导入的文件。</span></li>
<li><span>错误文件 &ndash;</span><span>导入发生时的错误文件（如果有）。</span></li>
<li><span>执行时间&mdash;&mdash;</span><span>导入过程的持续时间。</span></li>
<li><span>摘要 &ndash;</span><span>创建、删除、更新或发生错误的项目数。</span></li>
</ul>
<p><span>第四步：</span><span>点击导入文件栏下的</span><span>下载</span><span>，下载导入的文件。</span></p>]]></description>
      <pubDate>Sun, 23 Apr 2023 08:06:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置全页缓存]]></title>
      <link>https://www.360magento.com/blog/configure-full-page-cache-magento-2/</link>
      <description><![CDATA[<h2><span id="What_is_Full_Page_Cache_in_Magento_2">Magento 2 中的全页缓存是什么？</span></h2>
<p><span><span><span>Magento 2 全页缓存有助于减少服务器的加载时间并提高响应时间。</span><span>全页缓存有助于快速显示类别、产品和 CMS 页面。</span><span>全页缓存还有助于改善客户体验和转化率。</span></span></span></p>
<p><span><span><span>如果没有缓存，每个页面将运行代码块并从数据库中检索数据。</span><span>使用全页缓存，加载时间减少，页面检索数据更快。&nbsp;</span></span></span></p>
<h2><span id="How_does_Magento_2_Full_Page_Cache_Work">Magento 2 全页缓存如何工作？</span></h2>
<p><span><span><span>当您打开网页时，会向服务器发送生成页面内容的请求。</span><span>这个过程需要一些时间。</span><span>服务器不存储页面内容，并且每当有人访问该页面时都必须重新生成完整的页面。</span></span></span></p>
<p><span><span><span>当您使用完整页面缓存时，Magento 会在页面首次加载时在系统中保留该页面的副本。</span><span>因此，当第二次触发该页面时，它加载速度更快，因为它在缓存中包含副本。</span></span></span></p>
<h2><span id="Steps_to_Configure_Full_Page_Cache_in_Magento_2">在 Magento 2 中配置全页缓存的步骤：</span></h2>
<p><span>第 1 步：</span><span>在管理面板中，导航至</span><span>Store &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span>展开</span><span>&ldquo;高级&rdquo;选项</span><span>卡并选择</span><span>&ldquo;系统&rdquo;&nbsp;</span><span>。</span></p>
<p><span>第 3 步：</span><span>现在放大</span><span>Full Page Cache</span><span>选项。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/Configure-Full-Page-Cache.png" /></span></p>
<ul>
<li><span>缓存应用程序</span><span>&ndash; 选择以下选项之一：</span></li>
</ul>
<ol>
<li><span>内置缓存</span><span>&mdash;&mdash;在开发模式下使用。</span></li>
<li><span>Varnish Cache&nbsp;</span><span>&ndash; 这用于生产模式，是缓存的推荐选项。</span></li>
</ol>
<ul>
<li><span>公共内容的 TTL&nbsp;</span><span><span><span>&ndash; 设置页面缓存超时。</span><span>它的默认值为 86400。</span></span></span></li>
</ul>
<p><span>第四步：如果</span><span><span><span>在</span></span><span><span>Caching Application字段中</span></span></span><span>选择了</span>&nbsp;<span><span>Varnish Cache</span></span><span>选项</span><span><span><span>，则必须进行</span></span><span><span>Varnish Configuration</span></span><span><span>设置。</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/Configure-Varnish-Cache.png" /></span></span></span></p>
<ul>
<li><span>访问列表</span><span><span><span>&mdash;&mdash;输入以逗号&ldquo;,&rdquo;分隔的IP地址，可以清除Varnish配置生成配置文件。</span><span>访问列表的默认值为 localhost。</span></span></span></li>
<li><span>后端主机</span><span><span><span>&ndash; 输入生成配置文件的后端主机的 IP 地址。</span><span>后端主机的默认值为 localhost。</span></span></span></li>
<li><span>后端端口</span><span><span><span>&mdash;&mdash;确定配置文件生成的后端端口。</span><span>默认后端端口值为 8080。</span></span></span></li>
<li><span>宽限期</span><span><span><span>- 以秒为单位指定宽限期以生成配置文件。</span><span>默认宽限期值为 300。</span></span></span></li>
<li><span>导出配置</span><span>&mdash;&mdash;根据您使用的 Varnish 版本单击适当的按钮以导出 varnish.vcl 文件中的配置。</span></li>
</ul>
<p><span>第 5 步：</span><span>完成后，单击</span><span>&ldquo;保存配置&rdquo;</span><span>按钮。</span></p>]]></description>
      <pubDate>Sat, 22 Apr 2023 08:14:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加货币符号]]></title>
      <link>https://www.360magento.com/blog/add-currency-symbol-magento-2/</link>
      <description><![CDATA[<h2><span id="Steps_to_Add_Currency_Symbol_in_Magento_2">在 Magento 2 中添加货币符号的步骤：</span></h2>
<p><span>第 1 步：</span><span>从您的 Magento 2 商店的管理面板，转到</span><span>Stores &gt; Currency &gt; Currency Symbols&nbsp;</span><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/currency-symbol-configuration.png" /></span></p>
<p><span>第 2 步：</span><span><span><span>添加到您商店的货币将显示在这里。</span><span>如果您想要自定义货币符号，请取消选中使用标准复选框并输入货币符号。</span><span>选中使用标准以使用货币的标准符号。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/add-currency-symbol.png" /></span></p>
<p><span>在这里，我为美元添加了自定义货币符号。&nbsp;</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/custom-currency-symbol.png" /></span></p>
<p><span>第 3 步：</span><span>完成更改后，单击</span><span>右上角的</span><span>保存货币符号按钮。</span><span><span></span></span></p>
<p><span>注意：</span><span>确保您刷新 Magento 缓存以在前端应用更改。</span></p>
<p><span>输出：</span></p>
<p><span><span><span>现在检查您的 Magento 2 店面。</span><span>您可以看到自定义货币符号已成功应用。</span></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/custom-currency-symbol-frontend.png" /></span></p>
<p></p>]]></description>
      <pubDate>Fri, 21 Apr 2023 08:20:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置客户帐户选项]]></title>
      <link>https://www.360magento.com/blog/customer-account-options-magento-2/</link>
      <description><![CDATA[<p><span>从注册到售后服务，客户在您的 Magento 2 商店的旅程必须得到优化。</span><span>使用客户帐户配置，商店管理员可以轻松管理客户。</span><span>Magento 2 为客户管理提供了多种客户配置选项。</span></p>
<h2><span id="Steps_to_Setup_Customer_Account_Options_in_Magento_2">在 Magento 2 中设置客户帐户选项的步骤：</span></h2>
<p><span>第 1 步：</span><span>从</span><span>管理仪表板</span><span><span><span>。</span><span>转到</span></span></span><span>Stores &gt; Settings &gt; Configuration&nbsp;</span><span>。</span></p>
<p><span>第 2 步：现在</span><span>从左侧面板</span><span>展开</span><span>CUSTOMERS选项卡并选择</span><span><span><span>Customer Configuration&nbsp;</span></span><span><span>。</span></span></span><span><span></span></span><span><span></span></span><span><span></span></span></p>
<p><span>第 3 步：</span><span>现在扩大</span><span>Create New Account Options&nbsp;</span><span>。</span><br /><img src="https://www.360magento.com/media/wysiwyg/configuration-steps-1.png" /><br /><span>第 4 步：</span><span>现在根据需要应用设置。</span><br /><img src="https://www.360magento.com/media/wysiwyg/customer-account-options-2.png" /></p>
<ul>
<li><span>启用自动分配到客户组：</span><span>确定客户是否分配到默认客户组。</span></li>
<li><span>默认组：</span><span><span><span>设置默认客户组。</span></span></span></li>
<li><span>禁用基于 VAT ID 的自动组更改的默认值：</span><span>选择是否根据 VAT ID 自动更改客户组。</span></li>
<li><span>在店面显示增值税号：</span><span>设置增值税号是否对前面的客户可见。</span></li>
<li><span>Email is required field for Admin order creation：</span><span>确定在为新客户创建管理订单时是否需要电子邮件。</span></li>
<li><span>默认电子邮件域：</span><span>设置默认电子邮件域。</span></li>
<li><span>默认欢迎电子邮件：</span><span>用于默认欢迎电子邮件的电子邮件模板。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/customer-account-options-1.png" /></span></p>
<ul>
<li><span>Default Welcome Email Without Password：</span><span>默认的欢迎电子邮件模板，用于创建没有密码的客户。</span></li>
<li><span>电子邮件发件人：</span><span>从此处选择发件人电子邮件。</span></li>
<li><span>需要电子邮件确认：</span><span>确定是否需要确认才能创建帐户。</span></li>
<li><span>确认链接电子邮件：</span><span>用于确认电子邮件的电子邮件模板。</span></li>
<li><span>欢迎电子邮件：</span><span>帐户确认后，用于欢迎消息的电子邮件模板。</span></li>
<li><span>生成人性化的客户 ID：</span><span>用于输入和存储增值税 ID 的字段是否从店面可见。</span></li>
</ul>
<p><span>最后点击</span><span>保存配置</span><span>。</span></p>]]></description>
      <pubDate>Thu, 20 Apr 2023 08:25:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：更新客户资料]]></title>
      <link>https://www.360magento.com/blog/updating-customer-magento2/</link>
      <description><![CDATA[<p>有时管理员需要更新客户信息。管理员可以从管理面板管理所有客户资料。让我们了解更多。</p>
<p>客户资料包含个人详细信息、电子邮件、出生日期、地址、订单和其他信息。在 Magento 2 中，客户可以从&ldquo;我的帐户&rdquo;部分更新他们的信息。允许客户在您的 Magento 2 网站上添加个人资料图片，以提供个性化的用户体验。</p>
<h2><span id="Steps_to_Update_a_Customer_Profile_in_Magento_2">在 Magento 2 中更新客户资料的步骤：</span></h2>
<p><span>第 1 步：</span><span>登录到您的</span><span>Magento 2 管理面板</span><span>。</span></p>
<p><span>第 2 步：</span><span>导航至</span><span>客户 &gt; 所有客户</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/customer-steps.png" /></span></p>
<p><span><span>第3步：</span><span>从网格中找到客户，点击</span><span><span>操作栏中的</span></span><span>编辑。</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/customer-edit.png" /></span></span></p>
<p><span>第 4 步：</span><span>从左侧面板中选择您要编辑的信息类型并进行必要的更改。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/customer-details.png" /></span></p>
<p><span>客户信息</span></p>
<ul>
<li><span>客户视图</span><span>&mdash;&mdash;显示客户的个人信息。</span></li>
<li><span>帐户信息</span><span>&mdash;&mdash;它提供有关客户的详细信息，管理员可以在其中编辑个人详细信息、出生日期、电子邮件并将客户关联到网站。</span></li>
<li><span>地址</span><span>&mdash;&mdash;它允许编辑默认的账单地址和送货地址，甚至可以添加新地址。</span></li>
<li><span>订单</span><span>- 它包含客户订单的详细信息。</span></li>
<li><span>购物车</span><span><span><span>&mdash;&mdash;显示客户的购物车。</span><span>这意味着产品当前在购物车中并且尚未购买。</span></span></span></li>
<li><span>时事通讯</span><span>- 它显示发送给客户的所有电子邮件。</span></li>
<li><span>账单协议</span><span>&ndash; 包含客户与商店之间的所有 PayPal 账单协议。&nbsp;</span></li>
<li><span>产品评论</span><span>&ndash; 它显示客户提交的产品评论。</span></li>
<li><span>愿望清单</span><span>&mdash;&mdash;它显示了客户希望购买并可以稍后添加到购物车的产品列表。</span></li>
</ul>
<p><span>第 5 步：</span><span>完成后，单击</span><span>&ldquo;保存客户&rdquo;</span><span>按钮。</span></p>
<p><span>&nbsp;</span></p>]]></description>
      <pubDate>Wed, 19 Apr 2023 08:21:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何刷新 Magento 2 中的产品图片缓存]]></title>
      <link>https://www.360magento.com/blog/flush-cache-magento-2/</link>
      <description><![CDATA[<p>Magento 2 中的缓存管理有助于提高网站的性能。Magento 缓存有多种类型。其中之一是图像缓存。每当用户上传产品图片、为产品图片添加水印或调整其大小时，更改都不会反映在前端。那时，管理员需要刷新目录图像缓存。</p>
<h2><span id="Steps_to_Flush_the_Product_Image_Cache_in_Magento_2">在 Magento 2 中刷新产品图像缓存的步骤：</span></h2>
<p><span>第 1 步：</span><span>从</span><span>Admin Dashboard</span><span>导航至</span><span>System &gt; Tools &gt; Cache Management&nbsp;</span><span>。</span></p>
<p><span>第 2 步：</span><span>在</span><span>附加缓存管理</span><span>部分下，单击</span><span>刷新目录图像缓存</span><span>按钮。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/flush-catalog-images-cache.png" /></span></p>
<p><span><span>第 3 步：</span><span>您将在页面顶部收到图像缓存清理成功的消息。</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/image-cache-clean-success-message.png" /></span></span></p>
<p></p>
<p><span>这将清除预生成的产品图像文件。</span><span>它还将清除存储在 media/catalog/product/cache 中已自动调整大小和水印的目录图像。&nbsp;</span></p>]]></description>
      <pubDate>Tue, 18 Apr 2023 08:24:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何通过管理仪表板更改 Magento 2 加密密钥]]></title>
      <link>https://www.360magento.com/blog/magento-2-encryption-key/</link>
      <description><![CDATA[<p>你好 Magento 朋友们，</p>
<p>在此博客中，我们将了解如何通过管理仪表板更改 Magento 2 加密密钥。</p>
<p>加密密钥保护 Magento 2 中的密码和其他敏感数据。您可以允许 Magento 2 生成自己的加密密钥或自己创建一个。您可以从 Magento 2 管理仪表板中的加密密钥工具更改加密密钥。出于安全原因，最好定期更改加密密钥。</p>
<p></p>
<p>通过管理仪表板更改 Magento 2 加密密钥的步骤：<br />第 1 步：登录到您的Magento 2 管理面板。</p>
<p>第 2 步：从侧边栏菜单导航至&ldquo;系统&rdquo;&gt;&ldquo;其他设置&rdquo;&gt;&ldquo;管理加密密钥&rdquo; 。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/encryption-key-path.png" /></p>
<p><span>第 3 步：</span><span>执行以下设置</span></p>
<ul>
<li><span><span></span></span><span>将自动生成密钥</span><span>设置</span><span>为</span><span>是以</span><span>生成新密钥。</span></li>
<li><span><span></span></span><span>将自动生成密钥</span><span>设置</span><span>为</span><span>否</span><span>以使用不同的密钥。</span><span>然后在新密钥字段</span><span>中输入您要使用的密钥</span><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/encryption-key-configuration.png" /></span></p>
<p><span><span>第 4 步：</span><span>现在单击</span><span>&ldquo;更改加密密钥&rdquo;</span><span>按钮。</span></span></p>]]></description>
      <pubDate>Mon, 17 Apr 2023 08:15:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何翻译 Magento 2 中的产品字段标签]]></title>
      <link>https://www.360magento.com/blog/translate-product-field-magento-2/</link>
      <description><![CDATA[<p><span>Magento 2 提供了根据商店视图翻译产品字段标签的功能。</span><span>让我们看看如何在 Magento 2 中翻译产品字段标签。</span></p>
<p>在 Magento 2 中翻译产品字段标签的步骤：<br />第 1 步：从您的管理仪表板，导航至Stores &gt; Attributes &gt; Product 。</p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/configuration.png" /></span></p>
<p><span>第 2 步：</span><span>从列表中找到要翻译的属性，然后以编辑模式打开它。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/product-attributes.png" /><br /><span>第 3 步：</span><span>在&ldquo;属性信息&rdquo;下，选择</span><span>&ldquo;管理标签&rdquo;</span><span>并为每个商店视图输入翻译后的标签。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/manage-labels.png" /><br /><span>第 4 步：</span><span>最后，单击</span><span>&ldquo;保存属性&rdquo;</span><span>按钮。</span></p>]]></description>
      <pubDate>Sun, 16 Apr 2023 08:11:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中将产品翻译成其他语言]]></title>
      <link>https://www.360magento.com/blog/translate-products-language-magento-2/</link>
      <description><![CDATA[<p><span>将产品翻译成各种语言有助于改善商店的用户体验。</span><span>最好的部分是在 Magento 2 中，您不需要创建新产品来显示不同语言的产品。</span><span>Magento 提供后端功能，可以轻松地将产品翻译成其他语言。</span></p>
<p>在 Magento 2 中将产品翻译成其他语言的步骤：<br />第 1 步：从管理仪表板导航到目录 &gt; 产品。</p>
<p>第 2 步：选择您想要的产品并在编辑模式下打开它。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/product-edit.png" /></p>
<p><span>第 3 步：</span><span>选择要翻译产品的商店视图。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/store-view.png" /></span></p>
<p></p>
<p><span>第 4 步：</span><span>更改产品名称。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/product-name.png" /></span></p>
<p><span>另外，更改产品说明。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/product-description.png" /></span></p>
<p><span>最后，点击</span><span>保存</span><span>。</span></p>
<p><span><span><span>保存产品后，请检查商店的前端。</span><span>选择商店视图并打开产品。</span><span>您会看到产品已翻译成所选语言。</span></span></span></p>
<p></p>]]></description>
      <pubDate>Sat, 15 Apr 2023 08:08:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何将谷歌分析添加到 Magento 2]]></title>
      <link>https://www.360magento.com/blog/add-google-analytics-to-magento-2/</link>
      <description><![CDATA[<p>Google Analytics 是电子商务企业跟踪网站流量和客户行为的有力工具。如果您在 Magento 2 上经营在线商店，那么将 Google Analytics 集成到您的业务战略中绝对是必不可少的，这样您才能获得有关客户的宝贵见解，并做出明智的、数据驱动的决策，从而改善您的在线形象。使用 Google Analytics，您可以准确了解客户的行为，例如他们正在访问哪些页面、他们在页面上停留了多长时间以及他们来自哪里。此外，您还可以跟踪转化率、销售额和其他关键绩效指标 (KPI)，以更好地了解您的客户群并制定有效的策略来推动更多流量和转化。最终，Google Analytics（分析）可为您提供数据，以便为您的电子商务业务做出最佳决策。</p>
<p>本博客将介绍将 Google Analytics 添加到 Magento 2 的步骤。</p>
<p>第 1 步：创建一个 Google Analytics 帐户<br />如果您仍然需要 Google Analytics 帐户，请转到analytics.google.com并注册。注册后，您需要为您的网站创建一个属性。</p>
<p>第 2 步：获取跟踪代码<br />接下来，您需要获取网站的跟踪代码。转到您的 Google Analytics 帐户的管理部分，然后单击&ldquo;跟踪信息&rdquo;，然后单击&ldquo;跟踪代码&rdquo;。</p>
<p>复制提供的跟踪代码。您将在下一步中需要此代码。</p>
<p>第 3 步：将跟踪代码添加到 Magento 2<br />在您的 Magento 2 管理面板中，转到&ldquo;商店&rdquo;和&ldquo;设置&rdquo;。单击&ldquo;配置&rdquo;，然后转到&ldquo;销售&rdquo;，然后转到&ldquo;Google API&rdquo;。</p>
<p>在&ldquo;Google Analytics&rdquo;下，将您从 Google Analytics 复制的跟踪代码粘贴到&ldquo;GA 代码&rdquo;字段中。然后，为&ldquo;启用&rdquo;选择&ldquo;是&rdquo;，然后单击&ldquo;保存配置&rdquo;。</p>
<p>第 4 步：验证安装<br />要验证安装是否成功，请返回您的 Google Analytics 帐户并点击&ldquo;实时&rdquo;，然后点击&ldquo;概览&rdquo;。如果跟踪代码工作正常，您应该会看到您网站上的活跃用户数。</p>
<p>第五步：开始追踪<br />就是这样！您已经成功地将 Google Analytics 集成到您的 Magento 2 网站中。现在，您可以开始跟踪网站流量和客户行为。您可以在您的 Google Analytics 帐户中查看数据，并使用它来对您的在线商店做出明智的决定。</p>
<p>总之，将 Google Analytics 集成到您的 Magento 2 网站中既快速又简单。您将获得有关您的客户和网站流量的宝贵见解，这可以帮助您做出数据驱动的决策以改善您的在线形象。</p>]]></description>
      <pubDate>Fri, 14 Apr 2023 07:21:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[优化 Magento 性能：增加商店销售额的 10 种方法]]></title>
      <link>https://www.360magento.com/blog/magento-performance-10-ways/</link>
      <description><![CDATA[<p>如何优化 Magento 性能<br />1.启用平面目录<br />启用平面目录以优化 Magento 性能。Magento 使用 EAV 模型以特定方式存储数据，该模型允许自我扩展。但是，这是由于需要将任何请求扩展到商店，从而导致用户产生额外费用。平面目录允许您组合数据，从而加快收集和搜索数据的过程。因此，支持 Magento 的站点可以获得最佳性能。</p>
<p>2. 托管环境<br />将您的商店托管环境更改为服务器以处理您期望的流量。它还必须提供正确数据存储和检索所需的数据使用。重点应该放在 CPU 使用率上，以确定是否需要更换服务器。如果CPU使用率达到100%，说明服务器需要升级。</p>
<p>3. 服务器和缓存<br />您应该在您的站点上启用浏览器缓存，以简化和提高下载速度。这是因为站点可以从浏览器重新加载，而不是每次都向服务器发送请求。为临时数据存储运行内容分发网络 (CDN) 也是一个好主意，让用户可以快速且无问题地使用该站点。Web 应用程序加速器对于缓存特别有用，这些加速器可以将存储数据的检索速度提高 80%。</p>
<p>4.代码优化<br />用户必须进行代码优化。Magento 中的 PHP 优化通常需要像 Zend 这样的加速器。其他方法包括检测创建时可能发生的锁定和删除任何 PHP 模块。用户通常不需要它，但它会占用空间。</p>
<p>5.数据库优化<br />Magento 用户不应使用常规数据库，而应使用查询索引和更广泛的优化方案。它帮助他们的数据库移动得更快，并允许他们更有效地检索信息。数据库管理系统有助于定期加速数据库优化。</p>
<p>6.集成Magento编译功能<br />用户必须集成 Magento 的编译功能。此功能需要正确使用编译器来加快所涉及站点的加载速度。这种 Magento 性能优化技术直接支持自动加载功能。</p>
<p>7. Magento版本维护<br />此外，维护 Magento 版本也很重要。如果更新到最新版本，Magento 优化将变得更加有效。最新版本运行更流畅、更快，因为默认情况下它有许多最新的更新和修复。</p>
<p>8.文件大小标准化<br />这是 Magento 性能优化的另一个关键因素。必须通过确保所有文件、照片、图像和视频的大小使站点和服务器能够轻松处理它们来优化内容。它提供了所有内容都以几乎相同的速度加载，并且没有任何滞后或延迟页面加载。</p>
<p>9.Magento配置<br />配置是必要的，因为平台本身可能有许多未使用的扩展。如果商店最近改变了方向并且只需要一些旧材料，这应该会发生。它是优化 Magento 性能的基本方法之一。</p>
<p>10.自动缩放<br />Magento 的性能优化包括根据需要分配服务器功率的自动缩放。自动缩放允许服务器避免瓶颈，根据需要增加或减少其使用量。当服务器有时使用过多或过少时，它会阻止恒定级别。它还允许任何 Magento 站点在高流量期间使用更多服务器空间。多亏了这一点，一切都顺利进行。</p>
<p>Magento 2 是将近十年前问世的原始 Magento 平台的一个版本。将近四分之一的电子商务网站通过 Magento 运行。因此，Magento 性能优化已成为其流程的关键。用户可以通过多种方式优化 Magento 的性能。这取决于网站。它包括使用的形式和站点的所有者，即用户的技术能力。用户可以更新 Magento 以及他们使用的扩展和模块。它还包括服务器升级、自动缩放或其他形式的优化。</p>
<p>由于 Magento 是一种流行的 CMS，因此优化性能至关重要。因此，这意味着需要优化的 Magento 站点会将客户拒之门外。客户更有可能返回加载速度快并能快速为他们提供所需信息的地方。没有这些东西的站点将把客户拒之门外，因为他们在其他地方总有其他选择。</p>]]></description>
      <pubDate>Thu, 13 Apr 2023 07:17:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2 获取订单信息输出在模板]]></title>
      <link>https://www.360magento.com/blog/get-order-info-to-tmp/</link>
      <description><![CDATA[<p><span>要在 Magento 2 中获取订单信息，您可以在自定义模块或块类中使用以下代码：</span><br /><br /></p>
<pre>&lt;?php
namespace Vendor\Module\Block;

use Magento\Framework\View\Element\Template;
use Magento\Sales\Api\OrderRepositoryInterface;

class OrderInfo extends Template
{
    protected $orderRepository;

    public function __construct(
        Template\Context $context,
        OrderRepositoryInterface $orderRepository,
        array $data = []
    ) {
        $this-&gt;orderRepository = $orderRepository;
        parent::__construct($context, $data);
    }

    public function getOrderInfo($orderId)
    {
        $order = $this-&gt;orderRepository-&gt;get($orderId);
        return $order;
    }
}
</pre>
<p><span>在上面的代码中，我们正在创建一个</span><code>OrderInfo</code><span>扩展</span><code>Template</code><span>类的块类。</span><code>OrderRepositoryInterface</code><span><span>我们正在将用于获取订单信息的构造函数中</span><span>注入。</span><span>我们还定义了一个</span></span><code>getOrderInfo</code><span>方法，该方法将订单 ID 作为参数并返回订单信息。</span></p>
<p><span>要在模板中使用此块，您可以调用该</span><code>getOrderInfo</code><span>方法并传入订单 ID，如下所示：</span><br /><br /></p>
<pre>$orderInfoBlock = $block-&gt;getLayout()-&gt;createBlock('Vendor\Module\Block\OrderInfo');
$order = $orderInfoBlock-&gt;getOrderInfo($orderId);

</pre>
<p><span><span>这里</span></span><code>$orderId</code><span><span>是您要为其检索信息的订单的 ID。</span><span>然后，您可以使用该</span></span><code>$order</code><span><span>对象访问订单的各种属性，如订单号、客户名称、账单和送货地址等。</span></span></p>]]></description>
      <pubDate>Wed, 12 Apr 2023 07:37:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 的自定义模板上使用 Knockout JS]]></title>
      <link>https://www.360magento.com/blog/magento2-Knockout-JS/</link>
      <description><![CDATA[<p><br />在 Magento 2 中，Knockout JS 是一个流行的 JavaScript 库，用于创建动态用户界面。如果您想在 Magento 2 的自定义模板上使用 Knockout JS，可以按照以下步骤操作：<br />1、首先，在您的自定义模板中，确保您已经包含了 Knockout JS 库。您可以在以下位置找到该库：<br />vendor/magento/module-ui/view/base/web/js/lib/knockout/knockout.js</p>
<p>2、接下来，在您的 HTML 文件中，使用 data-bind 属性来绑定 Knockout JS 视图模型。例如，以下代码将使用 Knockout JS 视图模型来显示一个简单的文本输入框：</p>
<p>&lt;div data-bind="scope: 'myViewModel'"&gt;<br /> &lt;input type="text" data-bind="value: myValue"&gt;<br />&lt;/div&gt;</p>
<p>3、然后，创建一个 JavaScript 文件来定义您的 Knockout JS 视图模型。您可以在 Magento 2 中使用 RequireJS 来加载此文件。例如，以下代码将定义一个名为 myViewModel 的 Knockout JS 视图模型，并将 myValue 属性绑定到文本输入框：</p>
<p>define(['knockout'], function(ko) {<br /> return function() {<br /> var self = this;<br /> self.myValue = ko.observable('Hello, World!');<br /> };<br />});</p>
<p>4、最后，在您的 JavaScript 文件中，使用 ko.applyBindings() 函数将 Knockout JS 视图模型绑定到 HTML 元素。例如，以下代码将 myViewModel 绑定到之前定义的 HTML 元素：</p>
<p>define(['knockout', 'Magento_Ui/js/core/app'], function(ko, app) {<br /> return function() {<br /> var self = this;<br /> self.myValue = ko.observable('Hello, World!');<br /> app().applyBindings(self, 'my-custom-template');<br /> };<br />});</p>
<p>在这个例子中，my-custom-template 是您的自定义模板的名称。</p>
<p><br />这些步骤应该可以帮助您在 Magento 2 的自定义模板上使用 Knockout JS。</p>]]></description>
      <pubDate>Tue, 11 Apr 2023 07:05:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何使用API获取magento2的分类数据]]></title>
      <link>https://www.360magento.com/blog/get-magento2-category-example/</link>
      <description><![CDATA[<p>当然！ 以下是如何使用 Magento 2 API 获取分类数据的示例：<br /> 首先，您需要通过获取访问令牌来使用 Magento 2 API 进行身份验证。 您可以通过在请求正文中使用您的管理员用户名和密码向 /rest/V1/integration/admin/token 端点发送 POST 请求来执行此操作：</p>
<pre>POST https://your-magento2-domain.com/rest/V1/integration/admin/token 
Request body: { "username": "your-admin-username", "password": "your-admin-password" } 
</pre>
<p>这将返回一个访问令牌，您需要将其包含在对 API 的后续请求中。 接下来，您可以使用 /rest/V1/products/{sku} 端点获取特定产品的分类数据。 将 {sku} 替换为您感兴趣的产品的 SKU。fields 参数允许您指定要检索的属性：</p>
<pre>GET https://your-magento2-domain.com/rest/V1/products/{sku}?fields=category_ids,custom_attributes

Request headers:
Authorization: Bearer {access-token}
</pre>
<p>这将返回具有产品指定属性的 JSON 对象。 category_ids 属性将包含产品分配到的类别 ID 数组。 custom_attributes 属性将包含一组已分配给产品的自定义属性，包括用于分类的任何属性。 如果需要，您可以使用此信息来检索有关类别和属性的其他信息。 例如，您可以使用 /rest/V1/categories/{categoryId} 端点来获取有关特定类别的信息：</p>
<pre>GET https://your-magento2-domain.com/rest/V1/categories/{categoryId}

Request headers:
Authorization: Bearer {access-token}
</pre>
<p>您可以使用 /rest/V1/products/attributes/{attributeCode} 端点来获取有关特定属性的信息：</p>
<pre>GET https://your-magento2-domain.com/rest/V1/products/attributes/{attributeCode}

Request headers:
Authorization: Bearer {access-token}
</pre>
<p>希望对您有所帮助！</p>]]></description>
      <pubDate>Wed, 05 Apr 2023 08:07:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 API获取首页数据]]></title>
      <link>https://www.360magento.com/blog/how-to-homepage-data/</link>
      <description><![CDATA[<p>Magento 2 是一个功能强大且用途广泛的电子商务平台，它提供了一组广泛的 API 供开发人员使用。 在本文中，我们将探讨如何使用 Magento 2 API 获取首页数据，并提供完整的代码案例。</p>
<p>首先，让我们了解一下 Magento 2 API 的基础知识。 Magento 2 API 基于 REST（Representational State Transfer）架构，这意味着开发人员可以使用 GET、POST、PUT 和 DELETE 等 HTTP 方法与 Magento 2 进行交互。</p>
<p>要使用 Magento 2 API，您需要使用 OAuth 1.0a 协议验证您的 API 请求。 您可以通过导航至 Magento 2 管理面板中的系统 &gt; 集成为您的商店创建 API 凭据。</p>
<p>一旦您验证了您的 API 请求，您就可以使用 Magento 2 API 端点来检索主页数据。 检索主页数据的 API 端点是&ldquo;/V1/cmsPage/search&rdquo;。 此端点以 JSON 格式返回 CMS 页面列表，包括主页。</p>
<p>要使用 Magento 2 API 检索主页数据，您可以使用以下代码：</p>
<p></p>
<pre>$token = 'your_oauth_token_here';
$baseUrl = 'http://your_magento_base_url/rest';
$searchCriteria = [
    'searchCriteria' =--&gt; [
        'filterGroups' =&gt; [
            [
                'filters' =&gt; [
                    [
                        'field' =&gt; 'identifier',
                        'value' =&gt; 'home',
                        'condition_type' =&gt; 'eq'
                    ]
                ]
            ]
        ]
    ]
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $baseUrl . '/V1/cmsPage/search');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'Authorization: OAuth ' . $token
]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($searchCriteria));
$result = curl_exec($ch);
curl_close($ch);
$data = json_decode($result, true);
if (!empty($data['items'][0]['content'])) {
    echo $data['items'][0]['content'];
}

</pre>
<p>在上面的代码中，我们首先定义了 OAuth 令牌和 Magento 2 商店 API 的基本 URL。 然后，我们定义搜索条件以使用标识符&ldquo;home&rdquo;检索主页数据。 我们使用 cURL 向&ldquo;/V1/cmsPage/search&rdquo;端点发出 POST 请求，其中包含搜索条件和请求标头中的 OAuth 令牌。 然后我们解码 JSON 响应并输出主页内容（如果存在）。</p>
<p>总之，Magento 2 API 为开发人员提供了一个强大的工具集来与平台交互和检索数据。 使用&ldquo;/V1/cmsPage/search&rdquo;端点，开发人员可以检索主页数据并在他们的自定义应用程序中使用它。 上面的代码示例提供了使用 Magento 2 API 检索主页数据的完整解决方案。</p>]]></description>
      <pubDate>Tue, 04 Apr 2023 08:01:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中的Knockout.js 简介]]></title>
      <link>https://www.360magento.com/blog/knockout-js-magento-2/</link>
      <description><![CDATA[<div class="post-main__content post-content" style="width: 100% !important;">
<p><span>Knockout 是 Magento 2 前端世界中引入的最大变化之一，虽然一开始它真的很难掌握，但最终它会成为一个非常有用的工具，使用起来很有趣。</span></p>
<p><span><span>在您必须根据用户的输入或其他一些操作更新某些内容的情况下，所讨论的库确实很出色。</span><span>它将&ldquo;可观察值&rdquo;带到表中&mdash;&mdash;可以自动更新的变量，并通知所有相关方它们已被修改。</span><span>除此之外，我们还有一种&ldquo;计算&rdquo;类型的函数，它们会在更新其中任何可观察对象时自动触发。</span><span>添加将 html 元素绑定到这些变量的选项，现在应该清楚容易获得的可能性的数量。</span></span></p>
<p><span><span>在本文中，我们将创建一个简单的模块，负责与我们的客户打乒乓球。</span><span>我将向您展示如何：</span></span><br /><span>&ndash; 创建一个简单的前端模块，</span><br /><span>&ndash; 声明并为可观察变量赋值，</span><br /><span>&ndash; 将变量从模板/块/php 传递到 JavaScript，</span><br /><span>&ndash; 在模板中使用 knockout 可观察</span><br /><span>对象， &ndash; 在可观察到的变化。</span></p>
<p><span>让我们从创建模块 Magently_TableTennis 开始，该模块将为主页提供 JavaScript、模板和布局更新。</span></p>
<p>//registration.php</p>
<pre class=" language-php" id="snippet_01"><code class=" language-php"><span class="token delimiter">&lt;?php</span>
\<span class="token scope">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Component<span class="token punctuation">\</span>ComponentRegistrar<span class="token punctuation">::</span></span><span class="token function">register</span><span class="token punctuation">(</span>
    \<span class="token scope">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Component<span class="token punctuation">\</span>ComponentRegistrar<span class="token punctuation">::</span></span><span class="token constant">MODULE</span><span class="token punctuation">,</span>
    <span class="token string">'Magently_TableTennis'</span><span class="token punctuation">,</span>
    <span class="token constant">__DIR__</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>//etc/module.xml</p>
<pre class=" language-xml" id="snippet_02"><code class=" language-xml"><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>config</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><a class="vglnk" href="http://www.w3.org/2001/XMLSchema-instance" rel="nofollow"><span>http</span><span>://</span><span>www</span><span>.</span><span>w3</span><span>.</span><span>org</span><span>/</span><span>2001</span><span>/</span><span>XMLSchema</span><span>-</span><span>instance</span></a><span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:Module/etc/module.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>module</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magently_TableTennis<span class="token punctuation">"</span></span> <span class="token attr-name">setup_version</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0.1.0<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>sequence</span><span class="token punctuation">&gt;</span></span>
            <span class="token comment">&lt;!-- add sequence since we will update cms_index_index layout --&gt;</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>module</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento_Cms<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>sequence</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>module</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>config</span><span class="token punctuation">&gt;</span></span></code></pre>
<p>And this is where the fun part begins:<br /> //view/frontend/web/js/view/tableTennis.js</p>
<pre class=" language-javascript" id="snippet_03"><code class=" language-javascript"><span class="token comment">//first we have to define modules we want to use in our script</span>
<span class="token function">define</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
    <span class="token string">'uiComponent'</span><span class="token punctuation">,</span>
    <span class="token string">'ko'</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span>Component<span class="token punctuation">,</span> ko<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">//we'll make our game a Component to allow someone to easily modify it in the future</span>
    <span class="token keyword">return</span> Component<span class="token punctuation">.</span><span class="token function">extend</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        initialize<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//next line is basically equivalent of parent::__construct() in php </span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">_super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//let's divide our component to 2 separate elements</span>
            <span class="token comment">//one responsible for populating our game's interface</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">populateUi</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//and one responsible for the gameplay itself</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">gameplay</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        populateUi<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//here we are creating an observable array and set its items to ping and pong</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>userActions <span class="token operator">=</span> ko<span class="token punctuation">.</span><span class="token function">observableArray</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'ping'</span><span class="token punctuation">,</span> <span class="token string">'pong'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//this observable will be responsible for storing information about currently selected action</span>
            <span class="token comment">//initialMove will be passed from template</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>selectedAction <span class="token operator">=</span> ko<span class="token punctuation">.</span><span class="token function">observable</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>initialMove<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token comment">//and here we will create an observable without initial value</span>
            <span class="token comment">//that will be responsible for storing computer's action</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span>aiMove <span class="token operator">=</span> ko<span class="token punctuation">.</span><span class="token function">observable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        gameplay<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//assign this to self so we can use it inside a function</span>
            <span class="token keyword">var</span> self <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
            <span class="token comment">//handleMove will be fired every time an observable inside it changes</span>
            ko<span class="token punctuation">.</span><span class="token function">computed</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">handleMove</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
            <span class="token punctuation">{</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>self<span class="token punctuation">.</span><span class="token function">selectedAction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> self<span class="token punctuation">.</span><span class="token function">userActions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    self<span class="token punctuation">.</span><span class="token function">aiMove</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span><span class="token function">userActions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
                <span class="token keyword">else</span> <span class="token punctuation">{</span>
                    self<span class="token punctuation">.</span><span class="token function">aiMove</span><span class="token punctuation">(</span>self<span class="token punctuation">.</span><span class="token function">userActions</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><br /> //view/frontend/layout/cms_index_index.xml</p>
<pre class=" language-xml" id="snippet_04"><code class=" language-xml"><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span><a class="vglnk" href="http://www.w3.org/2001/XMLSchema-instance" rel="nofollow"><span>http</span><span>://</span><span>www</span><span>.</span><span>w3</span><span>.</span><span>org</span><span>/</span><span>2001</span><span>/</span><span>XMLSchema</span><span>-</span><span>instance</span></a><span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>referenceContainer</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>top.container<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>block</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>\Magento\Framework\View\Element\Template<span class="token punctuation">"</span></span>
                   <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>tabletennis<span class="token punctuation">"</span></span>
                   <span class="token attr-name">template</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magently_TableTennis::tabletennis.phtml<span class="token punctuation">"</span></span>
                   <span class="token attr-name">before</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>-<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>referenceContainer</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span></code></pre>
<p>//view/frontend/templates/tabletennis.phtml</p>
<pre class=" language-php" id="snippet_05"><code class=" language-php"><span class="token markup"><span class="token comment">&lt;!-- data-bind attribute lets us bind knockout entities to our elemets --&gt;</span></span>
<span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">data-bind</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>scope: <span class="token punctuation">'</span>tableTennis<span class="token punctuation">'</span><span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span></span>
    <span class="token markup"><span class="token comment">&lt;!-- here we create select input with options fetched from userActions observable array --&gt;</span></span>
    <span class="token markup"><span class="token comment">&lt;!-- and bind the selected option to selectedAction observable --&gt;</span></span>
    <span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>select</span> <span class="token attr-name">data-bind</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>options: userActions, value: selectedAction<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span></span><span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>select</span><span class="token punctuation">&gt;</span></span></span>
    <span class="token markup"><span class="token comment">&lt;!-- analogically we bind the text of a paragraph element to aiMove --&gt;</span></span>
    <span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">data-bind</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text: aiMove<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span></span><span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span></span>
<span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span></span>
<span class="token markup"><span class="token comment">&lt;!-- here we initialize our script --&gt;</span></span>
<span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text/x-magento-init<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span></span>
<span class="token punctuation">{</span>
    <span class="token php"><span class="token delimiter">&lt;?php</span> <span class="token comment">// we can specify site elements on which we want to trigger our script ?&gt;</span></span>
    <span class="token php"><span class="token delimiter">&lt;?php</span> <span class="token comment">// * means we launch it only once - for the whole page ?&gt;</span></span>
    <span class="token string">"*"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
        <span class="token php"><span class="token delimiter">&lt;?php</span> <span class="token comment">// this is javascript we are launching ?&gt;</span></span>
        <span class="token string">"Magento_Ui/js/core/app"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
            <span class="token php"><span class="token delimiter">&lt;?php</span> <span class="token comment">// and here we declare components of Magento_Ui/js/core/app ?&gt;</span></span>
            <span class="token string">"components"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                <span class="token string">"tableTennis"</span><span class="token punctuation">:</span> <span class="token punctuation">{</span>
                    <span class="token string">"component"</span><span class="token punctuation">:</span> <span class="token string">"Magently_TableTennis/js/view/tableTennis"</span><span class="token punctuation">,</span>
                    <span class="token php"><span class="token delimiter">&lt;?php</span> <span class="token comment">// here we set the initial move of the player ?&gt;</span></span>
                    <span class="token string">"initialMove"</span><span class="token punctuation">:</span> <span class="token string">"ping"</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token markup"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span></span></code></pre>
</div>
<div id="gtx-trans" style="position: absolute; left: -45px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 03 Apr 2023 08:16:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中展示畅销产品？]]></title>
      <link>https://www.360magento.com/blog/best-seller-products-in-magento-2/</link>
      <description><![CDATA[<h2><span>在 MAGENTO 2 中展示畅销产品的分步过程</span></h2>
<p><span>请按照以下步骤了解如何在您的 Magento 2 商店中展示畅销产品。<br /></span></p>
<p><span>首先，我们需要获得畅销产品集合。</span></p>
<p><span><span>为此，我们需要</span><span>在</span><strong><span>MageDelight/Productslider/Block/文件夹中创建一个名为</span></strong></span><strong>BestSellerProducts.php</strong><span>的块并粘贴以下代码：</span></p>
<p><span>&nbsp;</span></p>
<pre>&lt;?php

namespace MageDelight\Productslider\Block;

use Magento\Catalog\Block\Product\Context;

use Magento\Catalog\Model\Product\Visibility;

use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;

use Magento\Framework\App\Http\Context as HttpContext;

use Magento\Framework\Stdlib\DateTime\DateTime;

use Magento\Sales\Model\ResourceModel\Report\Bestsellers\CollectionFactory as BestSellersCollectionFactory;

use MageDelight\Productslider\Helper\Data;

/**

 * Class BestSellerProducts

 * @package MageDelight\Productslider\Block

 */

class BestSellerProducts extends AbstractSlider

{

    /**

     * @var BestSellersCollectionFactory

     */

    protected $_bestSellersCollectionFactory;

    /**

     * BestSellerProducts constructor.

     * @param Context $context

     * @param CollectionFactory $productCollectionFactory

     * @param Visibility $catalogProductVisibility

     * @param DateTime $dateTime

     * @param Data $helperData

     * @param HttpContext $httpContext

     * @param BestSellersCollectionFactory $bestSellersCollectionFactory

     * @param array $data

     */

    public function __construct(

        Context $context,

        CollectionFactory $productCollectionFactory,

        Visibility $catalogProductVisibility,

        DateTime $dateTime,

        Data $helperData,

        HttpContext $httpContext,

        BestSellersCollectionFactory $bestSellersCollectionFactory,

        array $data = []

    ) {

        $this-&gt;_bestSellersCollectionFactory = $bestSellersCollectionFactory;

        parent::__construct($context, $productCollectionFactory, $catalogProductVisibility, $dateTime, $helperData, $httpContext, $data);

    }

    /**

     * get collection of best-seller products

     * @return mixed

     */

    public function getProductCollection()

    {

        $productIds = [];

        $bestSellers = $this-&gt;_bestSellersCollectionFactory-&gt;create()

            -&gt;setPeriod('month');

        foreach ($bestSellers as $product) {

            $productIds[] = $product-&gt;getProductId();

        }

        $collection = $this-&gt;_productCollectionFactory-&gt;create()-&gt;addIdFilter($productIds);

        $collection-&gt;addMinimalPrice()

            -&gt;addFinalPrice()

            -&gt;addTaxPercents()

            -&gt;addAttributeToSelect('*')

            -&gt;addStoreFilter($this-&gt;getStoreId())-&gt;setPageSize($this-&gt;getProductsCount());

        return $collection;

    }

}
</pre>
<p><span>之后，我们需要将畅销产品集合插入块中的 phtml 文件中。</span></p>
<p><span><span>为此，在</span><strong><span>MageDelight/HelloWorld/view/frontend/templates/文件夹中创建一个</span></strong></span><strong>list.phtml</strong><span><span>文件</span><span>并粘贴以下代码：</span></span></p>
<pre>
<?php

$collection = $block->getProductCollection();

foreach ($collection as $_product) {

    echo $product->getName() . ' - ' . $product->getProductUrl() . '<br />';

}
</pre>]]></description>
      <pubDate>Sat, 01 Apr 2023 20:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置统一运费运输方式？]]></title>
      <link>https://www.360magento.com/blog/flat-rate-shipping-method-in-magento-2/</link>
      <description><![CDATA[<p><span>Flat rate shipping method是一种运输方式，允许您对任何具有不同尺寸、重量和送货地址的订单收取固定金额的运费。</span></p>
<p><span>它易于配置，在全球范围内受到不同类型的电子商务企业的欢迎。</span></p>
<h2><span>在 MAGENTO 2 中配置统一运费运输方式的步骤</span></h2>
<p><span>首先，打开管理面板并导航到&nbsp;</span><em><strong>Stores &gt; Settings &gt; Configuration</strong></em><span>。</span></p>
<p><span><span>之后，&nbsp;</span><span>&nbsp;从左侧面板&nbsp;打开</span></span><em>&ldquo;销售&rdquo;选项卡，然后单击</em><span></span><em>&ldquo;运输方式&rdquo;</em><span>&nbsp;选项卡。</span></p>
<p><span>然后，单击&nbsp;</span><em>&ldquo;统一费率&rdquo;</em><span>&nbsp;部分并执行以下操作：</span></p>
<ul>
<li><span><span>首先，&nbsp;通过选择</span><em><span>&ldquo;是&rdquo;来</span></em></span><em>&ldquo;启用&rdquo;</em><span><span>&nbsp;免费送货选项&nbsp;</span><span>。</span></span><em><span></span></em><span></span></li>
<li><span><span>接下来，写下&nbsp;</span><span>&nbsp;您要在结帐页面上为免费送货选项显示的</span></span><em>&ldquo;标题&rdquo; 。</em><span></span></li>
<li><span></span><em>然后，在&ldquo;方法名称&rdquo;</em><span><span>字段中写下免费送货选项的说明&nbsp;</span><span>&nbsp;。</span></span></li>
<li><span><span>之后，您需要明确适用统一运费送货方式的条款。</span><span>为此，&nbsp;</span><span>&nbsp;从以下选项之一 设置</span></span><em>&ldquo;类型&rdquo; ：</em><span></span>
<ul>
<li><strong>无：&nbsp;</strong><span>此类型表示运费为零，类似于免费送货方式。</span></li>
<li><strong>按订单：&nbsp;</strong><span>它对整个订单收取固定运费。</span></li>
<li><strong>每件商品：&nbsp;</strong><span><span>它对每件商品收取固定运费。</span><span>最终运费乘以购物车中的商品数量。</span></span></li>
</ul>
</li>
</ul>
<p><span>现在，您需要设置一个&nbsp;</span><em>&ldquo;价格&rdquo;，</em><span>&nbsp;您希望为固定运费收取费用。</span></p>
<p><span>如果您想添加一些额外的手续费，您可以通过&nbsp;在&ldquo;手续费&rdquo;字段中将</span><em>&ldquo;计算手续费&rdquo;</em><span>设置&nbsp;为&nbsp;</span><em>&ldquo;百分比&rdquo;</em><span><span>&nbsp;或&nbsp;</span><em><span>&ldquo;</span></em></span><em>固定&rdquo;</em><span><span>&nbsp;费用&nbsp;来实现</span><span>&nbsp;。</span></span><em><span></span></em><span></span></p>
<p><span></span><em>之后，在&ldquo;显示的错误消息&rdquo;</em><span><span>字段中写一个简短的文本以显示统一运费是否不可用&nbsp;</span><span>&nbsp;。</span></span></p>
<p><span><span>&nbsp;接下来，从以下选项之一</span><span>分配&nbsp;</span></span><em>&ldquo;运送到适用国家/地区&rdquo; ：</em><span></span></p>
<ul>
<li><strong>所有国家：</strong><span>&nbsp;免费送货到世界上每个国家。</span></li>
<li><strong>特定国家：</strong><span>&nbsp;免费送货到特定国家。</span></li>
</ul>
<p><span><span>&nbsp;最后，在结帐页面的送货方式上</span><span>设置</span></span><em>&nbsp;&ldquo;排序顺序&rdquo;字段。</em><span></span></p>
<p><span>现在，单击&nbsp;</span><em>&ldquo;保存配置&rdquo;</em><span>&nbsp;以完成该过程。</span></p>]]></description>
      <pubDate>Fri, 31 Mar 2023 08:28:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置固定费率运输方式]]></title>
      <link>https://www.360magento.com/blog/flat-rate-shipping-method/</link>
      <description><![CDATA[<p>Flat Rate Shipping Method是一种在您的商店配置运输方式的简单解决方案。它对具有不同尺寸或重量或任何送货地址的任何订单收取固定运费。由于易于配置和应用，统一运费受到许多运输商的欢迎。</p>
<p>如果您需要在您的商店收取不同的运费，您可以使用Free Shipping Method和Table Rate Shipping Method来完成。现在，我们将一起学习如何在 Magento 2 中配置统一费率运输方式。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/how-to-configure-flat-rate-shipping-method-magento-2-flat-rate-shipping-configuration.png" /></p>
<p>在 Magento 2 中配置统一费率运输方式的 4 个步骤：<br />在管理面板上，Stores &gt; Settings &gt; Configuration。<br />在左侧面板的 下Sales，选择Shipping Methods选项卡。<br />打开该Flat Rate部分，<br />Enable通过选择是的运输方式。届时，购物车的&ldquo;预估运费和税费&rdquo;部分以及结帐时的&ldquo;运费&rdquo;部分都可以使用统一费率。<br />在结帐页面上设置Title统一运费。<br />Method Name在购物车中计算的运费显示的字段中描述方法。方法名称默认为&ldquo;Fixed&rdquo;。<br />要阐明应用统一运费送货方式的条款，请将 设置Type为以下选项之一：<br />无：此类型的运费为零，类似于免费送货方式。<br />按订单：为整个订单设置固定运费<br />每件商品：为每件商品设置固定运费。费率乘以购物车中的商品数量，无论是否有多个相同或不同的商品。* 提供Price您想要收取统一运费的商品。* 如果您要求收取额外的手续费，请设置Calculate Handling Fee为'固定'或'百分比'，然后在字段中输入您要设置的数字Handling Fee。Displayed Error Message*如果统一运费不可用，请键入短文本。* 设置Ship to Applicable Countries为两个选项之一：<br />所有允许的国家：每个国家都支持免费送货。<br />特定国家/地区：仅选定国家/地区支持统一运费。*Sort Order在结帐页面的送货方式上设置。<br />Save Config去完成。</p>]]></description>
      <pubDate>Wed, 29 Mar 2023 09:22:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 电子邮件模板中使用的默认变量的完整列表]]></title>
      <link>https://www.360magento.com/blog/default-variables-used-in-magento-2-email-templates/</link>
      <description><![CDATA[<p>Magento 2 具有出色的功能，可以在购物周期的每个阶段向客户发送各种电子邮件。电子邮件定制和电子邮件模板是任何在线商店的重要主题。</p>
<p>作为一名开发人员，您可能不记得 Magento 2 中电子邮件模板中使用的每个默认变量。因此，以下列表可能会有所帮助。</p>
<p><img alt="" src="https://www.360magento.com/media/wysiwyg/FireShot-Capture-022---A-Complete-List-Of-Default-Variables-Used-In-Magento-2-Email-Template_---meetanshi.com.png" /></p>]]></description>
      <pubDate>Tue, 28 Mar 2023 09:42:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2.4.6 发行说明 - 重点介绍功能]]></title>
      <link>https://www.360magento.com/blog/magento2-magento2-4-6-new/</link>
      <description><![CDATA[<p>Magento 2.4.6 是一个新的版本，它为 Magento Commerce 和 Magento Open Source 用户提供了一些重要的新功能和修复了一些问题。以下是 Magento 2.4.6 中一些重点的功能介绍：</p>
<p>安全性增强<br />Magento 2.4.6 引入了一些安全性增强功能，包括对多个漏洞的修复，如 SQL 注入、跨站脚本攻击和未经身份验证的重置密码。</p>
<p>Elasticsearch 7.10 支持<br />Magento 2.4.6 增加了对 Elasticsearch 7.10 的支持，这将带来更好的搜索性能和更好的可伸缩性。</p>
<p>支持 PHP 8.0<br />Magento 2.4.6 现在支持 PHP 8.0，这将提高站点的性能和安全性。</p>
<p>集成 Adobe Stock 图像库<br />Magento 2.4.6 现在与 Adobe Stock 图像库集成，这将使站点管理者更轻松地搜索、预览和添加高质量的图像。</p>
<p>支持 Braintree Graph QL<br />Magento 2.4.6 支持 Braintree Graph QL，这意味着你现在可以使用 GraphQL 来处理支付和订单。</p>
<p>修复问题<br />Magento 2.4.6 修复了一些已知问题，包括对 PWA Studio 的修复，提高了整体站点的稳定性和可靠性。</p>
<p>总体来说，Magento 2.4.6 的功能增强和问题修复都有助于提高站点的性能、安全性和可用性。如果你是 Magento Commerce 或 Magento Open Source 用户，升级到 Magento 2.4.6 是值得考虑的。</p>
<div id="gtx-trans" style="position: absolute; left: -66px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 27 Mar 2023 08:07:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2 PWA 的详细安装指南]]></title>
      <link>https://www.360magento.com/blog/magento-pwa-magento2-react/</link>
      <description><![CDATA[<p>好的，下面是 Magento2 PWA 的详细安装指南：</p>
<p>前提条件： Magento 2.3 或更高版本 Node.js 10.14 或更高版本 NPM 6 或更高版本 Yarn 步骤1：安装 Magento PWA Studio 在终端中运行以下命令： bash</p>
<pre>git clone https://github.com/magento/pwa-studio.git
cd pwa-studio
yarn install
</pre>
<p>步骤2：创建 Magento2 PWA 应用程序 在终端中运行以下命令：</p>
<pre>yarn create @magento/pwa</pre>
<p>接下来，您将需要输入 Magento 2 的 URL、管理员用户名和密码。完成后，PWA 应用程序将被创建在 pwa-studio/packages 文件夹下。 步骤3：连接 Magento2 和 PWA Studio 在终端中运行以下命令： bash</p>
<pre>cd packages/your-pwa-name
yarn buildpack create-env-file .env</pre>
<p>然后打开 .env 文件并将 MAGENTO_BACKEND_URL 的值设置为您的 Magento 2 后端 URL。 步骤4：启动 PWA 应用程序 在终端中运行以下命令：</p>
<pre>yarn watch</pre>
<p>此命令将启动 PWA 应用程序，并在本地主机的默认端口上运行。您可以在浏览器中访问此 URL 来查看 PWA 应用程序：http://localhost:8000/。 步骤5：部署 PWA 应用程序 在终端中运行以下命令：</p>
<pre>yarn run build</pre>
<p>此命令将生成一个部署包，可以通过 Web 服务器部署到生产环境中。 以上就是 Magento2 PWA 的详细安装指南，希望能帮助到您。</p>]]></description>
      <pubDate>Sun, 26 Mar 2023 09:38:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[创建一个Magento 2模块。我们可以通过以下命令来创建一个基本的模块骨架]]></title>
      <link>https://www.360magento.com/blog/magento2-create-model-by-code/</link>
      <description><![CDATA[<p>1、创建Magento 2模块</p>
<p>首先，我们需要创建一个Magento 2模块。我们可以通过以下命令来创建一个基本的模块骨架：</p>
<pre>php bin/magento module:create --namespace=YourNamespace --module-name=YourModule</pre>
<p><br />这将在 app/code/YourNamespace/YourModule 目录下创建一个基本的模块骨架。</p>
<p>2、定义模块的路由<br />接下来，我们需要定义一个路由，以便在前端显示产品信息。我们可以通过在我们的模块目录下创建一个路由文件来实现：</p>
<p>在 app/code/YourNamespace/YourModule/etc/frontend/routes.xml 文件中加入以下代码：</p>
<pre>&lt;?xml version="1.0"?&gt;<br />&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;<br /> &lt;router id="standard"&gt;<br /> &lt;route id="yourmodule" frontName="yourmodule"&gt;<br /> &lt;module name="YourNamespace_YourModule"/&gt;<br /> &lt;/route&gt;<br /> &lt;/router&gt;<br />&lt;/config&gt;</pre>
<p><br />3、创建控制器<br />现在我们需要创建一个控制器，用于处理路由并返回产品信息。我们可以在 app/code/YourNamespace/YourModule/Controller/Index 文件夹下创建一个名为Index的控制器，并添加以下代码：</p>
<p>&lt;?php<br />namespace YourNamespace\YourModule\Controller\Index;</p>
<pre>use Magento\Framework\App\Action\Action;<br />use Magento\Framework\App\Action\Context;<br />use Magento\Framework\View\Result\PageFactory;</pre>
<p>class Index extends Action<br />{<br /> protected $resultPageFactory;</p>
<p>public function __construct(Context $context, PageFactory $resultPageFactory)<br /> {<br /> parent::__construct($context);<br /> $this-&gt;resultPageFactory = $resultPageFactory;<br /> }</p>
<p>public function execute()<br /> {<br /> $resultPage = $this-&gt;resultPageFactory-&gt;create();<br /> $resultPage-&gt;getConfig()-&gt;getTitle()-&gt;set(__('Product Information'));</p>
<p>return $resultPage;<br /> }<br />}</p>
<p><br />4、创建布局文件<br />我们还需要创建一个布局文件，用于定义前端页面的内容。我们可以在 app/code/YourNamespace/YourModule/view/frontend/layout 文件夹下创建一个名为yourmodule_index_index.xml的文件，并添加以下代码：</p>
<pre><br />&lt;?xml version="1.0"?&gt;<br />&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;<br /> &lt;body&gt;<br /> &lt;referenceContainer name="content"&gt;<br /> &lt;block class="Magento\Catalog\Block\Product\View"<br /> name="yourmodule.product.info"<br /> template="YourNamespace_YourModule::product_info.phtml"/&gt;<br /> &lt;/referenceContainer&gt;<br /> &lt;/body&gt;<br />&lt;/page&gt;</pre>
<p>5、创建模板文件<br />最后，我们需要创建一个模板文件，用于显示产品信息。我们可以在 app/code/YourNamespace/YourModule/view/frontend/templates 文件夹下创建一个名为product_info.phtml的文件，并添加以下代码：</p>
<pre>&lt;h1&gt;&lt;?php echo $block-&gt;getProduct()-&gt;getName(); ?&gt;&lt;/h1&gt;<br />&lt;p&gt;&lt;?php echo $block-&gt;getProduct()-&gt;getDescription(); ?&gt;&lt;/p&gt;</pre>
<p>6、清除缓存</p>]]></description>
      <pubDate>Sat, 25 Mar 2023 08:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何利用magento后台去维护商城的商品]]></title>
      <link>https://www.360magento.com/blog/magento2-about-procut-edit/</link>
      <description><![CDATA[<p>当您在使用Magento 2时，您需要维护您的商品以确保您的在线商店保持最新和有吸引力。以下是一些指南，可帮助您维护您的Magento 2商品。</p>
<p>## 1. 添加新商品</p>
<p>要添加新商品，请按照以下步骤操作：</p>
<p>1. 登录Magento 2后台。<br />2. 转到&ldquo;产品&rdquo;&gt;&ldquo;目录&rdquo;。<br />3. 点击&ldquo;添加产品&rdquo;按钮。<br />4. 填写产品的名称、价格、描述、图像等信息。<br />5. 点击&ldquo;保存并继续编辑&rdquo;按钮。<br />6. 添加其他详细信息，例如库存、税收、相关产品等。<br />7. 点击&ldquo;保存产品&rdquo;按钮。</p>
<p>## 2. 编辑商品</p>
<p>要编辑现有商品，请按照以下步骤操作：</p>
<p>1. 登录Magento 2后台。<br />2. 转到&ldquo;产品&rdquo;&gt;&ldquo;目录&rdquo;。<br />3. 找到您要编辑的产品，并点击&ldquo;编辑&rdquo;按钮。<br />4. 修改您需要更改的任何信息。<br />5. 点击&ldquo;保存产品&rdquo;按钮。</p>
<p>## 3. 删除商品</p>
<p>要删除现有商品，请按照以下步骤操作：</p>
<p>1. 登录Magento 2后台。<br />2. 转到&ldquo;产品&rdquo;&gt;&ldquo;目录&rdquo;。<br />3. 找到您要删除的产品，并点击&ldquo;删除&rdquo;按钮。<br />4. 在确认对话框中，点击&ldquo;确认&rdquo;。</p>
<p>## 4. 管理商品属性</p>
<p>Magento 2允许您为商品定义属性，例如颜色、大小等。要管理商品属性，请按照以下步骤操作：</p>
<p>1. 登录Magento 2后台。<br />2. 转到&ldquo;产品&rdquo;&gt;&ldquo;属性&rdquo;&gt;&ldquo;属性&rdquo;。<br />3. 找到您要编辑的属性，并点击&ldquo;编辑&rdquo;按钮。<br />4. 修改您需要更改的任何信息。<br />5. 点击&ldquo;保存属性&rdquo;按钮。</p>
<p>## 5. 管理商品分类</p>
<p>Magento 2允许您为商品定义分类，例如衣服、鞋子等。要管理商品分类，请按照以下步骤操作：</p>
<p>1. 登录Magento 2后台。<br />2. 转到&ldquo;产品&rdquo;&gt;&ldquo;目录&rdquo;。<br />3. 找到您要编辑的产品，并点击&ldquo;编辑&rdquo;按钮。<br />4. 在&ldquo;分类&rdquo;选项卡中，选择或取消选择适当的分类。<br />5. 点击&ldquo;保存产品&rdquo;按钮。</p>
<p>以上是一些基本的Magento 2商品维护指南。如果您需要更多帮助，请联系我们的团队。</p>
<div id="gtx-trans" style="position: absolute; left: -80px; top: -14.5px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Fri, 24 Mar 2023 08:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 可定制的选项]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Customizable-Options/</link>
      <description><![CDATA[<p><span><span>向产品添加可自定义的选项是提供带有文本、选择和日期输入类型的选项选择的简单方法。</span><span>如果您的库存需求很简单，可定制的选项是一个很好的解决方案。</span><span>但是，由于它们基于单个 SKU 的变体，因此它们不能用于管理库存或作为价格规则条件的基础。</span><span>如果您有多个具有相同选项的产品，您可以设置一个产品并将选项导入到其他产品。</span></span></p>
<p><span>当客户购买带有可定制选项的产品时，每个所选选项的描述都会显示在产品描述下方，并且任何相关的加价（或降价）都会自动应用于该商品的价格。</span></p>
<p><img alt="具有可定制选项的产品详细信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-customizable-option-product-detail.png?lang=en" /></p>
<p><span><span>如果购买触发了购物车价格规则，则初始计算首先适用于产品价格，其次适用于行项目价格，并对适用的可定制选项进行任何调整。</span><span>在以下示例中，客户以 74.00 美元的价格购买了一个行李袋，外加一个可定制的字母组合选项。</span><span>14.80 美元的加价应用于基本产品价格，调整后的价格显示为 88.80 美元。</span><span>在这种情况下，购买行李袋会触发基于产品 SKU 的购物车价格规则，并对购买应用折扣，外加免费送货。</span><span>虽然购物车价格规则不是由可定制选项触发的，但它会将折扣应用于购物车内容，其中包括可定制选项的标记。</span></span></p>
<p><img alt="带有可定制选项和价格规则的购物车" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-customizable-option-cart-price-rule.png?lang=en" /></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>目录价格规则折扣不适用于固定价格可定制选项。</span></p>
</div>
</div>
<h2 id="create-customizable-options"><span>创建可定制的选项</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>可</span><em>自定义选项</em><span>部分。</span></p>
</li>
<li>
<p><span>单击</span><span>添加选项</span><span>。</span></p>
<p><img alt="可定制的选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-customizable-options.png?lang=en" /></p>
</li>
<li>
<p><span>在左上角，单击</span><span>&ldquo;新建选项&rdquo;</span><span>。</span></p>
</li>
<li>
<p><span>完成新的选项设置：</span></p>
<ul>
<li>
<p><span>对于</span><span>Option Title</span><span>，输入选项的名称。</span></p>
</li>
<li>
<p><span>设置数据输入的</span><span>选项类型</span><span>。</span></p>
</li>
<li>
<p><span>如果该选项不是购买产品所必需的，请取消选中</span><span>Required</span><span>复选框。</span></p>
</li>
</ul>
<p><img alt="新选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-customizable-options-new-option.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>添加新行</span><span>并完成以下操作：</span></p>
<p><img alt="增值" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-customizable-options-add-values.png?lang=en" /></p>
<ul>
<li>
<p><span>对于</span><span>Title</span><span>，为此选项输入一个名称。</span></p>
</li>
<li>
<p><span>对于</span><span>Price</span><span>，输入适用于此选项的基本产品价格的任何加价或减价。</span></p>
</li>
<li>
<p><span>将</span><span>价格类型</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Fixed</code><span>- 变体的价格与基础产品的价格相差一个固定的金额，例如 1 美元。</span></li>
<li><code>Percentage</code><span>- 变体的价格与基础产品的价格相差一个百分比，例如 10%。</span></li>
</ul>
</li>
<li>
<p><span>输入选项的</span><span>SKU</span><span><span>。</span><span>选项 SKU 是添加到产品 SKU 的后缀。</span></span></p>
</li>
<li>
<p><span>如果</span><em>选项类型</em><span>为</span><code>File</code><span><span>，则设置文件的参数。</span><span>对于</span></span><span>Compatible File Extensions</span><span>，输入有效的扩展名作为逗号分隔值（例如</span><code>png, jpg, gif</code><span><span>）。</span><span>对于</span></span><span>最大图像尺寸</span><span>，输入最大图像尺寸（以像素为单位）。</span></p>
</li>
<li>
<p><span>要更改选项的顺序，请单击</span><span>更改顺序</span>&nbsp;<img alt="排序顺序图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-sort-order.png?lang=en" /><span>图标并将选项拖动到列表中的新位置。</span></p>
</li>
</ul>
<p><img alt="更改选项顺序" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-customizable-options-move.png?lang=en" /></p>
<p><span>对要添加的每个选项重复此步骤。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="import-customizable-options"><span>导入可自定义的选项</span></h2>
<ol>
<li>
<p><span>在</span><em>可自定义选项</em><span>部分，单击</span><span>导入选项</span><span>。</span></p>
<p><img alt="可定制的选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-customizable-options.png?lang=en" /></p>
</li>
<li>
<p><span>具有可定制选项的所有产品都出现在网格中。</span></p>
</li>
<li>
<p><span>在列表中，选中包含您要导入的选项的产品的复选框。</span></p>
</li>
<li>
<p><span>单击</span><span>导入</span><span>。</span></p>
</li>
<li>
<p><span>完成后，您可以继续添加更多自定义选项或单击</span><span>保存并关闭</span><span>。</span></p>
</li>
</ol>
<h2 id="input-types"><span>输入类型</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>类型</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>文本</span></td>
<td><span><span>客户可以在其中输入所需信息的输入行或文本框。</span><span>选项：</span></span><br /><span>Field</span><span>&nbsp;- 文本的单行输入字段。</span><br /><span>Area</span><span><span>&nbsp;- 多行输入字段。</span><span>此类型不支持 HTML 等高级格式。</span><span>使用最大字符数来限制可以输入的文本长度，并确保在管理员中正确表示输入的文本。</span></span></td>
</tr>
<tr>
<td><span>文件</span></td>
<td><span>允许客户上传文件。</span></td>
</tr>
<tr>
<td><span>选择</span></td>
<td><span><span>允许客户根据使用的输入类型选择单个选项或多个选项。</span><span>选项：</span></span><br /><span>下拉 -</span><span>选项的下拉列表，只允许一个选择。</span><br /><span>单选按钮</span><span>- 一组只允许一个选择的选项。</span><br /><span>复选框</span><span><span>- 复选框是是/否选项的变体。</span><span>如果产品有多个复选框，则可以进行多项选择。</span></span><br /><span>多项选择</span><span><span>- 接受多项选择的选项下拉列表框。</span><span>要选择多个选项，请按住 Ctrl (PC) 或 Command (Mac) 键并单击每个选项。</span></span></td>
</tr>
<tr>
<td><span>日期</span></td>
<td><span><span>允许客户输入日期或时间或从日历中选择值。</span><span>选项：</span></span><br /><span>Date</span><span><span>&nbsp;- 日期值的输入字段。</span><span>日期可以直接输入字段或从列表或日历中选择。</span><span>输入法和格式由</span></span>日期和时间自定义选项<span>配置决定。</span><br /><span>日期和时间</span><span>- 日期和时间值的输入字段。</span><br /><span>时间</span><span>- 时间值的输入字段。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Tue, 31 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 相关产品、追加销售和交叉销售]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Related-Products-Up-Sells-and-Cross-Sells/</link>
      <description><![CDATA[<p><span>使用&ldquo;</span><em>相关产品&rdquo;、&ldquo;追加销售&rdquo;和&ldquo;交叉销售</em><span><span>&rdquo;部分设置简单的促销块，展示客户可能感兴趣的一系列附加产品。</span><span><br /></span></span></p>
<p><img alt="相关产品、追加销售和交叉销售" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-related-up-sell-cross-sell.png?lang=en" /></p>
<p><span>每个块都包含属于特定选项的产品列表。</span></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>ID</span></td>
<td><span>分配给产品实体的唯一数字标识符。</span></td>
</tr>
<tr>
<td><span>缩略图</span></td>
<td><span>产品缩略图。</span></td>
</tr>
<tr>
<td><span>姓名</span></td>
<td><span>产品名称。</span></td>
</tr>
<tr>
<td><span>状态</span></td>
<td><span><span>指示产品状态。</span><span>选项：</span></span><code>Enabled</code><span>/&nbsp;</span><code>Disabled</code><span><span>。</span><span>禁用的产品不会显示在前端的块中。</span></span></td>
</tr>
<tr>
<td><span>属性集</span></td>
<td><span>用作产品模板的属性集的名称。</span></td>
</tr>
<tr>
<td><span>存货单位</span></td>
<td><span>分配给产品的唯一库存单位。</span></td>
</tr>
<tr>
<td><span>价格</span></td>
<td><span>产品的单价。</span></td>
</tr>
<tr>
<td><span>行动</span></td>
<td><span>选项：</span><code>Remove</code><span><span>。</span><span>从块中删除产品。</span></span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="related-products"><span>相关产品</span></h2>
<p><span><span>除了客户正在查看的项目之外，还应购买相关产品。</span><span>客户只需单击复选框即可将商品放入购物车。</span></span><em>相关产品</em><span><span>块的位置</span><span>因定义的主题和页面布局而异。</span><span>在下面的示例中，</span></span><em>相关产品</em><span>块显示在</span><em>产品视图</em><span><span>页面的底部。</span><span>对于两列布局，</span></span><em>相关产品</em><span>块通常出现在右侧边栏中。</span></p>
<p><img alt="相关产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-product-related-products.png?lang=en" /></p>
<p><span>设置相关产品：</span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>相关</span><span>产品、追加销售和交叉销售</span><span>部分。</span></p>
</li>
<li>
<p><span>单击</span><span>添加相关产品</span><span>。</span></p>
<p><img alt="相关产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-related-up-sell-cross-sell.png?lang=en" /></p>
</li>
<li>
<p><span>使用</span>过滤器控件<span>查找您想要的产品。</span></p>
</li>
<li>
<p><span>在列表中，选中您想要作为相关产品的任何产品的复选框。</span></p>
<p><img alt="相关产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/products-related-add.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>添加所选产品</span><span>。</span></p>
</li>
</ol>
<h2 id="up-sells"><span>追加销售</span></h2>
<p><span><span>追加销售产品是您的客户可能更喜欢的项目，而不是当前考虑的产品。</span><span>作为追加销售提供的商品可能质量更高、更受欢迎或利润率更高。</span><span>追加销售产品出现在产品页面上的标题下，例如</span></span><em>You may also be interested in the following products</em><span>。</span></p>
<p><img alt="追加销售" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-product-upsell.png?lang=en" /></p>
<p><span>选择追加销售产品：</span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>相关</span><span>产品、追加销售和交叉销售</span><span>部分。</span></p>
</li>
<li>
<p><span>点击</span><span>添加追加销售产品</span><span>。</span></p>
<p><img alt="添加追加销售产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-related-up-sell-cross-sell.png?lang=en" /></p>
</li>
<li>
<p><span>使用</span>过滤器控件<span>查找您想要的产品。</span></p>
</li>
<li>
<p><span>在列表中，选中您想要作为追加销售产品的任何产品的复选框。</span></p>
<p><img alt="追加销售产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-up-sell-add.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>添加所选产品</span><span>。</span></p>
</li>
</ol>
<h2 id="cross-sells"><span>交叉销售</span></h2>
<p><span><span>交叉销售商品类似于在收银台旁边放置的冲动购买。</span><span>作为交叉销售提供的产品出现在购物车页面上，就在客户开始结帐流程之前。</span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>要显示或隐藏每个商店视图的交叉销售项目，请参阅</span>结帐 &gt; 购物车<span>选项，称为在购物车中</span><em>显示交叉销售项目</em><span><span>。</span><span>您可能希望在特定销售期间隐藏交叉销售或在商店视图中进行 A/B 测试。</span></span></p>
</div>
</div>
<p><img alt="购物车交叉销售" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-cart-cross-sells.png?lang=en" /></p>
<p><span>选择交叉销售产品：</span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>相关</span><span>产品、追加销售和交叉销售</span><span>部分。</span></p>
</li>
<li>
<p><span>单击</span><span>添加交叉销售产品</span><span>。</span></p>
<p><img alt="添加交叉销售产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-related-up-sell-cross-sell.png?lang=en" /></p>
</li>
<li>
<p><span>使用</span>过滤器控件<span>查找您想要的产品。</span></p>
</li>
<li>
<p><span>在列表中，选中您想要作为交叉销售产品的任何产品的复选框。</span></p>
<p><img alt="交叉销售产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-cross-sell-add.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>添加所选产品</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Mon, 30 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置-搜索引擎优化]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Search-Engine-Optimization/</link>
      <description><![CDATA[<p><em>搜索引擎优化</em>部分指定了搜索引擎用来索引产品的<a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/catalog-urls.html?lang=en">URL 键</a>和元数据字段。虽然一些搜索引擎忽略元关键字，但其他搜索引擎继续使用它们。当前的SEO 最佳做法是在元标题和元描述中加入高价值关键字。</p>
<p><span><span>每个元数据字段的默认值可以根据配置中指定的值自动生成。</span><span>每个字段都包含一个由实际值替换的占位符。</span><span><br /></span></span></p>
<p><img alt="搜索引擎优化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-search-engine-optimization.png?lang=en" /></p>
<h2 id="complete-the-seo-fields"><span>完成 SEO 字段</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>搜索</span><em>引擎优化</em><span>部分。</span></p>
</li>
<li>
<p><span>输入</span><span>URL 密钥</span><span>（可选）。</span></p>
<p><span><span>默认 URL 密钥基于产品名称。</span><span>您可以使用默认值或根据需要更改它。</span><span>有关详细信息，请参阅</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/catalog-urls.html?lang=en">目录 URL</a><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>元标题</span><span>（可选）。</span></p>
<p><span><span>元标题是出现在浏览器窗口顶部的文本。</span><span>您可以使用基于产品名称的默认值，也可以根据需要进行更改。</span></span></p>
</li>
<li>
<p><span>添加</span><span>元关键字</span><span>（可选）。</span></p>
<p><span><span>一些搜索引擎比其他搜索引擎更多地使用元关键字。</span><span>最好输入一些高价值的关键词，以帮助产品获得更多的知名度。</span></span></p>
</li>
<li>
<p><span>输入</span><span>元描述</span><span>。</span></p>
<p><span><span>元描述是出现在搜索结果列表中的文本。</span><span>为获得最佳效果，请输入长度在 150-160 个字符之间的描述。</span></span></p>
</li>
</ol>
<h2 id="field-reference"><span>现场参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th>范围</th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>网址键</span></td>
<td><span>商店视图</span></td>
<td><span><span>确定产品的在线地址。</span><span>URL 键被添加到商店的基本 URL 并出现在浏览器的地址栏中。</span><span>Commerce 最初创建一个默认的、</span></span><em>搜索引擎友好的</em><span><span>URL，该 URL 基于产品名称。</span><span>URL 密钥应全部为小写字符，这些字符之间使用非尾随连字符而不是空格。</span><span>不要</span></span><code>.html</code><span>在 URL 密钥中包含后缀，因为它在配置中进行管理。</span></td>
</tr>
<tr>
<td><span>元标题</span></td>
<td><span>商店视图</span></td>
<td><span><span>标题出现在浏览器的标题栏和选项卡中，也用作搜索引擎结果页面 (SERP) 上的标题。</span><span>元标题对于页面来说应该是唯一的，并且长度少于 70 个字符。</span><span>自动生成的值：</span></span><code>{{name}}</code></td>
</tr>
<tr>
<td><span>元关键字</span></td>
<td><span>商店视图</span></td>
<td><span><span>产品的相关关键词。</span><span>考虑使用客户可能用来查找产品的关键字。</span><span>自动生成的值：</span></span><code>{{name}}</code></td>
</tr>
<tr>
<td><span>元描述</span></td>
<td><span>商店视图</span></td>
<td><span><span>元描述提供搜索结果列表页面的简要概述。</span><span>理想的长度在 150-160 个字符之间，最多 255 个字符。</span><span>虽然对客户不可见，但一些搜索引擎会在搜索结果页面上包含元描述。</span><span>自动生成的值：</span></span><code>{{name}} {{description}}</code></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Sun, 29 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 图片和视频]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Images-and-Videos/</link>
      <description><![CDATA[<p><span>从</span><em>图像和视频</em><span><span>部分，您可以执行基本的图像管理任务，例如上传多张图像、重新排列图像以及控制每张图像的使用方式。</span><span>要对单个图像进行额外控制，您可以在</span></span><em>详细视图</em><span>中打开每个图像。</span></p>
<h2 id="upload-a-new-image"><span>上传新图片</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>图像</span><em>和视频</em><span>部分。</span></p>
<p><img alt="图片和视频" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-simple-images-videos.png?lang=en" /></p>
</li>
<li>
<p><span>如果您准备好添加产品图片，请执行以下操作之一：</span></p>
<ul>
<li>
<p><span>将图像从桌面拖放到</span><em>相机</em><span>(&nbsp;</span><img alt="相机图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-camera.png?lang=en" /><span>) 磁贴上。</span></p>
</li>
<li>
<p><span>单击</span><em>相机</em><span>(&nbsp;</span><img alt="相机图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-camera.png?lang=en" /><span>) 磁贴，选择图像文件，然后单击</span><span>打开</span><span>。</span></p>
</li>
</ul>
</li>
</ol>
<p><span><span>在</span><span>产品图像可用之前，</span></span>占位符图像会出现在目录中。<span></span></p>
<h2 id="image-detail"><span>图像细节</span></h2>
<p><span>添加产品图像时，您可以自定义图像</span><em>详细信息</em><span>窗口中的图像显示。</span></p>
<p><img alt="产品图片" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/image-video.png?lang=en" /></p>
<p><span>为产品设置图像显示选项：</span></p>
<ol>
<li>
<p><span>单击产品图像。</span></p>
</li>
<li>
<p><span>输入</span><span>替代文字</span><span>。</span></p>
</li>
<li>
<p><span>选择显示图像的</span><span>角色</span><span>（一张图像可以选择所有角色）：</span></p>
<ul>
<li><code>Swatch</code></li>
<li><code>Base</code></li>
<li><code>Small</code></li>
<li><code>Thumbnail</code></li>
</ul>
<p><span>默认情况下，为第一个添加的图像选择所有这些角色。</span></p>
<p><img alt="图片详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-image-details.png?lang=en" /></p>
</li>
</ol>
<p><span>要从产品页面隐藏产品图像，请选中</span><span>从产品页面隐藏</span><span>复选框。</span></p>]]></description>
      <pubDate>Sat, 28 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 产品评论]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Product-Reviews/</link>
      <description><![CDATA[<p><em>产品评论</em><span><span>部分列出了客户提交的关于产品的所有评论</span><span>。</span><span>只有在第一次保存新产品后，此部分才会与其他产品信息一起出现。</span></span></p>
<p><img alt="产品评论" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-review.png?lang=en" /></p>
<h2 id="field-reference"><span>现场参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>ID</span></td>
<td><span>为产品评论条目生成的唯一数字 ID</span></td>
</tr>
<tr>
<td><span>已创建</span></td>
<td><span>评价发表日期</span></td>
</tr>
<tr>
<td><span>状态</span></td>
<td><span>查看状态（</span><code>Pending</code><span>、</span><code>Approved</code><span>或</span><code>Not Approved</code><span>）</span></td>
</tr>
<tr>
<td><span>标题</span></td>
<td><span>评论标题</span></td>
</tr>
<tr>
<td><span>昵称</span></td>
<td><span>留下评论的用户的昵称</span></td>
</tr>
<tr>
<td><span>审查</span></td>
<td><span>客户对当前产品的评论</span></td>
</tr>
<tr>
<td><span>能见度</span></td>
<td><span>商店评论中的可见性</span></td>
</tr>
<tr>
<td><span>类型</span></td>
<td><span>留下评论的用户类型（</span><code>Guest</code><span>或</span><code>Customer</code><span>）</span></td>
</tr>
<tr>
<td><span>产品</span></td>
<td><span>审核的产品名称</span></td>
</tr>
<tr>
<td><span>存货单位</span></td>
<td><span>分配给产品的唯一库存单位</span></td>
</tr>
<tr>
<td><span>行动</span></td>
<td><span>在编辑模式下打开产品</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="moderate-reviews-for-a-specific-product"><span>对特定产品的适度评论</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span>找到产品并在编辑模式下将其打开。</span></p>
</li>
<li>
<p><span>滚动到</span><em>产品评论</em><span>部分。</span></p>
</li>
<li>
<p><span>单击&ldquo;</span><span>编辑</span><span>&rdquo;查看带有</span><code>Pending</code><span>状态的产品评论，以查看和编辑详细信息。</span></p>
</li>
<li>
<p><span>设置审核状态：</span></p>
<ul>
<li><span>要批准待定审核，请选择</span><code>Approved</code><span>。</span></li>
<li><span>要拒绝评论，请选择</span><code>Not Approved</code><span>。</span></li>
<li><span>您可以随时将审核状态更改回</span><code>Pending</code><span>。</span></li>
</ul>
</li>
<li>
<p><span>完成后，点击</span><span>保存评论</span><span>。</span></p>
</li>
</ol>
<p><span>具有</span><code>Pending</code><span>和</span><code>Not Approved</code><span>状态的评论不会显示在店面上。</span></p>]]></description>
      <pubDate>Fri, 27 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 配置]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Configurations/</link>
      <description><![CDATA[<p><em>配置</em><span><span>部分列出了产品的</span><span>任何现有变体，可用于生成与可配置产品类型一起使用的变体。</span></span></p>
<p><img alt="配置部分" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-create-configurations.png?lang=en" /></p>
<p><img alt="产品配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurations-hoodie.png?lang=en" /></p>
<h2 id="field-reference"><span>现场参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>图片</span></td>
<td><span>产品图片</span></td>
</tr>
<tr>
<td><span>姓名</span></td>
<td><span>产品的唯一名称</span></td>
</tr>
<tr>
<td><span>存货单位</span></td>
<td><span>基于产品名称</span></td>
</tr>
<tr>
<td><span>价格</span></td>
<td><span>产品价格</span></td>
</tr>
<tr>
<td><span>数量</span></td>
<td><span>每种产品的现有库存量</span></td>
</tr>
<tr>
<td><span>重量</span></td>
<td><span>产品重量</span></td>
</tr>
<tr>
<td><span>状态</span></td>
<td><span>产品状态</span><span>启用</span><span>/</span><span>禁用</span></td>
</tr>
<tr>
<td><span>属性</span></td>
<td><span>一组用于描述产品的属性</span></td>
</tr>
<tr>
<td><span>动作</span></td>
<td><span><span>列出可应用于选定产品的所有操作。</span><span>操作：</span></span><br /><span>选择不同的产品</span><span>- 删除当前产品并将其替换为新选择。</span><br /><span>禁用产品</span><span>/</span><span>启用产品</span><span>- 禁用或启用所选产品。</span><br /><span>删除产品</span><span>- 从当前配置中删除选定的产品。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Thu, 26 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 内容]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Content/</link>
      <description><![CDATA[<p>内容部分用于输入和编辑出现在产品页面上的主要产品描述<em>。</em>简短描述可用于大多数 RSS 提要，也可能出现在目录列表中，具体取决于主题。</p>
<h2 id="add-the-product-description-in-page-builder"><span>在 Page Builder 中添加产品描述</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>内容</span><span>部分</span><span>。</span></p>
<p><img alt="产品内容" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-content.png?lang=en" /></p>
</li>
<li>
<p><span>输入产品的</span><span>简短描述</span><span>并使用</span>编辑器工具栏<span>根据需要设置格式。</span></p>
</li>
<li>
<p><span>在</span><span>Description</span><span>标签处，单击</span><span>Edit with Page Builder</span><span>。</span></p>
</li>
<li>
<p><span>使用</span>Page Builder<span>内容工具</span>编辑现有文本<span>并添加其他内容（如果需要）。</span></p>
</li>
</ol>
<h2 id="page-builder-preview"><span>页面构建器预览</span></h2>
<p><span><span>当您展开包含</span><span>使用 Page Builder 创建的内容的现有产品的</span></span><em>内容部分时，它会显示</em><span></span><span>描述</span><span><span>内容的预览，就像它会出现在产品页面中一样。</span><span>单击内容区域以打开 Page Builder 工作区，您可以在其中进行任何需要的更新。</span></span></p>
<p><img alt="说明预览" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/pb-product-category-content-preview.png?lang=en" /></p>
<p><span><span>默认情况下，为产品和类别表单启用此内容预览。</span><span>如果性能因加载预览而受到影响，您可以在</span></span>内容管理配置<span>设置中禁用预览。</span></p>
<h2 id="add-the-product-description-in-the-editor"><span>在编辑器中添加产品描述</span></h2>
<p><span><span>如果您的商店禁用了 Page Builder，请使用文本编辑器添加产品内容。</span><span>仅在文本框中输入纯 ASCII 字符。</span><span>如果从文字处理器粘贴文本，请先将其保存为纯 .TXT 文件以删除任何不可见的控制字符。</span><span>有关详细信息，请参阅</span></span>使用编辑器<span>。</span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>内容</span><span>部分</span><span>。</span></p>
<p><img alt="简单的产品内容" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-simple-content.png?lang=en" /></p>
</li>
<li>
<p><span>根据需要输入产品和格式的</span><span>简短描述</span><span>。</span></p>
</li>
<li>
<p><span>输入主要产品</span><span>描述</span><span>并使用编辑器工具栏根据需要进行格式化。</span></p>
<p><span>您可以拖动右下角来更改文本框的高度。</span></p>
</li>
</ol>]]></description>
      <pubDate>Wed, 25 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品设置 - 来源]]></title>
      <link>https://www.360magento.com/blog/Product-settings-Sources/</link>
      <description><![CDATA[<p>产品设置的<em>来源</em>部分列出了可以分发产品的来源。它用于分配和取消分配来源以及管理产品的数量和可用性。仅当为您的商店定义了多个来源时才会显示此部分。</p>
<h2 id="assign-a-source-for-a-product"><span>为产品分配来源</span></h2>
<ol>
<li>
<p><span>单击</span><span>分配源</span><span>。</span></p>
</li>
<li>
<p><span>选中所需来源的复选框。</span></p>
</li>
<li>
<p><span>单击</span><span>完成</span><span>。</span></p>
</li>
<li>
<p><span>选择</span><span>源项目状态</span><span>并根据需要输入</span><span>数量</span><span>和</span><span>通知数量</span><span>值。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>以保存更改。</span></p>
</li>
</ol>
<p><img alt="资源视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-sources-list.png?lang=en" /></p>
<h2 id="field-reference"><span>现场参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>姓名</span></td>
<td><span>源的唯一名称。</span></td>
</tr>
<tr>
<td><span>来源状态</span></td>
<td><span>确定产品在目录中是启用还是禁用。</span></td>
</tr>
<tr>
<td><span>来源项目状态</span></td>
<td><span><span>确定产品的当前可用性。</span><span>选项：</span></span><br /><span>In Stock</span><span>&nbsp;- 使产品可供购买。</span><br /><span>缺货</span><span>- 除非激活延期交货，否则会阻止产品可供购买并从目录中删除列表。</span></td>
</tr>
<tr>
<td><span>数量</span></td>
<td><span>每个来源的现有库存量。</span></td>
</tr>
<tr>
<td><span>通知数量</span></td>
<td><span><span>如果未选择</span><span>此特定来源</span></span><em>的数量通知</em><span>金额。</span><code>Notify Quantity Use Default</code><span></span></td>
</tr>
<tr>
<td><span>通知数量使用默认值</span></td>
<td><span>指示使用产品高级库存中的</span><em>数量通知</em><span><span>的默认设置或商店配置中的全局设置。</span><span><br /></span></span></td>
</tr>
<tr>
<td><span>动作</span></td>
<td><span>对于已分配的来源，单击</span><span>取消分配</span><span><span>以使该来源对产品不可用。</span><span>对于未分配的源，单击</span></span><span>分配源</span><span><span>以使源可用于产品。</span><span><br /></span></span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Tue, 24 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2安排产品更新]]></title>
      <link>https://www.360magento.com/blog/Schedule-product-updates/</link>
      <description><![CDATA[<p>产品更新可以按计划应用并与其他内容更改组合在一起。您可以使用内容暂存根据计划的产品更改创建活动，或将更改应用到现有活动。</p>
<p><img alt="预定更改" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-scheduled-changes.png?lang=en" /></p>
<h2 id="create-a-schedule-update"><span>创建计划更新</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span>选择现有产品并点击</span><span>编辑</span><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>安排新更新</span><span>。</span></p>
</li>
<li>
<p><span>选择</span><span>另存为新更新</span><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>更新名称</span><span>，输入新内容暂存活动的名称。</span></p>
</li>
<li>
<p><span>输入更新的简短</span><span>说明</span><span>及其使用方式。</span></p>
</li>
<li>
<p><span>使用日历 (&nbsp;</span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span>) 工具选择活动的</span><span>开始日期</span><span>和</span><span>结束日期</span><span>。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>活动</span><span>开始日期</span><span>和</span><span>结束日期</span><span>必须使用</span><span><em>默认</em></span><span><span>的管理时区定义，该时区是从每个网站的本地时区转换而来的。</span><span>例如，对于位于不同时区的多个网站，您希望根据美国时区开始营销活动，您需要为每个本地时区安排单独的更新。</span><span>为每个设置</span></span><span>开始日期</span><span>和</span><span>结束日期</span><span>，并将其从本地网站时区转换为默认的管理时区。</span></p>
</div>
</div>
</li>
<li>
<p><span>向下滚动到</span><em>价格</em><span>并点击</span><span>高级定价</span><span>。</span></p>
</li>
<li>
<p><span><span>在计划的活动期间为产品</span><span>输入</span></span><span>特价，然后点击</span><span></span><span>完成</span><span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="assign-to-existing-update"><span>分配给现有更新</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span>选择现有产品并点击</span><span>编辑</span><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>安排新更新</span><span>。</span></p>
</li>
<li>
<p><span>选择</span><span>分配给现有市场活动</span><span>。</span></p>
</li>
<li>
<p><span>在列表中，选择要修改的活动。</span></p>
<p><img alt="分配给现有的活动" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/scheduled-changes-assign-to-existing-campaign.png?lang=en" /></p>
</li>
<li>
<p><span>展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" />&nbsp;<span>内容</span><span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="view-the-scheduled-change"><span>查看预定的更改</span></h2>
<p><span>计划的更改显示在产品页面的顶部，以及活动的开始和结束日期。</span></p>
<p><img alt="预定变更" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/view-product-scheduled-changes.png?lang=en" /></p>
<h2 id="edit-the-scheduled-change"><span>编辑预定更改</span></h2>
<ol>
<li>
<p><span><span>在</span><span>页面顶部的</span></span><em>Scheduled Changes框中，单击</em><span></span><span>View/Edit</span><span>。</span></p>
</li>
<li>
<p><span>对计划的更新进行任何必要的更改。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="remove-the-scheduled-change"><span>删除计划的更改</span></h2>
<ol>
<li>
<p><span><span>在</span><span>页面顶部的</span></span><em>Scheduled Changes框中，单击</em><span></span><span>View/Edit</span><span>。</span></p>
</li>
<li>
<p><span>在顶部栏中，单击</span><span>从更新中删除</span><span>。</span></p>
</li>
<li>
<p><span>在对话框中，选择</span><span>删除更新</span><span>并单击</span><span>完成</span><span>。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>该产品已从更新中删除，所有计划的更改都将丢失。</span></p>
</div>
</div>
<p><img alt="删除计划更改" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/remove-product-scheduled-changes.png?lang=en" /></p>
</li>
</ol>
<h2 id="schedule-a-design-update"><span>安排设计更新</span></h2>
<p><span></span><em>计划设计更新</em><span><span>部分使您能够对</span><span>产品页面的外观进行临时更改。</span><span>您可以为一个季节、促销安排设计更改，或者只是为了让事情变得新鲜。</span><span>设计更改可以提前安排，因此它们会按照您定义的时间表生效或</span></span><em>滴落</em><span>。</span></p>
<p><img alt="计划的设计更新" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-design-update-scheduled.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>计划更新自/至</span></td>
<td><span>确定将自定义布局应用于产品的日期范围。</span></td>
</tr>
<tr>
<td><span>新主题</span></td>
<td><span>将自定义主题应用于产品。</span></td>
</tr>
<tr>
<td><span>新版面</span></td>
<td><span><span>对产品页面应用不同的布局。</span><span>选项：</span></span><br /><span>无布局更新</span><span>- 默认情况下，布局更新不适用于产品页面。</span><br /><span>空</span><span><span>- 允许您定义自己的布局，例如 4 栏页面。</span><span>（需要了解 XML。）</span></span><br /><span>1 列</span><span>- 将单列布局应用于产品页面。</span><br /><span>带左侧栏的2 列</span><span>- 将带有左侧栏的两列布局应用于产品页面。</span><br /><span>带右侧栏的2 列</span><span>- 将带有右侧栏的两列布局应用于产品页面。</span><br /><span>3 列</span><span>- 将三列布局应用于产品页面。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Mon, 23 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2最低广告价格]]></title>
      <link>https://www.360magento.com/blog/Minimum-Advertised-Price/</link>
      <description><![CDATA[<p><span><span>商家有时会被禁止显示低于制造商建议零售价 (MSRP) 的价格。</span><span>最低广告价格 (MAP) 使您能够在满足制造商要求的同时为您的客户提供更优惠的价格。</span><span>由于每个制造商的要求不同，您可以配置您的商店以防止在不允许的页面上显示您的实际价格。</span></span></p>
<p><span><span>MAP 功能添加了专用的&ldquo;点击价格&rdquo;按钮，而不是常规产品价格。</span><span>因此，如果您商店中的价格低于该产品的最低设定价格，则该价格要么不显示，要么显示标价/市场价格并带有删除线以强调您的价格更低。</span><span>如果买家点击&ldquo;Click for Price&rdquo;按钮，那么您销售产品的实际价格才会显示出来。</span></span></p>
<p><span><span>此外，MAP 功能允许您提出一些改进建议。</span><span>例如，当客户将此类产品添加到他们的购物车时，他们不会被重定向到购物车，而是会显示允许买家执行以下操作的报价：</span></span></p>
<ul>
<li>
<p><span>从购物车中移除商品（如果买家只是想了解价格，尚未做出购买决定，则可以这样做）</span></p>
</li>
<li>
<p><span>将其留在他们的购物车中并继续购物</span></p>
</li>
<li>
<p><span>进行结算</span></p>
</li>
</ul>
<h2 id="map-logic"><span>映射逻辑</span></h2>
<p><span><span>有些产品的价格取决于所选选项，例如自定义选项或具有自己的 SKU 和库存管理的简单产品）。</span><span>对于这些产品，根据产品类型和价格设置应用以下逻辑。</span><span>订单管理、客户管理工具和报告使用实际价格。</span></span></p>
<h2 id="using-map-with-product-types"><span>将 MAP 与产品类型一起使用</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>产品类别</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td>简单<span>,</span>虚拟</td>
<td><span><span>实际价格不会自动出现在目录列表和产品页面上，而只会根据显示实际价格设置包含在内。</span><span>自定义选项价格正常显示。</span></span></td>
</tr>
<tr>
<td>分组</td>
<td><span>关联的简单产品的价格不会自动出现在目录列表和产品页面上，而是仅根据显示实际价格设置包含在内。</span></td>
</tr>
<tr>
<td>可配置</td>
<td><span><span>实际价格不会自动出现在目录列表和产品页面上，而只会根据显示实际价格设置包含在内。</span><span>期权价格正常出现。</span></span></td>
</tr>
<tr>
<td>捆绑包<span>（固定价格）</span></td>
<td><span><span>实际价格不会自动出现在目录页面上，而是仅根据显示实际价格设置包含在内。</span><span>捆绑商品的价格正常显示。</span><span>MAP 不适用于具有动态定价的捆绑产品。</span></span></td>
</tr>
<tr>
<td>可下载</td>
<td><span><span>实际价格不会自动出现在目录列表和产品页面上，而只会根据显示实际价格设置包含在内。</span><span>与每个下载链接关联的价格正常显示。</span></span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="using-map-with-price-settings"><span>将 MAP 与价格设置结合使用</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>价格设定</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>主要价格</span></td>
<td><span>当 MAP 应用于主价格时，选项、捆绑项目和关联产品的价格（从主价格增加或减少）正常显示。</span></td>
</tr>
<tr>
<td><span>关联产品价格</span></td>
<td><span>如果产品没有主价格，并且其价格源自关联产品价格（例如在分组产品中），则应用关联产品的 MAP 设置。</span></td>
</tr>
<tr>
<td>建议零售价</td>
<td><span>如果购物车中的产品指定了制造商建议零售价 (MSRP)，则价格不会被划掉。</span></td>
</tr>
<tr>
<td>分级价格</td>
<td><span><span>如果设置了分级定价，则分级定价消息不会显示在目录中。</span><span>在产品页面上，会显示一条通知，表示订购超过一定数量可以降低价格，但折扣仅以百分比显示。</span><span>对于分组产品的关联产品，折扣不会显示在产品页面上。</span><span>等级价格根据显示实际价格设置显示。</span></span></td>
</tr>
<tr>
<td>特价</td>
<td><span>如果指定特价，则根据显示实际价格设置显示特价。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="map-configuration"><span>地图配置</span></h2>
<p><span><span>默认情况下不启用最低广告价格 (MAP) 功能。</span><span>如果您想将此功能添加到您的商店，您必须启用它并为您的产品配置 MAP 设置。</span><span>MAP 设置可应用于您目录中的所有产品或针对特定产品进行配置。</span><span>当全局启用 MAP 时，店面中的所有产品价格都将隐藏起来。</span><span>您可以使用多种配置选项来遵守您与制造商的协议条款，同时仍然为您的客户提供更优惠的价格。</span></span></p>
<p><img alt="实际价格出现&ldquo;手势&rdquo;" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-msrp-on-gesture.png?lang=en" /></p>
<p><span><span>在全局级别，您可以启用或禁用 MAP，将其应用于所有产品，定义实际价格的显示方式。</span><span>您还可以编辑商店中显示的相关消息和信息提示的文本。</span></span></p>
<p><span><span>启用 MAP 后，产品级 MAP 设置可用。</span><span>您可以通过输入厂商建议零售价并选择实际价格在商店中的显示方式，将 MAP 应用于单个产品。</span><span>产品级 MAP 设置会覆盖全局 MAP 设置。</span></span></p>
<p><img alt="点击价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-price-map.png?lang=en" /></p>
<h3 id="step-1%3A-enable-map-for-the-store-view"><span>第 1 步：为商店视图启用 MAP</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span><span>如果适用，将</span><span>右上角的</span></span><span>Store View设置为应用配置的视图。</span><span></span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>Sales</span><span><span>并选择</span><span>下方的</span></span><span>Sales 。</span><span></span></p>
</li>
<li>
<p><span>展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>最低</span><em>广告价格</em><span>部分。</span></p>
</li>
<li>
<p><span>如有必要，将</span><span>启用 MAP</span><span>设置为</span><code>Yes</code><span>。</span></p>
<p><img alt="地图配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/sales-minimum-advertised-price.png?lang=en" /></p>
<p><span></span></p>
</li>
</ol>
<h3 id="step-2%3A-configure-the-map-settings"><span>第 2 步：配置 MAP 设置</span></h3>
<p><span>使用以下方法之一配置 MAP 设置：</span></p>
<h4 id="method-1%3A-configure-map-for-all-products"><span>方法一：为所有产品配置MAP</span></h4>
<ol>
<li>
<p><span>要确定您希望客户在何时何地看到实际价格，请执行以下操作：</span></p>
<ul>
<li>
<p><span>要更改默认值，请取消选择</span><span>使用系统值</span><span>复选框。</span></p>
</li>
<li>
<p><span>将</span><span>显示实际价格</span><span>设置为以下之一：</span></p>
<ul>
<li><code>In Cart</code></li>
<li><code>Before Order Confirmation</code></li>
<li><code>On Gesture (on click)</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><span>输入您希望在</span><span>默认弹出文本消息</span><span>中显示的文本。</span></p>
</li>
<li>
<p><span>输入您希望在</span><span>默认&ldquo;这是什么&rdquo;文本消息</span><span>中显示的任何其他说明。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h4 id="method-2%3A-configure-map-for-a-single-product"><span>方法二：为单个产品配置MAP</span></h4>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>库存</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span></span><span>在编辑</span><span><span>模式下</span><span>打开产品。</span></span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>Advanced Settings</span><span>并选择</span><span>Advanced Pricing</span><span>。</span></p>
<p><img alt="厂商建议零售价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-msrp.png?lang=en" /></p>
</li>
<li>
<p><span>输入</span><span>制造商的建议零售价</span><span>(MSRP)。</span></p>
<p><span>在此示例中，产品价格为 54.00 美元，建议零售价为 59.95。</span></p>
</li>
<li>
<p><span>将</span><span>显示实际价格</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Use config</code><span><span>-（默认）应用 MAP 配置设置。</span><span>|</span></span></li>
<li><code>On Gesture</code><span></span><em>- 当客户单击&ldquo;点击价格</em><span>&rdquo;或</span><em>&ldquo;这是什么？&rdquo;</em><span><span>时，在弹出窗口中显示实际产品价格。</span><span>关联。</span></span></li>
<li><code>In Cart</code><span>- 显示购物车中的实际产品价格。</span></li>
<li><code>Before Order Confirmation</code><span>- 在结帐过程结束时显示实际产品价格，就在确认订单之前。</span></li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>制造商的建议零售价和显示实际价格字段仅</span><span>在配置中启用</span></span>最低广告价格时出现。<span></span></p>
</div>
</div>
</li>
</ol>
<h3 id="step-3%3A-save-the-configuration"><span>第三步：保存配置</span></h3>
<p><span>完成后，点击</span><span>完成</span><span>，然后点击</span><span>保存</span><span>。</span></p>]]></description>
      <pubDate>Sun, 22 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2分级价格]]></title>
      <link>https://www.360magento.com/blog/Tier-Price/</link>
      <description><![CDATA[<p><span><span>分级定价让您可以从店面的产品列表或产品页面提供数量折扣。</span><span>折扣可以应用于特定的商店视图或客户组或共享目录。</span></span></p>
<p><span><span>如果您有许多产品要更新，最有效的方法是导入层级价格更改，而不是单独输入它们。</span><span><br /></span></span></p>
<p><img alt="店面产品页面上的分级价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-tier-storefront.png?lang=en" /></p>
<p><span>产品页面计算数量折扣并显示一条消息，例如：</span></p>
<p><code>Buy 6 for $5.95 each and save 15%</code></p>
<p><span><span>店面中的价格从最高到最低数量优先。</span><span>如果您有数量等级价格和数量等级价格</span></span><code>5</code><span>，</span><code>10</code><span>并且客户将五、六、七、八或九件商品添加到购物车，客户将收到数量</span><code>5</code><span><span>等级的折扣价。</span><span>当客户添加第十个项目时，为数量</span></span><code>10</code><span>层指定的折扣价取代数量层</span><code>5</code><span>，折扣价</span><code>10</code><span>适用。</span></p>
<h2 id="add-a-price-tier-for-a-product"><span>为产品添加价格等级</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span></span><em>在价格</em><span><span>字段</span><span>下方，点击</span></span><span>高级定价</span><span>。</span></p>
</li>
<li>
<p><span>在</span><em>分级价格</em><span>部分，点击</span><span>添加</span><span>。</span></p>
<p><span>如果您要创建包含多个价格的层级，请为每个附加层级单击</span><span>添加</span><span><span>，这样您就可以同时处理所有层级。</span><span>组中的每一层都有相同的网站和客户组或共享目录分配，但数量和价格不同。</span></span></p>
</li>
</ol>
<h2 id="configure-the-price-tier"><span>配置价格层</span></h2>
<ol>
<li>
<p><span><span>如果您的商店有多个网站，请选择</span><span>分级定价适用的</span></span><span>网站。</span><span></span></p>
</li>
<li>
<p><span></span><span>如有必要，通过选择客户组</span><span>或</span><span>共享目录</span><span>（</span><img alt="Adobe Commerce 的 B2B" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/b2b.svg?lang=en" /><span>仅</span>适用于 Adob​​e Commerce 的 B2B<span><span>&nbsp;）来限制定价层的可用性</span><span>。</span></span></p>
</li>
<li>
<p><span>对于</span><span>数量</span><span>，输入享受折扣必须订购的数量。</span></p>
<ul>
<li>
<p><span>方式一：输入价格为固定金额</span></p>
<p><span>将</span><span>价格</span><span>设置为</span><code>Fixed</code><span>并输入该层的一个单位的调整后价格。</span></p>
<p><img alt="固定金额的分级价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-tier-fixed.png?lang=en" /></p>
</li>
<li>
<p><span>方法 2：以百分比形式输入价格</span></p>
<p><span>将</span><span>价格</span><span>设置为</span><code>Discount</code><span>并输入折扣价作为产品基本价格的百分比。</span></p>
<p><span>例如，对于 15% 的折扣，输入数字</span><code>15</code><span><span>。</span><span>（价格保留两位小数，如</span></span><code>15.00</code><span>.）</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span></span><em>要获得折扣价，将根据价格</em><span><span>字段中定义的值计算定义的百分比&nbsp;</span><span>&nbsp;，而不是 _Special Price** 字段。</span></span></p>
</div>
</div>
</li>
</ul>
<p><img alt="等级价格百分比" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-tier-discount.png?lang=en" /></p>
</li>
</ol>
<h2 id="complete-the-price-configuration"><span>完成价格配置</span></h2>
<ol>
<li>
<p><span>要为不同的网站或客户组添加另一组层级定价，请重复前面的步骤。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>完成</span><span>，然后点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>最终</span><span>产品价格按最低相关价格计算</span></span><span><em>，</em></span><span></span><span><em>使用</em></span><span>以下公式：</span><br /><code>Final Price=Min(Regular(Base) Price, Group(Tier) Price, Special Price, Catalog Price Rule) + Sum(Min Price per each required custom option)</code></p>
</div>
</div>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><em>固定价格</em></span><span>产品可定制选项</span><em>不受</em><span>团体价格、分级价格、特价或目录价格规则的影响。</span></p>
</div>
</div>]]></description>
      <pubDate>Sat, 21 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2特价]]></title>
      <link>https://www.360magento.com/blog/Special-Price/</link>
      <description><![CDATA[<p><span><span>可以在指定时间段内提供特价。</span><span>在指定的时间段内，将显示特价而不是正常价格，后跟显示正常价格的符号。</span></span></p>
<p><img alt="产品页面上的特价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-price-special.png?lang=en" /></p>
<h2 id="apply-special-price-to-an-individual-product"><span>对单个产品应用特价</span></h2>
<p><span>您可以轻松地为目录中的单个产品设置特价。</span></p>
<h3 id="use-a-scheduled-update"><span>使用计划更新</span></h3>
<p><span>Adobe Commerce 包括对</span>预定更新<span><span>的支持。</span><span>使用这些促销工具在指定时间段内对特定产品应用特价。</span></span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>单击</span><span>预定更新</span><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>更新名称</span><span>，输入特价促销的名称。</span></p>
</li>
<li>
<p><span>输入简短</span><span>说明</span><span>。</span></p>
</li>
<li>
<p><span>使用</span><span>日历</span><span>(&nbsp;</span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span><span>) 选择</span><span>特价促销的</span></span><span>开始日期</span><span>和</span><span>结束日期。</span><span></span></p>
<p><span>您也可以使用</span><span>小时</span><span>和</span><span>分钟</span><span><span>滑块来选择开始和结束时间。</span><span>设置开始和结束后</span><span>单击</span></span><span>关闭。</span><span></span></p>
<p><img alt="另存为新更新" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-scheduled-update.png?lang=en" /></p>
</li>
<li>
<p><span>向下滚动到</span><em>价格</em><span>字段，点击</span><span>高级定价，然后输入</span><span></span><span>特价</span><span><span>的金额</span><span>。</span></span></p>
<p><img alt="特殊定价设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>完成</span><span>，然后点击</span><span>保存</span><span>。</span></p>
<p><span>在店面中，特价应出现在目录列表和产品页面上。</span></p>
<p><span></span><em>预定更改</em><span><span>显示在</span><span>页面顶部。</span></span></p>
<p><img alt="计划变更" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-scheduled-change.png?lang=en" /></p>
</li>
</ol>
<h3 id="use-a-simple-start-and-end-date"><span>使用简单的开始和结束日期</span></h3>
<p><span>Magento Open Source 在 Advanced Pricing 选项中包含简单的开始和结束日期选项。</span></p>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>向下滚动到</span><em>价格</em><span>字段，点击</span><span>高级定价</span><span>，然后输入</span><span>特价</span><span>金额。</span></p>
</li>
<li>
<p><span>使用</span><em>日历</em><span>(&nbsp;</span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span><span>) 选择</span><span>特价促销的</span></span><span>开始日期</span><span>和</span><span>结束日期。</span><span></span></p>
<p><span>特价在开始日期开始的午夜 (00:01) 后立即生效，一直持续到结束日期前一天的午夜 (23:59) 之前。</span></p>
<p><img alt="特殊定价设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>完成</span><span>，然后点击</span><span>保存</span><span>。</span></p>
<p><span>在店面中，特价应出现在目录列表和产品页面上。</span></p>
</li>
</ol>
<h2 id="apply-a-special-price-to-multiple-products"><span>对多个产品应用特价</span></h2>
<p><span>您还可以为多个产品分配特价，例如可</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-configurable.html?lang=en">配置产品</a><span>的多个变体。</span></p>
<h3 id="set-a-special-price-for-selected-products"><span>为所选产品设置特价</span></h3>
<p><span>以下示例显示如何将相同的特价分配给 Adob​​e Commerce 中可配置产品的多个产品变体。</span></p>
<ol>
<li>
<p><span>在</span><em>产品</em><span>页面上，单击</span><span>过滤器</span><span>并输入可配置产品的</span><span>名称</span><span>。</span></p>
</li>
<li>
<p><span>将</span><span>类型</span><span>设置为</span><code>Configurable Product</code><span>并单击</span><span>应用过滤器</span><span>。</span></p>
</li>
<li>
<p><span>如果要为所有产品分配相同的特价，请将第一列标题中的控件设置为</span><code>Select All</code><span>。</span></p>
<p><span>或者，您可以选中要包含的每个产品的复选框。</span></p>
</li>
<li>
<p><span>将</span><span>动作</span><span>控件设置为</span><code>Update attributes</code><span>。</span></p>
</li>
<li>
<p><span>向下滚动到 _Special Price** 字段并选中 _Special Price** 字段下方的</span><span>Change</span><span>复选框，然后输入您要提供的特价。</span></p>
<p><img alt="特殊价格字段" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-commerce.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<p><span><span>商店中提供的特价显示在目录列表和产品页面上。</span><span>对于可配置产品，选择选项后，正常价格也会显示在产品页面上。</span></span></p>
<h3 id="set-a-special-price-and-date-range-for-selected-products"><span>为所选产品设置特价和日期范围</span></h3>
<p><span>以下示例显示如何将相同的特价分配给 Magento Open Source 中可配置产品的多个产品变体。</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>过滤器</span><span>。</span></p>
</li>
<li>
<p><span>输入可配置产品的</span><span>名称</span><span>。</span></p>
</li>
<li>
<p><span>将</span><span>类型</span><span>设置为</span><code>Simple Product</code><span>。</span></p>
<p><img alt="过滤器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-filter.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>应用过滤器</span><span>。</span></p>
<p><span>网格列出了作为可配置产品的变体关联的所有简单产品。</span></p>
<p><img alt="产品变化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-filter-grid.png?lang=en" /></p>
</li>
<li>
<p><span>如果要为所有产品分配相同的特价，请将第一列标题中的控件设置为</span><code>Select All</code><span>。</span></p>
<p><span>或者，您可以选中要包含的每个产品的复选框。</span></p>
</li>
<li>
<p><span>将</span><span>动作</span><span>控件设置为</span><code>Update attributes</code><span>。</span></p>
<p><img alt="更新属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-action-update-attributes.png?lang=en" /></p>
</li>
<li>
<p><span>向下滚动到 _Special Price** 字段并执行以下操作：</span></p>
<ul>
<li>
<p><span>选中 _Special Price** 字段下方的</span><span>Change</span><span>复选框，然后输入您要提供的特价。</span></p>
</li>
<li>
<p><span><span>选中</span><em><span>特价起始日期</span></em><span>字段下方的</span></span><span>更改</span><span><span>复选框，单击</span><em><span>日历</span></em><span>(&nbsp;</span><span>)，然后选择特价促销的第一个日期。</span></span><em><span></span></em><span></span><em><span></span></em><span></span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span></span></p>
<p><span>特价在开始日期开始的午夜 (00:01) 后立即生效，一直持续到结束日期前一天的午夜 (23:59) 之前。</span></p>
</li>
<li>
<p><span><span>选中</span><em><span>特价截止日期</span></em><span>字段下方的</span></span><span>更改</span><span><span>复选框，单击</span><em><span>日历</span></em><span>(&nbsp;</span><span>)，然后选择特价促销的最后日期。</span></span><em><span></span></em><span></span><em><span></span></em><span></span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span></span></p>
</li>
</ul>
<p><img alt="特殊价格字段" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-special-action-update-attributes-fields.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
<p><span>一条消息指示用特价更新了多少条记录。</span></p>
<p><span><span>特价在指定日期在商店中可用，并显示在目录列表和产品页面上。</span><span>对于可配置产品，选择选项后，正常价格也会显示在产品页面上。</span></span></p>
<p><img alt="可配置产品特价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-special-price-configurable-product-detail.png?lang=en" /></p>
</li>
</ol>
<h2 id="testing"><span>测试</span></h2>
<p><span>如果特价没有在目录列表和产品页面的店面中正确显示，请清除浏览器缓存：</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>系统</span><span>&gt;</span><span>缓存管理</span><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>刷新 Magento 缓存</span><span>。</span></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>最终</span><span>产品价格按最低相关价格计算</span></span><span><em>，</em></span><span></span><span><em>使用</em></span><span>以下公式：</span><br /><code>Final Price=Min(Regular(Base) Price, Group(Tier) Price, Special Price, Catalog Price Rule) + Sum(Min Price per each required custom option)</code></p>
</div>
</div>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><em>固定价格</em></span><span>产品可定制选项</span><em>不受</em><span>团体价格、分级价格、特价或目录价格规则的影响。</span></p>
</div>
</div>]]></description>
      <pubDate>Fri, 20 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2团体价]]></title>
      <link>https://www.360magento.com/blog/Group-Price/</link>
      <description><![CDATA[<p><span><span>您可以使用管理员中的配置设置，根据商店中的客户群设置打折商品的价格。</span><span>这称为</span></span><em>团体定价</em><span>。</span></p>
<p><span><span>当购物者登录到他们的帐户时，可以向特定客户群的成员提供任何产品的折扣价。</span><span>客户组价格与正常价格一起显示在产品页面上，以便购物者可以轻松比较价格并采取相应行动。</span><span>在他们将产品添加到购物车后，正常价格将被基于其客户群的团体价格所取代。</span></span></p>
<p><span>客户群体的定价是</span>分层定价<span><span>的一个组成部分，并以类​​似的方式设置。</span><span>唯一的区别是客户组价格的数量为 1。</span></span></p>
<p><img alt="客户群折扣" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-price-group.png?lang=en" /></p>
<h2 id="benefits-of-using-group-pricing"><span>使用团体定价的好处</span></h2>
<ul>
<li>
<p><span>适合批发买家</span></p>
</li>
<li>
<p><span>激励客户升级他们的客户群以利用折扣</span></p>
</li>
<li>
<p><span>有针对性的营销活动</span></p>
</li>
<li>
<p><span>通过奖励忠诚的客户建立信任和信誉</span></p>
</li>
</ul>
<h2 id="set-up-a-group-price"><span>设置团价</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span></span><em>在价格</em><span><span>字段</span><span>下方，点击</span></span><span>高级定价</span><span>。</span></p>
</li>
<li>
<p><span>在</span><em>客户组价格</em><span>部分，点击</span><span>添加</span><span>。</span></p>
<p><img alt="高级定价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-group.png?lang=en" /></p>
</li>
<li>
<p><span>配置团价：</span></p>
<ul>
<li>
<p><span><span>对于多站点安装，请选择</span><span>适用团体价格的</span></span><span>网站。</span><span></span></p>
</li>
<li>
<p><span>选择要获得折扣的</span><span>客户组</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>数量</span><span></span><code>1</code><span><span>。</span><span>_</span></span></p>
</li>
<li>
<p><span>对于</span><span>Price</span><span>，设置定价类型和金额：</span></p>
<ul>
<li>
<p><code>Fixed</code><span>- 输入折扣后的产品价格。</span></p>
</li>
<li>
<p><code>Discount</code><span>- 输入折扣价占产品价格的百分比。</span></p>
</li>
</ul>
<p><img alt="客户团体价 10% 折扣" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-price-group-discount.png?lang=en" /></p>
</li>
</ul>
</li>
<li>
<p><span>要添加另一个组价格，请单击</span><span>添加</span><span>并重复上一步。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>完成</span><span>，然后点击</span><span>保存</span><span>。</span></p>
<p><img alt="购物车中的组价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-cart-price-group-discount.png?lang=en" /></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>最终</span><span>产品价格按最低相关价格计算</span></span><span><em>，</em></span><span></span><span><em>使用</em></span><span>以下公式：</span><br /><code>Final Price=Min(Regular(Base) Price, Group(Tier) Price, Special Price, Catalog Price Rule) + Sum(Min Price per each required custom option)</code></p>
</div>
</div>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><em>固定价格</em></span><span>产品可定制选项</span><em>不受</em><span>团体价格、分级价格、特价或目录价格规则的影响。</span></p>
</div>
</div>]]></description>
      <pubDate>Thu, 19 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2高级定价]]></title>
      <link>https://www.360magento.com/blog/Advanced-Pricing/</link>
      <description><![CDATA[<p><span><span>Adobe Commerce 和 Magento Open Source 支持各种定价选项，您可以使用这些选项进行促销，或满足制造商的最低广告定价要求。</span><span>可以按计划更改产品定价，也可以根据在产品级别或购物车中应用的价格规则进行更改。</span></span></p>
<p><span>使用高级定价管理您的产品价格，为客户提供更优惠的价格，鼓励消费者花更多钱，增加您网站的流量，并清理旧库存。</span></p>
<p><span></span><em>高级定价</em><span><span>设置定义了可用于特定客户组或共享目录的特殊定价所需的条件</span><span>。</span><span>高级定价可应用于简单、虚拟、可下载和捆绑产品。</span><span>要将折扣价应用于其他产品类型，请使用</span></span>目录价格规则<span><span>。</span><span>有关详细信息，请参阅</span></span>价格范围<span>。</span></p>
<p><span><span>高级定价数据与产品页面同步。</span><span>例如，如果您更新层级价格数量，系统会更新产品页面上的值。</span></span></p>
<p><img alt="Adobe Commerce 的 B2B" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/b2b.svg?lang=en" /><span>（仅</span>适用于 Adob​​e Commerce 的 B2B<span><span>）如果您使用共享目录，高级定价数据将与产品页面和共享目录同步。</span><span>例如，如果您更新层级价格数量，系统会更新共享目录和产品页面上的值。</span><span>共享目录中指示的任何自定义定价都优先于客户组定价。</span><span>另请参阅</span><em><span>B2B for Adob​​e Commerce 指南</span></em><span>中的</span></span>设置定价和结构<span>。</span><em><span></span></em><span></span></p>
<p><img alt="高级定价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-pricing-advanced-link.png?lang=en" /></p>
<h2 id="access-the-advanced-pricing-options"><span>访问高级定价选项</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>在</span><span>价格</span><span>下，单击</span><span>高级定价</span><span>。</span></p>
</li>
<li>
<p><span>按照所需高级定价类型的说明进行操作。</span></p>
<ul>
<li>
<p>团体价</p>
</li>
<li>
<p>特价</p>
</li>
<li>
<p>分级价格</p>
</li>
<li>
<p>最低广告价格</p>
</li>
</ul>
</li>
</ol>
<h2 id="page-reference"><span>页面参考</span></h2>
<h3 id="special-price"><span>特价</span></h3>
<p><span><span>输入特价以在指定时间段或预定活动期间提供折扣价。</span><span>当有特价时，零售价会被划掉，特价会以粗体大字显示在下方。</span></span></p>
<h4 id="special-price-from-dates"><span>特价日期</span></h4>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>从</span></td>
<td><span><span>设置特价可用的第一个日期。</span><span>您可以输入日期或从日历中选择日期。</span></span></td>
</tr>
<tr>
<td><span>到</span></td>
<td><span><span>设置特价可用的最后日期。</span><span>您可以输入日期或从日历中选择日期。</span></span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="cost"><span>成本</span></h3>
<p><span>这是物品的实际成本。</span></p>
<h3 id="customer-group-price"><span>客户团价</span></h3>
<p><img alt="高级定价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-pricing-advanced.png?lang=en" /></p>
<p><span>为特定客户群设置促销和等级价格。</span></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>物品</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>网站</span></td>
<td><span><span>标识应用组价规则的网站。</span><span>仅当安装有多个网站时才会出现此选项。</span></span></td>
</tr>
<tr>
<td><span>客户群</span></td>
<td><span><span>（必需）标识有资格获得折扣价的客户组。</span><span>当更改组或目录字段中的值时，与先前设置匹配的相应自定义价格行将从共享目录中删除。</span></span><br /><span>所有组</span><span>- 将规则应用于所有客户组。</span><br /><span>NOT LOGGED IN</span><span>&nbsp;- 应用规则来宾和未登录其帐户的客户。</span></td>
</tr>
<tr>
<td><span>数量</span></td>
<td><span>指定接收分级价格所需的数量。</span></td>
</tr>
<tr>
<td><span>价格</span></td>
<td><span><span>（必需）在特定网站内为客户组成员指定固定或折扣产品价格。</span><span>选项：</span></span><br /><span>Fixed</span><span><span>&nbsp;-（默认）折扣价作为固定的小数值输入。</span><span>例如，输入</span></span><code>9.99</code><span>折扣价。</span><br /><span>折扣</span><span><span>- 折扣价以基本产品价格的百分比 (%) 形式输入。</span><span>例如，输入</span></span><code>10</code><span>10% 的折扣。</span></td>
</tr>
<tr>
<td><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan-solid.png?lang=en" /></td>
<td><span>删除当前规则。</span></td>
</tr>
<tr>
<td><span>添加</span></td>
<td><span>为新规则插入另一行。</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="catalog-and-tier-price"><span>目录和等级价格</span></h3>
<p><span>为特定的共享目录和客户组设置促销和分级价格。</span></p>
<p><img alt="分层定价" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-pricing-promotional-tiered-b2b.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>物品</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>网站</span></td>
<td><span><span>标识应用组价规则的网站。</span><span>仅当安装有多个网站时才会出现此选项。</span></span><br /><span><em>重要提示：</em></span><span><span>还要在</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/pricing/catalog-price-scope.html?lang=en"><span>目录价格范围</span></a><span>配置中选择</span></span><em>网站</em><span><span>，否则会为</span><span><span>所有</span></span><span>网站显示设置的高级价格。</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/pricing/catalog-price-scope.html?lang=en"><span></span></a><span></span><span><span></span></span><span></span></td>
</tr>
<tr>
<td><span>组或目录</span></td>
<td><span><span>（必需）标识有资格获得折扣价的客户组或共享目录。</span><span>当更改组或目录字段中的值时，与先前设置匹配的相应自定义价格行将从共享目录中删除。</span></span><br /><span>所有组</span><span><span>- 将规则应用于所有客户组。</span><span>该值不适用于共享目录，高级定价数据的更改不会与共享目录同步。</span></span><br /><span>NOT LOGGED IN</span><span>&nbsp;- 应用规则来宾和未登录其帐户的客户。</span><br /><span>共享目录</span><span>- 将规则应用于特定的共享目录。</span></td>
</tr>
<tr>
<td><span>数量</span></td>
<td><span>指定接收分级价格所需的数量。</span></td>
</tr>
<tr>
<td><span>价格</span></td>
<td><span><span>（必需）在特定网站内为客户组成员指定固定或折扣产品价格。</span><span>选项：</span></span><br /><span>Fixed</span><span><span>&nbsp;-（默认）折扣价作为固定的小数值输入。</span><span>例如，输入</span></span><code>9.99</code><span>折扣价。</span><br /><span>折扣</span><span><span>- 折扣价以基本产品价格的百分比 (%) 形式输入。</span><span>例如，输入</span></span><code>10</code><span>10% 的折扣。</span></td>
</tr>
<tr>
<td><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan-solid.png?lang=en" /></td>
<td><span>删除当前规则。</span></td>
</tr>
<tr>
<td><span>添加</span></td>
<td><span>为新规则插入另一行。</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="minimum-advertised-price"><span>最低广告价格</span></h3>
<p><span>产品的最低广告价格 (MAP)。</span></p>
<h3 id="display-actual-price"><span>显示实际价格</span></h3>
<p><span>确定客户可以在何处看到产品的实际价格。</span></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>物品</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>使用配置</span></td>
<td><span>使用价格显示的当前配置设置。</span></td>
</tr>
<tr>
<td><span>关于手势</span></td>
<td><span>在弹出窗口中显示实际产品价格，以响应</span><em>点击价格</em><span>或</span><em>这是什么？</em><span>关联。</span></td>
</tr>
<tr>
<td><span>在购物车</span></td>
<td><span>显示购物车中的实际产品价格。</span></td>
</tr>
<tr>
<td><span>订单确认前</span></td>
<td><span>在结帐过程结束时显示实际产品价格，就在提交订单之前。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Wed, 18 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2价格范围]]></title>
      <link>https://www.360magento.com/blog/Price-Scope/</link>
      <description><![CDATA[<p>用于产品价格的基础货币的范围可以配置为适用于全球或网站级别。如果应用于全球级别，则在整个商店层次结构中使用相同的价格。如果应用于网站级别，则可以从与不同网站关联的商店以不同价格购买相同的产品。默认情况下，产品定价的范围是全局的。</p>
<p><span><span>不同的因素会影响同一产品在一个地方的价格，而不会影响另一个地方的价格。</span><span>例如，产品可能有额外的分销成本，以及影响特定商店销售产品价格的其他考虑因素。</span><span>下图显示了将基础货币设置为网站级别的多站点安装。</span><span>与每个网站关联的商店和商店视图反映了在网站级别设置的产品定价。</span></span></p>
<h2 id="configure-price-scope"><span>配置价格范围</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>菜单上，转到</span><span>商店</span><span>&gt;</span><em>设置</em><span>&gt;</span><span>配置</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>向下滚动到</span><span>价格</span><span>部分并将</span><span>目录价格范围</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Global</code></li>
<li><code>Website</code></li>
</ul>
<p><span>您选择的范围设置显示在目录中的价格字段下方。</span></p>
<p><img alt="目录价格范围" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-price.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h2 id="use-scope-to-set-up-product-prices"><span>使用范围设置产品价格</span></h2>
<p><span><span>Commerce 不允许为每个商店设置产品价格。</span><span>但是您可以更改每个网站的价格：</span></span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>菜单上，转到</span><span>商店</span><span>&gt;</span><em>设置</em><span>&gt;</span><span>配置</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>在</span><span>Price</span><span>选项卡中，将 price scope 设置为</span><code>Website</code><span>而不是 global。</span></p>
</li>
<li>
<p><span>通过打开产品编辑页面设置价格，选择左上角的范围，然后输入每个网站的新价格。</span></p>
</li>
</ol>]]></description>
      <pubDate>Tue, 17 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2添加产品视频]]></title>
      <link>https://www.360magento.com/blog/Add-product-videos/</link>
      <description><![CDATA[<p><span><span>要添加产品视频，您必须先从您的 Google 帐户获取 API 密钥并将其输入到您的商店配置中。</span><span>然后，您可以链接到产品中的视频。</span></span></p>
<h2 id="step-1%3A-get-your-youtube-api-key"><span>第 1 步：获取您的 YouTube API 密钥</span></h2>
<ol>
<li>
<p><span>登录到您的 Google 帐户并访问</span>Google Developers Console<span>。</span></p>
</li>
<li>
<p><span>在顶部的搜索字段中，输入</span><code>YouTube Data API v3</code><span>并单击搜索图标。</span></p>
</li>
<li>
<p><span>当显示 API 页面时，确保它已启用。</span></p>
</li>
<li>
<p><span>在左侧面板中，选择</span><span>Credentials</span><span>。</span></p>
</li>
<li>
<p><span>根据您是否有凭据，执行以下操作之一：</span></p>
<ul>
<li>
<p><span>如果您已经拥有所需的凭据，请复制</span><em>API 密钥</em><span>表中的密钥。</span></p>
</li>
<li>
<p><span><span>如果您还没有此 API 的凭据，请单击</span><span>&nbsp;顶部的</span></span><span>创建凭据并按照提示创建所需的凭据。</span><span>在</span><em>Get your credentials</em><span>下，复制 API 密钥并单击</span><span>Done</span><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>将 API 密钥复制到剪贴板。</span></p>
</li>
<li>
<p><span>单击右侧的编辑图标并设置限制以确保 API 密钥仅限于正确的引荐来源网址。</span></p>
</li>
<li>
<p><span>生成密钥时稍等片刻，然后将密钥复制到剪贴板。</span></p>
<p><span>在下一步中，您会将密钥粘贴到商店的配置中。</span></p>
</li>
</ol>
<h2 id="step-2%3A-configure-the-key-in-commerce"><span>第 2 步：在 Commerce 中配置密钥</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><em><span>产品视频</span></em><span>部分并粘贴您的</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>YouTube&nbsp;</span><span><span>API 密钥</span></span><span>。</span></span><em><span></span></em><span></span><span><span></span></span><span></span></p>
<p><img alt="产品视频" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-product-video.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>出现提示时，刷新缓存。</span></p>
</li>
</ol>
<h2 id="step-3%3A-link-to-the-video"><span>第 3 步：链接到视频</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>在</span><em>图片和视频</em><span>部分，点击</span><span>添加视频</span><span>。</span></p>
<p><span>如果您尚未配置 YouTube API 密钥，请单击&ldquo;</span><span>确定</span><span><span>&nbsp;&rdquo;继续。</span><span>您不能链接到 YouTube 视频，但您可以完成该过程。</span></span></p>
<p><img alt="添加视频" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-video-add.png?lang=en" /></p>
</li>
<li>
<p><span>输入 YouTube 或 Vimeo 视频的</span><span>URL</span><span>&nbsp;&nbsp;。</span></p>
</li>
<li>
<p><span>在字段外单击并等待对 API 密钥或视频的反馈。</span></p>
<p><span>如果一切正常，YouTube 会提供视频的基本信息</span></p>
</li>
<li>
<p><span>输入视频的</span><span>标题</span><span>和</span><span>描述</span><span>。</span></p>
</li>
<li>
<p><span>要上传</span><span>预览图像</span><span>，请浏览至图像并选择文件。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>上传后，显示的预览图像由外部视频服务提供商自动生成。</span><span>您不能从 Adob​​e Commerce Admin 编辑图像。</span></span></p>
</div>
</div>
</li>
<li>
<p><span>如果您更喜欢使用视频元数据，请单击</span><span>获取视频信息</span><span>。</span></p>
</li>
<li>
<p><span>要确定视频在商店中的使用方式，请选中适用的每个</span><span>角色</span><span>的复选框：</span></p>
<ul>
<li><code>Base Image</code></li>
<li><code>Small Image</code></li>
<li><code>Swatch Image</code></li>
<li><code>Thumbnail</code></li>
<li><code>Hide from Product Page</code></li>
</ul>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
<p><img alt="新视频" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-video-new-with-data.png?lang=en" /></p>
</li>
</ol>
<h2 id="maintain-api-access"><span>维护 API 访问</span></h2>
<p><span>根据 Google 开发者</span>条款和条件<span><span>，YouTube 可能会禁用已闲置时间超过 90 天的帐户的 API 访问权限。</span><span>这可能会导致您的视频无法显示。</span><span>为防止出现这种情况，请使用 cron 作业定期 ping API：</span></span></p>
<div class="code-toolbar">
<pre class="language-code"><code class="language-code">30 10 1 * * curl -i -G -e https://yourdomain.com/ -d "part=snippet&amp;maxResults=1&amp;q=test&amp;key=YOUTUBEAPIKEY" https://www.googleapis.com/youtube/v3/search &gt;/dev/null 2&gt;&amp;1
</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy"><span>复制</span></button></div>
</div>
</div>
<h2 id="field-reference"><span>现场参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>网址</span></td>
<td><span>关联视频的 URL。</span></td>
</tr>
<tr>
<td><span>标题</span></td>
<td><span>视频标题。</span></td>
</tr>
<tr>
<td><span>描述</span></td>
<td><span>视频说明。</span></td>
</tr>
<tr>
<td><span>预览图像</span></td>
<td><span>上传的图像，用作商店中视频的预览。</span></td>
</tr>
<tr>
<td><span>获取视频信息</span></td>
<td><span><span>检索存储在主机服务器上的视频元数据。</span><span>您可以使用原始数据或根据需要更新它。</span></span></td>
</tr>
<tr>
<td><span>角色</span></td>
<td><span><span>确定预览图像在您的商店中的使用方式。</span><span>您可以选择选项的任意组合：</span></span><code>Base Image</code><span>,&nbsp;</span><code>Small Image</code><span>,&nbsp;</span><code>Thumbnail</code><span>,&nbsp;</span><code>Swatch Image</code><span>,</span><code>Hide from Product Page</code></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Mon, 16 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2管理产品图片和视频]]></title>
      <link>https://www.360magento.com/blog/Manage-product-images-and-videos/</link>
      <description><![CDATA[<p>对于每个产品，您可以上传多个图像和视频，重新排列它们的顺序，并控制每个图像和视频的使用方式。如果您要管理大量图像，您可能更愿意将它们成批导入，而不是单独上传每一个。有关详细信息，请参阅导入产品图片。</p>
<p><span>如果您计划上传大图片以在&ldquo;</span><em>产品详细信息</em><span><span>&rdquo;页面上查看，您可能需要考虑设置最大像素大小（宽度和高度）并在上传时自动调整文件大小。</span><span>我们提供了一个选项，可以在您上传时自动调整较大图像文件的大小。</span><span>有关详细信息，请参阅</span></span>调整产品图片大小<span>。</span></p>
<h2 id="update-the-product-images"><span>更新产品图片</span></h2>
<ol>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span><span>要使用特定的商店视图，请将</span><span>左上角的</span></span><span>商店视图选择器设置为适用的视图。</span><span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>新产品图片</span><span><em>始终会上传并在</em></span><span></span><span><em>所有</em></span><span><span>商店视图中可见</span><span>，即使</span></span><code>All Store Views</code><span>范围未用于上传也是如此。</span><br /><br /><span>要从特定商店视图中隐藏任何产品图像，您必须切换到该商店视图，为该图像选中</span><span>从产品页面隐藏</span><span>复选框，然后单击</span><span>保存</span><span>。</span></p>
</div>
</div>
</li>
<li>
<p><span>向下滚动并展开</span><em>图像和视频</em><span>部分。</span></p>
</li>
</ol>
<h3 id="upload-an-image"><span>上传图片</span></h3>
<p><span>为获得最佳兼容性，建议上传所有带有</span><code>sRGB</code><span><span>颜色配置文件的产品图片。</span><span>在产品图片上传期间，所有其他颜色配置文件会自动转换为</span></span><code>sRGB</code><span>颜色配置文件，这可能会导致上传图片中的颜色不一致。</span></p>
<p><span>图像文件名长度，包括扩展名，不能超过 90 个字符。</span></p>
<p><span>要上传图像，请执行以下操作之一：</span></p>
<ul>
<li>
<p><span><span>将桌面上的图像拖放到</span><em><span>图像和视频</span></em><span>框中的</span></span><em>相机</em><span>(&nbsp;&nbsp;</span><img alt="相机图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-camera.png?lang=en" /><span>) 磁贴上。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>在</span><em>图像和视频</em><span>框中，单击</span><em>相机</em><span>(&nbsp;&nbsp;</span><img alt="相机图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-camera.png?lang=en" /><span>) 磁贴，选择计算机上的图像文件，然后单击</span><span>打开</span><span>。</span></p>
<p><img alt="上传或拖放" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-images-and-video-jewel-tee.png?lang=en" /></p>
</li>
</ul>
<h3 id="rearrange-images"><span>重新排列图像</span></h3>
<p><span><span>要更改图库中图像的顺序，请单击</span><span>&nbsp;图像块底部的</span></span><em>排序</em><span><span>(&nbsp; ) 图标并将图像拖动到</span><em><span>图像和视频</span></em><span>框中的不同位置。</span></span><img alt="排序图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-icon-sort.png?lang=en" /><span></span><em><span></span></em><span></span></p>
<p><img alt="改变顺序" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-images-and-videos-drag.png?lang=en" /></p>
<h3 id="delete-an-image"><span>删除图像</span></h3>
<p><span>要从图库中删除图像，请单击图像块右上角的</span><span>删除</span><span>(&nbsp;&nbsp;</span><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan.png?lang=en" /><span>&nbsp;) 图标，然后单击</span><span>保存</span><span>。</span></p>
<h3 id="set-image-details"><span>设置图像细节</span></h3>
<p><span>单击要在详细视图中打开的图像并执行以下任一操作：</span></p>
<p><img alt="图像细节视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-image-detail-jewel-tee.png?lang=en" /></p>
<p><span>要关闭详细视图，请单击右上角的</span><em>关闭</em><span>(&nbsp;&nbsp;</span><img alt="关闭图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-close-x.png?lang=en" /><span>) 图标。</span></p>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
<h4 id="enter-alt-text"><span>输入替代文字</span></h4>
<p><span><span>图像替代文本被屏幕阅读器引用以提高网络可访问性，搜索引擎在索引站点时也引用该文本。</span><span>某些浏览器会在鼠标悬停时显示 Alt 文本。</span><span>替代文本可以是几个词长，并包括精心挑选的关键词。</span></span></p>
<p><span>在&ldquo;</span><em>替代文本</em><span>&rdquo;框中，输入图像的简短说明。</span></p>
<h4 id="assign-roles"><span>分配角色</span></h4>
<p><span><span>默认情况下，所有角色都分配给上传到产品的第一张图像。</span><span>要将角色重新分配给另一个图像，请执行以下操作：</span></span></p>
<p><span>在</span><em>角色</em><span>框中，选择要分配给图像的角色。</span></p>
<p><span>当您返回</span><em>图像和视频</em><span>部分时，当前分配的角色会出现在每个图像下方。</span></p>
<p><img alt="分配的角色" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-images-video-swatch.png?lang=en" /></p>
<h4 id="hide-an-image"><span>隐藏图片</span></h4>
<p><span>要从缩略图库中排除图像，请选中</span><span>隐藏</span><span>复选框并单击</span><span>保存</span><span>。</span></p>
<p><img alt="隐藏图像" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-images-and-videos-hidden.png?lang=en" /></p>
<h2 id="image-roles"><span>形象角色</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>形象角色</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>缩略图</span></td>
<td><span><span>缩略图图像出现在缩略图库、购物车和某些块（如相关项目）中。</span><span>示例尺寸：50 x 50 像素</span></span></td>
</tr>
<tr>
<td><span>小图</span></td>
<td><span><span>小图像用于类别和搜索结果页面列表中的产品图像，以及显示追加销售、交叉销售和新产品列表等部分所需的产品图像。</span><span>示例尺寸：470 x 470 像素</span></span></td>
</tr>
<tr>
<td><span>基本图像</span></td>
<td><span><span>基本图像是产品详细信息页面上的主要图像。</span><span>如果您上传的图像大于图像容器，则会激活图像缩放。</span><span>根据您想要实现的缩放级别，基本图像应该是容器大小的两倍或三倍。</span><span>示例尺寸：470 x 470 像素（无缩放）、1100 x 1100 像素（有缩放）</span></span></td>
</tr>
<tr>
<td><span>斯沃琪</span></td>
<td><span></span>样本<span><span>可</span><span>用于说明颜色、图案或纹理。</span><span>示例尺寸：50 x 50 像素</span></span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="watermarks"><span>水印</span></h2>
<p><span><span>如果您不惜代价创建自己的原创产品图片，那么您将无能为力地防止不法竞争者通过单击鼠标窃取它们。</span><span>但是，您可以通过在每张图像上放置水印以将它们标识为您的财产，从而使它们成为不太吸引人的目标。</span><span>水印文件可以是 JPG (JPEG)、GIF 或 PNG 图像。</span><span>GIF 和 PNG 文件类型都支持透明层，可用于为水印提供透明背景。</span></span></p>
<p><span>以下示例中用于</span><em>小</em><span>图像的水印是具有透明背景的黑色徽标，并使用以下设置保存为 PNG 文件：</span></p>
<ul>
<li><span>尺寸：50x50</span></li>
<li><span>不透明度：5</span></li>
<li><span>位置：瓷砖</span></li>
</ul>
<p><img alt="平铺水印" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-watermark-tiled.png?lang=en" /></p>
<h3 id="add-watermarks-to-product-images"><span>为产品图片添加水印</span></h3>
<ol>
<li>
<p><span>在</span><em>Admin</em><span>侧边栏上，转到</span><span>Content</span><span>&nbsp;&gt;&nbsp;</span><em>Design</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
<p><span>有关设计配置的更多信息，请参阅</span>设计配置<span>。</span></p>
</li>
<li>
<p><span><span>找到您要配置的商店视图，然后单击</span><em><span>操作</span></em><span>列</span><span>中的</span></span><span>编辑。</span><span></span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>在</span><em>其他设置</em><span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>下</span><span>，展开</span></span><span>产品图片水印</span><span>部分。</span></p>
</li>
<li>
<p><span>完成</span><span>Base</span><span>、</span><span>Thumbnail</span><span>、</span><span>Small</span><span>和</span><span>Swatch Image</span><span>图像设置，如下所示。</span></p>
<p><span>每个部分中的字段是相同的。</span></p>
<ul>
<li>
<p><span><span>以百分比形式</span><span>输入</span></span><span>图像不透明度。</span><span>例如：</span><code>40</code></p>
</li>
<li>
<p><span>输入</span><span>图像大小</span><span><span>（以像素为单位）。</span><span>例如：</span></span><code>200 x 200</code></p>
</li>
<li>
<p><span>单击</span><span>上传</span><span>并选择您要使用的图像文件。</span></p>
</li>
<li>
<p><span>设置</span><span>图像位置</span><span>以确定水印出现的位置。</span></p>
</li>
</ul>
<p><img alt="产品图片水印 - 基础" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/config-design-product-image-watermarks-base.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>当提示刷新缓存时，点击系统消息中的</span><span>缓存管理</span><span>，刷新失效的缓存。</span></p>
<p><img alt="刷新缓存" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/msg-cache-management.png?lang=en" /></p>
</li>
</ol>
<div class="extension tip">
<div><span><span>提示</span></span></div>
<div>
<p><span>您可以单击</span><span>使用默认值</span>&nbsp;<img alt="箭头返回" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-arrow-return.png?lang=en" /><span>来恢复默认值。</span></p>
</div>
</div>
<h3 id="delete-a-watermark"><span>删除水印</span></h3>
<ol>
<li>
<p><span>在图像的左下角，单击</span><span>删除</span><span>(&nbsp;&nbsp;</span><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan-solid.png?lang=en" /><span>&nbsp;) 图标。</span></p>
<p><img alt="删除水印" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-image-watermark-delete.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>当提示刷新缓存时，点击系统消息中的</span><span>缓存管理</span><span>，刷新失效的缓存。</span></p>
<p><span>如果水印图像仍然存在于店面中，请返回缓存管理并单击</span><span>Flush Magento Cache</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sun, 15 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品图片配置]]></title>
      <link>https://www.360magento.com/blog/Product-image-configuration/</link>
      <description><![CDATA[<p><span>如果您计划上传大图片以在&ldquo;</span><em>产品详细信息</em><span><span>&rdquo;页面上查看，您可能需要考虑设置最大像素大小（宽度和高度）并在上传时自动调整文件大小。</span><span>为了支持这种类型的产品图片上传，有一个选项可以在您上传时自动调整较大图片文件的大小。</span><span>对于要添加到目录但还没有要显示的图像资产的产品，您可以配置占位符图像。</span></span></p>
<h2 id="product-image-resizing"><span>产品图片调整大小</span></h2>
<p><span></span><em>上传产品图片时，您可以添加不同尺寸的较大图片，以在&ldquo;产品详细信息</em><span><span>&rdquo;页面</span><span>上提供详细、高质量的缩放。</span><span>为确保所有图像具有相似的大小和外观，我们提供了一个图像大小调整选项，以确保所有图像都匹配特定的像素大小。</span><span>此选项使用配置设置自动调整所有产品图像的大小，这有助于提高缩放性能、更快地加载图像并保持产品图像的统一外观。</span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>为获得最佳兼容性，建议上传所有带有</span><code>sRGB</code><span><span>颜色配置文件的产品图片。</span><span>在产品图片上传期间，所有其他颜色配置文件会自动转换为</span></span><code>sRGB</code><span>颜色配置文件，这可能会导致上传图片中的颜色不一致。</span></p>
</div>
</div>
<p><span><span>设置最大像素宽度和高度可按像素将图像调整为物理尺寸。</span><span>Commerce 在保持比例的同时，根据宽度或高度的较大值调整图像大小。</span><span>降低 JPG 图像的质量数量可减小文件大小。</span></span></p>
<p><span><span>例如，100% 的 3000 x 2100 像素 JPG 可能是 5mb 以上的图像文件。</span><span>调整此图像的大小会将宽度减小到 1920 像素，同时保持比例和质量为 80%，以提供更小的文件大小和更高的质量。</span></span></p>
<h3 id="enable-image-resizing"><span>启用图像大小调整</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>Advanced</span><span>并选择</span><span>System</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><em><span>图像上传配置</span></em></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><em><span></span></em><span></span></p>
<p><span>要更改默认设置，您可能需要取消选择</span><span>使用系统值</span><span>复选框。</span></p>
<p><img alt="图片上传配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/system-image-upload-configuration.png?lang=en" /></p>
<p><span><span>有关这些配置设置的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span><em>图像上传配置</em><span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>要启用，请确保</span><span>Enable Frontend Resize</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span><span>输入介于</span><span>和</span><span>%之间的</span></span><span>质量</span><span>设置。</span><code>1</code><span></span><code>100</code><span></span></p>
<p><span>我们建议将设置设置在 80-90% 之间，以减小文件大小并提高质量。</span></p>
</li>
<li>
<p><span>设置图像的</span><span>最大宽度</span><span>（以像素为单位）。</span></p>
<p><span>调整图像大小时，它不会超过此宽度并保持比例。</span></p>
</li>
<li>
<p><span>设置图像的</span><span>最大高度</span><span>（以像素为单位）。</span></p>
<p><span>调整图像大小时，它不会超过此高度并保持比例。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h3 id="field-descriptions"><span>字段说明</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th>范围</th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>质量</span></td>
<td><span>全球的</span></td>
<td><span><span>确定调整大小的图像的 JPG 质量。</span><span>较低的质量会减小文件大小。</span><span>我们建议 80-90% 以帮助减小文件大小并保持高质量。</span><span>默认值：80</span></span></td>
</tr>
<tr>
<td><span>启用前端调整大小</span></td>
<td><span>全球的</span></td>
<td><span>允许 Commerce 调整您可能为&ldquo;</span><em>产品详细信息</em><span><span>&rdquo;页面上传的大型、超大图像的大小。</span><span>Commerce 在上传文件时使用 JavaScript 调整图像文件的大小。</span><span>调整图像大小时，它会保持准确的比例，以满足且不超过最大宽度或最大高度的最大尺寸。</span><span>默认：</span></span><code>Yes</code></td>
</tr>
<tr>
<td><span>最大宽度</span></td>
<td><span>全球的</span></td>
<td><span><span>确定图像的最大像素宽度。</span><span>调整图像大小时，它不会超过此宽度。</span><span>默认：</span></span><code>1920</code></td>
</tr>
<tr>
<td><span>最大高度</span></td>
<td><span>全球的</span></td>
<td><span><span>确定图像的最大像素高度。</span><span>调整图像大小时，它不会超过此高度。</span><span>默认：</span></span><code>1200</code></td>
</tr>
</tbody>
</table>
</div>
<h2 id="image-placeholders"><span>图片占位符</span></h2>
<p><span><span>在永久产品图像可用之前，Adobe Commerce 和 Magento Open Source 使用临时图像作为占位符。</span><span>可以为每个角色上传不同的占位符。</span><span>初始占位符图像是示例徽标，您可以将其替换为您选择的图像。</span></span></p>
<p><img alt="图片占位符" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-image-placeholder.png?lang=en" /></p>
<p><span>要上传占位符图像：</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>产品图片占位符</span></span></span><img alt="扩展图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><span><span>有关这些配置设置的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span><em>产品图像占位符</em><span>。</span><em><span></span></em><span></span></p>
<p><img alt="产品图片占位符" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-product-image-placeholders.png?lang=en" /></p>
</li>
<li>
<p><span>对于每个图像角色，单击</span><span>选择文件</span><span>，在您的计算机上找到图像，然后上传文件。</span></p>
<p><span>您可以为所有三个角色使用相同的图像，也可以为每个角色上传不同的占位符图像。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sat, 14 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2礼品卡产品]]></title>
      <link>https://www.360magento.com/blog/Gift-card-product/</link>
      <description><![CDATA[<p>每张礼品卡都有一个唯一的代码，在结账时只能由一位顾客兑换。必须先建立代码池，然后才能销售礼品卡。有关如何在购物车中兑换礼品卡的信息，请参阅礼品卡工作流程。</p>
<p><img alt="礼品卡产品页面" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-giftcard-product-page.png?lang=en" /></p>
<p><span>礼品卡产品分为三种：</span></p>
<ul>
<li>
<p><span>虚拟</span><span><span>- 虚拟礼品卡会发送到收件人的电子邮件地址，这是购买礼品卡时需要的。</span><span>送货地址不是必需的。</span></span></p>
</li>
<li>
<p><span>实物</span><span>- 实物礼品卡会运送到收件人的地址，这是购买礼品卡时所必需的。</span></p>
</li>
<li>
<p><span>合并</span><span>-</span>合并后的礼品卡<span><span>将发送并通过电子邮件发送给收件人。</span><span>购买礼品卡时需要收件人的电子邮件和送货地址。</span></span></p>
</li>
</ul>
<h2 id="create-a-gift-card-product"><span>创建礼品卡产品</span></h2>
<p><span>以下说明演示了使用</span>产品模板<span><span>、必填字段和基本设置创建礼品卡的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<h3 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span></span><em>在添加产品</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span><span>) 菜单</span><span>的右上角，选择</span></span><span>礼品卡</span><span>。</span></p>
<p><img alt="添加礼品卡" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-gift-card.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h3>
<p><span>您可以使用默认</span><code>Gift Card</code><span><span>属性集或选择另一个。</span><span>要选择用作产品模板的属性集，请执行以下操作之一：</span></span></p>
<ul>
<li>
<p><span>单击&ldquo;</span><span>属性集</span><span>&rdquo;字段并输入属性集的全部或部分名称。</span></p>
</li>
<li>
<p><span>在显示的列表中，选择要使用的属性集。</span></p>
</li>
</ul>
<p><img alt="选择属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set-gift-card.png?lang=en" /></p>
<h3 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h3>
<ol>
<li>
<p><span>输入礼品卡的</span><span>产品名称</span><span>。</span></p>
<p><span><span>您还可以在名称中注明礼品卡的类型。</span><span>例如，</span></span><em>Luma 虚拟礼品卡</em><span>。</span></p>
</li>
<li>
<p><span>输入产品的</span><span>SKU</span><span>。</span></p>
<p><span>默认情况下，产品名称用作默认 SKU。</span></p>
</li>
<li>
<p><span>将</span><span>卡类型</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Virtual</code><span>- 虚拟礼品卡通过电子邮件发送给收件人。</span></li>
<li><code>Physical</code><span>- 实物礼品卡可提前量产并压印独特编码。</span></li>
<li><code>Combined</code><span>- 组合礼品卡兼具虚拟礼品卡和实体礼品卡的特点。</span></li>
</ul>
<p><img alt="礼品卡类型" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-gift-card-type.png?lang=en" /></p>
</li>
<li>
<p><span>要为客户提供固定金额的选择，请单击&ldquo;</span><span>添加金额</span><span>&rdquo;并以小数形式输入卡的第一个固定值。</span></p>
<p><span>重复此步骤输入固定金额的选择。</span></p>
<p><img alt="礼品卡金额" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-gift-card-amounts.png?lang=en" /></p>
</li>
<li>
<p><span>要让客户能够设置礼品卡的价值，请执行以下操作：</span></p>
<ul>
<li>
<p><span>将</span><span>未结金额</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>要定义最小和最大可接受值的范围，请输入未结</span><span>金额从</span><span>和</span><span>到</span><span>值。</span></p>
</li>
</ul>
<p><span>您可以创建具有固定定价、开放金额定价或两者的礼品卡。</span></p>
</li>
</ol>
<h3 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h3>
<ol>
<li>
<p><span>对于实体礼品卡或组合礼品卡，请输入库存</span><span>数量</span><span>。</span></p>
</li>
<li>
<p><span>如果是要运送的礼品卡，请输入包裹的</span><span>重量</span><span>。</span></p>
</li>
<li>
<p><span>在</span><span>类别</span><span>字段中，选择</span><code>Gift Card</code><span>。</span></p>
</li>
</ol>
<p><span><span>可能还有其他描述产品的单独属性。</span><span>选择不同的属性集，您可以稍后完成它们。</span></span></p>
<h3 id="step-5%3A-complete-the-gift-card-information"><span>第五步：填写礼品卡信息</span></h3>
<p><span>产品设置的</span><em>礼品卡信息</em><span>部分可用于覆盖确定礼品卡管理方式的</span>礼品卡配置<span>设置。</span></p>
<ol>
<li>
<p><span>向下滚动到</span><em>礼品卡信息</em><span>部分。</span></p>
<p><span>本节中的默认设置由系统配置决定。</span></p>
<p><img alt="礼品卡信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-gift-card-information.png?lang=en" /></p>
</li>
<li>
<p><span>根据您希望礼品卡的功能更改其他字段：</span></p>
<ul>
<li>
<p><span>Treat Balance as Store Credit</span><span>&nbsp;- 确定礼品卡持有人是否可以将余额兑换为商店信用。</span></p>
</li>
<li>
<p><span>有效期（天）</span><span><span>&nbsp;- 确定购买后到礼品卡过期的天数。</span><span>如果您不想为卡的使用寿命设置限制，请将此字段留空。</span></span></p>
</li>
<li>
<p><span>允许消息</span><span><span>- 确定礼品卡的购买者是否可以输入消息给收件人。</span><span>虚拟（通过电子邮件发送）和实物（运送）礼品卡都可以包含礼品留言。</span></span></p>
</li>
<li>
<p><span>电子邮件模板</span><span>- 确定用于向礼品卡收件人发送通知的电子邮件模板。</span></p>
</li>
</ul>
</li>
</ol>
<h3 id="step-6%3A-complete-the-product-information"><span>第六步：填写产品信息</span></h3>
<p><span>根据需要填写以下部分中的信息：</span></p>
<ul>
<li>内容</li>
<li>图片和视频</li>
<li>相关产品、追加销售和交叉销售</li>
<li>搜索引擎优化</li>
<li>可定制的选项</li>
<li>网站中的产品</li>
<li>设计</li>
<li>礼品选项</li>
</ul>
<h3 id="step-7%3A-publish-the-product"><span>第 7 步：发布产品</span></h3>
<ol>
<li>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>开关设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>执行以下操作之一：</span></p>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;</span><span>) 菜单上选择</span></span><span>客户视图，</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
</li>
</ul>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/admin-customer-view.png?lang=en" /></p>
<p><span>方法 2：</span><span>保存并关闭</span></p>
<p><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>) 菜单上，选择</span><span>保存并关闭</span><span>。</span></p>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
</li>
</ol>
<h2 id="things-to-remember"><span>要记住的事情</span></h2>
<ul>
<li>
<p><span>必须先生成唯一编号的</span><em>代码池</em><span>，然后才能提供礼品卡进行销售。</span></p>
</li>
<li>
<p><span>礼品卡可以设置为</span><code>Redeemable</code><span>或</span><code>Non-Redeemable</code><span>。</span></p>
</li>
<li>
<p><span></span><span><em>购买礼品卡时不对</em></span><span><span>礼品卡</span><span>征税。</span><span>仅当购买的礼品卡用于购买产品时，才会对产品征税。</span></span></p>
</li>
<li>
<p><span>礼品卡的有效期可以是无限的，也可以设置为指定的天数。</span></p>
</li>
<li>
<p><span>礼品卡的价值可以设置为固定金额，也可以设置为具有最小值和最大值的开放金额。</span></p>
</li>
<li>
<p><span>可以在下订单或开具发票时为客户创建礼品卡帐户。</span></p>
</li>
</ul>]]></description>
      <pubDate>Fri, 13 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2目录图片和视频]]></title>
      <link>https://www.360magento.com/blog/Catalog-images-and-video/</link>
      <description><![CDATA[<p><span><span>使用比例一致的高质量图像可以使您的目录具有专业的外观和商业吸引力。</span><span>如果您有一个大型目录，每个产品有多个图像，那么您可以轻松地管理数百个（如果不是数千个）产品图像。</span><span>在开始之前，为您的图像文件建立一个命名约定，并组织它们，以便您可以在需要时找到原件。</span></span></p>
<p><img alt="产品图片" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-images-videos-swatch.png?lang=en" /></p>
<p><span><span>单个产品图像在整个目录中以不同的尺寸呈现。</span><span>图像容器在页面上的显示大小在主题的样式表中定义。</span><span>但是，图像在您商店中的显示位置取决于分配给图像的角色。</span><span>主要产品图像或</span></span><em>基本</em><span><span>图像必须足够大以产生缩放所需的放大率。</span><span>除了主图片之外，同一图片的较小版本可能会出现在产品列表中，或作为缩略图出现在购物车中。</span><span>您可以上传所需的最大尺寸的图像或使用</span></span>Adob​​e Stock<span><span>图像，然后让 Commerce 呈现每次使用所需的尺寸。</span><span>可以为所有角色使用相同的图像，也可以为每个角色分配不同的图像。</span><span>默认情况下，上传的第一张图像分配给所有三个角色。</span></span></p>
<h2 id="storefront-media-browser"><span>店面媒体浏览器</span></h2>
<p><span><span>产品页面上的媒体浏览器显示与产品相关的多个图像、视频或样本。</span><span>每个缩略图都可以显示产品的不同视图或变体。</span><span>单击缩略图浏览媒体资产。</span><span>尽管媒体浏览器的位置因主题而异，但默认位置就在产品页面主图像的下方。</span><span><br /></span></span></p>
<p><img alt="店面媒体浏览器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-thumbnail-gallery.png?lang=en" /></p>
<h3 id="image-zoom"><span>图像缩放</span></h3>
<p><span>如果</span>基本图像<span><span>足够大以创建缩放效果，则客户可以在鼠标悬停时查看图像的放大部分。</span><span>启用缩放后，客户可以单击主图像并四处移动光标以放大图像的不同部分。</span><span>放大的选区出现在图像的右侧。</span></span></p>
<p><img alt="图像缩放" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-image-zoom.png?lang=en" /></p>]]></description>
      <pubDate>Thu, 12 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2可下载产品]]></title>
      <link>https://www.360magento.com/blog/Downloadable-product/</link>
      <description><![CDATA[<p><span><span>可下载产品可以是您可以作为文件提供的任何内容，例如电子书、音乐、视频、软件应用程序或更新。</span><span>您可以出售一张专辑并单独出售每首歌曲。</span><span>您还可以使用可下载产品来提供产品目录的电子版本。</span></span></p>
<p><span><span>由于购买后才能下载，因此您可以提供样本，例如书籍的摘录、音频文件的剪辑或视频的预告片。</span><span>这是客户在购买产品之前可以尝试的东西。</span><span>您提供的可供下载的文件可以上传到您的服务器，也可以从其他服务器上传。</span></span></p>
<p><img alt="可下载产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-product-downloadable.png?lang=en" /></p>
<p><span><span>可下载的产品可以配置为要求客户登录帐户以接收链接，或者可以通过电子邮件发送并与他人共享。</span><span>下载可用之前的订单状态、默认值和其他交付选项都在配置中设置。</span><span>在计划添加可下载目录时，请注意以下事项：</span></span></p>
<ul>
<li>
<p><span>可下载的产品可以上传到服务器或从互联网上的另一台服务器链接。</span></p>
</li>
<li>
<p><span>您可以确定客户可以下载产品的次数。</span></p>
</li>
<li>
<p><span>购买可下载产品的客户可能需要在结账前先登录。</span></p>
</li>
<li>
<p><span>当订单处于 a</span><code>Pending</code><span>或</span><code>Invoiced</code><span>状态时，可以交付可下载产品。</span></p>
</li>
<li>
<p><span>由于可下载产品未发货，因此当购物车仅包含可下载产品时，结帐的</span><em>发货</em><span>步骤将被跳过。</span></p>
</li>
</ul>
<h2 id="configure-the-download-options"><span>配置下载选项</span></h2>
<p><span>可下载配置设置确定可下载产品的默认值和交付选项，并指定访客是否可以购买下载。</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>可</span><em>下载产品选项</em><span>部分。</span></p>
<p><img alt="可下载的产品选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-downloadable-product-options.png?lang=en" /></p>
<p><span><span>有关这些配置选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的可</span></span><em>下载产品选项</em><span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>要在下载可用时确定订单流程的状态，请将</span><span>订单项目状态设置为启用下载</span><span>为以下之一：</span></p>
<ul>
<li><code>Pending</code></li>
<li><code>Invoiced</code></li>
</ul>
</li>
<li>
<p><span>要为单个客户可以进行的下载次数设置默认限制，请为</span><span>默认最大下载</span><span>次数输入数字。</span></p>
</li>
<li>
<p><span>将</span><span>可共享</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Yes</code><span>- 允许客户通过电子邮件将下载链接发送给他人。</span></li>
<li><code>No</code><span>- 通过要求客户登录到他们的帐户才能访问下载链接来防止客户与他人共享下载链接。</span></li>
</ul>
</li>
<li>
<p><span>对于</span><span>Default Sample Title</span><span>，输入您希望显示在样本选择上方的标题。</span></p>
<p><img alt="样本标题" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-downloadable-config-sample-title.png?lang=en" /></p>
</li>
<li>
<p><span>对于</span><span>Default Link Title</span><span>，输入要用于下载链接的默认文本。</span></p>
</li>
<li>
<p><span>如果您希望下载链接在新的浏览器窗口中打开，请将</span><span>&ldquo;在新窗口中打开链接&rdquo;</span><span>设置为</span><code>Yes</code><span>。</span></p>
<p><span>此设置用于使您商店的浏览器窗口保持打开状态。</span></p>
</li>
<li>
<p><span>要确定可下载内容的交付方式，请将</span><span>使用内容处置</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Attachment</code><span>- 通过电子邮件作为附件提供下载链接。</span></li>
<li><code>Inline</code><span>- 将下载链接作为网页上的链接提供。</span></li>
</ul>
</li>
<li>
<p><span>如果您想要要求购买者在购买下载之前注册客户帐户并登录，请将</span><span>如果购物车包含可下载项目则禁用访客结账</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h2 id="create-a-downloadable-product"><span>创建可下载的产品</span></h2>
<p><span>以下说明演示了使用</span>产品模板<span><span>、必填字段和基本设置创建可下载产品的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>可下载的文件名可以包含字母和数字。</span><span>破折号或下划线字符可用于表示单词之间的空格。</span><span>文件名中的任何无效字符都将替换为下划线。</span></span></p>
</div>
</div>
<h3 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span><span>在</span><span>右上角的</span></span><em>添加产品</em><span><span>( ) 菜单上，选择</span><span>。</span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span></span><code>Downloadable Product</code><span></span></p>
<p><img alt="添加可下载产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-downloadable.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h3>
<p><span><span>样本数据包括一个</span><span>名为</span><em><span>Downloadable的</span></em></span>属性集<span><span>，它具有用于可下载产品的特殊字段。</span><span>您可以使用现有模板或在保存产品之前创建另一个模板。</span></span><em><span></span></em><span></span></p>
<p><span>要选择用作产品模板的属性集，请执行以下操作之一：</span></p>
<ul>
<li>
<p><span>对于</span><span>Search</span><span>，输入属性集的名称。</span></p>
</li>
<li>
<p><span>在列表中，选择</span><code>Downloadable</code><span>属性集。</span></p>
</li>
</ul>
<p><span>更新表格以反映更改。</span></p>
<p><img alt="选择属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set-downloadable.png?lang=en" /></p>
<h3 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h3>
<ol>
<li>
<p><span>输入</span><span>产品名称</span><span>。</span></p>
</li>
<li>
<p><span><span>接受基于产品名称</span><span>的默认</span></span><span>SKU或输入其他名称。</span><span></span></p>
</li>
<li>
<p><span>输入产品</span><span>价格</span><span>。</span></p>
</li>
<li>
<p><span>由于产品尚未准备好发布，因此将</span><span>Enable Product</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
<p><span>保存产品后，</span>商店视图<span>选择器会出现在左上角。</span></p>
</li>
<li>
<p><span><span>选择</span><span>产品可用的</span></span><span>商店视图。</span><span></span></p>
<p><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h3>
<ol>
<li>
<p><span>将</span><span>税级</span><span>设置为以下之一：</span></p>
<ul>
<li><code>None</code></li>
<li><code>Taxable Goods</code></li>
</ul>
</li>
<li>
<p><span>输入当前库存产品的</span><span>数量</span><span>。</span></p>
<p><span>请注意以下事项：</span></p>
<ul>
<li>
<p><span>默认情况下，</span><span>库存状态</span><span>设置为</span><code>Out of Stock</code><span>。</span></p>
</li>
<li>
<p><span><span>因为可下载的产品不发货，所以</span><span>不使用</span></span><span>重量字段。</span><span>如果您启用此功能，它会变成一个</span>简单的产品<span>，并且</span><em>这个产品是可下载的吗？</em><span>选项卡不能使用。</span></p>
</li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>如果启用</span>库存管理<span><span>，单一来源商户在此部分设置数量。</span><span>多来源商家在&ldquo;来源&rdquo;部分添加来源和数量。</span><span>请参阅以下</span></span><em>分配来源和数量（库存管理）</em><span>部分。</span></p>
</div>
</div>
</li>
<li>
<p><span>接受默认的</span><span>可见性</span><span>设置</span><code>Catalog, Search</code><span>。</span></p>
</li>
<li>
<p><span>要在</span>新产品列表中展示<span>该产品，请选中</span><span>将产品设置为新</span><span>复选框。</span></p>
</li>
<li>
<p><span>要为产品分配</span><em>类别</em><span>，请单击&ldquo;</span><span>选择...</span><span>&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p><span>选择现有类别</span><span>：</span></p>
<ul>
<li>
<p><span>开始在框中键入以查找匹配项。</span></p>
</li>
<li>
<p><span>选中要分配的每个类别的复选框。</span></p>
</li>
</ul>
<p><span>创建类别</span><span>：</span></p>
<ul>
<li>
<p><span>单击</span><span>新建类别</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>并选择</span><span>父类别</span><span>以确定其在</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/categories/category-root.html?lang=en">菜单结构</a><span>中的位置。</span></p>
</li>
<li>
<p><span>单击</span><span>创建类别</span><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>将</span><span>格式</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Download</code></li>
<li><code>DVD</code></li>
</ul>
<p><span>如有必要，您可以编辑</span>属性<span>以添加更多值。</span></p>
<p><img alt="产品详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-details-downloadable.png?lang=en" /></p>
<p><span><span>可能还有其他描述产品的属性。</span><span>选择因属性集而异，您可以稍后完成它们。</span></span></p>
</li>
</ol>
<h4 id="assign-sources-and-quantities-(inventory-management)"><span>分配来源和数量（库存管理）</span></h4>
<p><span></span>对于使用库存管理<span><span>的多来源商家</span><span>，向下滚动到</span></span><span>来源</span><span>部分并分配来源和数量：</span></p>
<ol>
<li>
<p><span>要添加源，请单击</span><span>分配源</span><span>。</span></p>
</li>
<li>
<p><span>浏览或搜索来源并选中要为产品添加的来源旁边的复选框。</span></p>
<p><img alt="为产品分配来源" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-assign-sources_c1.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>完成</span><span>以添加源。</span></p>
</li>
<li>
<p><span>要管理源的数量和状态，请单击&ldquo;</span><span>高级库存</span><span>&rdquo;并将&ldquo;</span><span>管理库存</span><span>&rdquo;设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>将</span><span>源项状态</span><span>设置为</span><code>In Stock</code><span>。</span></p>
</li>
<li>
<p><span>输入数量更新现有库存的</span><span>数量</span><span>。</span></p>
</li>
<li>
<p><span>要设置库存数量通知，请执行以下操作之一：</span></p>
<ul>
<li>
<p><em>自定义通知数量</em><span>- 清除</span><span>通知数量使用默认复选框并在</span><span></span><span>通知数量</span><span><span>中输入一个数量</span><span>。</span></span></p>
</li>
<li>
<p><em>默认通知数量</em><span>- 选择</span><span>通知数量使用默认</span><span><span>复选框。</span><span>Commerce 检查并使用 Advanced Inventory 或全局商店配置中的设置。</span></span></p>
</li>
</ul>
<p><img alt="更新每个来源的产品数量" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-quantity_c1.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-5%3A-complete-the-downloadable-information"><span>第 5 步：完成可下载信息</span></h3>
<p><span>向下滚动，展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>Downloadable&nbsp;</span><em>Information</em><span>部分，然后选择</span><span>Is this downloadable product?&nbsp;</span><span>复选框。</span></p>
<p><span>启用后，可</span><em>下载信息</em><span><span>部分分为两部分。</span><span>第一部分描述了每个下载链接，第二部分描述了每个示例文件。</span><span>许多这些选项的默认值可以在</span></span>配置<span>中设置。</span></p>
<p><img alt="可下载信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-downloadable-information.png?lang=en" /></p>
<h4 id="complete-the-links"><span>完成链接</span></h4>
<ol>
<li>
<p><span>在&ldquo;</span><em>链接</em><span><span>&rdquo;部分，输入</span><span>要用作下载链接标题的标题</span></span><span>。</span><span></span></p>
</li>
<li>
<p><span>如果适用，请选中</span><span>链接可单独购买</span><span>复选框。</span></p>
</li>
<li>
<p><span>单击</span><span>添加链接</span><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>输入下载的</span><span>标题</span><span>和</span><span>价格</span><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>文件</span><span>和</span><span>示例</span><span>文件，选择以下下载分发方法之一：</span></p>
<ul>
<li><code>Upload File</code><span><span>- 选择此方式将分发文件上传到服务器。</span><span>浏览到文件并选择它进行上传。</span></span></li>
<li><code>URL</code><span><span>- 选择此方法从 URL 访问分发文件。</span><span>输入下载文件的完整 URL。</span></span></li>
</ul>
</li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>您不能将指向外部资源的链接用作可下载产品。</span><span>有效链接域在</span></span><code>env.php</code><span>文件中以编程方式预定义</span><span>。</span></p>
</div>
</div>
<ul>
<li>
<p><span>将</span><span>可共享</span><span>设置为以下之一：</span></p>
<ul>
<li>
<p><code>No</code><span>- 要求客户登录他们的帐户才能访问下载链接。</span></p>
</li>
<li>
<p><code>Yes</code><span>- 通过电子邮件发送链接，客户可以与他人分享。</span></p>
</li>
<li>
<p><code>Use Config</code><span></span>- 使用可下载产品选项<span><span>配置</span><span>中指定的方法。</span></span></p>
</li>
</ul>
</li>
<li>
<p><span>执行以下操作之一：</span></p>
<ul>
<li><span>要限制每个客户的下载，请为最大输入最大数量</span><span><span><span>。</span><span>下载</span></span></span><span>。</span></li>
<li><span>要允许无限制下载，请选中</span><span>无限制</span><span>复选框。</span></li>
</ul>
</li>
</ul>
<p><img alt="链接详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-downloadable-link-detail.png?lang=en" /></p>
</li>
<li>
<p><span>要添加另一个链接，请单击</span><span>添加链接</span><span>并重复这些步骤。</span></p>
</li>
</ol>
<h4 id="complete-the-samples"><span>完成样本</span></h4>
<ol>
<li>
<p><span>在</span><em>示例</em><span><span>部分中，输入</span><span>要用作示例标题的标题</span></span><span>。</span><span></span></p>
</li>
<li>
<p><span>要完成每个样本的信息，请点击</span><span>添加链接</span><span>。</span></p>
<p><img alt="样品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-downloadable-samples.png?lang=en" /></p>
</li>
<li>
<p><span>完成链接详细信息如下：</span></p>
<ul>
<li>
<p><span>输入单个样本的</span><span>标题</span><span>。</span></p>
</li>
<li>
<p><span>选择以下分发方式之一：</span></p>
<ul>
<li><code>Upload File</code><span><span>- 选择此方式将分发文件上传到服务器。</span><span>浏览到文件并选择它进行上传。</span></span></li>
<li><code>URL</code><span><span>- 选择此方法从 URL 访问分发文件。</span><span>输入下载文件的完整 URL。</span></span></li>
</ul>
</li>
<li>
<p><span>要添加另一个示例，请单击</span><span>添加链接</span><span>并重复这些步骤。</span></p>
</li>
<li>
<p><span>要更改示例的顺序，请抓住</span><em>更改顺序</em><span>(&nbsp;</span><img alt="位置控制器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-sort-order.png?lang=en" /><span>) 图标并将示例拖动到新位置。</span></p>
</li>
</ul>
</li>
</ol>
<h3 id="step-6%3A-complete-the-product-information"><span>第六步：填写产品信息</span></h3>
<p><span>向下滚动并根据需要完成以下部分中的信息：</span></p>
<ul>
<li>内容</li>
<li>图片和视频</li>
<li>搜索引擎优化</li>
<li>相关产品、追加销售和交叉销售</li>
<li>可定制的选项</li>
<li>网站中的产品</li>
<li>设计</li>
<li>礼品选项</li>
</ul>
<h3 id="step-7%3A-publish-the-product"><span>第 7 步：发布产品</span></h3>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>设置为</span><code>Yes</code><span>并执行以下操作之一：</span></p>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;</span><span>) 菜单上选择</span></span><span>客户视图。</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
<p><span>商店在新的浏览器选项卡中打开。</span></p>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/admin-customer-view.png?lang=en" /></p>
</li>
</ul>
<p><span>方法 2：</span><span>保存并关闭</span></p>
<p><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>) 菜单上，选择</span><span>保存并关闭</span><span>。</span></p>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
<h2 id="storefront-experience"><span>店面体验</span></h2>
<p><span>在客户帐户仪表板中，&ldquo;</span><em>我的可下载产品</em><span><span>&rdquo;页面链接到可下载产品的每个订单。</span><span>订单完成后，可以从客户的帐户下载。</span></span></p>
<p><img alt="我的可下载产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/customer-account-my-downloadable-products.png?lang=en" /></p>
<p><span>下表描述了</span><em>我的可下载产品</em><span>值：</span></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>柱子</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>命令＃</span></td>
<td><span>购买可下载产品的</span>订单<span><span>。</span><span>提供指向订单详细信息的链接。</span></span></td>
</tr>
<tr>
<td><span>日期</span></td>
<td><span>订单创建日期。</span></td>
</tr>
<tr>
<td><span>标题</span></td>
<td><span><span>随订单购买的可下载产品的名称。</span><span>提供指向可下载产品的链接。</span></span></td>
</tr>
<tr>
<td><span>状态</span></td>
<td><span>订单处理状态。</span></td>
</tr>
<tr>
<td><span>剩余下载量</span></td>
<td><span>已下载产品的可用下载次数。</span></td>
</tr>
</tbody>
</table>
</div>
<p><em><span>从帐户仪表板下载产品文件</span></em></p>
<ol>
<li>
<p><span>在他们的帐户仪表板中，客户选择</span><span>My Downloadable Products</span><span>。</span></p>
</li>
<li>
<p><span>在列表中找到订单并单击标题后面的链接。</span></p>
</li>
<li>
<p><span>在下载窗口的右下角，单击</span><em>下载</em><span>图标。</span></p>
</li>
<li>
<p><span>在其下载位置找到文件并将文件保存到所需位置。</span></p>
</li>
</ol>]]></description>
      <pubDate>Wed, 11 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2捆绑产品]]></title>
      <link>https://www.360magento.com/blog/Bundle-product/</link>
      <description><![CDATA[<p><span>捆绑包是</span><em>构建您自己的</em><span><span>、可定制的产品。</span><span>捆绑包中的每个项目都可以基于以下产品类型之一：</span></span></p>
<ul>
<li>简单产品</li>
<li>虚拟产品</li>
</ul>
<p><img alt="捆绑产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle.png?lang=en" /></p>
<p><span>当客户单击&ldquo;</span><span>自定义</span><span>&rdquo;或&ldquo;</span><span>添加到购物车</span><span><span>&rdquo;时，会出现这些选项。</span><span>由于捆绑包中包含的产品各不相同，因此可以将 SKU、价格和重量设置为动态值或固定值。</span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>最低广告价格 (MAP) 不适用于使用动态定价的捆绑产品。</span></p>
</div>
</div>
<p><span>如果</span>即时购买<span>可用，</span><em>即时购买</em><span><span>按钮会出现</span><span>在捆绑包中每个项目的</span></span><em>添加到购物车按钮下方。</em><span></span></p>
<p><img alt="自定义捆绑包" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-customize.png?lang=en" /></p>
<p><span>以下说明将引导您完成使用</span>产品模板<span><span>、必填字段和基本设置创建捆绑产品的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<h2 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span></span><em>在添加产品</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span><span>&nbsp;) 菜单</span><span>的右上角，选择</span></span><span>捆绑产品</span><span>。</span></p>
<p><img alt="添加捆绑产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-bundle.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h2>
<p><span><span>要选择</span><span>用作产品模板的</span></span>属性集，请执行以下操作之一：<span></span></p>
<ul>
<li><span>对于</span><span>Search</span><span>，输入属性集的名称，</span></li>
<li><span>在列表中，选择要使用的属性集。</span></li>
</ul>
<p><span>更新表格以反映更改。</span></p>
<p><img alt="选择模板" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set.png?lang=en" /></p>
<h2 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h2>
<ol>
<li>
<p><span>输入产品</span><span>Product Name</span><span>。</span></p>
</li>
<li>
<p><span><span>接受</span><span>基于产品名称的默认</span></span><span>SKU或输入不同的值。</span><span></span></p>
<p><span>要确定分配给每个捆绑商品的 SKU 类型，请执行以下操作：</span></p>
<ul>
<li>
<p><span>通过为默认 SKU 添加后缀，可以将</span><span>动态 SKU</span><span><span>自动分配给每个捆绑商品。</span><span>默认情况下，此项设置为</span></span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>如果您希望为每个捆绑商品分配唯一的 SKU，请将</span><span>动态 SKU</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
</ul>
<p><img alt="动态 SKU 和价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-dynamic-sku-price.png?lang=en" /></p>
</li>
<li>
<p><span>要确定捆绑包的价格，请执行以下操作之一：</span></p>
<ul>
<li>
<p><span>要让价格反映客户选择的选项，请将</span><span>动态价格</span><span>设置为</span><code>Yes</code><span>并将</span><span>价格</span><span>留空。</span></p>
</li>
<li>
<p><span>要为捆绑包收取固定价格，请将</span><span>动态价格</span><span>设置为</span><code>No</code><span><span>并输入</span><span>您要为捆绑包收取的</span></span><span>价格。</span><span></span></p>
</li>
</ul>
</li>
<li>
<p><span>由于产品尚未准备好发布，因此将</span><span>Enable Product</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
<p><span>保存产品后，</span>商店视图<span>选择器会出现在左上角。</span></p>
</li>
<li>
<p><span><span>选择</span><span>产品可用的</span></span><span>商店视图。</span><span></span></p>
<p><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h2>
<ol>
<li>
<p><span>如果捆绑包具有固定定价，请将</span><span>Tax Class</span><span>设置为以下之一：</span></p>
<ul>
<li><code>None</code></li>
<li><code>Taxable Goods</code></li>
</ul>
<p><span>如果捆绑包具有动态定价，则为</span><span><em>每个</em></span><span><span>捆绑包项目确定税费。</span><span>如果捆绑包具有固定定价，则为</span></span><span><em>整个</em></span><span>捆绑包产品确定税费。</span></p>
</li>
<li>
<p><span>请注意以下事项：</span></p>
<ul>
<li>
<p><span></span><span>数量</span><span><span>不可用，因为该值是为每个捆绑项确定的</span><span>。</span></span></p>
</li>
<li>
<p><span>默认情况下，</span><span>库存状态</span><span>设置为</span><code>In Stock</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>要确定包裹的重量，请执行以下操作之一：</span></p>
<ul>
<li>
<p><span>要使重量反映客户选择的选项，请设置</span><span>动态重量</span><span>集</span><code>Yes</code><span>并将</span><span>重量</span><span>留空。</span></p>
</li>
<li>
<p><span>要为束分配固定权重，请将</span><span>动态权重</span><span>设置为</span><code>No</code><span>并输入束的权</span><span>重</span><span>。</span></p>
</li>
</ul>
<p><img alt="动态重量" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-dynamic-weight.png?lang=en" /></p>
</li>
<li>
<p><span></span>要在新产品<span><span>列表中展示该产品</span><span>，请选中</span></span><span>将产品设置为新</span><span>复选框。</span></p>
</li>
<li>
<p><span>接受默认的</span><span>可见性</span><span>设置</span><code>Catalog, Search</code><span>。</span></p>
</li>
<li>
<p><span>要为产品分配</span><em>类别</em><span>，请单击&ldquo;</span><span>选择...</span><span>&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p><span>选择现有类别：</span></p>
<ul>
<li>
<p><span>开始在框中键入以查找匹配项。</span></p>
</li>
<li>
<p><span>选中要分配的每个类别的复选框。</span></p>
</li>
</ul>
<p><span>创建类别：</span></p>
<ul>
<li>
<p><span>单击</span><span>新建类别</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>并选择</span><span>父类别</span><span>以确定其在菜单结构中的位置。</span></p>
</li>
<li>
<p><span>单击</span><span>创建类别</span><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>选择</span><span>制造国</span><span>。</span></p>
<p><img alt="捆绑包详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-details.png?lang=en" /></p>
<p><span><span>可能还有其他描述产品的属性。</span><span>选择不同的属性集，您可以稍后完成它们。</span></span></p>
</li>
</ol>
<h2 id="step-5%3A-add-the-bundle-items"><span>第 5 步：添加捆绑商品</span></h2>
<p><span></span><em>Bundle Items</em><span><span>部分用于将项目添加到 Bundle 产品类型并编辑当前的项目选择</span><span>。</span></span></p>
<p><img alt="为产品定义的捆绑商品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-items-ball.png?lang=en" /></p>
<ol>
<li>
<p><span>向下滚动到</span><em>Bundle Items</em><span>部分并将</span><span>Ship Bundle Items</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Separately</code></li>
<li><code>Together</code></li>
</ul>
<p><img alt="捆绑物品部分" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-items.png?lang=en" /></p>
<p><span>如果您选择</span><code>Together</code><span>，则必须为所有捆绑项目分配相同的</span>来源<span>。</span></p>
</li>
<li>
<p><span>单击</span><span>添加选项</span><span>并执行以下操作：</span></p>
<p><img alt="添加捆绑选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-new-option.png?lang=en" /></p>
<ul>
<li>
<p><span><span>输入</span><span>要用作字段标签的</span></span><span>选项标题。</span><span></span></p>
</li>
<li>
<p><span>将</span><span>输入类型</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Drop-down</code></li>
<li><code>Radio buttons</code></li>
<li><code>Checkbox</code></li>
<li><code>Multiple Select</code></li>
</ul>
</li>
<li>
<p><span>要使该字段成为必填项，请选中</span><span>必填</span><span>复选框。</span></p>
</li>
<li>
<p><span>单击</span><span>将产品添加到选项</span><span>，然后选中要包含在此选项中的每个产品的复选框。</span></p>
<p><span>如果有很多产品，请使用列表过滤器和分页控件来查找您需要的产品。</span></p>
</li>
<li>
<p><span>单击</span><span>添加所选产品</span><span>。</span></p>
<p><img alt="添加所选产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-add-products-to-option.png?lang=en" /></p>
</li>
<li>
<p><span>项目出现在&ldquo;</span><em>选项</em><span>&rdquo;部分后，选择一个项目作为</span><span>默认</span><span>选择。</span></p>
</li>
<li>
<p><span>在</span><em>默认数量</em><span>列中，输入当客户选择项目时要添加到捆绑包中的每个项目的数量。</span></p>
</li>
<li>
<p><span>要允许客户更改捆绑商品的数量，请选择</span><span>用户定义</span><span>。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>数量可以是预设值或用户定义的值。</span><span>但是，不要将</span></span><em>用户定义</em><span>属性分配给复选框或多选输入类型。</span></p>
</div>
</div>
<p><span><span>默认情况下，客户无法更改捆绑商品中包含的默认数量。</span><span>但是，客户可以输入要包含在捆绑包中的项目数量。</span></span></p>
<p><span>例如，如果 Sprite 状态球的默认数量设置为</span><code>2</code><span>并且该捆绑选项的客户订单</span><code>4</code><span>，则购买的球总数为</span><code>8</code><span>。</span></p>
<p><img alt="物品详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-item-detail.png?lang=en" /></p>
</li>
</ul>
</li>
<li>
<p><span>对要添加到捆绑包中的每个项目重复这些步骤。</span></p>
</li>
<li>
<p><span>要更改捆绑包部分中项目的顺序，请单击行开头的</span><em>移动</em><span>(&nbsp;</span><img alt="移动图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-move.png?lang=en" /><span>) 图标并将项目拖动到位。</span></p>
<p><img alt="更改捆绑项目的顺序" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-items-move.png?lang=en" /></p>
<p><span><span>也可以在导出的捆绑产品的数据中更改项目的顺序，然后重新导入到目录中。</span><span>有关详细信息，请参阅</span></span>导入捆绑产品<span>。</span></p>
</li>
<li>
<p><span>要更改捆绑产品中各部分的顺序，请单击该部分标题中的</span><em>移动</em><span>(&nbsp;</span><img alt="移动图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-move.png?lang=en" /><span>) 图标并将该部分拖动到新位置。</span></p>
<p><span>要更好地查看工作区，请先折叠每个部分，然后将它们拖动到位。</span></p>
<p><img alt="更改捆绑部分的顺序" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-section-move.png?lang=en" /></p>
</li>
<li>
<p><span>要从捆绑包中删除任何项目，请单击</span><span>删除</span><span>(&nbsp;&nbsp;</span><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan.png?lang=en" /><span>&nbsp;) 图标。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="step-6%3A-complete-the-product-information"><span>第六步：填写产品信息</span></h2>
<p><span>向下滚动并根据需要完成以下部分中的信息：</span></p>
<ul>
<li>内容</li>
<li>图片和视频</li>
<li>搜索引擎优化</li>
<li>相关产品、追加销售和交叉销售</li>
<li>可定制的选项</li>
<li>网站中的产品</li>
<li>设计</li>
<li>礼品选项</li>
</ul>
<h2 id="step-7%3A-publish-the-product"><span>第 7 步：发布产品</span></h2>
<ol>
<li>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>设置为</span><code>Yes</code><span>(&nbsp;&nbsp;</span><img alt="切换是" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-yes.png?lang=en" /><span>&nbsp;)。</span></p>
</li>
<li>
<p><span>执行以下操作之一：</span></p>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;&nbsp;</span><span>&nbsp;) 菜单上选择</span></span><span>客户视图。</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
<p><span>商店在新的浏览器选项卡中打开。</span></p>
</li>
</ul>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-customer-view.png?lang=en" /></p>
<p><span>方法二：</span><span>保存关闭</span></p>
<p><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>&nbsp;) 菜单上，选择</span><span>保存并关闭</span><span>。</span></p>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
</li>
</ol>
<h2 id="input-controls"><span>输入控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th><th><span>例子</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>落下</span></td>
<td><span><span>显示带有产品名称和价格的选项下拉列表。</span><span>只能选择一项。</span></span></td>
<td><img alt="落下" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-input-type-drop-down.png?lang=en" /></td>
</tr>
<tr>
<td><span>单选按钮</span></td>
<td><span><span>为每个选项显示一个单选按钮，后跟产品名称和价格。</span><span>只能选择一项。</span></span></td>
<td><img alt="单选按钮" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-input-type-radio-buttons.png?lang=en" /></td>
</tr>
<tr>
<td><span>复选框</span></td>
<td><span><span>为每个选项显示一个复选框，后跟产品名称和价格。</span><span>可以选择多个项目。</span></span></td>
<td><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-input-type-checkbox.png?lang=en" /></td>
</tr>
<tr>
<td><span>多选</span></td>
<td><span><span>显示带有产品名称和价格的选项列表。</span><span>要选择多个项目，请按住 Ctrl 键 (PC) 或 Command 键 (Mac) 并单击每个项目。</span></span></td>
<td><img alt="多选" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-bundle-input-type-multiple-select.png?lang=en" /></td>
</tr>
</tbody>
</table>
</div>
<h2 id="field-descriptions"><span>字段说明</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>存货单位</span></td>
<td><span><span>确定是否为每件商品分配了可变或动态 SKU，或者捆绑包是否使用固定 SKU。</span><span>选项：</span></span><code>Fixed</code><span>/</span><code>Dynamic</code></td>
</tr>
<tr>
<td><span>重量</span></td>
<td><span><span>指定重量是根据所选项目计算的，还是整个捆绑包的固定重量。</span><span>选项：</span></span><code>Fixed</code><span>/</span><code>Dynamic</code></td>
</tr>
<tr>
<td><span>价格查看</span></td>
<td><span><span>确定产品价格是否显示为范围，从最便宜到最贵（价格范围）或显示最便宜的价格（低至）。</span><span>选项：</span></span><code>Price Range</code><span>/</span><code>As Low As</code></td>
</tr>
<tr>
<td><span>运送捆绑物品</span></td>
<td><span>指定单个项目是否可以单独运送。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="bundle-product-stock-status"><span>捆绑产品库存状态</span></h2>
<p><span><span>当出现以下任一情况时，</span><span>捆绑产品库存状态将</span></span><span><em>自动更改为缺货：</em></span><span></span></p>
<ul>
<li>
<p><span>所有选项都是可选的，所有相关产品都</span><em>缺货</em><span>。</span></p>
</li>
<li>
<p><span>某些选项是必需的，与任何必需选项相关联的产品都</span><em>缺货</em><span>。</span></p>
</li>
</ul>
<p><span><span>发生以下任一情况时，</span><span>捆绑产品库存状态</span></span><span><em>不会自动更改为缺货：</em></span><span></span></p>
<ul>
<li>
<p><span>所有选项都是可选的，并且至少有一种关联产品有</span><em>库存</em><span>。</span></p>
</li>
<li>
<p><span>一些选项是必需的，并且每个必需选项中至少有一个关联产品是</span><em>In Stock</em><span>。</span></p>
</li>
</ul>
<h2 id="things-to-remember"><span>要记住的事情</span></h2>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span>客户可以</span><em>构建自己的</em><span>捆绑产品。</span></p>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span>捆绑商品可以是没有自定义选项的简单或虚拟产品。</span></p>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span>价格视图可以设置为</span><code>Price Range</code><span>或</span><code>As Low As</code><span>。</span></p>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span>SKU 和重量可以是</span><code>Fixed</code><span>或</span><code>Dynamic</code><span>。</span></p>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span><span>数量可以是预设值或用户定义的值。</span><span>但是，不要将</span></span><em>用户定义</em><span>属性分配给复选框或多选输入类型。</span></p>
<p><img alt="复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox.png?lang=en" /><span>捆绑商品可以一起或分开运送。</span></p>]]></description>
      <pubDate>Tue, 10 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2虚拟产品]]></title>
      <link>https://www.360magento.com/blog/Virtual-product/</link>
      <description><![CDATA[<p><span style="color: #000000;">虚拟产品或数字商品代表无形项目，例如会员资格、服务、保证或书籍、音乐、视频或其他产品的订阅和数字下载。虚拟产品可以单独销售，也可以作为Grouped Product、Configurable Product或Bundle Product产品类型的一部分包含在内。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="box-sizing: inherit; vertical-align: inherit;">除了缺少</span><span style="color: #000000;"><em style="box-sizing: inherit;">Weight</em></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">字段外，创建虚拟产品和简单产品的过程是相同的。</span><span style="box-sizing: inherit; vertical-align: inherit;">以下说明演示了使用</span></span><span style="color: #000000;"><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/create/attribute-sets.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">产品模板</span></a></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">、必填字段和基本设置创建虚拟产品的过程。</span><span style="box-sizing: inherit; vertical-align: inherit;">当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<div class="extension note" style="box-sizing: inherit; -webkit-locale: auto; box-shadow: rgba(10, 10, 10, 0.1) 0px 0.5em 1em -0.125em, rgba(10, 10, 10, 0.02) 0px 0px 0px 1px; color: #000000; padding: 1rem; margin-bottom: 1.5rem; border-width: 1px 1px 1px 3rem; border-style: solid; border-color: var(--spectrum-semantic-informative-background-color); border-image: initial; font-family: adobe-clean, sans-serif; font-size: 16px; border-radius: 0px !important;">
<div style="box-sizing: inherit; -webkit-locale: auto; display: flex !important; align-items: center; font-weight: bold;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">笔记</span></span></div>
<div style="box-sizing: inherit; -webkit-locale: auto;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">PayPal 已弃用对通过 PayPal Express Checkout 销售数字商品的支持。</span><span style="box-sizing: inherit; vertical-align: inherit;">他们建议您使用</span></span><span style="color: #000000;"><a href="https://experienceleague.adobe.com/docs/commerce-admin/stores-sales/payments/paypal/paypal-payments-standard.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">PayPal 支付标准</span></a></span><span style="box-sizing: inherit; vertical-align: inherit;">或任何其他 PayPal 支付网关来处理任何包含虚拟产品的订单。</span></p>
</div>
</div>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;"><img alt="虚拟产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-virtual-membership.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
<h2 id="step-1%3A-choose-the-product-type" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第一步：选择产品类型</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">在</span><span style="color: #000000;"><em style="box-sizing: inherit;">管理</em></span><span style="box-sizing: inherit; vertical-align: inherit;">侧栏上，转到</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">目录</span><span style="box-sizing: inherit; vertical-align: inherit;">&gt;</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">产品</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">在</span><span style="box-sizing: inherit; vertical-align: inherit;">右上角的</span></span><span style="color: #000000;"><em style="box-sizing: inherit;">添加产品</em></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">( ) 菜单中，选择</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;"><span style="box-sizing: inherit; vertical-align: inherit;">虚拟产品</span></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></span><span style="color: #000000;"><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span><span style="box-sizing: inherit; vertical-align: inherit;"></span><span style="box-sizing: inherit; color: #000000; font-weight: bold;"><span style="box-sizing: inherit; vertical-align: inherit;"></span></span><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;"><img alt="添加虚拟产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-virtual.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
</li>
</ol>
<h2 id="step-2%3A-choose-the-attribute-set" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第 2 步：选择属性集</span></h2>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">要选择</span><span style="box-sizing: inherit; vertical-align: inherit;">用作产品模板的</span></span><span style="color: #000000;"><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/create/attribute-sets.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">属性集，请执行以下操作之一：</span></a></span><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
<ul style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; list-style-position: initial; list-style-image: initial; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">单击&ldquo;</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">属性集</span><span style="box-sizing: inherit; vertical-align: inherit;">&rdquo;字段并输入属性集的全部或部分名称。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">在显示的列表中，选择要使用的属性集。</span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="box-sizing: inherit; vertical-align: inherit;">更新表格以反映更改。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;"><img alt="选择属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
<h2 id="step-3%3A-complete-the-required-settings" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第 3 步：完成所需的设置</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">输入</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">产品名称</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">接受基于产品名称</span><span style="box-sizing: inherit; vertical-align: inherit;">的默认</span></span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">SKU或输入其他名称。</span><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">输入产品</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">价格</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">由于产品尚未准备好发布，因此将</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">Enable Product</span><span style="box-sizing: inherit; vertical-align: inherit;">设置为</span><span style="color: #000000;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">No</code></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">单击</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">保存</span><span style="box-sizing: inherit; vertical-align: inherit;">并继续。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">保存产品后，</span><span style="color: #000000;"><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/introduction.html?lang=en#product-scope" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">商店视图</span></a></span><span style="box-sizing: inherit; vertical-align: inherit;">选择器会出现在左上角。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">选择</span><span style="box-sizing: inherit; vertical-align: inherit;">产品可用的</span></span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">商店视图。</span><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;"><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-basic-settings" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第四步：完成基本设置</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">将</span><span style="box-sizing: inherit; font-weight: bold;">税级</span><span style="box-sizing: inherit; vertical-align: inherit;">设置为以下之一：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">None</code></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Taxable Goods</code></li>
</ul>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">输入当前库存产品的</span><span style="box-sizing: inherit; font-weight: bold;">数量</span><span style="box-sizing: inherit; vertical-align: inherit;">并执行以下操作：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">接受默认的</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">Stock Status</span><span style="box-sizing: inherit; vertical-align: inherit;">设置</span><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">In Stock</code><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">由于虚拟产品未发货，因此</span><span style="box-sizing: inherit; vertical-align: inherit;">未使用</span></span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">重量字段。</span><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">接受默认的</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">可见性</span><span style="box-sizing: inherit; vertical-align: inherit;">设置</span><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Catalog, Search</code><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
</ul>
<div class="extension note" style="box-sizing: inherit; -webkit-locale: auto; box-shadow: rgba(10, 10, 10, 0.1) 0px 0.5em 1em -0.125em, rgba(10, 10, 10, 0.02) 0px 0px 0px 1px; color: #000000; padding: 1rem; border-width: 1px 1px 1px 3rem; border-style: solid; border-color: var(--spectrum-semantic-informative-background-color); border-image: initial; border-radius: 0px !important; margin-bottom: 2rem !important;">
<div style="box-sizing: inherit; -webkit-locale: auto; display: flex !important; align-items: center; font-weight: bold;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">笔记</span></span></div>
<div style="box-sizing: inherit; -webkit-locale: auto;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">如果启用</span><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">库存管理</span></span></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">，单一来源商户在此部分设置数量。</span><span style="box-sizing: inherit; vertical-align: inherit;">多来源商家在&ldquo;来源&rdquo;部分添加来源和数量。</span><span style="box-sizing: inherit; vertical-align: inherit;">请参阅以下</span></span><em style="box-sizing: inherit;">分配来源和数量（库存管理）</em><span style="box-sizing: inherit; vertical-align: inherit;">部分。</span></p>
</div>
</div>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">要为产品分配</span><span style="box-sizing: inherit; font-weight: bold;">类别</span><span style="box-sizing: inherit; vertical-align: inherit;">，请单击&ldquo;</span><span style="box-sizing: inherit; font-weight: bold;">选择...</span><span style="box-sizing: inherit; vertical-align: inherit;">&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; font-weight: bold;">选择现有类别</span><span style="box-sizing: inherit; vertical-align: inherit;">：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">开始在框中键入以查找匹配项。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">选中要分配的类别的复选框。</span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; color: #363636; font-weight: bold;">创建类别</span><span style="box-sizing: inherit; vertical-align: inherit;">：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">单击</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">新建类别</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">输入</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">类别名称</span><span style="box-sizing: inherit; vertical-align: inherit;">并选择</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">父类别</span><span style="box-sizing: inherit; vertical-align: inherit;">以确定其在菜单结构中的位置。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">单击</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">创建类别</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">可能还有其他描述产品的单独属性。</span><span style="box-sizing: inherit; vertical-align: inherit;">选择因属性集而异，您可以稍后完成它们。</span></span></p>
</li>
</ol>
<h3 id="assign-sources-and-quantities-(inventory-management)" style="box-sizing: inherit; margin: 0px; padding: 0px; font-size: 1.25rem; font-weight: 400; color: #4a4a4a; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">分配来源和数量（库存管理）</span></h3>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="box-sizing: inherit; vertical-align: inherit;"></span><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">对于使用库存管理</span></span></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">的多来源商家</span><span style="box-sizing: inherit; vertical-align: inherit;">，向下滚动到</span></span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">来源</span><span style="box-sizing: inherit; vertical-align: inherit;">部分并分配来源和数量：</span></p>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">要添加源，请单击</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">分配源</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">浏览或搜索来源并选中要为产品添加的来源旁边的复选框。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;"><img alt="为产品分配来源" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-assign-sources_c1.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">单击</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">完成</span><span style="box-sizing: inherit; vertical-align: inherit;">以添加源。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">要管理源的数量和状态，请单击&ldquo;</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">高级库存</span><span style="box-sizing: inherit; vertical-align: inherit;">&rdquo;并将&ldquo;</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">管理库存</span><span style="box-sizing: inherit; vertical-align: inherit;">&rdquo;设置为</span><span style="color: #000000;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Yes</code></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">将</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">源项状态</span><span style="box-sizing: inherit; vertical-align: inherit;">设置为</span><span style="color: #000000;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">In Stock</code></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">输入数量更新现有库存的</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">数量</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">要设置库存数量通知，请执行以下操作之一：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><em style="box-sizing: inherit;">自定义通知数量</em><span style="box-sizing: inherit; vertical-align: inherit;">- 清除</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">通知数量使用默认复选框并在</span><span style="box-sizing: inherit; vertical-align: inherit;"></span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">通知数量</span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">中输入一个数量</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><em style="box-sizing: inherit;">默认通知数量</em><span style="box-sizing: inherit; vertical-align: inherit;">- 选择</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">通知数量使用默认</span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">复选框。</span><span style="box-sizing: inherit; vertical-align: inherit;">Commerce 检查并使用 Advanced Inventory 或全局商店配置中的设置。</span></span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><img alt="更新每个来源的产品数量" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-quantity_c1.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></p>
</li>
</ol>
<h2 id="step-5%3A-complete-the-product-information" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第五步：填写产品信息</span></h2>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="box-sizing: inherit; vertical-align: inherit;">根据需要填写以下部分中的信息：</span></p>
<ul style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; list-style-position: initial; list-style-image: initial; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">内容</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">图片和视频</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">搜索引擎优化</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">相关产品、追加销售和交叉销售</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">可定制的选项</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">网站中的产品</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">设计</span></span></span></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">礼品选项</span></span></span></li>
</ul>
<div class="extension note" style="box-sizing: inherit; -webkit-locale: auto; box-shadow: rgba(10, 10, 10, 0.1) 0px 0.5em 1em -0.125em, rgba(10, 10, 10, 0.02) 0px 0px 0px 1px; color: #000000; padding: 1rem; margin-bottom: 1.5rem; border-width: 1px 1px 1px 3rem; border-style: solid; border-color: var(--spectrum-semantic-informative-background-color); border-image: initial; font-family: adobe-clean, sans-serif; font-size: 16px; border-radius: 0px !important;">
<div style="box-sizing: inherit; -webkit-locale: auto; display: flex !important; align-items: center; font-weight: bold;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">笔记</span></span></div>
<div style="box-sizing: inherit; -webkit-locale: auto;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">这</span><span style="color: #000000;"><em style="box-sizing: inherit;">是可下载的产品吗？</em></span><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">默认情况下禁用该选项。</span><span style="box-sizing: inherit; vertical-align: inherit;">为虚拟产品启用此功能使产品可</span></span><span style="color: #378ef0;"><span style="box-sizing: inherit; cursor: pointer;"><span style="color: #000000;">下载</span></span></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</div>
</div>
<h2 id="step-6%3A-publish-the-product" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">第 6 步：发布产品</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">如果您准备好在目录中发布产品，请将</span><span style="box-sizing: inherit; color: #000000; font-weight: bold;">启用产品</span><span style="box-sizing: inherit; vertical-align: inherit;">设置为</span><span style="color: #000000;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Yes</code></span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">执行以下操作之一：</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; color: #363636; font-weight: bold;">方法一：</span><span style="box-sizing: inherit; vertical-align: inherit;">保存预览</span></p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">在右上角，单击&ldquo;</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">保存</span><span style="box-sizing: inherit; vertical-align: inherit;">&rdquo; 。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">要查看商店中的产品，请</span><span style="box-sizing: inherit; vertical-align: inherit;">在</span><em style="box-sizing: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;">管理</span></em><span style="box-sizing: inherit; vertical-align: inherit;">(&nbsp;</span><span style="box-sizing: inherit; vertical-align: inherit;">) 菜单上选择</span></span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">客户视图。</span><span style="box-sizing: inherit; vertical-align: inherit;"></span><em style="box-sizing: inherit;"><span style="box-sizing: inherit; vertical-align: inherit;"></span></em><span style="box-sizing: inherit; vertical-align: inherit;"></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /><span style="box-sizing: inherit; vertical-align: inherit;"></span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">商店在新的浏览器选项卡中打开。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-customer-view.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; color: #363636; font-weight: bold;">方法二：</span><span style="box-sizing: inherit; vertical-align: inherit;">保存关闭</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">在</span><em style="box-sizing: inherit;">保存</em><span style="box-sizing: inherit; vertical-align: inherit;">(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /><span style="box-sizing: inherit; vertical-align: inherit;">) 菜单上，选择</span><span style="box-sizing: inherit; color: #363636; font-weight: bold;">保存并关闭</span><span style="box-sizing: inherit; vertical-align: inherit;">。</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></p>
</li>
</ul>
</li>
</ol>
<h2 id="things-to-remember" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="box-sizing: inherit; vertical-align: inherit;">要记住的事情</span></h2>
<ul style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; list-style-position: initial; list-style-image: initial; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">虚拟产品用于无形产品，例如服务、订阅和保修。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">虚拟产品很像简单的产品，但没有重量。</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="box-sizing: inherit; vertical-align: inherit;">除非购物车中有有形产品，否则结账时不会出现送货选项。</span></p>
</li>
</ul>
<p></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;"><em style="box-sizing: inherit;">Weight</em>&nbsp;field, the process of creating a virtual product and a simple product is the same. The following instructions demonstrate the process of creating a virtual product using a&nbsp;<a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/create/attribute-sets.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">product template</span></a>, required fields, and basic settings. When you finish the basics, you can complete the other product settings as needed.</span></p>
<div class="extension note" style="box-sizing: inherit; -webkit-locale: auto; box-shadow: rgba(10, 10, 10, 0.1) 0px 0.5em 1em -0.125em, rgba(10, 10, 10, 0.02) 0px 0px 0px 1px; color: #000000; padding: 1rem; margin-bottom: 1.5rem; border-width: 1px 1px 1px 3rem; border-style: solid; border-color: var(--spectrum-semantic-informative-background-color); border-image: initial; font-family: adobe-clean, sans-serif; font-size: 16px; border-radius: 0px !important;">
<div style="box-sizing: inherit; -webkit-locale: auto; display: flex !important; align-items: center; font-weight: bold;"><span style="color: #000000;">NOTE</span></div>
<div style="box-sizing: inherit; -webkit-locale: auto;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">PayPal has deprecated support for the sale of digital goods through PayPal Express Checkout. They recommend that you use either&nbsp;<a href="https://experienceleague.adobe.com/docs/commerce-admin/stores-sales/payments/paypal/paypal-payments-standard.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">PayPal Payments Standard</span></a>&nbsp;or any other PayPal payment gateway to process any order that includes virtual products.</span></p>
</div>
</div>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;"><img alt="虚拟产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-virtual-membership.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
<h2 id="step-1%3A-choose-the-product-type" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="color: #000000;">Step 1: Choose the product type</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">On the&nbsp;<em style="box-sizing: inherit;">Admin</em>&nbsp;sidebar, go to&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Catalog</span>&nbsp;&gt;&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Products</span>.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">On the&nbsp;<em style="box-sizing: inherit;">Add Product</em>&nbsp;(&nbsp;<img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" />&nbsp;) menu at the upper-right corner, choose&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Virtual Product</span>.</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;"><img alt="添加虚拟产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-virtual.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
</li>
</ol>
<h2 id="step-2%3A-choose-the-attribute-set" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="color: #000000;">Step 2: Choose the attribute set</span></h2>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;">To choose the&nbsp;<a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/create/attribute-sets.html?lang=en" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">attribute set</span></a>&nbsp;that is used as a template for the product, do one of the following:</span></p>
<ul style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; list-style-position: initial; list-style-image: initial; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Click in the&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Attribute Set</span>&nbsp;field and enter all or part of the name of the attribute set.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">In the displayed list, choose the attribute set that you want to use.</span></p>
</li>
</ul>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;">The form is updated to reflect the change.</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-left: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important;"><span style="color: #000000;"><img alt="选择属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
<h2 id="step-3%3A-complete-the-required-settings" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="color: #000000;">Step 3: Complete the required settings</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Enter the&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Product Name</span>.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Accept the default&nbsp;<span style="box-sizing: inherit; font-weight: bold;">SKU</span>&nbsp;that is based on the product name or enter another.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Enter the product&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Price</span>.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Because the product is not yet ready to publish, set&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Enable Product</span>&nbsp;to&nbsp;<code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">No</code>.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">click&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Save</span>&nbsp;and continue.</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">When the product is saved, the&nbsp;<a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/introduction.html?lang=en#product-scope" style="box-sizing: inherit; color: #378ef0; cursor: pointer; text-decoration-line: none;"><span style="color: #000000;">Store View</span></a>&nbsp;chooser appears in the upper-left corner.</span></p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;">Choose the&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Store View</span>&nbsp;where the product is to be available.</span></p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;"><span style="color: #000000;"><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" style="box-sizing: inherit; height: auto; max-width: 100%;" /></span></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-basic-settings" style="box-sizing: inherit; margin: 0px 0px 1.5rem; padding: 0px; font-size: 1.5rem; word-break: break-word; color: #4a4a4a; line-height: 1.125; font-family: adobe-clean, sans-serif;"><span style="color: #000000;">Step 4: Complete the basic settings</span></h2>
<ol style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; padding: 0px; color: #4a4a4a; font-family: adobe-clean, sans-serif; font-size: 16px; margin-bottom: 1rem !important; margin-left: 2rem !important;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">Set&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Tax Class</span>&nbsp;to one of the following:</p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">None</code></li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;"><code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Taxable Goods</code></li>
</ul>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">Enter the&nbsp;<span style="box-sizing: inherit; font-weight: bold;">Quantity</span>&nbsp;of the product that is currently in stock and do the following:</p>
<ul style="box-sizing: inherit; margin-top: 1rem !important; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 2rem !important; padding: 0px; list-style: disc;">
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">Accept the default&nbsp;<span style="box-sizing: inherit; color: #363636; font-weight: bold;">Stock Status</span>&nbsp;setting of&nbsp;<code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">In Stock</code>.</p>
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">Because a virtual product is not shipped, the&nbsp;<span style="box-sizing: inherit; color: #363636; font-weight: bold;">Weight</span>&nbsp;field is not used.</p>
</li>
<li style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px; list-style: disc !important;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 1rem !important; margin-left: 0px; padding: 0px;">Accept the default&nbsp;<span style="box-sizing: inherit; color: #363636; font-weight: bold;">Visibility</span>&nbsp;setting of&nbsp;<code style="box-sizing: inherit; -webkit-font-smoothing: auto; background-color: unset; font-size: 0.875em; color: unset !important; padding: 0px !important;">Catalog, Search</code>.</p>
</li>
</ul>
<div class="extension note" style="box-sizing: inherit; -webkit-locale: auto; box-shadow: rgba(10, 10, 10, 0.1) 0px 0.5em 1em -0.125em, rgba(10, 10, 10, 0.02) 0px 0px 0px 1px; color: #000000; padding: 1rem; border-width: 1px 1px 1px 3rem; border-style: solid; border-color: var(--spectrum-semantic-informative-background-color); border-image: initial; border-radius: 0px !important; margin-bottom: 2rem !important;">
<div style="box-sizing: inherit; -webkit-locale: auto; display: flex !important; align-items: center; font-weight: bold;">NOTE</div>
<div style="box-sizing: inherit; -webkit-locale: auto;">
<p style="box-sizing: inherit; margin-top: 0px; margin-right: 0px; margin-bottom: 0px !important; margin-left: 0px; padding: 0px;">If you enable&nbsp;&lt;a href="https://experienceleague.adobe.com/docs/commerce-admin/inventory/introductio]]></description>
      <pubDate>Mon, 09 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2可配置产品]]></title>
      <link>https://www.360magento.com/blog/Configurable-product/</link>
      <description><![CDATA[<p><span><span>可配置的产品看起来像一个单一的产品，每个变体都有一个下拉列表。</span><span>每个列表项实际上是一个单独的简单产品，具有唯一的 SKU，这使得跟踪每个产品变体的库存成为可能。</span><span>您可以通过使用具有自定义选项的简单产品来实现类似的效果，但无法跟踪每个变体的库存。</span></span></p>
<p><span>以下说明演示了使用</span>产品模板<span><span>、必填字段和基本设置创建可配置产品的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<p><img alt="可配置产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable.png?lang=en" /></p>
<h2 id="part-1%3A-creating-a-configurable-product"><span>第 1 部分：创建可配置产品</span></h2>
<p><span><span>尽管可配置产品使用更多 SKU，并且最初可能需要更长的时间来设置，但它最终可以为您节省时间。</span><span>如果您计划发展业务，可配置的产品类型是具有多种选择的产品的不错选择。</span></span></p>
<p><span>在开始之前，准备一个</span>属性集<span><span>，其中包含一个属性，该属性设置为每个产品变体的允许输入类型之一。</span><span>例如，属性集可能包括颜色和大小的下拉属性。</span></span></p>
<p><span>用于可配置产品变体的每个属性的特性必须具有以下设置：</span></p>
<h3 id="product-variation-attribute-requirements"><span>产品变体属性要求</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>财产</span></th><th><span>环境</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>范围</span></td>
<td><code>Global</code></td>
</tr>
<tr>
<td><span>店主的目录输入类型</span></td>
<td><span>用于产品变体的任何属性的输入类型必须是以下之一：</span><code>Dropdown</code><span>、</span><code>Visual Swatch</code><span>或</span><code>Text Swatch</code><span>。</span></td>
</tr>
<tr>
<td><span>需要值</span></td>
<td><code>Yes</code></td>
</tr>
</tbody>
</table>
</div>
<h3 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到&nbsp;</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span><span>在</span><span>&nbsp;右上角的</span></span><em>添加产品</em><span><span>( ) 菜单中，选择</span><span><span>可配置产品</span></span><span>。</span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span></span><span><span></span></span><span></span></p>
<p><img alt="添加可配置产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-configurable.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h3>
<p><span></span>属性集<span><span>决定了产品中使用的字段选择</span><span>。</span><span>以下示例中使用的属性集具有颜色和大小属性。</span><span>属性集的名称显示在页面顶部，最初设置为</span></span><code>Default</code><span>。</span></p>
<ol>
<li>
<p><span>要为产品选择属性集，请单击页面顶部的字段并执行以下操作之一：</span></p>
<ul>
<li><span>对于</span><span>Search</span><span>，输入属性集的名称。</span></li>
<li><span>在列表中，选择要使用的属性集。</span></li>
</ul>
<p><span>更新表格以反映更改。</span></p>
</li>
<li>
<p><span>如果您需要将另一个属性添加到属性集中，请单击</span><span>添加属性</span><span>并按照添加属性中的说明进行</span>操作<span>。</span></p>
<p><img alt="选择模板" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h3>
<ol>
<li>
<p><span>输入产品</span><span>Product Name</span><span>。</span></p>
</li>
<li>
<p><span><span>接受基于产品名称</span><span>的默认</span></span><span>SKU或输入其他名称。</span><span></span></p>
</li>
<li>
<p><span>输入产品</span><span>价格</span><span>。</span></p>
</li>
<li>
<p><span>由于产品尚未准备好发布，因此将</span><span>Enable Product</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
<p><span>保存产品后，</span>商店视图<span>选择器会出现在左上角。</span></p>
</li>
<li>
<p><span><span>选择</span><span>产品可用的</span></span><span>商店视图。</span><span></span></p>
<p><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" /></p>
</li>
</ol>
<h3 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h3>
<ol>
<li>
<p><span>将</span><span>税级</span><span>设置为以下之一：</span></p>
<ul>
<li><code>None</code></li>
<li><code>Taxable Goods</code></li>
</ul>
</li>
<li>
<p><span></span><span>数量</span><span><span>由</span><span>产品变体决定，因此您可以将其留空。</span></span></p>
</li>
<li>
<p><span></span><span>将Stock Status</span><span><span>保留</span><span>为已设置。</span></span></p>
<p><span><span>可配置产品的库存状态由每个关联的配置决定。</span><span>因为产品是在没有输入数量的情况下保存的，所以</span></span><span>Stock Status</span><span>设置为</span><code>Out of Stock</code><span>。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>可配置产品的</span><span>库存状态</span><span>是一个</span><span><em>半手动</em></span><span><span>控制的设置。</span><span>它部分受其子产品的库存状态控制。</span><span>它是</span></span><span><em>多标准</em></span><span>库存状态计算的一部分，这在</span>配置库存状态<span>部分中有描述。</span></p>
</div>
</div>
</li>
<li>
<p><span>输入产品</span><span>重量</span><span>。</span></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>可配置产品必须始终具有权重。</span><span>如果您</span><span>从下拉列表中选择</span></span><span>此项目没有重量</span><span>，它会在保存产品后自动更改为此</span><span>项目有重量。</span><span></span></p>
</div>
</div>
<ol>
<li>
<p><span>接受默认的</span><span>可见性</span><span>设置</span><code>Catalog, Search</code><span>。</span></p>
</li>
<li>
<p><span></span>要在新产品<span><span>列表中展示该产品</span><span>，请选中</span></span><span>将产品设置为新</span><span>复选框。</span></p>
</li>
<li>
<p><span>要为产品分配类别，请单击&ldquo;</span><span>选择...</span><span>&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p><span>选择现有类别</span><span>：</span></p>
<ul>
<li>
<p><span>开始在框中键入以查找匹配项。</span></p>
</li>
<li>
<p><span>选中要分配的类别的复选框。</span></p>
</li>
</ul>
<p><span>创建类别</span><span>：</span></p>
<ul>
<li>
<p><span>单击</span><span>新建类别</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>并选择</span><span>父类别</span><span>以确定其在菜单结构中的位置。</span></p>
</li>
</ul>
<p><span>s- 单击</span><span>创建类别</span><span>。</span></p>
</li>
<li>
<p><span>选择</span><span>制造国</span><span>。</span></p>
<p><img alt="产品详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-details-configurable.png?lang=en" /></p>
<p><span><span>可能还有用于描述产品的其他属性。</span><span>选择因属性集而异，您可以稍后完成它们。</span></span></p>
</li>
</ol>
<h3 id="step-5%3A-save-and-continue"><span>第 5 步：保存并继续</span></h3>
<p><span><span>这是保存您的工作的好时机。</span><span>在右上角，点击</span></span><span>保存</span><span><span>。</span><span>在接下来的一系列步骤中，您将为产品的每个变体设置配置。</span></span></p>
<h2 id="part-2%3A-adding-configurations"><span>第 2 部分：添加配置</span></h2>
<p><span><span>以下示例显示如何为三种颜色和三种尺寸添加配置。</span><span>总共创建了九种具有独特 SKU 的简单产品，以涵盖各种可能的变体组合。</span><span>默认情况下，每个变体的产品名称和 SKU 基于属性值和父产品名称或 SKU。</span></span></p>
<p><span>页面顶部的进度条显示您在流程中的位置，并指导您完成每个步骤。</span></p>
<p><img alt="进度条" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-progress-bar-step1.png?lang=en" /></p>
<h3 id="step-1%3A-choose-the-attributes"><span>第 1 步：选择属性</span></h3>
<ol>
<li>
<p><span>从上面继续，向下滚动到</span><em>Configurations</em><span>部分并单击</span><span>Create Configurations</span><span>。</span></p>
<p><img alt="配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-create-configurations.png?lang=en" /></p>
</li>
<li>
<p><span>选中要作为配置包含的每个属性的复选框。</span></p>
<p><span>对于这个例子，我们选择</span><code>color</code><span>和</span><code>size</code><span>。</span></p>
</li>
<li>
<p><span>该列表包括可在可配置产品中使用的属性集中的所有属性。</span></p>
<p><img alt="选择属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-configurable-step1.png?lang=en" /></p>
</li>
<li>
<p><span>如果您需要添加属性，请单击</span><span>创建新属性</span><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>完成属性属性。</span></p>
</li>
<li>
<p><span>单击</span><span>保存属性</span><span>。</span></p>
</li>
<li>
<p><span>选中复选框以选择属性。</span></p>
</li>
</ul>
</li>
<li>
<p><span>在右上角，单击</span><span>&ldquo;下一步&rdquo;</span><span>。</span></p>
</li>
</ol>
<h3 id="step-2%3A-enter-the-attribute-values"><span>第 2 步：输入属性值</span></h3>
<ol>
<li>
<p><span>对于每个属性，选中适用于产品的值的复选框。</span></p>
<p><img alt="属性值" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-configurable-step2.png?lang=en" /></p>
</li>
<li>
<p><span>要重新排列属性，请抓住</span><em>更改顺序</em><span>(&nbsp;&nbsp;</span><img alt="排序顺序图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-sort-order.png?lang=en" /><span>) 图标并将该部分移动到新位置。</span></p>
<p><span>顺序决定了下拉列表在产品页面上的位置。</span></p>
</li>
<li>
<p><span>在进度条中，单击</span><span>&ldquo;下一步&rdquo;</span><span>。</span></p>
</li>
</ol>
<h3 id="step-3%3A-configure-the-images%2C-price%2C-and-quantity"><span>第 3 步：配置图片、价格和数量</span></h3>
<p><span><span>此步骤确定每个配置的图像、定价和数量。</span><span>每个选项的可用选项都相同，您只能选择一个。</span><span>您可以对所有 SKU 应用相同的设置，对每个 SKU 应用独特的设置，或者暂时跳过这些设置。</span></span></p>
<p><span>选择适用的配置选项。</span></p>
<p><span>使用以下方法之一配置</span><span>图像</span><span>：</span></p>
<p><span>方法 1：</span><span>将一组图像应用于所有 SKU</span></p>
<ol>
<li>
<p><span>选择</span><span>将单组图像应用于所有 SKU</span><span>。</span></p>
</li>
<li>
<p><span>浏览到要包含在产品库中的每个图像，或将它们拖到框中。</span></p>
</li>
</ol>
<p><img alt="对所有 SKU 使用相同的图片" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurations-images-apply-single-set.png?lang=en" /></p>
<p><span>方法 2：</span><span>为每个 SKU 应用唯一图像</span></p>
<p><span><span>因为父产品的图片已经上传，所以这个例子使用这个选项来上传每种颜色的图片。</span><span>这是当有人购买特定颜色的衬衫时出现在购物车中的图像。</span></span></p>
<ol>
<li>
<p><span>选择</span><span>Apply unique images by attribute to each SKU</span><span>。</span></p>
</li>
<li>
<p><span>选择图像说明的</span><span>属性</span><span>，例如</span><code>color</code><span>。</span></p>
</li>
<li>
<p><span>对于每个属性值，浏览到要用于该配置的图像或将它们拖到框中。</span></p>
<p><span><span>如果将图像拖到值框，它也会出现在其他值的部分中。</span><span>如果要删除图像，请单击</span></span><em>垃圾桶</em><span>(&nbsp;</span><img alt="垃圾桶图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-delete-trashcan-solid.png?lang=en" /><span>) 图标。</span></p>
<p><img alt="每个 SKU 的独特图像" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-create-configurations-add-images-unique.png?lang=en" /></p>
</li>
</ol>
<p><span>使用以下方法之一配置</span><span>价格</span><span>：</span></p>
<p><span>方法一：</span><span>对所有SKU应用相同的价格</span></p>
<ol>
<li>
<p><span>如果所有变体的价格都相同，请选择</span><span>Apply single price to all SKUs</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>价格</span><span>。</span></p>
<p><img alt="每个 SKU 价格相同" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-create-configurations-price-all-skus.png?lang=en" /></p>
</li>
</ol>
<p><span>方法 2：</span><span>为每个 SKU 应用不同的价格</span></p>
<ol>
<li>
<p><span>如果每个产品或某些变体的价格不同，请选择</span><span>Apply unique prices by attribute to each SKU</span><span>。</span></p>
</li>
<li>
<p><span><span>选择作为</span><span>价格差异基础的</span></span><span>属性。</span><span></span></p>
</li>
<li>
<p><span>输入每个属性值的</span><span>价格</span><span>。</span></p>
<p><span>在此示例中，XL 码的价格更高。</span></p>
<p><img alt="每个 SKU 的唯一价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurable-create-configurations-price-unique.png?lang=en" /></p>
</li>
</ol>
<p><span>使用以下方法之一配置</span><span>Quantity</span><span>：</span></p>
<p><span>方法 1：</span><span>对所有 SKU 应用相同的数量</span></p>
<ol>
<li>
<p><span>如果所有 SKU 的数量都相同，请选择</span><span>Apply single quantity to each SKU</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>数量</span><span>。</span></p>
<p><img alt="所有 SKU 的数量相同" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurations-quantity-same-all-skus.png?lang=en" /></p>
</li>
<li>
<p><span>如果需要，将相同数量应用于所有 SKU（库存管理）。</span></p>
<p><span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/inventory/introduction.html?lang=en">对于使用库存管理</a><span><span>的多源商家</span><span>，为所有生成的产品变体分配来源并添加数量：</span></span></p>
<ul>
<li>
<p><span>选择</span><span>将单个数量应用到每个 SKU</span><span>选项。</span></p>
</li>
<li>
<p><span>要添加源，请单击</span><span>分配源</span><span>。</span></p>
</li>
<li>
<p><span><span>浏览或搜索您要添加的来源。</span><span>选中要为产品添加的来源旁边的复选框。</span></span></p>
</li>
<li>
<p><span>输入每个来源的现有库存量。</span></p>
</li>
</ul>
<p><img alt="所有 SKU 的数量相同" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-configure-product-quantity.png?lang=en" /></p>
</li>
</ol>
<ul>
<li><span>方法二：</span><span>按属性应用不同的数量</span></li>
</ul>
<ol>
<li>
<p><span>如果每个 SKU 的数量不同，请选择</span><span>Apply unique quantity by attribute to each SKU</span><span>。</span></p>
</li>
<li>
<p><span>输入每个的</span><span>数量</span><span>。</span></p>
<p><img alt="每个属性的数量不同" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-configurations-quantity-different.png?lang=en" /></p>
</li>
</ol>
<p><span>图片、价格、数量配置完成后，点击右上角的</span><span>下一步</span><span>。</span></p>
<h3 id="step-4%3A-generate-the-product-configurations"><span>第 4 步：生成产品配置</span></h3>
<p><span>等待产品列表出现，然后执行以下操作之一：</span></p>
<ul>
<li>
<p><span>如果您对配置感到满意，请单击</span><span>&ldquo;下一步&rdquo;</span><span>。</span></p>
</li>
<li>
<p><span>要进行更正，请单击</span><span>&ldquo;返回&rdquo;</span><span>。</span></p>
</li>
</ul>
<p><span></span><em>当前产品变体显示在&ldquo;配置</em><span><span>&rdquo;部分的底部</span><span>。</span></span></p>
<p><img alt="当前配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-configurable-summary.png?lang=en" /></p>
<h3 id="step-5%3A-add-a-product-image"><span>第 5 步：添加产品图片</span></h3>
<ol>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>图像</span><em>和视频</em><span>部分。</span></p>
</li>
<li>
<p><span>单击&ldquo;</span><em>相机</em><span>&rdquo;磁贴并浏览到要用于可配置产品的主图像。</span></p>
</li>
</ol>
<p><span>有关详细信息，请参阅</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/settings/product-images-and-video.html?lang=en">图像和视频</a><span>。</span></p>
<h3 id="step-6%3A-complete-the-product-information"><span>第六步：填写产品信息</span></h3>
<p><span>向下滚动并根据需要完成以下部分中的信息：</span></p>
<ul>
<li>
<p>内容</p>
</li>
<li>
<p>相关产品、追加销售和交叉销售</p>
</li>
<li>
<p>搜索引擎优化</p>
</li>
<li>
<p>可定制的选项</p>
</li>
<li>
<p>网站中的产品</p>
</li>
<li>
<p>设计</p>
</li>
<li>
<p>礼品选项</p>
</li>
</ul>
<h3 id="step-7%3A-publish-the-product"><span>第 7 步：发布产品</span></h3>
<ol>
<li>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>设置为</span><code>Yes</code><span>并执行以下操作之一：</span></p>
<ul>
<li>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;&nbsp;</span><span>&nbsp;) 菜单上选择</span></span><span>客户视图。</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
</li>
</ul>
<p><span>商店在新的浏览器选项卡中打开。</span></p>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-customer-view.png?lang=en" /></p>
</li>
<li>
<p><span>方法二：</span><span>保存关闭</span></p>
<p><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>) 菜单上，选择</span><span>保存并关闭</span><span>。</span></p>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
</li>
</ul>
</li>
</ol>
<h3 id="step-8%3A-configure-the-cart-thumbnails"><span>第 8 步：配置购物车缩略图</span></h3>
<p><span>如果每个变体都有不同的图像，则可以将配置设置为使用正确的图像作为购物车缩略图。</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>Sales</span><span><span>并选择</span><span>下方的</span></span><span>Checkout 。</span><span></span></p>
</li>
<li>
<p><span><span>展开</span><em><span>购物车</span></em></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>将</span><span>可配置产品图片</span><span>设置为</span><code>Product Thumbnail Itself</code><span>.</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
<p><img alt="购物车 - 可配置的产品图片" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/configurable-product.png?lang=en" /></p>
</li>
</ol>
<h2 id="configure-the-stock-status"><span>配置库存状态</span></h2>
<p><span><span>可配置产品库存状态不同于简单产品的库存状态，后者直接表示产品可用性。</span><span>对于可配置产品，库存状态是</span></span><span><em>多标准</em></span><span>库存状态计算的一部分。</span></p>
<h3 id="overview"><span>概述</span></h3>
<p><span>库存状态关系的主要原则如下：</span></p>
<ul>
<li>
<p><span><span>当您将</span><span>可配置产品的</span></span><span>库存状态</span><span></span><code>Out of Stock</code><span>更改为并单击</span><span>保存</span><span>时，它</span><span><em>不受</em></span><span><span>其子产品库存状态的控制。</span><span>它始终显示</span></span><code>Out of Stock</code><span>在管理员和店面中。</span></p>
</li>
<li>
<p><span><span>当您将</span><span>可配置产品的</span></span><span>Stock Status</span><span></span><code>In Stock</code><span>设置为并单击</span><span>Save</span><span>时，它</span><span><em>​​仅部分</em></span><span>受其子产品的库存状态控制，这些状态反映在 Admin 和 Storefront 中。</span></p>
</li>
</ul>
<h3 id="detailed-description"><span>详细说明</span></h3>
<p><span>可配置产品的</span><em>库存</em><span>状态部分受其子产品的库存状态控制，并根据以下</span><span><em>多标准</em></span><span>库存状态计算：</span></p>
<h4 id="with-default-source%2Fstock-only%3A"><span>仅使用默认来源/库存：</span></h4>
<ul>
<li>
<p><span><span>如果可配置产品库存状态</span><span>由管理员用户、文件导入或 API 调用</span></span><span><em>手动</em></span><span><span>设置为，它将</span><span>在</span><span><em><span>管理员</span></em></span><span>和</span><span><em><span>店面</span></em></span><span>中保持不变，直到它被&nbsp;</span><span>管理员用户、文件导入或 API 调用</span><span><em><span>手动</span></em></span><span>更改为。</span><span>它不能通过其子产品的库存状态来控制。</span></span><code>Out of Stock</code><span></span><code>Out of Stock</code><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><code>In stock</code><span></span></p>
</li>
<li>
<p><span><span>如果可配置产品库存状态</span><span>由管理员用户、文件导入或 API 调用</span></span><span><em>手动</em></span><span><span>设置为，则其库存状态由</span><span><em><span>Admin</span></em></span><span>和</span><span><em><span>Storefront</span></em></span><span>上的子产品的库存状态</span><span><em><span>自动控制</span></em></span><span>。</span></span><code>In Stock</code><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span></p>
</li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>库存和来源是</span>库存管理<span>工具的一部分。</span></p>
</div>
</div>
<h4 id="with-at-least-one-custom-source%2Fstock%3A"><span>至少有一个自定义来源/库存：</span></h4>
<ul>
<li>
<p><span><span>如果可配置产品库存状态值</span><span>由管理员用户、文件导入或 API 调用</span></span><span><em>手动</em></span><span><span>设置为，它将</span><span>在</span><span><em><span>管理员</span></em></span><span>和</span><span><em><span>店面</span></em></span><span>中保持不变，直到它被</span><span>管理员用户、文件导入或 API 调用</span><span><em><span>手动</span></em></span><span>更改为。</span><span>它</span><span><em><span>不能通过</span></em></span><span>其子产品的库存状态来控制。</span></span><code>Out of Stock</code><span></span><code>Out of Stock</code><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><code>In Stock</code><span></span><span><em><span></span></em></span><span></span></p>
</li>
<li>
<p><span><span>如果可配置产品库存状态值</span><span>由管理员用户、文件导入或 API 调用</span></span><span><em>手动</em></span><span><span>设置，则其库存状态仅由</span><span><em><span>店面</span></em></span><span>中其子产品的库存状态</span><span><em><span>自动控制</span></em></span><span>。</span></span><code>In Stock</code><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span></p>
</li>
<li>
<p><span><span>如果可配置产品库存状态值</span><span>由管理员用户、文件导入或 API 调用</span></span><span><em>手动</em></span><span><span>设置为，它将保持</span><span>在</span><span><em><span>管理员</span></em></span><span>中，直到它被管理员用户、文件导入或 API 调用</span><span><em><span>手动</span></em></span><span>更改为</span><span>。</span><span>它</span><span><em><span>不能通过</span></em></span><span>其子产品的库存状态来控制。</span></span><code>In Stock</code><span></span><code>In Stock</code><span></span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span><code>Out of Stock</code><span></span><span><em><span></span></em></span><span></span></p>
</li>
</ul>
<h2 id="things-to-remember"><span>要记住的事情</span></h2>
<ul>
<li>
<p><span><span>可配置的产品允许购物者从下拉菜单、多选、视觉样本和文本样本输入类型中选择选项。</span><span>每个选项都是一个单独的简单产品。</span></span></p>
</li>
<li>
<p>可配置产品的库存状态<span><span>是一种半手动控制的设置。</span><span>这与简单产品的库存状态不同，后者直接表示产品可用性。</span><span>对于可配置产品，库存状态是多标准库存状态计算的一部分。</span></span></p>
</li>
<li>
<p><span>可配置的子产品可以是</span><span>没有自定义选项</span><span><span>的简单产品或虚拟产品。</span><span>要使自定义子产品虚拟化，您必须为每个子产品选择</span></span><code>Тhis item has no weight</code><span>权</span><span>重</span><span>设置。</span></p>
</li>
<li>
<p><span><span>用于产品变体的属性必须具有全局范围，并且必须要求客户选择一个值。</span><span>产品变体属性必须包含在用作可配置产品模板的属性集中。</span></span></p>
</li>
<li>
<p><span>用作可配置产品模板的属性集必须包括包含每个产品变体所需值的属性。</span></p>
</li>
<li>
<p><span>购物车中的缩略图可以设置为显示来自可配置产品记录或来自产品变体的图像。</span></p>
</li>
<li>
<p><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/swatches.html?lang=en#create-swatches-for-products"><span></span></a><span>通过在管理员的属性编辑页面将</span><span>更新产品预览图像</span><span><span>选项值设置为选择样本时，可以将</span><span>样本属性</span><span>配置为不显示相应的简单产品图像。</span></span><code>No</code><span></span></p>
</li>
<li>
<p><span>当用户在产品配置之间切换时，主题控制图片库的行为方式。</span><em>空白</em><span><span>主题的默认行为</span><span>是用选定的产品变体覆盖父级可配置产品图像。</span><span>对于 Luma 主题，默认行为是将所选产品变体图像添加到父级可配置产品图像中。</span></span></p>
</li>
</ul>]]></description>
      <pubDate>Sun, 08 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2分组产品]]></title>
      <link>https://www.360magento.com/blog/Grouped-product/</link>
      <description><![CDATA[<p><span><span>分组产品由作为一组显示的简单独立产品组成。</span><span>您可以提供单一产品的变体，或按季节或主题对它们进行分组。</span><span>展示分组的产品可以激励顾客购买额外的物品。</span><span>分组产品提供了一种简单的方法来提供产品的变体并将它们全部列在同一页面上。</span></span></p>
<p><span><span>例如，您可能会出售开放库存的扁平餐具，并列出在正式场所设置中使用的每种器具。</span><span>有些人可能会订购多个沙拉叉、鱼叉、餐叉、餐刀、鱼刀、黄油刀、汤匙和甜点匙。</span><span>其他顾客可能会订购简单的叉子、刀子和勺子。</span><span>客户可以根据需要订购任意数量的每件商品。</span></span></p>
<p><span><span>虽然它们作为一个组显示，但组中的每个产品都是作为单独的项目购买的。</span><span>在购物车中，每个项目和购买的数量显示为一个单独的行项目。</span></span></p>
<p><span>以下说明演示了使用</span>产品模板<span><span>、必填字段和基本设置创建分组产品的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<p><img alt="分组产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped.png?lang=en" /></p>
<h2 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span><span>在</span><span>&nbsp;右上角的</span></span><em>添加产品</em><span><span>( ) 菜单上，选择</span><span><span>分组产品</span></span><span>。</span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span></span><span><span></span></span><span></span></p>
<p><img alt="添加分组产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-grouped.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h2>
<p><span><span>要选择</span><span>用作产品模板的</span></span>属性集，请执行以下操作之一：<span></span></p>
<ul>
<li><span>要搜索，请输入</span><span>属性集</span><span>的名称。</span></li>
<li><span>在列表中，选择要使用的属性集。</span></li>
</ul>
<p><span>更新表格以反映更改。</span></p>
<p><img alt="选择模板" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-create-choose-attribute-set.png?lang=en" /></p>
<p><span>如果所需的属性不存在，您可以在创建产品时添加新属性：</span></p>
<ul>
<li>
<p><span>在右上角，单击&ldquo;</span><span>添加属性</span><span>&rdquo; 。</span></p>
</li>
<li>
<p><span>定义新属性（请参阅</span>向产品添加属性<span>）。</span></p>
<p><img alt="新属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-attribute-add-select.png?lang=en" /></p>
</li>
</ul>
<p><span>要将现有属性添加到产品，请使用</span>过滤器控件<span>在网格中查找属性并执行以下操作：</span></p>
<ul>
<li><span>选中要添加的每个属性的第一列中的复选框。</span></li>
<li><span>单击</span><span>添加所选</span><span>。</span></li>
</ul>
<h2 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h2>
<ol>
<li>
<p><span>输入</span><span>产品名称</span><span>。</span></p>
</li>
<li>
<p><span><span>接受基于产品名称</span><span>的默认</span></span><span>SKU或输入其他名称。</span><span></span></p>
<p><span>请注意，</span><span>数量</span><span>字段不可用，因为该值是从组成该组的单个产品派生的。</span></p>
</li>
<li>
<p><span>由于产品尚未准备好发布，因此将</span><span>启用产品</span><span>设置为</span><code>No</code><span>(&nbsp;&nbsp;</span><img alt="切换否" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-no.png?lang=en" /><span>)。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
<p><span>保存产品后，产品名称会出现在页面顶部，</span>商店视图<span>选择器会出现在左上角。</span></p>
</li>
<li>
<p><span><span>选择</span><span>产品可用的</span></span><span>商店视图。</span><span></span></p>
<p><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-create-store-view-choose.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h2>
<ol>
<li>
<p><span>接受 的</span><span>Stock Status</span><span>设置</span><code>In Stock</code><span>。</span></p>
</li>
<li>
<p><span>要为产品分配</span><span>类别</span><span>，请单击&ldquo;</span><span>选择...</span><span>&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p><span>选择现有类别：</span></p>
<ul>
<li>
<p><span>开始在框中键入以查找匹配项。</span></p>
</li>
<li>
<p><span>选中要分配的类别的复选框。</span></p>
</li>
</ul>
<p><span>创建类别：</span></p>
<ul>
<li>
<p><span>单击</span><span>新建类别</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>并选择</span><span>父类别</span><span>以确定其在菜单结构中的位置。</span></p>
</li>
<li>
<p><span>单击</span><span>创建类别</span><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>接受的</span><span>可见性</span><span>设置</span><code>Catalog, Search</code><span>。</span></p>
</li>
<li>
<p><span>要在</span>新产品列表中展示<span>该产品，请在日历上选择</span><span>将产品设置为新</span>&nbsp;<span>的</span><span></span><span>开始</span><span><span>日期和结束</span><span>日期。</span></span></p>
</li>
<li>
<p><span>选择</span><span>制造国</span><span>。</span></p>
<p><span><span>可能还有其他描述产品的单独属性。</span><span>选择不同的属性集，您可以稍后完成它们。</span></span></p>
<p><img alt="分组产品详细信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-details.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-5%3A-add-products-to-the-group"><span>第 5 步：将产品添加到组中</span></h2>
<ol>
<li>
<p><span>向下滚动到</span><span>Grouped Products</span><span>部分并单击</span><span>Add Products to Group</span><span>。</span></p>
<p><img alt="分组产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-products.png?lang=en" /></p>
</li>
<li>
<p><span>如有必要，使用</span>筛选器<span>查找要包含在组中的产品。</span></p>
</li>
<li>
<p><span>在列表中，选中要包含在组中的每个项目的复选框。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>只有没有可配置选项的简单、可下载和虚拟产品才能分组为子产品。</span><span>其他产品类型不会出现在选择列表中。</span></span></p>
</div>
</div>
<p><img alt="添加所选产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-add-products.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>添加所选产品</span><span>以将它们添加到组中。</span></p>
<p><span>所选产品出现在</span><em>分组产品</em><span>部分。</span></p>
<p><span>对于具有</span>库存管理<span>的多源商家，网格包括</span><span>每个来源的数量</span><span>列以及每个分配的来源和库存库存量。</span></p>
<p><img alt="集团产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-grouped-grouped-products-section.png?lang=en" /></p>
</li>
<li>
<p><span>输入任何项目的</span><span>默认数量</span><span>。</span></p>
</li>
<li>
<p><span>要更改产品的顺序，请抓住第一列中的</span><em>更改顺序</em><span>图标 (&nbsp;&nbsp;</span><img alt="位置控制器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-sort-order.png?lang=en" /><span>) 并将产品拖动到列表中的新位置。</span></p>
</li>
<li>
<p><span>要从组中删除产品，请点击</span><span>删除</span><span>。</span></p>
</li>
</ol>
<h2 id="step-5%3A-complete-the-product-information"><span>第五步：填写产品信息</span></h2>
<p><span>根据需要填写以下部分中的信息：</span></p>
<ul>
<li>内容</li>
<li>图片和视频</li>
<li>搜索引擎优化</li>
<li>相关产品、追加销售和交叉销售</li>
<li>可定制的选项</li>
<li>网站中的产品</li>
<li>设计</li>
<li>礼品选项</li>
</ul>
<h2 id="step-6%3A-publish-the-product"><span>第 6 步：发布产品</span></h2>
<ol>
<li>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>执行以下操作之一：</span></p>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;&nbsp;</span><span>&nbsp;) 菜单上选择</span></span><span>客户视图。</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
<p><span>商店在新的浏览器选项卡中打开。</span></p>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-customer-view.png?lang=en" /></p>
</li>
</ul>
<p><span>方法 2：</span><span>保存并关闭</span></p>
<ul>
<li><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>&nbsp;) 菜单上，选择</span><span>保存并关闭</span><span>。</span></li>
</ul>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-7%3A-configure-the-cart-thumbnails-(optional)"><span>第 7 步：配置购物车缩略图（可选）</span></h2>
<p><span>如果组中的每个产品都有不同的图像，您可以设置配置以使用正确的图像作为购物车缩略图。</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>Sales</span><span>并选择</span><span>Checkout</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>购物</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>车</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="购物车" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/cart-grouped-product.png?lang=en" /></p>
<p><span><span>有关这些配置选项的信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span>购物车<span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>将</span><span>分组产品图片</span><span>设置为</span><code>Product Thumbnail Itself</code><span>。</span></p>
<p><span>如有必要，取消选中</span><span>使用系统值</span><span>复选框以设置此选项。</span></p>
</li>
<li>
<p><span>单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h2 id="things-to-remember"><span>要记住的事情</span></h2>
<ul>
<li>
<p><span>分组产品本质上是简单关联产品的集合。</span></p>
</li>
<li>
<p><span>分组的子产品可以是简单的、可下载的或</span><span>没有自定义选项</span><span>的虚拟产品。</span></p>
</li>
<li>
<p><span>购买的每件商品单独出现在购物车中，而不是作为组的一部分。</span></p>
</li>
<li>
<p><span>购物车中的缩略图可以设置为显示分组父产品或关联产品的图像。</span></p>
</li>
</ul>]]></description>
      <pubDate>Sat, 07 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2简单的产品]]></title>
      <link>https://www.360magento.com/blog/Simple-product/</link>
      <description><![CDATA[<p><span><span>利用产品类型的力量的关键之一是学习何时使用简单、独立的产品。</span><span>简单的产品可以单独销售，也可以作为组合、可配置或捆绑产品的一部分销售。</span><span>具有自定义选项的简单产品有时称为</span></span><em>复合产品</em><span>。</span></p>
<p><span>以下说明演示了使用</span>产品模板<span><span>、必填字段和基本设置创建简单产品的过程。</span><span>每个必填字段都标有红色星号 (&nbsp;</span></span><code>*</code><span><span>)。</span><span>当您完成基础设置后，您可以根据需要完成其他产品设置。</span></span></p>
<p><img alt="简单的产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-simple.png?lang=en" /></p>
<h2 id="step-1%3A-choose-the-product-type"><span>第一步：选择产品类型</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span><span>在</span><span>右上角的</span></span><em>添加产品</em><span><span>( ) 菜单中，选择</span><span><span>简单产品</span></span><span>。</span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span></span><span><span></span></span><span></span></p>
<p><img alt="添加简单产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-add-simple.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-2%3A-choose-the-attribute-set"><span>第 2 步：选择属性集</span></h2>
<p><span><span>要选择</span><span>用作产品模板的</span></span>属性集：<span></span></p>
<ul>
<li>
<p><span>单击&ldquo;</span><span>属性集</span><span>&rdquo;字段并输入属性集的全部或部分名称。</span></p>
</li>
<li>
<p><span>在显示的列表中，选择要使用的属性集。</span></p>
</li>
</ul>
<p><span>更新表格以反映更改。</span></p>
<p><img alt="选择属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-choose-attribute-set.png?lang=en" /></p>
<h2 id="step-3%3A-complete-the-required-settings"><span>第 3 步：完成所需的设置</span></h2>
<ol>
<li>
<p><span>输入</span><span>产品名称</span><span>。</span></p>
</li>
<li>
<p><span><span>接受基于产品名称</span><span>的默认</span></span><span>SKU或输入其他名称。</span><span></span></p>
</li>
<li>
<p><span>输入产品</span><span>价格</span><span>。</span></p>
</li>
<li>
<p><span>因为产品还没有准备好发布，所以将</span><span>Enable Product</span><span>选项设置为</span><code>No</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
<p><span>保存产品后，</span>商店视图<span>选择器会出现在左上角。</span></p>
</li>
<li>
<p><span><span>选择</span><span>产品可用的</span></span><span>商店视图。</span><span></span></p>
<p><img alt="选择商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-create-store-view-choose.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-basic-settings"><span>第四步：完成基本设置</span></h2>
<ol>
<li>
<p><span>将</span><span>税级</span><span>设置为以下之一：</span></p>
<ul>
<li><code>None</code></li>
<li><code>Taxable Goods</code></li>
<li><code>Refund Adjustments</code></li>
<li><code>Gift Options</code></li>
<li><code>Order Gift Wrapping</code></li>
<li><code>Item Gift Wrapping</code></li>
<li><code>Printed Gift Card</code></li>
<li><code>Reward Points</code></li>
<li><code>VAT Reduced</code></li>
<li><code>VAT Standard</code></li>
</ul>
</li>
<li>
<p><span>输入当前库存产品的</span><span>数量</span><span>。</span></p>
<p><span>默认情况下，</span><span>库存状态</span><span>设置为</span><code>In Stock</code><span>。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>如果启用</span>库存管理<span><span>，单一来源商户在此部分设置数量。</span><span>多来源商家在&ldquo;来源&rdquo;部分添加来源和数量。</span><span>请参阅以下</span></span><em>分配来源和数量（库存管理）</em><span>部分。</span></p>
</div>
</div>
</li>
<li>
<p><span>输入产品的</span><span>重量</span><span>。</span></p>
</li>
<li>
<p><span>接受默认的</span><span>可见性</span><span>设置</span><code>Catalog, Search</code><span>。</span></p>
</li>
<li>
<p><span>要为产品分配</span><em>类别</em><span>，请单击&ldquo;</span><span>选择...</span><span>&nbsp;&rdquo;框并执行以下任一操作：</span></p>
<p><span>选择现有类别</span><span>：</span></p>
<ul>
<li>
<p><span>开始在框中键入以查找匹配项。</span></p>
</li>
<li>
<p><span>选中要分配的每个类别的复选框。</span></p>
</li>
</ul>
<p><span>创建类别</span><span>：</span></p>
<ul>
<li>
<p><span>单击</span><span>新建类别</span><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>并选择</span><span>父类别</span><span>以确定其在菜单结构中的位置。</span></p>
</li>
<li>
<p><span>单击</span><span>创建类别</span><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span></span>要在新产品<span><span>列表中展示该产品</span><span>，请选中</span></span><span>将产品设置为新</span><span>复选框。</span></p>
</li>
<li>
<p><span>选择</span><span>制造国</span><span>。</span></p>
<p><img alt="产品详情" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-details-simple.png?lang=en" /></p>
</li>
</ol>
<p><span><span>可能还有其他描述产品的单独属性。</span><span>选择因属性集而异，您可以稍后完成它们。</span></span></p>
<h3 id="assign-sources-and-quantities-(inventory-management)"><span>分配来源和数量（库存管理）</span></h3>
<p><span></span>对于使用库存管理<span><span>的多来源商家</span><span>，向下滚动到</span></span><span>来源</span><span>部分并分配来源和数量：</span></p>
<ol>
<li>
<p><span>要添加源，请单击</span><span>分配源</span><span>。</span></p>
</li>
<li>
<p><span>浏览或搜索来源并选中要为产品添加的来源旁边的复选框。</span></p>
<p><img alt="为产品分配来源" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-assign-sources_c1.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>完成</span><span>以添加源。</span></p>
</li>
<li>
<p><span>要管理源的数量和状态，请单击&ldquo;</span><span>高级库存</span><span>&rdquo;并将&ldquo;</span><span>管理库存</span><span>&rdquo;设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>将</span><span>源项状态</span><span>设置为</span><code>In Stock</code><span>。</span></p>
</li>
<li>
<p><span>输入数量更新现有库存的</span><span>数量</span><span>。</span></p>
</li>
<li>
<p><span>要设置库存数量通知，请执行以下操作之一：</span></p>
<ul>
<li>
<p><em>自定义通知数量</em><span>- 清除</span><span>通知数量使用默认复选框并在</span><span></span><span>通知数量</span><span><span>中输入一个数量</span><span>。</span></span></p>
</li>
<li>
<p><em>默认通知数量</em><span>- 选择</span><span>通知数量使用默认</span><span><span>复选框。</span><span>Commerce 检查并使用 Advanced Inventory 或全局商店配置中的设置。</span></span></p>
</li>
</ul>
<p><img alt="更新每个来源的产品数量" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/inventory-product-quantity_c1.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-5%3A-complete-the-product-information"><span>第五步：填写产品信息</span></h2>
<p><span>向下滚动并根据需要完成以下部分中的信息：</span></p>
<ul>
<li>内容</li>
<li>图片和视频</li>
<li>相关产品、追加销售和交叉销售</li>
<li>搜索引擎优化</li>
<li>可定制的选项</li>
<li>网站中的产品</li>
<li>设计</li>
<li>礼品选项</li>
</ul>
<h2 id="step-6%3A-publish-the-product"><span>第 6 步：发布产品</span></h2>
<ol>
<li>
<p><span>如果您准备好在目录中发布产品，请将</span><span>启用产品</span><span>开关设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>执行以下操作之一：</span></p>
<ul>
<li>
<p><span>方法一：</span><span>保存预览</span></p>
<ul>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span><span>要查看商店中的产品，请</span><span>在</span><em><span>管理</span></em><span>(&nbsp;</span><span>) 菜单上选择</span></span><span>客户视图。</span><span></span><em><span></span></em><span></span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-black.png?lang=en" /><span></span></p>
</li>
</ul>
<p><span>商店在新的浏览器选项卡中打开。</span></p>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-customer-view.png?lang=en" /></p>
</li>
<li>
<p><span>方法 2：</span><span>保存并关闭</span></p>
<p><span>在</span><em>保存</em><span>(&nbsp;</span><img alt="菜单箭头" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-menu-down-arrow-red.png?lang=en" /><span>) 菜单上，选择</span><span>保存并关闭</span><span>。</span></p>
<p><img alt="保存并关闭" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-edit-save-close.png?lang=en" /></p>
</li>
</ul>
</li>
</ol>
<h2 id="things-to-remember"><span>要记住的事情</span></h2>
<ul>
<li>
<p><span>简单产品可以包含在可配置、捆绑和分组产品类型中。</span></p>
</li>
<li>
<p><span>简单产品配置会覆盖特定产品的可配置产品配置。</span></p>
</li>
<li>
<p><span>一个简单的产品可以有各种输入类型的自定义选项，这使得从一个 SKU 销售许多产品变体成为可能。</span></p>
</li>
</ul>]]></description>
      <pubDate>Fri, 06 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2创建产品]]></title>
      <link>https://www.360magento.com/blog/Create-a-product/</link>
      <description><![CDATA[<p><span><span>选择产品类型是创建产品必须做的首要事情之一。</span><span>如果您刚刚开始构建产品目录，则可以创建一些样本产品来试验每种产品类型。</span><span>除了基本产品类型外，术语</span></span><em>复杂产品</em><span>有时用于指代具有多种选择的产品，例如具有多种颜色和尺寸的可配置产品。</span></p>
<p><img alt="店面的产品页面" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-product-page.png?lang=en" /></p>
<h2 id="product-types"><span>产品类型</span></h2>
<p><span>简单产品</span><span><span>- 简单产品是具有单个 SKU 的物理项目。</span><span>简单的产品有不同的定价和输入控制，这使得销售产品的变体成为可能。</span><span>简单产品可以与分组、捆绑和可配置产品结合使用。</span></span></p>
<p><span>可配置产品</span><span><span>- 可配置产品看起来是一个单一的产品，每个变体都有选项列表。</span><span>但是，每个选项代表一个单独的、简单的产品，具有不同的 SKU，这使得跟踪每个变体的库存成为可能。</span></span></p>
<p><span>分组产品</span><span><span>- 分组产品将多个独立产品呈现为一个组。</span><span>您可以提供单个产品的变体，或将它们分组进行促销。</span><span>产品可以单独购买，也可以成组购买。</span></span></p>
<p><span>虚拟产品</span><span><span>&mdash;&mdash;虚拟产品不是有形产品，通常用于服务、会员资格、保修和订阅等产品。</span><span>虚拟产品可以与分组产品和捆绑产品结合使用。</span></span></p>
<p><span>捆绑产品</span><span><span>&nbsp;&mdash;&mdash;捆绑产品允许客户从各种选项中&ldquo;构建自己的&rdquo;。</span><span>捆绑包可以是礼品篮、电脑或任何其他可以定制的东西。</span><span>捆绑包中的每个项目都是单独的独立产品。</span></span></p>
<p><span>可下载产品</span><span><span>- 数字可下载产品由一个或多个下载的文件组成。</span><span>这些文件可以驻留在您的服务器上，也可以作为 URL 提供给任何其他服务器。</span></span></p>
<p><span>礼品卡</span><span>-（</span>仅限Adob​​e Commerce<span>）礼品卡分为三种。</span><em>虚拟</em><span>礼品卡通过电子邮件发送。</span><em>实物</em><span>礼品卡会运送给收件人。</span><em>结合</em><span><span>了虚拟和实体的组合礼品卡。</span><span>每个都有一个唯一的代码，在结账时兑换。</span><span>礼品卡也可以包含在分组产品中。</span></span></p>
<h2 id="product-settings"><span>产品设置</span></h2>
<p><span><span>最常用的产品设置和属性位于页面顶部，其次是自定义属性。</span><span>任何其他产品设置都在页面底部的可扩展部分中。</span></span></p>
<p><img alt="产品设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-settings-include-sources.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>环境</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td>来源</td>
<td><span>列出可以分发产品的来源。</span></td>
</tr>
<tr>
<td>内容</td>
<td><span>用于输入和编辑出现在店面产品页面上的主要产品描述。</span></td>
</tr>
<tr>
<td>配置</td>
<td><span>列出产品的任何现有变体，并可用于生成与可配置产品类型一起使用的变体。</span></td>
</tr>
<tr>
<td>产品评论</td>
<td><span>列出客户为产品提交的所有评论。</span></td>
</tr>
<tr>
<td>搜索引擎优化</td>
<td><span>指定搜索引擎用来索引产品的 URL 键和元数据字段。</span></td>
</tr>
<tr>
<td>相关产品、追加销售和交叉销售</td>
<td><span>用于在店面上设置简单的促销块，展示客户可能感兴趣的一系列附加产品。</span></td>
</tr>
<tr>
<td>可定制的选项</td>
<td><span>向产品添加可定制的选项。</span></td>
</tr>
<tr>
<td>网站中的产品</td>
<td><span>根据商店层次结构标识提供产品的每个网站。</span></td>
</tr>
<tr>
<td>设计</td>
<td><span>用于将不同的主题应用到产品页面、更改列布局、确定产品选项出现的位置以及输入自定义 XML 代码。</span></td>
</tr>
<tr>
<td>礼品选择</td>
<td><span>用于在产品级别的结帐期间启用或禁用礼品消息选项。</span></td>
</tr>
<tr>
<td>共享目录中的产品</td>
<td><img alt="Adobe Commerce 的 B2B" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/b2b.svg?lang=en" /><span>（仅</span>适用于 Adob​​e Commerce 的 B2B<span>）支持使用不同公司的自定义定价维护共享目录，并访问使用不同定价结构的两种类型的共享目录。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="advanced-pricing-and-inventory"><span>高级定价和库存</span></h2>
<p><span></span><span>要访问高级定价和库存设置，请单击价格</span><span>和</span><span>数量</span><span><span>下方的链接</span><span>。</span><span>有关详细信息，请参阅</span></span>管理定价<span>和</span>库存管理<span>。</span></p>
<p><img alt="价格和数量选项链接" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-details-simple.png?lang=en" /></p>]]></description>
      <pubDate>Thu, 05 Jan 2023 08:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品工作区]]></title>
      <link>https://www.360magento.com/blog/Product-workspace/</link>
      <description><![CDATA[<p><em>Store View</em>&nbsp;chooser appears at the upper left of the form.</p>
<p><img alt="产品工作区" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-workspace-ee.png?lang=en" /></p>
<h2 id="enable-product-setting">Enable Product setting</h2>
<p>The online status of the product is indicated by the switch at the top of the form. To change the online status, set the&nbsp;<span>Enable Product</span>&nbsp;switch to&nbsp;<code>Yes</code>&nbsp;or&nbsp;<code>No</code>.</p>
<div class="table-container">
<table>
<thead>
<tr><th>Control</th><th>Description</th></tr>
</thead>
<tbody>
<tr>
<td><img alt="切换是" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-yes.png?lang=en" /></td>
<td>Indicates that the product is online.</td>
</tr>
<tr>
<td><img alt="切换否" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-no.png?lang=en" /></td>
<td>Indicates that the product is offline.</td>
</tr>
</tbody>
</table>
</div>
<h2 id="attribute-set">Attribute set</h2>
<p>The name of the&nbsp;attribute set&nbsp;appears in the upper-left corner and determines the fields that appear in the product record. To choose a different attribute set, click the down arrow next to the default attribute set name.</p>
<p><img alt="属性集" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-attribute-set.png?lang=en" /></p>
<h2 id="expand%2Fcollapse">Expand/collapse</h2>
<p>To expand or collapse a section, click either the expand&nbsp;<img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" />&nbsp;or collapse&nbsp;<img alt="折叠选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-collapse.png?lang=en" />&nbsp;icon.</p>
<h2 id="save-menu">Save menu</h2>
<p>The&nbsp;<em>Save</em>&nbsp;menu includes several options that let you save and continue, save and create a product, save and duplicate the product, or save and close.</p>
<p><img alt="保存菜单" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-save-menu.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th>Command</th><th>Description</th></tr>
</thead>
<tbody>
<tr>
<td>Save</td>
<td>Save the current product and continue working.</td>
</tr>
<tr>
<td>Save &amp; New</td>
<td>Save and close the current product, and begin a new product based on the same product type and template.</td>
</tr>
<tr>
<td>Save &amp; Duplicate</td>
<td>Save and close the current product, and open a new duplicate copy.</td>
</tr>
<tr>
<td>Save &amp; Close</td>
<td>Save the current product and return to the&nbsp;<em>Products</em>&nbsp;workspace.</td>
</tr>
</tbody>
</table>
</div>
<h2 id="default-field-values">Default field values</h2>
<p>To save time when creating products, the default value of several product fields references values from another field. You can either accept the default value or enter another. The following fields have automatically generated default values:</p>
<div class="table-container">
<table>
<thead>
<tr><th>Field</th><th>Default</th></tr>
</thead>
<tbody>
<tr>
<td>SKU</td>
<td>Based on product name.</td>
</tr>
<tr>
<td>Meta Title</td>
<td>Based on product name.</td>
</tr>
<tr>
<td>Meta Keywords</td>
<td>Based on product name.</td>
</tr>
<tr>
<td>Meta Description</td>
<td>Based on product name and description.</td>
</tr>
</tbody>
</table>
</div>
<p><span>表示另一个字段值的占位符包含在双花括号中。</span>产品属性集中<span><span>包含的任何属性代码</span><span>都可以用作占位符。</span></span></p>
<p><img alt="产品字段自动生成" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-product-fields-auto-generation.png?lang=en" /></p>
<p><span><span>有关这些设置的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span>产品字段自动生成<span>。</span><em><span></span></em><span></span></p>
<h3 id="edit-the-placeholder-value"><span>编辑占位符值</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>产品字段自动生成</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分并对</span><span>占位符值进行任何必要的更改。</span></span><span><span></span></span><span></span></p>
<p><span>例如，如果您希望为每个产品包含一个特定关键字，或者您希望在每个元描述中包含一个短语，请将值直接输入到相应的字段中。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>如果要保留现有的占位符值，请保留包含每个标记标签的双花括号。</span></p>
</div>
</div>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h3 id="common-placeholders"><span>常见占位符</span></h3>
<ul>
<li><code>{{color}}</code></li>
<li><code>{{country_of_manufacture}}</code></li>
<li><code>{{description}}</code></li>
<li><code>{{gender}}</code></li>
<li><code>{{material}}</code></li>
<li><code>{{name}}</code></li>
<li><code>{{short_description}}</code></li>
<li><code>{{size}}</code></li>
<li><code>{{sku}}</code></li>
</ul>]]></description>
      <pubDate>Wed, 04 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品列表]]></title>
      <link>https://www.360magento.com/blog/products-lists/</link>
      <description><![CDATA[<p><span>目录中的所有产品都可以从管理员的</span><em>产品</em><span><span>页面访问，您可以在其中创建产品和编辑现有产品。</span><span>对于多站点安装，每个网站都可以从同一目录中提供不同的待售产品选择。</span></span></p>
<p><span></span><em>产品</em><span><span>列表包括目录中的</span><span>所有产品，指示它们可用的网站，以及它们当前是否可以销售。</span></span>在启用了共享目录<span><span>的 Adob​​e Commerce B2B 安装中</span><span>，网格包含一个列，指示哪些产品在共享目录中具有替代折扣定价。</span></span></p>
<p><span><span>您可以逐页浏览列表，或搜索特定产品。</span><span>使用标准</span></span>控件<span><span>对列表进行排序和过滤，并对</span><span>选定产品应用</span></span>操作。<span></span></p>
<p><img alt="产品网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/products-grid.png?lang=en" /></p>
<h2 id="page-controls"><span>页面控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>添加产品</span></td>
<td><span><span>启动创建新的简单产品的流程。</span><span>要选择特定的产品类型，请单击向下箭头。</span><span>选项：</span></span>简单产品<span>/</span>可配置产品<span>/</span>分组产品<span>/</span>虚拟产品<span>/</span>捆绑产品<span>/</span>可下载产品<span>/</span>礼品卡</td>
</tr>
<tr>
<td><span>导出完整目录</span></td>
<td><span>（需要</span>MCOM 连接器<span>）手动请求从 Adob​​e Commerce</span>导出完整目录<span><span>。</span><span>外发消息批量导出到 .csv 文件。</span></span></td>
</tr>
<tr>
<td><span>动作</span></td>
<td><span><span>列出可应用于列表中选定产品的所有操作。</span><span>要对一个产品或一组产品应用操作，请选中每个产品第一列中的复选框。</span><span>选项：</span></span><code>Delete</code><span>/&nbsp;</span><code>Change Status</code><span>/&nbsp;</span><code>Update Attributes</code><span>/&nbsp;</span><code>Assign Inventory Source</code><span>/&nbsp;</span><code>Unassign Inventory Source</code><span>/</span><code>Transfer Inventory To Source</code></td>
</tr>
<tr>
<td><span>过滤器</span></td>
<td><span>根据当前过滤器启动目录搜索。</span></td>
</tr>
<tr>
<td><span>默认视图</span></td>
<td><span><span>指示当前网格列布局。</span><span>如果有保存的网格列视图，您可以选择另一个。</span></span></td>
</tr>
<tr>
<td><span>列</span></td>
<td><span><span>列出可应用于列表中选定产品的所有操作。</span><span>要对一个产品或一组产品应用操作，请选中每个产品第一列中的复选框。</span></span></td>
</tr>
<tr>
<td><span>按关键字搜索</span></td>
<td><span>左上角的搜索框用于按关键字查找产品。</span></td>
</tr>
<tr>
<td><span>编辑</span></td>
<td><span><span>在编辑模式下打开产品。</span><span>您可以通过单击行中的任意位置来完成相同的操作。</span></span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="default-columns"><span>默认列</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>柱子</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>（复选框）</span></td>
<td><span><span>选择要执行操作的多个记录。</span><span>每个选定记录的第一列中的复选框被标记。</span><span>选项：</span></span><br /><span>全选</span><span>- 选择找到的与当前过滤器设置匹配的所有记录。</span><br /><span>全选此页</span><span>- 仅选择在当前页面上找到的与过滤器设置匹配的记录。</span></td>
</tr>
<tr>
<td><span>ID</span></td>
<td><span>首次保存新产品时分配的唯一序列号。</span></td>
</tr>
<tr>
<td><span>缩略图</span></td>
<td><span>显示主要产品图像的缩略图。</span></td>
</tr>
<tr>
<td><span>姓名</span></td>
<td><span>产品名称。</span></td>
</tr>
<tr>
<td><span>类型</span></td>
<td><span>产品类型。</span></td>
</tr>
<tr>
<td><span>属性集</span></td>
<td><span>用作产品模板的属性集的名称。</span></td>
</tr>
<tr>
<td><span>存货单位</span></td>
<td><span>分配给产品的唯一库存单位。</span></td>
</tr>
<tr>
<td><span>价格</span></td>
<td><span>产品的单价。</span></td>
</tr>
<tr>
<td><span>数量</span></td>
<td><span>当前库存的数量。</span></td>
</tr>
<tr>
<td><span>可售数量</span></td>
<td><span>该产品所有可用单位的总和。</span></td>
</tr>
<tr>
<td><span>能见度</span></td>
<td><span><span>指示产品在目录中的可见位置。</span><span>选项：</span></span><code>Not Visible Individually</code><span>/&nbsp;</span><code>Catalog</code><span>/&nbsp;</span><code>Search</code><span>/</span><code>Catalog, Search</code></td>
</tr>
<tr>
<td><span>状态</span></td>
<td><span><span>指示产品的状态。</span><span>选项：</span></span><code>Enabled</code><span>和</span><code>Disabled</code></td>
</tr>
<tr>
<td><span>网站</span></td>
<td><span>表示提供产品的网站。</span></td>
</tr>
<tr>
<td><span>行动</span></td>
<td><span>在编辑模式下打开产品。</span></td>
</tr>
<tr>
<td><span>共享目录</span></td>
<td><img alt="Adobe Commerce 的 B2B" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/b2b.svg?lang=en" /><span>（仅</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/introduction.html?lang=en">适用于 Adob​​e Commerce 的 B2B</a><span>）表示包含产品自定义定价的共享目录。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="other-columns"><span>其他专栏</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>柱子</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>简短的介绍</span></td>
<td><span>产品的简短描述。</span></td>
</tr>
<tr>
<td><span>特价日期</span></td>
<td><span>特价促销的第一天。</span></td>
</tr>
<tr>
<td><span>迄今为止的特价</span></td>
<td><span>特价促销的最后日期。</span></td>
</tr>
<tr>
<td><span>成本</span></td>
<td><span>项目的实际成本。</span></td>
</tr>
<tr>
<td><span>制造商</span></td>
<td><span>产品的制造商。</span></td>
</tr>
<tr>
<td><span>元关键字</span></td>
<td><span>产品的元关键字。</span></td>
</tr>
<tr>
<td><span>颜色</span></td>
<td><span>产品颜色。</span></td>
</tr>
<tr>
<td><span>将产品设置为新日期</span></td>
<td><span>设置产品的第一个日期为新促销。</span></td>
</tr>
<tr>
<td><span>将产品设置为最新</span></td>
<td><span>将产品设置为新促销的最后日期。</span></td>
</tr>
<tr>
<td><span>活动自/至</span></td>
<td><span>产品开始和结束日期。</span></td>
</tr>
<tr>
<td><span>布局</span></td>
<td><span>产品布局。</span></td>
</tr>
<tr>
<td><span>最低广告价格</span></td>
<td><span>产品的最低广告价格。</span></td>
</tr>
<tr>
<td><span>允许礼物消息</span></td>
<td><span>给购买礼品卡的客户的礼品信息。</span></td>
</tr>
<tr>
<td><span>特价</span></td>
<td><span>产品特价。</span></td>
</tr>
<tr>
<td><span>重量</span></td>
<td><span>产品重量。</span></td>
</tr>
<tr>
<td><span>元标题</span></td>
<td><span>产品的元标题。</span></td>
</tr>
<tr>
<td><span>元描述</span></td>
<td><span>产品元数据描述。</span></td>
</tr>
<tr>
<td><span>制造国</span></td>
<td><span>制造国。</span></td>
</tr>
<tr>
<td><span>新主题</span></td>
<td><span>将自定义主题应用于产品。</span></td>
</tr>
<tr>
<td><span>网址键</span></td>
<td><span>产品的 URL 密钥。</span></td>
</tr>
<tr>
<td><span>税级</span></td>
<td><span>产品税级。</span></td>
</tr>
<tr>
<td><span>允许礼物消息</span></td>
<td><span>显示产品的礼品消息选项的可用性。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Tue, 03 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2分类权限]]></title>
      <link>https://www.360magento.com/blog/Category-permissions/</link>
      <description><![CDATA[<p><span>类别访问可以仅限于特定的客户组，也可以完全限制。</span><span>您可以控制产品价格的显示，并确定哪些客户群可以将产品添加到购物车，并指定登陆页面。</span></p>
<p><span><span>例如，如果您只销售给批发客户，您可以允许任何人浏览目录，但显示价格并只允许批发客户组中的人购买。</span><span>在以下示例中，只有登录用户才能访问&ldquo;收藏&rdquo;类别。</span><span>对于来宾，&ldquo;收藏&rdquo;选项不会出现在主菜单中。</span></span></p>
<p><img alt="登录用户查看&ldquo;收藏&rdquo;类别" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-category-permissions-logged-in.png?lang=en" /></p>
<p><span>启用后，新的</span><em>类别权限</em><span><span>部分会出现在类别页面上，允许您为每个类别应用所需的访问权限。</span><span>您可以为不同的网站和客户群体为每个类别添加多个权限规则。</span></span></p>
<h2 id="step-1%3A-configure-category-permissions"><span>第 1 步：配置类别权限</span></h2>
<div class="extension important">
<div><span><span>重要的</span></span></div>
<div>
<p><span><span><em><span>启用共享目录</span></em></span><span>功能后，目录中的</span><span><em><span>所有</span></em></span><span>类别都会</span><span>忽略</span><span>所有现有</span></span>组权限设置。<span>共享目录在启用时完全控制目录中的所有类别权限。</span><span><em><span></span></em></span><span></span><span><em><span></span></em></span><span></span></p>
</div>
</div>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>类别权限</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="类别权限" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-category-permissions.png?lang=en" /></p>
<p><span><span>有关这些选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span>类别权限<span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>将</span><span>启用</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>根据您希望在商店中允许或限制的内容完成其他选项（请参阅以下部分）。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>当提示更新缓存时，单击系统消息中的</span><span>缓存管理</span><span>链接并按照说明刷新缓存。</span></p>
</li>
</ol>
<h3 id="allow-browsing-category"><span>允许浏览类别</span></h3>
<p><span>此选项适用于</span>网站<span>中的所有类别。</span></p>
<p><span>要允许</span><span><em>特定客户组</em></span><span>的成员浏览类别产品，请执行以下操作：</span></p>
<ol>
<li>
<p><span>将</span><span>允许浏览类别</span><span>设置为</span><code>Specified Customer Groups</code><span>。</span></p>
</li>
<li>
<p><span>在&ldquo;</span><span>客户组</span><span>&rdquo;框中，选择允许浏览类别中产品的每个组。</span></p>
<p><span>要选择多个组，请在单击每个组时按住 Ctrl 键 (PC) 或 Command 键 (Mac)。</span></p>
<p><img alt="允许批发客户组浏览" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-allow-browsing-customer-groups.png?lang=en" /></p>
</li>
</ol>
<p><span>要</span><span><em>限制访问并重定向到登录页面</em></span><span>，请执行以下操作：</span></p>
<ol>
<li>
<p><span>将</span><span>允许浏览类别</span><span>设置为</span><code>No, Redirect to Landing Page</code><span>。</span></p>
</li>
<li>
<p><span><span>选择</span><span>重定向访问者的</span></span><span>着陆页。</span><span></span></p>
<p><img alt="重定向到主页" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-browse-category-landing-page.png?lang=en" /></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>虽然</span><em>允许浏览类别</em><span>设置适用于网站中的所有类别，但您可以为每个商店视图配置不同的登录页面。</span></p>
</div>
</div>
</li>
</ol>
<h3 id="display-product-prices"><span>显示产品价格</span></h3>
<p><span>此选项适用于</span>网站<span>中的所有类别。</span></p>
<p><span>要仅允许</span><span><em>特定客户组</em></span><span>的成员查看类别中产品的价格，请执行以下操作：</span></p>
<ol>
<li>
<p><span>将</span><span>显示产品价格</span><span>设置为</span><code>Yes, for Specified Customer Groups</code><span>。</span></p>
</li>
<li>
<p><span>在&ldquo;</span><span>客户组</span><span>&rdquo;框中，选择允许查看类别中产品价格的每个组。</span></p>
<p><span>要选择多个组，请在单击每个组时按住 Ctrl 键 (PC) 或 Command 键 (Mac)。）</span></p>
<p><img alt="只有批发客户组可以看到价格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-price-customer-groups.png?lang=en" /></p>
</li>
</ol>
<h3 id="allow-adding-to-cart"><span>允许加入购物车</span></h3>
<p><span>此选项适用于</span>网站<span>中的所有类别。</span></p>
<p><span>要仅允许</span><span><em>特定客户组</em></span><span>的成员将类别产品放入购物车，请执行以下操作：</span></p>
<ol>
<li>
<p><span>将</span><span>允许添加到购物车</span><span>设置为</span><code>Yes, for Specified Customer Groups</code><span>。</span></p>
</li>
<li>
<p><span>在&ldquo;</span><span>客户组</span><span>&rdquo;框中，选择允许将类别中的产品添加到购物车的每个组。</span></p>
<p><span>要选择多个组，请在单击每个组时按住 Ctrl 键 (PC) 或 Command 键 (Mac)。</span></p>
<p><img alt="只有批发客户群才能将产品放入购物车" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-cart-customer-groups.png?lang=en" /></p>
</li>
</ol>
<h3 id="disallow-catalog-search"><span>禁止目录搜索</span></h3>
<p><span><span>设置此选项可防止特定客户组的成员使用目录搜索。</span><span>它适用于</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/start/setup/websites-stores-views.html?lang=en">网站</a><span>中的所有类别。</span></p>
<ul>
<li>
<p><span>要</span><span><em>仅允许登录的客户</em></span><span>使用目录搜索，请选择</span><code>NOT LOGGED IN</code><span>。</span></p>
</li>
<li>
<p><span>要</span><span><em>仅允许特定客户组</em></span><span>使用目录搜索，请选择要排除在使用类别搜索之外的每个组。</span></p>
<p><span>要选择多个组，请在单击每个组时按住 Ctrl 键 (PC) 或 Command 键 (Mac)。</span></p>
<p><img alt="一般客户组不允许目录搜索" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-disallow-category-search.png?lang=en" /></p>
</li>
</ul>
<h2 id="step-2%3A-apply-category-permissions"><span>第 2 步：应用类别权限</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在类别树中，选择目标类别。</span></p>
</li>
<li>
<p><span>展开页面上的</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" />&nbsp;<span>类别权限</span><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>要创建权限规则，请单击</span><span>新建权限</span><span>。</span></p>
<p><img alt="类别权限部分" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-permissions-section-admin.png?lang=en" /></p>
</li>
<li>
<p><span>选择适用的</span><span>网站</span><span>和</span><span>客户组</span><span>。</span></p>
</li>
<li>
<p><span>根据需要设置个人权限。</span></p>
</li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>当为任何父分类设置</span><code>Browsing Category</code><span>=</span><code>Deny</code><span><span>权限时，它不会显示在</span><span>子分类页面的</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/navigation/navigation-breadcrumb-trail.html?lang=en">Breadcrumb Trail中。</a><span></span></p>
</div>
</div>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Mon, 02 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别的预定更改]]></title>
      <link>https://www.360magento.com/blog/Scheduled-changes-for-categories/</link>
      <description><![CDATA[<p><span>类别更新可以按计划应用，并与其他内容更改组合在一起。</span><span>您可以根据对类别的预定更改创建广告系列，或将更改应用到现有广告系列。</span></p>
<p><img alt="预定更改" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-scheduled-changes.png?lang=en" /></p>
<h2 id="schedule-an-update-to-a-category"><span>安排更新类别</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左侧分类树中，选择需要修改的分类。</span></p>
</li>
<li>
<p><span><span>在</span><span>页面顶部的</span></span><em>计划更改框中，单击</em><span></span><span>计划新更新</span><span>。</span></p>
</li>
<li>
<p><span>选择&ldquo;</span><span>另存为新更新&rdquo;</span><span>选项后，设置更新的基本参数：</span></p>
<ul>
<li>
<p><span>对于</span><span>更新名称</span><span>，输入新内容暂存活动的名称。</span></p>
</li>
<li>
<p><span>输入更新的简短</span><span>说明</span><span>及其使用方式。</span></p>
</li>
<li>
<p><span>使用日历 (&nbsp;</span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span>) 工具选择活动的</span><span>开始日期</span><span>和</span><span>结束日期</span><span>。</span></p>
</li>
</ul>
</li>
</ol>
<div class="extension important">
<div><span><span>重要的</span></span></div>
<div>
<p><span>活动</span><span>开始日期</span><span>和</span><span>结束日期</span><span>必须使用</span><span><em>默认</em></span><span><span>的管理时区定义，该时区是从每个网站的本地时区转换而来的。</span><span>例如，对于位于不同时区的多个网站，您希望根据美国时区开始营销活动，您需要为每个本地时区安排单独的更新。</span><span>您为每个设置</span></span><span>开始日期</span><span>和</span><span>结束日期</span><span>，这是从本地网站时区转换为默认的管理时区。</span></p>
</div>
</div>
<ol>
<li>
<p><span>对计划的更新进行任何必要的更改。</span></p>
</li>
<li>
<p><span><span>单击</span><span>右上角按钮栏中的预览以预览更改</span></span><span>。</span><span></span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="assign-to-an-existing-update"><span>分配给现有更新</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左侧分类树中，选择需要修改的分类。</span></p>
</li>
<li>
<p><span><span>在</span><span>页面顶部的</span></span><em>计划更改框中，单击</em><span></span><span>计划新更新</span><span>。</span></p>
</li>
<li>
<p><span>选择</span><span>分配给现有市场活动</span><span>。</span></p>
</li>
<li>
<p><span>在列表中，找到所需的营销活动并点击</span><span>选择</span><span>。</span></p>
</li>
<li>
<p><span>对计划的更新进行必要的更改。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sun, 01 Jan 2023 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2添加和删​​除类别产品]]></title>
      <link>https://www.360magento.com/blog/Add-and-remove-category-products/</link>
      <description><![CDATA[<p>从&ldquo;类别中的产品&rdquo;部分，商店管理员可以将产品添加到类别中。此部分列出分配给该类别的所有产品，并在按规则匹配产品设置为时显示添加产品。</p>
<p><img alt="类别部分的产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-product.png?lang=en" /></p>
<h2 id="search-for-products-to-add"><span>搜索要添加的产品</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左侧的类别树中，选择要添加产品的类别。</span></p>
</li>
<li>
<p><span><span>展开</span><em><span>类别</span></em><span>部分中</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>的产品。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>单击</span><span>添加产品</span><span>。</span></p>
</li>
<li>
<p><span>使用</span><em>按关键字</em><span>或过滤器搜索来查找您要添加的产品。</span></p>
<p><img alt="搜索所有产品选项卡" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-all-product.png?lang=en" /></p>
</li>
<li>
<p><span>在&ldquo;</span><em>分配</em><span>&rdquo;列中，将选项切换</span><code>Yes</code><span>为您要添加的每个产品。</span></p>
<p><span>如果您想包括所有显示的产品，您可以单击列标题中的菜单箭头并选择</span><span>全选</span><span>。</span></p>
</li>
<li>
<p><span>要应用您的更改，请点击</span><span>保存并关闭</span><span>。</span></p>
</li>
</ol>
<h3 id="actions"><span>动作</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>行动</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>全选</span></td>
<td><span>选中列表中所有记录的复选框。</span></td>
</tr>
<tr>
<td><span>全部取消选择</span></td>
<td><span>清除列表中所有记录的复选框。</span></td>
</tr>
<tr>
<td><span>全选本页</span></td>
<td><span>选中当前页面上记录的复选框。</span></td>
</tr>
<tr>
<td><span>取消选择此页面上的所有内容</span></td>
<td><span>清除当前页面上记录的复选框。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="add-products-by-sku"><span>按 SKU 添加产品</span></h2>
<ol>
<li>
<p><span>单击</span><span>添加产品</span></p>
</li>
<li>
<p><span>选择</span><span>按 SKU 添加产品</span><span>选项卡。</span></p>
</li>
<li>
<p><span>输入 SKU（每行一个）并点击</span><span>分配</span><span>。</span></p>
<p><span>要放弃更改，请单击</span><span>删除</span><span>。</span></p>
<p><img alt="按 SKU 选项卡添加产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/add-product-by-sku.png?lang=en" /></p>
</li>
<li>
<p><span>要应用您的更改，请点击</span><span>保存并关闭</span><span>。</span></p>
</li>
</ol>
<h2 id="remove-products-from-a-category"><span>从类别中删除产品</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左侧的类别树中，选择要编辑的类别。</span></p>
</li>
<li>
<p><span><span>展开</span><em><span>类别</span></em><span>部分中</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>的产品。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>找到要删除的产品。</span></p>
</li>
<li>
<p><span>在</span><em>操作</em><span>列中，单击</span><span>取消分配</span><span>。</span></p>
</li>
<li>
<p><span>要应用您的更改，请点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sat, 31 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2排序类别产品]]></title>
      <link>https://www.360magento.com/blog/Sort-category-products/</link>
      <description><![CDATA[<p>可以通过将产品拖放到某个位置或应用预定义的排序顺序来手动指定产品在类别中的位置。默认情况下，产品可以按库存水平、年龄、颜色、名称、SKU 和价格排序。自动排序会覆盖当前排序顺序并重置手动设置的任何拖放位置。颜色的排序顺序和要包含在列表中的产品可能需要的最低库存水平在Visual Merchandiser配置中设置。</p>
<p>您可以为每个商店<span><span>单独设置类别选项，</span><span>以确定产品的选择、它们在列表中的相对位置以及可用于类别规则的属性。</span><span>但是，只能将一个排序顺序分配给任何商店的</span></span>商店视图<span>级别。</span></p>
<h2 id="step-1%3A-set-the-scope-of-the-configuration"><span>第一步：设置配置范围</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>如有必要，选择应用设置的</span><span>商店视图</span><span>。</span></p>
<p><span>对于多商店安装，</span><em>Store View</em><span>设置将排序顺序应用于商店内的所有可用视图。</span></p>
</li>
<li>
<p><span>在左侧的类别树中，选择要编辑的类别。</span></p>
<p><img alt="类别树" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-selected.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-2%3A-sort-the-products"><span>第 2 步：对产品进行排序</span></h2>
<p><span></span><em>在类别</em><span><span>部分的产品中</span><span>，单击图块 (&nbsp;</span></span><img alt="查看磁贴" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-view-tiles.png?lang=en" /><span><span>) 图标以在网格中显示产品图块。</span><span>使用手动或自动方法对产品进行分类。</span></span></p>
<p><img alt="产品板块" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-products-tiles.png?lang=en" /></p>
<h3 id="method-1%3A-manual-sort"><span>方法一：手动排序</span></h3>
<ol>
<li>
<p><span><span>根据您的喜好</span><span>设置</span></span><span>排序顺序。</span><span></span></p>
</li>
<li>
<p><span>单击</span><span>排序</span><span>以应用新的排序顺序。</span></p>
<p><img alt="排序" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-edit-sort-order.png?lang=en" /></p>
</li>
<li>
<p><span>要保存排序顺序，请单击&ldquo;</span><span>保存类别</span><span>&rdquo; 。</span></p>
</li>
<li>
<p><span>出现提示时，更新任何无效的索引器。</span></p>
</li>
</ol>
<h3 id="method-2%3A-automatic-sort"><span>方法二：自动排序</span></h3>
<ol>
<li>
<p><span></span><span>将按规则匹配产品</span><span>(&nbsp;</span><img alt="切换是" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-yes.png?lang=en" /><span><span>)</span><span>设置为</span></span><code>Yes</code><span>。</span></p>
<p><img alt="按规则匹配产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-edit-automatic-sorting.png?lang=en" /></p>
</li>
<li>
<p><span><span>根据您的喜好</span><span>设置</span></span><span>自动排序。</span><span></span></p>
</li>
<li>
<p><span>按照下一步中的说明创建类别规则。</span></p>
</li>
</ol>
<h2 id="step-3%3A-create-a-category-rule"><span>第 3 步：创建类别规则</span></h2>
<ol>
<li>
<p><span></span><span>将按规则匹配产品</span><span>(&nbsp;</span><img alt="切换是" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-yes.png?lang=en" /><span><span>)</span><span>设置为</span></span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>添加条件</span><span>。</span></p>
<p><img alt="分类条件" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-edit-condition.png?lang=en" /></p>
</li>
<li>
<p><span><span>选择作为</span><span>条件基础的</span></span><span>属性。</span><span></span></p>
</li>
<li>
<p><span>将</span><span>运算符</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Equal</code></li>
<li><code>Not equal</code></li>
<li><code>Greater than</code></li>
<li><code>Greater than or equal to</code></li>
<li><code>Less than</code></li>
<li><code>Less than or equal to</code></li>
<li><code>Contains</code></li>
</ul>
</li>
<li>
<p><span>输入适当的</span><span>值</span><span>。</span></p>
</li>
<li>
<p><span>要添加另一个条件，请单击</span><span>添加条件</span><span>并重复该过程。</span></p>
</li>
</ol>
<h2 id="step-4%3A-save%2C-refresh%2C-and-verify"><span>第 4 步：保存、刷新和验证</span></h2>
<ol>
<li>
<p><span>完成后，点击</span><span>保存类别</span><span>。</span></p>
</li>
<li>
<p><span>当提示刷新缓存时，单击</span><span>缓存管理</span><span>并刷新每个无效缓存。</span></p>
</li>
<li>
<p><span>在店面中，验证产品选择、排序和类别规则是否正常工作。</span></p>
<p><span>如果您需要进行调整，请更改设置并重试。</span></p>
</li>
</ol>]]></description>
      <pubDate>Fri, 30 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别产品分配]]></title>
      <link>https://www.360magento.com/blog/Category-product-assignments/</link>
      <description><![CDATA[<p>对于类别，使用&ldquo;类别中的<em>产品&rdquo;</em>部分查看当前分配给该类别的产品。每列顶部的搜索过滤器用于在类别中添加和删除产品。您还可以使用类别规则（<img alt="Adobe 商务" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/adobe-logo.svg?lang=en" />仅限 Adob​​e Commerce）在满足一组条件时动态更改产品选择。</p>
<p><img alt="分类产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-products-in-category.png?lang=en" /></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>在类别页面上，</span><code>Out of stock</code><span>产品始终显示</span><span><em>在</em></span>&nbsp;<code>In Stock</code><span>所有排序类型的产品列表中的产品之后。</span></p>
</div>
</div>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span></span><em>库存列仅显示</em><span></span><em><span>选定类别范围内</span></em><span><span>的</span><span>可销售产品数量</span><span>。</span><span>当为产品管理多个库存时，您应该在相应范围之间切换以在</span><em><span>类别产品</span></em><span>网格中显示其他</span></span><em>库存</em><span>列值。</span><em><span></span></em><span></span></p>
</div>
</div>
<h2 id="apply-a-category-rule"><span>应用类别规则</span></h2>
<ol>
<li>
<p><span></span><span>将按规则匹配产品</span><span><span>设置</span><span>为</span></span><code>Yes</code><span>。</span></p>
<p><span>出现自动排序和条件选项。</span></p>
<p><img alt="按规则匹配产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-match-products-by-rule.png?lang=en" /></p>
</li>
<li>
<p><span>设置</span><span>自动排序</span><span>顺序。</span></p>
<p><span>此自动排序基于当前条件。</span></p>
<ul>
<li><code>Stock level</code><span>- 移动到顶部或底部。</span></li>
<li><code>Special price</code><span>- 移动到顶部或底部。</span></li>
<li><code>New Products</code><span>- 首先列出最新产品。</span></li>
<li><code>Color</code><span>- 按颜色字母顺序排序。</span></li>
<li><code>Name</code><span>- 按名称升序或降序排序。</span></li>
<li><code>SKU</code><span>- 按SKU升序或降序排序</span></li>
<li><code>Price</code><span>- 按价格升序或降序排序。</span></li>
</ul>
</li>
<li>
<p><span>单击</span><span>添加条件</span><span>并执行以下操作：</span></p>
<ul>
<li><span><span>选择作为</span><span>条件基础的</span></span><span>属性。</span><span></span></li>
<li><span><span>选择</span><span>形成表达式所需的</span></span><span>运算符。</span><span></span></li>
<li><span><span>输入</span><span>要匹配的</span></span><span>值。</span><span></span></li>
</ul>
<p><img alt="将条件添加到类别规则" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-rule-create.png?lang=en" /></p>
<p><span><span>对描述要满足的条件所需的每个属性重复此过程。</span><span>例如，要匹配 7 到 30 天前创建的产品，请执行以下操作：</span></span></p>
<ul>
<li><span>将</span><span>创建日期</span><span>设置为</span><code>Less than 30</code><span>。</span></li>
<li><span>将</span><span>逻辑</span><span>设置为</span><code>AND</code><span>。</span></li>
<li><span>将</span><span>修改日期</span><span>设置为</span><code>Greater than 7</code><span>。</span></li>
</ul>
</li>
<li>
<p><span>完成后，点击</span><span>保存类别</span><span>。</span></p>
</li>
</ol>
<h3 id="page-options"><span>页面选项</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>选项</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>按规则匹配产品</span></td>
<td><span><span>确定类别中的产品列表是否由类别规则动态生成。</span><span>选项：</span></span><code>Yes</code><span>/</span><code>No</code></td>
</tr>
<tr>
<td><span>自动分拣</span></td>
<td><span><span>自动将排序顺序应用于类别产品列表。</span><span>选项：</span></span><br /><code>None</code><br /><code>Move low stock to top</code><br /><code>Move low stock to bottom</code><br /><code>Special price to top</code><br /><code>Special price to bottom</code><br /><code>Newest products first</code><br /><code>Sort by color</code><br /><code>Name: A - Z</code><br /><code>Name: Z - A</code><br /><code>SKU: Ascending</code><br /><code>SKU: Descending</code><br /><code>Price: High to Low</code><br /><code>Price: Low to High</code></td>
</tr>
<tr>
<td><span>添加条件</span></td>
<td><span>向规则添加另一个条件。</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="page-conditions"><span>页面条件</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>选项</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>属性</span></td>
<td><span><span>确定用作条件基础的属性。</span><span>选项：</span></span><br /><span>Clone Category ID(s)</span><span>&nbsp;- 根据类别 ID 从多个类别动态克隆产品，不带排序和顺序。</span><br /><span>颜色</span><span>- 包括基于颜色的产品。</span><br /><span>创建日期（天前）</span><span>&nbsp;- 根据产品添加到目录后的天数包括产品。</span><br /><span>修改日期（天前）</span><span>&nbsp;- 根据产品上次修改后的天数包括产品。</span><br /><span>名称</span><span>- 包括基于产品名称的产品。</span><br /><span>价格</span><span>- 包括基于价格的产品。</span><br /><span>数量</span><span>- 包括基于库存数量的产品。</span><br /><span>存货单位</span><span>- 包括基于 SKU 的产品。</span></td>
</tr>
<tr>
<td><span>操作员</span></td>
<td><span><span>指定应用于属性值以满足条件的运算符。</span><span>除非指定运算符，否则</span></span><code>Equal</code><span><span>默认使用。</span><span>选项：</span></span><code>Equal</code><span>/&nbsp;</span><code>Not equal</code><span>/&nbsp;</span><code>Greater than</code><span>/&nbsp;</span><code>Greater than or equal to</code><span>/&nbsp;</span><code>Less than</code><span>/&nbsp;</span><code>Less than or equal to</code><span>/</span><code>Contains</code></td>
</tr>
<tr>
<td><span>价值</span></td>
<td><span>指定属性必须满足条件的值。</span></td>
</tr>
<tr>
<td><span>逻辑</span></td>
<td><span><span>用于定义多个条件，仅在添加另一个条件时出现。</span><span>选项：</span></span><code>OR</code><span>/</span><code>AND</code></td>
</tr>
</tbody>
</table>
</div>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>具有子选项的可配置产品的数量是通过合并所有可销售的子产品数量来计算的。</span><span>例如，如果您的可配置产品</span></span><em>Endurance Fitness Tank</em><span>有紫色、红色和黄色选项，每种颜色的数量不同，则父产品数量是紫色、红色和黄色子产品的总可售数量。</span></p>
</div>
</div>
<h2 id="controls"><span>控件</span></h2>
<h2 id="page-controls"><span>页面控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><img alt="查看列表" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-view-list.png?lang=en" /></td>
<td><span>查看列表</span></td>
</tr>
<tr>
<td><img alt="以图块形式查看" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-view-tiles.png?lang=en" /></td>
<td><span>查看为瓷砖</span></td>
</tr>
<tr>
<td><img alt="切换否" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-no.png?lang=en" /></td>
<td><span>按规则匹配 - 否</span></td>
</tr>
<tr>
<td><img alt="切换是" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/toggle-yes.png?lang=en" /></td>
<td><span>按规则匹配 - 是</span></td>
</tr>
<tr>
<td><img alt="移动控制器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-move.png?lang=en" /></td>
<td><span><span>拖放控件允许您抓取产品并将其移动到网格当前页面中的另一个位置。</span><span><br /></span></span></td>
</tr>
<tr>
<td><img alt="位置控制器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/control-position.png?lang=en" /></td>
<td><span>确定产品在列表中的位置。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="page-controls-1"><span>页面控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><img alt="选中的复选框" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/checkbox-selected.png?lang=en" /></td>
<td><span><span>使用第一列标题中的复选框选择所有产品或清除所有选择。</span><span>第一行中的控件确定搜索类型，可以设置为包含任何记录，或仅包含已分配或未分配给该类别的记录。</span><span>每行第一列中的复选框标识要添加到类别中的产品。</span><span>选项：</span></span><code>Yes</code><span>/&nbsp;</span><code>No</code><span>/</span><code>Any</code></td>
</tr>
<tr>
<td><span>搜索过滤器</span></td>
<td><span>每列顶部的过滤器控件可用于输入您要包含或从列表中忽略的特定值，具体取决于&ldquo;全选&rdquo;设置。</span></td>
</tr>
<tr>
<td><span>重置过滤器</span></td>
<td><span>清除所有搜索过滤器。</span></td>
</tr>
<tr>
<td><span>搜索</span></td>
<td><span>根据过滤条件搜索目录并显示结果。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Thu, 29 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2修改类别]]></title>
      <link>https://www.360magento.com/blog/Modify-a-category/</link>
      <description><![CDATA[<p><span><span>类别建立后，可以对其进行编辑、移动到类别树中的其他位置或从目录中删除。</span><span>如果您的目录是实时的，请首先考虑更改可能如何影响该类别中任何现有产品的链接。</span><span>例如，如果您的产品 URL 包含类别路径，并且类别名称已更改，则指向该类别中产品的任何现有链接都将被破坏。</span><span>为避免此问题，您可以将目录配置为在 URL 键更改时自动创建永久重定向。</span><span>您还可以使用 URL 重写工具将流量从旧 URL 重定向到新 URL。</span></span></p>
<h2 id="move-a-category"><span>移动类别</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>要移动类别，请将该类别拖放到树中的新位置。</span></p>
<p><span>对类别结构的更改会自动保存。</span></p>
</li>
</ol>
<h2 id="delete-a-category"><span>删除类别</span></h2>
<ol>
<li>
<p><span>在类别树中，选择要删除的类别。</span></p>
<p><span>已删除的类别无法恢复，因此请确保在继续之前选择了正确的类别。</span></p>
</li>
<li>
<p><span>单击</span><span>删除类别</span><span>。</span></p>
</li>
<li>
<p><span>当提示确认时，单击</span><span>确定</span><span>。</span></p>
</li>
</ol>
<p><span><span>您还可以从&ldquo;</span><span><span>事件</span></span><span>&rdquo;页面或&ldquo;</span><span><span>类别&rdquo;页面</span></span></span>更新<span><span>与类别关联的事件</span><span>。</span></span></p>]]></description>
      <pubDate>Wed, 28 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别 - 设计设置]]></title>
      <link>https://www.360magento.com/blog/Categories-Design-settings/</link>
      <description><![CDATA[<p><em>设计</em><span><span>部分使您可以控制类别、所有相关产品页面和页面布局的</span><span>外观。</span><span>您可以自定义类别页面及其关联产品以进行促销，或区分类别。</span><span>例如，您可能会为某个品牌或特殊系列产品开发独特的设计，或者针对特定时间段应用更新。</span></span></p>
<p><img alt="类别的设计设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-design.png?lang=en" /></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>当同一产品被分配到多个类别且每个类别的设计设置不同时，建议</span><span>在</span><a href="https://docs.magento.com/user-guide/configuration/catalog/catalog.html#search-engine-optimization"><span>搜索引擎优化配置选项中设置</span></a></span><span>Use Categories Path for Product URLs</span><span><span>&nbsp;=&nbsp;</span><span>。</span><span>要访问此设置，请转到</span><span><span>Stores</span></span><span>&nbsp;&gt;&nbsp;</span><em><span>Settings</span></em><span>&nbsp;&gt;&nbsp;</span><span><span>Configuration</span></span><span>，展开</span><span><span>Catalog</span></span><span>并选择左侧面板下方的</span><span><span>Catalog</span></span><span>，然后展开页面上的</span><span><span>Search Engine Optimization</span></span><span>部分。</span></span><code>Yes</code><span></span><a href="https://docs.magento.com/user-guide/configuration/catalog/catalog.html#search-engine-optimization"><span></span></a><span></span><span><span></span></span><span></span><em><span></span></em><span></span><span><span></span></span><span></span><span><span></span></span><span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
</div>
</div>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>使用父类别设置</span></td>
<td><span><span>允许当前类别继承父类别的设计设置。</span><span>如果使用，设计部分中的所有其他字段将变得不可用。</span><span>选项：</span></span><code>Yes</code><span>/</span><code>&nbsp;No</code></td>
</tr>
<tr>
<td><span>主题</span></td>
<td><span>将自定义主题应用于类别。</span></td>
</tr>
<tr>
<td><span>布局</span></td>
<td><span><span>将不同的布局应用于类别页面。</span><span>选项：</span></span><br /><span>无布局更新</span><span>- 默认情况下，布局更新不适用于类别页面。</span><br /><span>空</span><span><span>- 用于定义您自己的页面布局。</span><span>（需要了解 XML。）</span></span><br /><span>1 列</span><span>- 将单列布局应用于类别页面。</span><br /><span>带左侧栏的2 列</span><span>- 将带有左侧栏的两列布局应用于类别页面。</span><br /><span>带右侧栏的2 列</span><span>- 将带有右侧栏的两列布局应用于类别页面。</span><br /><span>3 列</span><span>- 将三列布局应用于类别页面。</span><br /><span>页面 - 全宽</span><span>- （需要</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/page-builder/introduction.html?lang=en">页面生成器</a><span>) 将 CMS 页面的全角布局应用于类别页面。</span><br /><span>类别 - 全宽</span><span>-（需要页面构建器）将类别页面的全宽布局应用于类别页面。</span><br /><span>产品 - 全宽</span><span>-（需要页面构建器）将产品页面的全宽布局应用于类别页面。</span></td>
</tr>
<tr>
<td><span>自定义布局更新</span></td>
<td><span><span>列出服务器上可用的自定义布局更新文件。</span><span>选择要应用到类别的自定义布局更新。</span></span></td>
</tr>
<tr>
<td><span>将设计应用于产品</span></td>
<td><span>选择后，将自定义设置应用于类别中的所有产品。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="scheduled-design-update"><span>计划的设计更新</span></h2>
<div class="table-container">
<table>
<tbody>
<tr>
<td><img alt="Magento 开源功能" height="20" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/open-source.svg?lang=en" width="20" /><span>Magento 开源所需的替代方法（</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/user-guides/home.html?lang=en#product-editions">了解更多</a><span>）</span></td>
</tr>
</tbody>
</table>
</div>
<p><span>计划的</span><em>设计更新</em><span>部分确定将自定义设计应用于类别页面的日期范围。</span></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>计划更新自/至</span></td>
<td><span>确定将自定义布局应用于类别时的日期范围。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Tue, 27 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别 - 搜索引擎优化设置]]></title>
      <link>https://www.360magento.com/blog/Categories-Search-Engine-Optimization-settings/</link>
      <description><![CDATA[<p><em>搜索引擎优化</em>部分指定搜索引擎用来索引类别的URL 键和元数据字段。尽管一些搜索引擎忽略元关键字，但其他搜索引擎继续使用它们。当前的 SEO 最佳做法是在元标题和元描述中加入高价值关键字。</p>
<p>&nbsp;</p>
<p><img alt="搜索引擎优化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/categories-search-engine-optimization.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th>范围</th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>网址键</span></td>
<td><span>商店视图</span></td>
<td><span><span>确定类别页面的在线地址。</span><span>URL 键被添加到商店的基本 URL，并出现在浏览器的地址栏中。</span><span>在配置中，您可以在产品 URL 中包含或排除类别 URL 键。</span><span>URL 密钥应全部为小写字符，这些字符之间使用非尾随连字符而不是空格。</span><span>不要包含 .html 等后缀，因为它在配置中进行管理。</span></span></td>
</tr>
<tr>
<td><span>元标题</span></td>
<td><span>商店视图</span></td>
<td><span><span>标题出现在浏览器的标题栏和选项卡中，也是搜索引擎结果页面 (SERP) 上的标题。</span><span>元标题对于页面应该是唯一的并且长度为 s。</span></span></td>
</tr>
<tr>
<td><span>元关键字</span></td>
<td><span>商店视图</span></td>
<td><span><span>该类别的相关关键字。</span><span>考虑使用客户可能用来在类别中查找产品的关键字。</span></span></td>
</tr>
<tr>
<td><span>元描述</span></td>
<td><span>商店视图</span></td>
<td><span><span>元描述提供搜索结果列表页面的简要概述。</span><span>理想的长度在 150-160 个字符之间，最多 255 个字符。</span><span>虽然对客户不可见，但一些搜索引擎会在搜索结果页面上包含元描述。</span></span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Mon, 26 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别 - 显示设置]]></title>
      <link>https://www.360magento.com/blog/Categories-Display-settings/</link>
      <description><![CDATA[<p><span><span>显示设置确定哪些内容元素出现在类别页面上以及产品出现的顺序。</span><span>您可以启用 CMS 块，设置类别的锚点状态，并从&ldquo;</span></span><em>显示设置&rdquo;</em><span><span>选项卡管理排序选项。</span><span>有关类别如何反映在店面中的示例，请参阅</span></span>目录导航<span>。</span></p>
<p><img alt="类别的显示设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-display-settings.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>显示模式</span></td>
<td><span><span>确定类别页面上显示的内容元素。</span><span>选项：</span></span><code>Products Only</code><span>/&nbsp;</span><code>Static Block Only</code><span>/</span><code>Static Block and Products</code></td>
</tr>
<tr>
<td><span>锚</span></td>
<td><span><span>设置为 时，</span><span>在分层导航中</span></span><code>Yes</code><span>包括</span><em>按属性筛选部分。</em><span>选项：</span><code>Yes</code><span>/</span><code>No</code></td>
</tr>
<tr>
<td><span>可用产品列表排序依据</span></td>
<td><span>（必需）默认值为</span><code>Position</code><span>、</span><code>Name</code><span>和</span><code>Price</code><span><span>。</span><span>要自定义排序选项，请取消选择&ldquo;</span></span><span>使用所有可用属性</span><span><span>&rdquo;复选框并选择要使用的属性。</span><span>您可以根据需要定义和添加属性。</span></span></td>
</tr>
<tr>
<td><span>默认产品列表排序依据</span></td>
<td><span>（必需）要定义默认</span><em>排序</em><span>方式选项，请取消选择</span><span>使用配置设置</span><span>复选框并选择一个属性。</span></td>
</tr>
<tr>
<td><span>分层导航价格步骤</span></td>
<td><span><span>默认情况下，Commerce 以 10、100 和 1000 的增量显示价格范围，具体取决于列表中的产品。</span><span>要更改价格步长范围，请取消选择</span></span><span>使用配置设置</span><span>复选框。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Sun, 25 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别 - 内容设置]]></title>
      <link>https://www.360magento.com/blog/Categories-Content-settings/</link>
      <description><![CDATA[<p><em>内容</em>设置确定类别页面上显示的任何其他内容。除了类别产品列表之外，页面还可以包含图像、描述和 CMS 块。您可以使用页面构建器内容工具来定义类别描述。</p>
<ol>
<li>
<p><span>在编辑模式下打开类别。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>内容</span><span>部分</span><span>。</span></p>
<p><img alt="分类内容" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-content.png?lang=en" /></p>
</li>
<li>
<p><span>在</span><span>描述</span><span>区域的右上角，单击</span><span>使用页面构建器编辑</span><span>。</span></p>
</li>
<li>
<p><span>使用</span>页面构建器<span>&nbsp;内容工具</span>编辑任何现有文本<span>并添加其他内容（如果需要）。</span></p>
</li>
</ol>
<h2 id="page-builder-preview"><span>页面构建器预览</span></h2>
<p><span><span>当您展开</span><span>现有类别​​的</span></span><em>内容部分（其中包含使用页面构建器创建的内容）时，它会显示</em><span></span><span>描述</span><span><span>内容的预览，就像它会出现在类别页面中一样。</span><span>单击内容区域以打开 Page Builder 工作区，您可以在其中进行任何需要的更新。</span></span></p>
<p><img alt="说明预览" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/pb-product-category-content-preview.png?lang=en" /></p>
<p><span><span>默认情况下，为产品和类别表单启用此内容预览。</span><span>如果性能因加载预览而受到影响，您可以在</span></span>内容管理配置<span>设置中禁用预览。</span></p>
<h2 id="add-the-category-description-in-the-editor"><span>在编辑器中添加类别描述</span></h2>
<p><span><span>仅在文本框中输入纯 ASCII 字符。</span><span>如果从文字处理器粘贴文本，请先将其保存为纯 .TXT 文件以删除任何不可见的控制字符。</span></span></p>
<p><span>有关详细信息，请参阅</span>使用编辑器<span>。</span></p>
<ol>
<li>
<p><span>在编辑模式下打开类别。</span></p>
</li>
<li>
<p><span>向下滚动并展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>内容</span><span>部分</span><span>。</span></p>
<p><img alt="分类内容" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-content-ce.png?lang=en" /></p>
</li>
<li>
<p><span>输入类别</span><span>描述</span><span>并使用</span>编辑器工具栏<span>根据需要设置格式。</span></p>
<p><span>您可以拖动右下角来更改文本框的高度。</span></p>
</li>
</ol>
<h2 id="add-a-cms-block-to-the-category-page"><span>将 CMS 块添加到类别页面</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在类别树中，选择要编辑的类别。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>内容</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
</li>
<li>
<p><span>对于</span><span>添加 CMS 块</span><span>，选择要添加的块。</span></p>
</li>
<li>
<p><span>展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>显示</span><span>设置</span><span>部分。</span></p>
</li>
<li>
<p><span>将</span><span>显示模式</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Static block only</code></li>
<li><code>Static block and products</code></li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存</span><span>并查看店面上的块显示（需要刷新缓存）。</span></p>
</li>
</ol>
<h2 id="content-settings-reference"><span>内容设置参考</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>环境</span></th><th>范围</th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>分类图片</span></td>
<td><span>商店视图</span></td>
<td><span><span>指定类别页面顶部的图像。</span><span>方法：</span></span><br /><br /><span>上传</span><span>- 将图像文件从您的本地计算机上传到图库并将其用作类别图像。</span><br /><br /><span>从图库中选择</span><span>- 提示您从图库中选择现有图像。</span><br /><br /><img alt="页面生成器相机图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-camera.png?lang=en" /><span>- 将图像文件拖到相机图块或浏览到图像并从本地文件系统中选择它。</span></td>
</tr>
<tr>
<td><span>描述</span></td>
<td><span>商店视图</span></td>
<td><span>指定出现在类别页面上的描述。</span><br /><br /><span>使用页面构建器编辑</span><span>- 打开</span>页面构建器工作区<span>，您可以在其中编辑描述。</span><br /><br /><span>显示/隐藏编辑器</span><span>- 在所见即所得编辑器和 HTML 模式之间切换显示。</span></td>
</tr>
<tr>
<td><span>添加 CMS 块</span></td>
<td><span>商店视图</span></td>
<td><span>将现有的</span>CMS 块<span>添加到类别页面。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Sat, 24 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2创建类别]]></title>
      <link>https://www.360magento.com/blog/Create-categories/</link>
      <description><![CDATA[<p>目录的类别结构就像一棵倒置的树，根在顶部。树的每个部分都可以展开和折叠。任何禁用或隐藏的类别都显示为灰色。第一级（根以下）的类别通常作为选项出现在主菜单中。根据配置中设置的最大菜单深度，您可以根据需要创建任意数量的附加子类别。可以将类别拖放到树中的其他位置。类别 ID 号显示在页面顶部类别名称后的括号中。</p>
<p><span>对于有多个</span>商店<span>的网站，您可以为每个商店创建不同的根类别，定义用于</span>顶部导航<span>的类别集。</span></p>
<p><img alt="类别树" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-selected.png?lang=en" /></p>
<h2 id="best-practices"><span>最佳实践</span></h2>
<p><span>在规划和创建类别时使用这些最佳实践。</span></p>
<h3 id="category-structure"><span>类别结构</span></h3>
<p><span><span>主菜单中类别的结构会影响客户体验和性能。</span><span>作为最佳实践，您应该确定一个包罗万象的顶级类别，并避免使用相同名称的其他类别。</span><span>例如，而不是在不同部门下组织多个&ldquo;儿童&rdquo;类别，例如</span></span><code>Clothing/Kids</code><span>,&nbsp;</span><code>Shoes/Kids</code><span>,&nbsp;</span><code>Accessories/Kids</code><span><span>.&nbsp;</span><span>做顶层的父分类</span></span><code>Kids</code><span><span>，然后根据需要在下面创建子分类会更高效。</span><span>与类别结构保持一致，并对目录中的所有产品类型使用相同的方法。</span></span></p>
<h3 id="business-rules-and-automation"><span>业务规则和自动化</span></h3>
<p><span><span>在使用业务逻辑在目录页面上显示类似项目或设置个性化促销、自动化流程或搜索条件时，请考虑类别结构和可用属性值。</span><span>例如，如果您将&ldquo;polo&rdquo;指定为父类别，则结果可能包括混合的性别和不适合年龄的产品。</span><span>但是，如果您匹配 Polo 衫的特定子类别，则结果范围更窄并且可能会吸引特定客户。</span><span>当与针对特定客户的其他属性值结合使用时，结果可能会更加具体。</span><span>考虑引用特定类别路径时必须过滤和检索的产品数量。</span><span>结果的差异可能是巨大的。</span><span>考虑以下类别路径返回的不同结果：</span></span></p>
<ul>
<li><code>[Category: All Products/Shirts/Father's Day/Polos/Sale]</code></li>
<li><code>[Category Path: Men/Shirts/Polos]</code></li>
<li><code>[Child Category: Polos]</code></li>
</ul>
<p><span>明确定义分类关系很重要，例如：</span></p>
<ul>
<li><span>父类</span></li>
<li><span>子类别</span></li>
<li><span>类别路径</span></li>
</ul>
<p><span>还要定义任何关联的关键字和属性，例如：</span></p>
<ul>
<li><span>可用性</span></li>
<li><span>销售价格</span></li>
<li><span>品牌</span></li>
<li><span>尺寸</span></li>
<li><span>颜色</span></li>
</ul>
<h2 id="step-1%3A-create-a-category"><span>第 1 步：创建类别</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>设置</span><span>商店视图</span><span>以确定新类别的可用位置。</span></p>
</li>
<li>
<p><span>在类别树中，选择新类别的父类别。</span></p>
<p><span>父级比新类别高一级。</span></p>
<p><span>如果您从头开始，没有任何数据，则列表中可能只有两个类别：</span><em>默认类别</em><span>（根类别）和</span><em>示例类别</em></p>
</li>
<li>
<p><span>单击</span><span>添加子类别</span><span>。</span></p>
</li>
</ol>
<h2 id="step-2%3A-complete-the-basic-information"><span>第二步：填写基本信息</span></h2>
<ol>
<li>
<p><span>如果您希望该类别在商店中立即可用，请将</span><span>启用类别</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span></span>要在顶部导航<span><span>中包含该类别</span><span>，请将</span></span><span>Include in Menu</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>输入</span><span>类别名称</span><span>。</span></p>
<p><img alt="基本品类信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-categories-currently-active.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
</li>
</ol>
<h2 id="step-3%3A-complete-the-category-content"><span>第三步：完成分类内容</span></h2>
<ol>
<li>
<p><span><span>展开</span><span><span>内容</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="分类内容" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-content.png?lang=en" /></p>
</li>
<li>
<p><span>要在页面顶部显示</span><span>类别图像</span><span>，您可以上传自己的图像或使用</span>媒体存储<span>中存在的图像。</span></p>
<ul>
<li>
<p><span>要上传您自己的图片，请单击</span><span>上传</span><span>并选择您想要代表该类别的图片。</span></p>
</li>
<li>
<p><span>要使用媒体存储中的图像，请单击</span><span>从图库</span><span>中选择并选择您要代表该类别的图像。</span></p>
</li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>在媒体库中，您还可以使用</span>Adob​​e Stock 集成<span>通过单击</span><span>搜索 Adob​​e Stock</span><span>来查找合适的图像。</span></p>
</div>
</div>
</li>
<li>
<p><span>对于</span><span>Description</span><span>，输入您希望在类别登陆页面上显示的文本或其他内容。</span></p>
</li>
<li>
<p><span><span>要在类别登陆页面上包含内容块，请选择</span><span>要显示的</span></span><span>CMS 块。</span><span></span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
</li>
</ol>
<h2 id="step-4%3A-complete-the-display-settings"><span>第四步：完成显示设置</span></h2>
<ol>
<li>
<p><span>展开</span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>显示</span><span>设置</span><span>部分。</span></p>
<p><img alt="显示设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-display-settings.png?lang=en" /></p>
</li>
<li>
<p><span>将</span><span>显示模式</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Products Only</code></li>
<li><code>Static Block Only</code></li>
<li><code>Static Block and Products</code></li>
</ul>
</li>
<li>
<p><span>如果希望分类页面包含</span><em><code>Filter by Attribute</code></em><span>分层导航部分，请将</span><span>Anchor</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>可用产品列表排序</span><span>依据选项，选择一个或多个可用值以供客户对列表进行排序。</span></p>
<p><span><span>默认情况下，包括所有可用值。</span><span>取消选中</span></span><span>全部使用</span><span><span>复选框以更改选择。</span><span>例如，这些值可能包括：</span></span></p>
<ul>
<li><code>Position</code></li>
<li><code>Product Name</code></li>
<li><code>Price</code></li>
</ul>
</li>
<li>
<p><span>要设置类别的默认排序顺序，请选择</span><span>默认产品列表排序</span><span>依据值。</span></p>
</li>
<li>
<p><span>要更改默认的分层导航</span>价格步长<span>设置，请执行以下操作：</span></p>
<ul>
<li>
<p><span>取消选中</span><span>使用配置设置</span><span>复选框。</span></p>
</li>
<li>
<p><span>输入要用作分层导航的增量价格步骤的值。</span></p>
</li>
</ul>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
</li>
</ol>
<h2 id="step-5%3A-complete-the-search-engine-optimization-settings"><span>第五步：完成搜索引擎优化设置</span></h2>
<ol>
<li>
<p><span><span>展开</span><span><span>搜索引擎优化设置</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="搜索引擎优化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-categories-search-engine-optimization.png?lang=en" /></p>
<p><span>有关这些选项的更多信息，请参阅</span>搜索引擎优化<span>。</span></p>
</li>
<li>
<p><span><span>完成类别</span><span>的以下</span></span>元数据：<span></span></p>
<ul>
<li><span>元标题</span></li>
<li><span>元关键字</span></li>
<li><span>元描述</span></li>
</ul>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
</li>
</ol>
<h2 id="step-6%3A-choose-the-products-in-category"><span>第6步：选择类别中的产品</span></h2>
<ol>
<li>
<p><span><span>展开</span><span><span>类别</span></span><span>部分中</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>的产品。</span><span><span></span></span><span></span></p>
<p><img alt="产品类别" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-categories-products-in-category.png?lang=en" /></p>
</li>
<li>
<p><span>根据需要使用</span>过滤器<span>来查找产品。</span></p>
<p><span>要显示尚未包含在该类别中的所有记录，请将第一列中的记录选择器设置为</span><code>No</code><span>，然后单击</span><span>Search</span><span>。</span></p>
</li>
<li>
<p><span>在第一列中，选中要包含在类别中的每个产品的复选框。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>并继续。</span></p>
</li>
</ol>
<h2 id="step-7%3A-set-the-category-permissions"><span>第七步：设置分类权限</span></h2>
<ol>
<li>
<p><span><span>展开</span><span><span>类别权限</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
</li>
<li>
<p><span><span>对于多站点安装，请选择</span><span>类别权限适用的</span></span><span>网站。</span><span></span></p>
</li>
<li>
<p><span><span>选择</span><span>类别权限适用的</span></span><span>客户组。</span><span></span></p>
<p><img alt="Adobe Commerce 的 B2B" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/b2b.svg?lang=en" /><span>（仅限</span>Adob​​e Commerce 的 B2B<span>）如果需要，您可以选择</span><span>共享目录</span><span>。</span></p>
</li>
<li>
<p><span>根据需要设置以下权限：</span></p>
<ul>
<li><span>浏览类别</span></li>
<li><span>显示产品价格</span></li>
<li><span>添加到购物车</span></li>
</ul>
</li>
<li>
<p><span>要添加另一个权限规则，请单击</span><span>&ldquo;新建权限&rdquo;</span><span>并重复该过程。</span></p>
<p><img alt="分类权限" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-create-permissions.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-8%3A-complete-the-design-settings"><span>第八步：完成设计设置</span></h2>
<ol>
<li>
<p><span><span>展开</span><span><span>设计</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
</li>
<li>
<p><span>根据需要设置设计设置：</span></p>
<ul>
<li>
<p><span>（仅限</span>Adob​​e Commerce 的 B2B<span>）要将父类别设计设置应用于此类别，请将</span><span>&ldquo;使用父类别设置&rdquo;设置</span><span>为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span><span>要更改类别页面的设计，请选择</span><span>您要应用的</span></span><span>主题。</span><span></span></p>
</li>
<li>
<p><span><span>要更改类别页面的列布局，请选择</span><span>您要应用的</span></span><span>布局。</span><span></span></p>
</li>
<li>
<p><span>要输入自定义代码，请在</span><span>布局更新 XML</span><span>框中输入有效的 XML 代码。</span></p>
</li>
<li>
<p><span>要对产品页面使用相同的设计，请将</span><span>Apply Design to Products</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
<p><img alt="设计设定" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-design.png?lang=en" /></p>
</li>
<li>
<p><img alt="Magento 开源" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/open-source.svg?lang=en" /><span>（仅限 Magento Open Source）要安排特定时间段的设计更新，请执行以下操作：</span></p>
<ul>
<li>
<p><span>展开</span><em>计划设计更新</em><span>部分。</span></p>
</li>
<li>
<p><span>使用日历 (&nbsp;</span><img alt="日历图标" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-calendar.png?lang=en" /><span><span>) 选择计划更新</span><span><span>的</span></span></span><span>起止</span><span><span>日期</span><span>。</span></span><span><span></span></span><span></span></p>
</li>
</ul>
<p><img alt="计划的设计更新" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-scheduled-design-update.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Fri, 23 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2隐藏类别]]></title>
      <link>https://www.360magento.com/blog/Hidden-categories/</link>
      <description><![CDATA[<p><span><span>有很多方法可以使用隐藏类别。</span><span>您可能希望为自己的内部目的创建额外的类别级别，但只向您的客户显示更高级别的类别。</span><span>或者，您可能希望链接到导航菜单中未包含的类别。</span></span></p>
<h2 id="create-hidden-categories"><span>创建隐藏类别</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在类别树中，选择要隐藏的类别并执行以下操作：</span></p>
<ul>
<li><span><span>设置</span><span>为</span></span><span>活动</span><span></span><code>Yes</code><span>。</span></li>
<li><span>将</span><span>&ldquo;包含在菜单</span><span>中&rdquo;设置为</span><code>No</code><span>。</span></li>
</ul>
</li>
<li>
<p><span>在</span><span>Display Settings</span><span>部分，将</span><span>Anchor</span><span>设置为</span><code>No</code><span>。</span></p>
<p><img alt="隐藏分类" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/hidden-categories.png?lang=en" /></p>
<p><span>隐藏类别处于活动状态，但不会出现在顶部菜单或分层导航中。</span></p>
</li>
<li>
<p><span>为每个隐藏的子类别完成以下设置以创建子类别：</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>虽然该类别是隐藏的，但您可以在其下创建子类别并激活它们。</span></p>
</div>
</div>
<ul>
<li><span>将</span><span>启用类别</span><span>设置为</span><code>Yes</code><span>。</span></li>
<li><span>在</span><span>Display Settings</span><span>部分，将</span><span>Anchor</span><span>设置为</span><code>Yes</code><span>。</span></li>
</ul>
<p><span>作为活动类别，您现在可以从商店的其他地方链接到它们，但它们不会出现在菜单中。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Thu, 22 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2根类别和层次结构]]></title>
      <link>https://www.360magento.com/blog/Root-category-and-hierarchy/</link>
      <description><![CDATA[<p>主菜单中的产品由分配给商店的根目录决定。根类别基本上是类别树中主菜单的容器。您可以创建包含一组全新产品的根目录或从现有根目录复制产品。根类别可以分配给当前商店或同一网站中的任何其他商店。</p>
<h2 id="step-1%3A-create-a-root-category"><span>第 1 步：创建根类别</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左侧，单击</span><span>添加根类别</span><span>。</span></p>
<p><img alt="新的根类别" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-root-ee.png?lang=en" /></p>
</li>
<li>
<p><span>分配</span><span>类别名称</span><span>。</span></p>
<p><span>您选择的名称最初分配给所有商店视图。</span></p>
</li>
<li>
<p><span>如果要将产品从当前目录添加到目录，请执行以下操作：</span></p>
<ul>
<li>
<p><span><span>展开</span><em><span>类别</span></em><span>部分中</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>的产品。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>使用</span>搜索过滤器<span>查找您想要的产品，然后选中您要复制到新目录中的每个产品的复选框。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h2 id="step-2%3A-build-out-the-main-menu"><span>第 2 步：构建主菜单</span></h2>
<ol>
<li>
<p><span>在左侧，选择您在上一步中创建的新根类别。</span></p>
</li>
<li>
<p><span>单击</span><span>添加子类别</span><span>并按照说明为主菜单创建</span>类别结构<span>。</span></p>
</li>
</ol>
<h2 id="step-3%3A-assign-the-root-category-to-the-store"><span>第 3 步：将根类别分配给商店</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>商店</span><span>&gt;</span><em>设置</em><span>&gt;</span><span>所有商店</span><span>。</span></p>
</li>
<li>
<p><span>在网格的</span><em>Stores</em><span>列中，单击要分配新目录的商店。</span></p>
</li>
<li>
<p><span>将</span><span>根类别</span><span>设置为您创建的新根类别。</span></p>
</li>
<li>
<p><span><span>确保商店已</span><span>分配</span></span><span>默认商店视图。</span><span></span></p>
<p><span>该商店必须至少有一个</span>商店视图<span>。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存商店</span><span>。</span></p>
</li>
<li>
<p><span>要验证商店是否有新目录，请执行以下操作：</span></p>
<ul>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
<p><span>任何复制到新目录的产品都会出现在网格中。</span></p>
</li>
<li>
<p><span>访问店面以验证新目录和主菜单是否正常工作。</span></p>
</li>
</ul>
</li>
</ol>]]></description>
      <pubDate>Wed, 21 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2管理搜索词]]></title>
      <link>https://www.360magento.com/blog/Manage-search-terms/</link>
      <description><![CDATA[<p>搜索词的登陆页面可以是内容页面、类别页面、产品详细信息页面，甚至是不同站点上的页面。</p>
<p>使用搜索词来捕获常见的拼写错误并将它们重定向到适当的页面。例如，如果您销售锻铁庭院家具，您就会知道很多人将术语拼错为<em>rod iron</em>，甚至是<em>rot iron</em>。您可以输入每个拼写错误的单词作为搜索词，并使它们成为<em>锻铁的</em>同义词。即使单词拼写错误，搜索也会定向到锻铁页面。</p>
<p><span><span>您还可以通过检查客户用于在您的商店中查找产品的搜索词来了解他们正在寻找什么。</span><span>如果有足够多的人寻找不在您的目录中的产品，则可能表明存在销售机会。</span><span>同时，您可以将他们重定向到目录中的其他产品，而不是让他们空手而归。</span></span></p>
<h2 id="add-search-terms"><span>添加搜索词</span></h2>
<p><span>当您学习人们用来在您的商店中搜索的新词时，您可以将它们添加到您的搜索词列表中，以将人们引导至您的目录中最匹配的产品。</span></p>
<p><img alt="搜索词网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-terms.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>柱子</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>搜索查询</span></td>
<td><span>用于执行搜索的查询。</span></td>
</tr>
<tr>
<td><span>店铺</span></td>
<td><span>应用搜索查询的商店。</span></td>
</tr>
<tr>
<td><span>结果</span></td>
<td><span>查询找到的结果数。</span></td>
</tr>
<tr>
<td><span>用途</span></td>
<td><span>使用次数。</span></td>
</tr>
<tr>
<td><span>重定向网址</span></td>
<td><span>执行搜索后用户被重定向到的目标页面的 URL。</span></td>
</tr>
<tr>
<td><span>建议条款</span></td>
<td><span>确定查询结果是否显示建议的术语。</span></td>
</tr>
<tr>
<td><span>动作</span></td>
<td><span>在编辑模式下打开产品。</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="add-a-search-term"><span>添加搜索词</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>营销</span><span>&gt;</span><em>搜索引擎优化和搜索</em><span>&gt;</span><span>搜索词</span><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>添加新搜索词</span><span>并执行以下操作：</span></p>
<p><img alt="搜索词一般信息" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-terms-information.png?lang=en" /></p>
<ul>
<li>
<p><span><span>在</span><span>&ldquo;</span><span><span>搜索查询&rdquo;框中的&ldquo;</span></span></span><em>一般信息</em><span>&rdquo;下，输入要添加为新搜索词的词或短语。</span><span><span></span></span><span></span></p>
</li>
<li>
<p><span>如果您的商店提供多种语言，请选择适用的</span><span>商店</span><span>视图。</span></p>
</li>
<li>
<p><span>要将搜索结果重定向到您商店中的另一个页面或另一个网站，请在</span><span>重定向 URL</span><span>字段中输入目标页面的完整 URL。</span></p>
</li>
<li>
<p><span>如果您希望在搜索未返回任何结果时将该词用作建议，请将</span><span>&ldquo;在建议词中显示&rdquo;</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，点击</span><span>保存搜索</span><span>。</span></p>
</li>
</ol>
<h2 id="edit-a-search-term"><span>编辑搜索词</span></h2>
<ol>
<li>
<p><span>在</span><em>搜索</em><span>词网格中，单击任何记录的行以在编辑模式下打开搜索词。</span></p>
</li>
<li>
<p><span>进行必要的更改。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存搜索</span><span>。</span></p>
</li>
</ol>
<h2 id="delete-a-search-term"><span>删除搜索词</span></h2>
<p><span>有两种删除搜索词的方法&mdash;&mdash;从网格中和在编辑页面上。</span></p>
<p><span>方法 1：</span><span>在</span><em>搜索词</em><span>网格中</span></p>
<ol>
<li>
<p><span>在列表中，选中要删除的术语的复选框。</span></p>
</li>
<li>
<p><span>在列表的左上角，将</span><span>Actions</span><span>设置为</span><code>Delete</code><span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>提交</span><span>。</span></p>
</li>
</ol>
<p><span>方法 2：</span><span>在&ldquo;</span><em>编辑搜索词</em><span>&rdquo;页面上</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>营销</span><span>&gt;</span><em>搜索引擎优化和搜索</em><span>&gt;</span><span>搜索词</span><span>。</span></p>
</li>
<li>
<p><span>找到要删除的搜索词并在编辑模式下打开它。</span></p>
</li>
<li>
<p><span>单击</span><span>删除搜索</span><span>。</span></p>
</li>
<li>
<p><span>要确认该操作，请单击</span><span>确定</span><span>。</span></p>
</li>
</ol>
<h2 id="popular-search-terms"><span>热门搜索词</span></h2>
<p><span>商店页脚中的</span><em>搜索</em><span><span>词链接显示您商店的访问者使用的搜索词，按受欢迎程度排名。</span><span>搜索词以</span></span><em>标签云</em><span>格式出现，其中文本的大小表示该词的流行程度。</span></p>
<p><span><span>默认情况下，Popular Search Terms 作为搜索引擎优化工具启用，但与目录搜索过程没有直接联系。</span><span>由于&ldquo;搜索词&rdquo;页面由搜索引擎编入索引，因此页面上的任何词都有助于提高您的搜索引擎排名和商店的知名度。</span><span>热门搜索词页面的 URL 是：</span></span><code>mystore.com/search/term/popular/</code></p>
<p><img alt="示例店面 - 热门搜索词" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/store-front-search-terms-yoga-pants.png?lang=en" /></p>
<p><span>配置热门搜索词：</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>搜索引擎优化</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="目录配置-搜索引擎优化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-search-engine-optimization_c1.png?lang=en" /></p>
<p><span><span>有关这些选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span><a href="https://docs.magento.com/user-guide/configuration/catalog/catalog.html#search-engine-optimization">搜索引擎优化</a><span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>根据需要设置</span><span>热门搜索</span><span>词。</span></p>
<p><span>如果需要，清除</span><span>使用系统值</span><span>复选框以更改此设置。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/search/search-configuration.html?lang=en">您可以进一步配置流行目录搜索</a><span><span>的缓存</span><span>。</span></span></p>
</div>
</div>
<h2 id="search-synonyms"><span>搜索同义词</span></h2>
<p><span>提高</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/search/search-configuration.html?lang=en">目录搜索</a><span><span>效率的一种方法是包括人们可能用来描述同一项目的不同术语。</span><span>您不想因为有人在寻找</span></span><em>沙发</em><span>而失去销售机会，而您的产品被列为</span><em>沙发</em><span>。</span><em>您可以通过输入sofa</em><span>、</span><em>davenport</em><span>和</span><em>loveseat</em><span>作为</span><em>couch</em><span><span>的同义词来捕获更广泛的搜索词</span><span>，并将它们引导至同一登陆页面。</span></span></p>
<p><span>Adobe Commerce 支持两种不同的同义词管理解决方案：</span></p>
<ul>
<li><span>Live Search&nbsp;</span><a href="https://experienceleague.adobe.com/docs/commerce-merchant-services/live-search/live-search-admin/synonyms/synonyms.html?lang=en">Synonyms</a><span>功能适用于安装了 Live Search 的 Adob​​e Commerce 安装。</span></li>
<li><span>标准搜索同义词功能（如本页所述）对于所有 Adob​​e Commerce 安装都是开箱即用的。</span></li>
</ul>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span><em><span>标准搜索同义词仅</span></em></span><span>具有开箱即用的支持</span></span><code>name</code><span>和</span><code>sku</code><span><span>产品属性</span><span>。</span></span><span><em><span></span></em></span><span></span></p>
</div>
</div>
<p><img alt="示例店面 - 具有同义词的搜索结果" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-results-synonyms.png?lang=en" /></p>
<h3 id="create-a-synonym-group"><span>创建同义词组</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>营销</span><span>&gt;</span><em>搜索引擎优化和搜索</em><span>&gt;</span><span>搜索同义词</span><span>。</span></p>
<p><span>出现</span><em>搜索同义词</em><span><span>网格。</span><span>如果这是您第一次使用搜索同义词，则网格是空的。</span></span></p>
<p><img alt="搜索同义词网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-synonyms-grid-empty.png?lang=en" /></p>
</li>
<li>
<p><span>单击</span><span>新建同义词组</span><span>并执行以下操作：</span></p>
<p><img alt="新搜索同义词组" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-synonym-group-new.png?lang=en" /></p>
<ul>
<li>
<p><span>将</span><span>范围</span><span>设置为应用同义词的商店视图。</span></p>
</li>
<li>
<p><span><span>输入组中的每个同义词，以逗号分隔。</span><span>选择人们可能用作搜索条件的词。</span><span>例如：</span></span></p>
<ul>
<li><code>sweatshirt, sweat shirt, hoodie, fleece</code></li>
<li><code>cell phone, mobile phone, smart phone</code></li>
<li><code>couch, sofa, davenport</code></li>
<li><code>wrought iron, rot iron, rod iron</code></li>
</ul>
</li>
<li>
<p><span>要将这些同义词与具有相同范围的其他同义词合并到一个组中，请选中</span><span>合并现有同义词</span><span>复选框。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存同义词组</span><span>。</span></p>
<p><img alt="搜索同义词组网格 - 已保存的组" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-synonym-group-grid.png?lang=en" /></p>
</li>
</ol>
<h3 id="edit-a-synonym-group"><span>编辑同义词组</span></h3>
<ol>
<li>
<p><span>在</span><em>搜索同义词</em><span>网格中，单击任何记录的行以在编辑模式下打开同义词组。</span></p>
</li>
<li>
<p><span>进行必要的更改。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存同义词组</span><span>。</span></p>
</li>
</ol>
<h3 id="delete-a-synonym-group"><span>删除同义词组</span></h3>
<p><span>有两种删除同义词组的方法&mdash;&mdash;从网格中和在编辑页面上。</span></p>
<p><span>方法 1：</span><span>在搜索同义词网格中</span></p>
<ol>
<li>
<p><span>在&ldquo;</span><em>搜索同义词</em><span>&rdquo;网格中，选中要删除的组的复选框。</span></p>
</li>
<li>
<p><span>在列表的左上角，将</span><span>Actions</span><span>设置为</span><code>Delete</code><span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>提交</span><span>。</span></p>
</li>
</ol>
<p><span>方法 2：</span><span>在&ldquo;编辑同义词组&rdquo;页面上</span></p>
<ol>
<li>
<p><span>在搜索同义词网格中，单击任何记录的行以在编辑模式下打开同义词组。</span></p>
</li>
<li>
<p><span>单击</span><span>删除同义词组</span><span>。</span></p>
</li>
<li>
<p><span>出现提示时，确认删除组。</span></p>
</li>
</ol>
<h2 id="search-terms-report"><span>搜索字词报告</span></h2>
<p><span><span>搜索词报告显示每个词的结果数，以及该词被使用的次数（点击）。</span><span>报告数据可以按术语、商店、结果和命中率进行过滤，并导出以供进一步分析。</span></span></p>
<h3 id="view-the-report"><span>查看报告</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>报告</span><span>&gt;</span><em>营销</em><span>&gt;</span><span>搜索词</span><span>。</span></p>
</li>
<li>
<p><span>根据需要使用控件过滤报告。</span></p>
<p><img alt="搜索字词报告" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-terms-report.png?lang=en" /></p>
</li>
</ol>]]></description>
      <pubDate>Tue, 20 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2配置目录搜索]]></title>
      <link>https://www.360magento.com/blog/Configure-catalog-search/</link>
      <description><![CDATA[<p>目录搜索配置有两种变体。第一种方法描述了安装Live Search时的可用设置。第二种方法描述了原生 Adob​​e Commerce 与Elasticsearch的配置设置。</p>
<p>有关每个目录搜索配置选项的信息，请参阅<em>配置参考</em>中的<em>Elasticsearch 建议和推荐设置</em>。</p>
<h2 id="method-1%3A-adobe-commerce-with-live-search"><span>方法 1：带有实时搜索的 Adob​​e Commerce</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>目录搜索</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="用于实时搜索的目录搜索" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-search-live-search.png?lang=en" /></p>
<p><span>有关这些选项的更多信息，请参阅</span>实时搜索的目录搜索<span>。</span></p>
</li>
<li>
<p><span>要限制搜索查询文本的长度和字数，请为</span><span>Minimum Query Length</span><span>和</span><span>Maximum Query Length</span><span>设置一个值。</span></p>
</li>
<li>
<p><span>要限制要缓存的热门搜索结果数量以加快响应速度，请为</span><span>Number of top search results to cache</span><span>设置数量。</span></p>
<p><span>默认值为</span><code>100</code><span><span>。</span><span>输入值</span></span><code>0</code><span>第二次输入时缓存所有搜索词和结果。</span></p>
</li>
<li>
<p><span></span>要更改可用于店面弹出窗口<span><span>中返回结果的最大行数，请</span><span>输入不同的</span></span><span>自动完成限制</span><span>值。</span></p>
<p><span><span>限制行数可提高搜索性能并减小返回列表的大小。</span><span>默认值为</span></span><code>8</code><span>行。</span></p>
</li>
</ol>
<h2 id="method-2%3A-commerce-with-elasticsearch"><span>方法 2：使用 Elasticsearch 进行商务</span></h2>
<h3 id="step-1%3A-configure-general-search-options"><span>第 1 步：配置常规搜索选项</span></h3>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>在 ElasticSearch 中，没有对后缀搜索的开箱即用支持。</span><span>例如，如果关键字仅包含 SKU 的末尾部分，则按 SKU 搜索可能不会返回预期的结果。</span></span></p>
</div>
</div>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>目录搜索</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="弹性搜索设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/elasticsearch-1.png?lang=en" /></p>
<p><span><span>有关这些选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span>Adob​​e Commerce with Elasticsearch<span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>要限制搜索查询文本的长度和字数，请为</span><span>Minimum Query Length</span><span>和</span><span>Maximum Query Length</span><span>设置一个值。</span></p>
<div class="extension important">
<div><span><span>重要的</span></span></div>
<div>
<p><span><span>为这个最小和最大范围设置的值必须与 Elasticsearch 搜索引擎配置中设置的相应范围兼容。</span><span>例如，如果您在 Commerce 中设置这些值</span></span><code>2</code><span>，</span><code>300</code><span>请更新搜索引擎中的相应值。</span></p>
</div>
</div>
</li>
<li>
<p><span>要限制要缓存的热门搜索结果数量以加快响应速度，请为</span><span>Number of top search results to cache</span><span>设置数量。</span></p>
<p><span>默认值为</span><code>100</code><span><span>。</span><span>输入值</span></span><code>0</code><span>第二次输入时缓存所有搜索词和结果。</span></p>
</li>
<li>
<p><span>如果要启用或禁用产品 EAV 索引器，请设置</span><span>启用 EAV 索引器</span><span>。</span></p>
<p><span>此功能可提高索引编制速度并限制索引器被第三方扩展使用。</span></p>
</li>
<li>
<p><span>要限制为搜索自动完成显示的搜索结果的最大数量，请为</span><span>Autocomplete Limit</span><span>设置一个数量。</span></p>
<p><span><span>限制此数量可提高搜索性能并减小显示的列表大小。</span><span>默认值为</span></span><code>8</code><span>。</span></p>
</li>
</ol>
<h3 id="step-2%3A-configure-the-elasticsearch-connection"><span>第 2 步：配置 Elasticsearch 连接</span></h3>
<div class="extension important">
<div><span><span>重要的</span></span></div>
<div>
<p><span>安装或升级 Commerce 时配置了</span><span>Search Engine</span><span>、</span><span>Elasticsearch Server Hostname</span><span>、</span><span>Elasticsearch Server Port</span><span>、</span><span>Elasticsearch Index Prefix</span><span>、</span><span>Enable Elasticsearch HTTP Auth</span><span>和</span><span>Elasticsearch Server Timeout</span><span><span>字段。</span><span>只有在升级或修改 Elasticsearch 时才应更改这些值。</span></span></p>
</div>
</div>
<p><img alt="弹性搜索连接设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/elasticsearch-2.png?lang=en" /></p>
<ol>
<li>
<p><span>对于</span><span>搜索引擎</span><span>，接受默认值</span><code>Elasticsearch 7</code><span>。</span></p>
<p><span>所有 Commerce 安装都需要 Elasticsearch 7.6.x。</span></p>
</li>
<li>
<p><span>对于</span><span>Elasticsearch Server Hostname</span><span>，接受安装 Commerce 时配置的默认值。</span></p>
<p><span>在此示例中，默认值为</span><code>elasticsearch.internal</code><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>Elasticsearch Server Port</span><span>，接受安装 Commerce 时配置的默认值。</span></p>
<p><span>在此示例中，默认值为</span><code>9200</code><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>Elasticsearch Index Prefix</span><span>，输入前缀以标识 Elasticsearch 索引。</span></p>
<p><span>默认值为</span><code>magento2</code><span>。</span></p>
</li>
<li>
<p><span>要使用 HTTP 身份验证提示输入用户名和密码以访问 Elasticsearch Server，请将</span><span>启用 Elasticsearch HTTP</span><span>身份验证设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>Elasticsearch Server Timeout</span><span>，输入系统超时前的秒数。</span></p>
<p><span>默认值为</span><code>15</code><span>。</span></p>
</li>
<li>
<p><span>要验证配置，请单击</span><span>测试连接</span><span>。</span></p>
</li>
</ol>
<h3 id="step-3%3A-configure-suggestions-and-recommendations"><span>第三步：配置建议和建议</span></h3>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>搜索建议和建议会影响服务器性能。</span></p>
</div>
</div>
<ol>
<li>
<p><span>要提供建议，请将</span><span>启用搜索建议</span><span>设置为</span><code>Yes</code><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>对于</span><span>Search Recommendation Count</span><span>，输入要提供的推荐数量。</span></p>
</li>
<li>
<p><span>要显示为每个建议找到的结果数，请将每个建议的</span><span>显示结果计数</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>将</span><span>启用搜索建议</span><span>设置为</span><code>Yes</code><span>并执行以下操作：</span></p>
<p><img alt="Elasticsearch 建议和推荐设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/elasticsearch-3.png?lang=en" /></p>
<ul>
<li>
<p><span>对于</span><span>Search Suggestions Count</span><span>，输入要提供的搜索建议的数量。</span></p>
</li>
<li>
<p><span>要显示为每个建议找到的结果数，请将</span><span>显示每个建议</span><span>的结果设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
</li>
</ol>
<h3 id="step-4%3A-configure-minimum-terms-to-match"><span>第 4 步：配置要匹配的最少条款</span></h3>
<p><span>要控制搜索结果应匹配以便返回的查询中的最少字词数，请为</span><span>Minimum Terms to Match</span><span><span>指定一个值。</span><span>这确保了购物者的最佳结果相关性。</span><span>有关可接受值的列表，请参阅Elasticsearch 文档中的</span></span><a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-minimum-should-match.html">minimum_should_match 参数</a><span>。</span></p>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>]]></description>
      <pubDate>Mon, 19 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2搜索结果]]></title>
      <link>https://www.360magento.com/blog/Search-results/</link>
      <description><![CDATA[<p><em>搜索结果</em>列表包括与在快速搜索框或高级搜索表单中输入的搜索条件相匹配的所有产品。目录中的每个产品列表都具有基本相同的控件。唯一的区别是，一个是搜索查询的结果，另一个是导航的结果。</p>
<p>结果可以格式化为网格或列表，并按选择的属性排序。如果页面上容纳的产品多，则会出现分页控件。使用这些控件从一页移动到下一页。每页的记录数由目录前端配置决定。有关详细信息，请参阅产品列表。</p>
<p><span>使用</span><span>弹性搜索</span><span>：</span></p>
<ul>
<li><span><span>没有对后缀搜索的开箱即用支持。</span><span>例如，如果关键字仅包含 SKU 的末尾部分，则按 SKU 搜索可能不会返回预期的结果。</span></span></li>
<li><span></span><code>name</code><span>仅对产品</span><code>sku</code><span><span>属性</span><span>的前缀搜索（部分关键字搜索）提供开箱即用的支持。</span><span>所有其他产品属性均按整个关键字搜索，完全匹配。</span></span></li>
<li><span></span><code>name</code><span><span>和产品属性的</span><span>搜索结果</span></span><code>sku</code><span><span>基于相关性，而不是完全匹配。</span><span>首先列出</span><span>最相关的匹配项，例如完全匹配的</span></span><em>Product Name</em><span>或</span><em>SKU 。</em><span><span>要搜索完全匹配，客户可以在搜索查询中使用双引号。</span><span>例如，</span></span><code>WSH12-32-Red</code><span><span>搜索查询可能返回多个产品，按相关性排序。</span><span>但是</span></span><code>"WSH12-32-Red"</code><span>搜索查询只返回一个与</span><span><em>完全</em></span><span>匹配的产品</span><code>sku</code><span>。</span></li>
</ul>
<p><img alt="带有分页控件的搜索结果" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-results-shorts.png?lang=en" /></p>
<h2 id="keyword-mapping-to-extend-search-results"><span>用于扩展搜索结果的关键字映射</span></h2>
<p><span><span>此技术使用属性在两个产品之间创建基于关键字的关联，以便对任一产品的搜索返回两个产品的结果。</span><span>您可以使用关键字映射在搜索结果中推广产品，否则该产品不会出现。</span></span></p>
<p><img alt="使用关键字映射的搜索结果" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-results-extended.png?lang=en" /></p>
<p><span><span>以下示例使用基于 SKU 的关键字映射。</span><span>在搜索框中输入任一 SKU 时，两种产品都会出现在结果中。</span><span>映射了以下可配置产品的 SKU，而不是产品变体的 SKU：</span></span></p>
<ul>
<li><span>蒙大拿风衣 (MJ03)</span></li>
<li><span>Chaz 袋鼠连帽衫 (MH01)</span></li>
</ul>
<h3 id="step-1%3A-create-an-attribute"><span>第 1 步：创建属性</span></h3>
<ol>
<li>
<p><span>在</span><em>产品</em><span>列表中，以编辑模式打开</span><code>Montana Wind Jacket</code><span>(MJ03)。</span></p>
</li>
<li>
<p><span>在右上角，单击&ldquo;</span><span>添加属性</span><span>&rdquo; 。</span></p>
</li>
<li>
<p><span>在&ldquo;</span><em>选择属性</em><span>&rdquo;页面上，单击</span><span>&ldquo;创建新属性&rdquo;</span><span>。</span></p>
</li>
<li>
<p><span>完成属性属性如下：</span></p>
<p><span>属性属性</span></p>
<ul>
<li><span>属性标签 -</span><code>Search Keywords</code></li>
<li><span>店主的目录输入类型 -</span><code>Text Field</code></li>
</ul>
<p><span>高级属性</span></p>
<ul>
<li><span>添加到列选项 -&nbsp;</span><code>Yes</code><span>（默认）</span></li>
<li><span>在过滤器选项中使用 -&nbsp;</span><code>Yes</code><span>（默认）</span></li>
</ul>
<p><span>店面属性</span></p>
<ul>
<li><span>在搜索中使用 -</span><code>Yes</code></li>
<li><span>在店面的目录页面上可见 -</span><code>No</code></li>
<li><span>用于产品清单 -</span><code>No</code></li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存属性</span><span>。</span></p>
<p><span>该属性已添加到产品的属性集中。</span></p>
</li>
</ol>
<h3 id="step-2%3A-map-the-first-product"><span>第 2 步：映射第一个产品</span></h3>
<ol>
<li>
<p><span>在产品设置页面上，向下滚动并展开</span><em>属性</em><span>部分。</span></p>
</li>
<li>
<p><span>在</span><span>搜索关键字</span><span></span><code>MH01</code><span><span>字段中，输入要映射到该产品</span><span>的 SKU 。</span></span></p>
<p><span><span>您可以在搜索关键字字段中输入多个 SKU，以空格分隔。</span><span>在这个例子中，只输入了一个。</span></span></p>
<p><img alt="带有搜索关键字的属性部分" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-keywords-attribute.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span>转到</span><span>System</span><span>&nbsp;&gt;&nbsp;</span><em>Tools</em><span>&nbsp;&gt;&nbsp;</span><span>Cache Management</span><span>并刷新</span><span>Page Cache</span><span>。</span></p>
</li>
</ol>
<h3 id="step-3%3A-map-the-second-product"><span>第 3 步：映射第二个产品</span></h3>
<ol>
<li><span>在</span><em>产品</em><span>列表中，以编辑模式打开</span><code>Chaz Kangaroo Hoodie</code><span>(MH01)。</span></li>
<li><span>向下滚动并展开</span><span>属性</span><span>部分。</span></li>
<li><span>在</span><span>搜索关键字</span><span>字段中，输入其他产品的 SKU&nbsp;</span><code>MJ03</code><span>。</span></li>
<li><span>单击</span><span>保存</span><span>。</span></li>
<li><span>转到</span><span>System</span><span>&nbsp;&gt;&nbsp;</span><em>Tools</em><span>&nbsp;&gt;&nbsp;</span><span>Cache Management</span><span>并刷新</span><span>Page Cache</span><span>。</span></li>
</ol>
<h3 id="step-4%3A-test-it-in-the-storefront"><span>第 4 步：在店面进行测试</span></h3>
<ol>
<li><span>转到店面并</span><code>MJ03</code><span>在&ldquo;</span><em>快速搜索</em><span>&rdquo;框中输入。</span></li>
<li><span>确认这两种产品都在搜索结果列表中返回。</span></li>
</ol>
<h2 id="weighted-search"><span>加权搜索</span></h2>
<p><span><span>可以为目录搜索启用的产品属性分配权重，以便在搜索结果中赋予它们更高的价值。</span><span>权重较大的属性在权重较低的属性之前返回。</span><span>例如，如果系统中有两个属性，搜索权重为 3 的</span></span><em>颜色</em><span>和搜索权重为 1 的</span><em>描述</em><span>。搜索单词</span><em>red</em><span>返回颜色属性值为 的产品列表</span><code>red</code><span>，但不返回描述中包含单词</span><em>red</em><span><span>的产品。</span><span>在此示例中，</span></span><code>color</code><span>属性具有比</span><code>description</code><span>属性更大的定义权重。</span></p>
<p><img alt="搜索权重" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/search-weight.png?lang=en" /></p>
<p><span>要设置属性的搜索权重属性：</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Attributes</em><span>&nbsp;&gt;&nbsp;</span><span>Product</span><span>。</span></p>
</li>
<li>
<p><span>在列表中找到属性并以编辑模式打开。</span></p>
</li>
<li>
<p><span>在左侧面板中，选择</span><span>Storefront Properties</span><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>要在搜索查询中包含该属性，请将</span><span>Use in Search</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>要建立属性的搜索值，请将</span><span>搜索</span><span>权重设置为 1 到 10 之间的一个数字，其中</span><code>10</code><span><span>的优先级最高。</span><span>如果未输入任何值，则所有属性默认为搜索权重</span></span><code>1</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存属性</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sun, 18 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2分层导航]]></title>
      <link>https://www.360magento.com/blog/Layered-navigation/</link>
      <description><![CDATA[<p><span><span>分层导航使您可以根据类别、价格范围或任何其他可用属性轻松查找产品。</span><span>分层导航通常出现在搜索结果和分类页面的左栏，有时也出现在首页。</span><span>标准导航包括类别和价格范围的</span></span><em>购物</em><span><span>清单。</span><span>您可以配置分层导航的显示，包括产品数量和价格范围。</span></span></p>
<p><img alt="按类别和价格分层导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/navigation-layered-basic.png?lang=en" /></p>
<h2 id="filterable-attributes"><span>可过滤的属性</span></h2>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>本主题中描述的可过滤属性要求与</span>Live Search<span><span>不同。</span><span>要了解更多信息，请参阅</span></span>构面<span>。</span></p>
</div>
</div>
<p><span><span>分层导航可用于按类别或按属性搜索产品。</span><span>例如，当购物者从顶部导航中选择男装/短裤类别时，初始结果包括该类别中的所有产品。</span><span>可以通过选择特定样式、气候、颜色、材料、图案或价格或值的组合来进一步过滤列表。</span><span>可过滤的属性出现在列出每个属性值的扩展部分中。</span><span>作为一个选项，可以将具有匹配结果的产品列表配置为包含匹配或不匹配的产品。</span></span></p>
<p><span><span>属性特性与产品输入类型相结合，决定了哪些属性可用于分层导航。</span><span>分层导航仅适用于</span></span><em>锚</em><span><span>类别，但也可以添加到搜索结果页面。</span><span>每个属性的商店所有者属性的</span></span><span>目录输入类型</span><span>必须设置为</span><code>Yes/No</code><span>、</span><code>Dropdown</code><span>、</span><code>Multiple Select</code><span>或</span><code>Price</code><span><span>。</span><span>要使属性可过滤，</span><span>必须将每个属性的&ldquo;</span></span><span>在分层导航中使用</span><span></span><code>Filterable (with results)</code><span>&rdquo;属性设置为或</span><code>Filterable (no results)</code><span>。</span></p>
<p><img alt="分层导航中的可过滤属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-layered-navigation-filtered.png?lang=en" /></p>
<p><img alt="没有结果的可过滤样本值" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-product-attribute-filter-no-results.png?lang=en" /></p>
<p><span><span>以下说明显示如何设置具有可过滤属性的基本分层导航。</span><span>有关带有价格步骤的高级分层导航，请参阅</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/navigation/navigation-layered.html?lang=en#configure-price-navigation">价格导航</a><span>。</span></p>
<h2 id="step-1%3A-set-up-the-attribute-properties"><span>第 1 步：设置属性属性</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Attributes</em><span>&nbsp;&gt;&nbsp;</span><span>Product</span><span>。</span></p>
</li>
<li>
<p><span>浏览或使用过滤搜索在列表中查找属性并在编辑模式下打开它。</span></p>
<p><img alt="每列输入搜索词以使用过滤搜索" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/attribute-search.png?lang=en" /></p>
</li>
<li>
<p><span>在左侧面板中，选择</span><span>Storefront Properties</span><span>并将</span><span>在 Layered Navigation</span><span>中使用设置为以下选项之一：</span></p>
<ul>
<li>
<p><code>Filterable (with results)</code><span><span>- 分层导航仅包括那些可以找到匹配产品的过滤器。</span><span>已应用于列表中显示的所有产品的任何属性值仍应显示为可用过滤器。</span><span>可用过滤器列表中忽略了具有零 (0) 个产品匹配项的属性值。</span><span>过滤后的产品列表仅包含与过滤器匹配的产品。</span><span>仅当所选过滤器更改显示的内容时，产品列表才会更新。</span></span></p>
</li>
<li>
<p><code>Filterable (no results)</code><span><span>- 分层导航包括针对所有可用属性值及其产品计数的过滤器，包括具有零 (0) 个产品匹配项的过滤器。</span><span>如果属性值是样本，则该值显示为过滤器，但被划掉了。</span><span>此选项不支持价格分层过滤，并且不影响价格过滤器。</span></span></p>
</li>
</ul>
</li>
<li>
<p><span>将</span><span>在搜索结果中使用分层导航</span><span>设置为</span><code>Yes</code><span>。</span></p>
<p><img alt="店面属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/attribute-storefront-properties.png?lang=en" /></p>
</li>
<li>
<p><span>对要包含在分层导航中的每个属性重复这些步骤。</span></p>
</li>
</ol>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>默认情况下，</span><a href="https://docs.magento.com/user-guide/stores/attributes-product.html">位置字段</a><span><span>是灰色的。</span><span>您必须先保存该属性，然后才能修改此设置。</span></span></p>
</div>
</div>
<h2 id="step-2%3A-make-the-category-an-anchor"><span>第 2 步：将类别设为锚点</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在类别树中，选择要使用分层导航的类别。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>Display Settings</span></span><span>部分并将</span><span><span>Anchor</span></span><span>设置</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>为</span><span>。</span></span><span><span></span></span><span></span><span><span></span></span><span></span><code>Yes</code><span></span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>。</span></p>
<p><img alt="类别显示设置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-layered-navigation-anchor.png?lang=en" /></p>
</li>
</ol>
<h2 id="step-3%3A-test-the-results"><span>第 3 步：测试结果</span></h2>
<p><span><span>要测试设置，请访问您的商店并从主菜单导航到该类别。</span><span>可筛选属性的选择出现在类别页面的分层导航中。</span></span></p>
<p><span>搜索、过滤和查看显示的产品。</span></p>
<h2 id="remove-filterable-attribute-values-from-layered-navigation"><span>从分层导航中删除可过滤的属性值</span></h2>
<p><span>分层导航包括针对所有可用属性值及其产品计数的筛选器，包括具有零 (0) 个产品匹配项的筛选器（如下图所示）。</span></p>
<p><img alt="零过滤器显示" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/filterable-attributes-on-plp.png?lang=en" /></p>
<p><span>这使得客户很难选择喜欢的产品，也不需要在前端显示属性值为0的产品。</span></p>
<p><span>您可以使用以下步骤从分层导航中删除具有 0 个产品的可过滤属性值：</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Attributes</em><span>&nbsp;&gt;&nbsp;</span><span>Product</span><span>。</span></p>
</li>
<li>
<p><span>浏览或使用过滤搜索在列表中查找属性并在编辑模式下打开它。</span></p>
</li>
<li>
<p><span>在</span><em>属性信息</em><span>下，单击</span><span>店面属性</span><span>。</span></p>
<p><img alt="属性信息部分" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-properties-tab.png?lang=en" /></p>
</li>
<li>
<p><span>对于</span><span>分层导航</span><span>，选择</span><code>Filterable (with results)</code><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>保存属性</span><span>。</span></p>
</li>
</ol>
<h2 id="price-navigation"><span>价格导航</span></h2>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>本主题中描述的价格导航配置与</span><a href="https://experienceleague.adobe.com/docs/commerce-merchant-services/live-search/overview.html?lang=en">Live Search</a><span>不同。</span></p>
</div>
</div>
<p><span><span>价格导航可用于在分层导航中按价格范围分发产品。</span><span>您还可以按间隔拆分每个范围。</span><span>有几种计算价格导航的方法：</span></span></p>
<ul>
<li><span>自动（均衡价格范围）</span></li>
<li><span>自动（均衡产品计数）</span></li>
<li><span>手动的</span></li>
</ul>
<p><span><span>对于前两种方法，导航步骤是自动计算的。</span><span>手动方法允许您指定价格区间的划分限制。</span><span>以下示例显示了 10 和 100 的价格导航步长之间的差异。</span></span></p>
<p><span><span>迭代拆分提供了价格范围内产品的最佳分布。</span><span>通过迭代拆分，在选择 $0.00-$99 范围后，客户可以向下钻取多个价格子范围。</span><span>当产品数量达到Interval Division Limit 设置的阈值时，价格范围拆分停止。</span></span></p>
<h2 id="example%3A-price-navigation-steps"><span>示例：价格导航步骤</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>价格步进 10</span></th><th><span>价格步进 100</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>20.00 美元 - 29.99 美元 (1)</span></td>
<td><span>0.00 美元 - 99.99 美元 (4)</span></td>
</tr>
<tr>
<td><span>30.00 美元 - 39.99 美元 (2)</span></td>
<td><span>100 美元 - 199.99 美元 (5)</span></td>
</tr>
<tr>
<td><span>70.00 美元 - 79.99 美元 (1)</span></td>
<td><span>400.00 美元 - 499.99 美元 (2)</span></td>
</tr>
<tr>
<td><span>100.00 美元 - 109.99 美元 (1)</span></td>
<td><span>$700.00 及以上 (1)</span></td>
</tr>
<tr>
<td><span>120.00 美元 - 129.99 美元 (2)</span></td>
<td></td>
</tr>
<tr>
<td><span>150.00 美元 - 159.99 美元 (1)</span></td>
<td></td>
</tr>
<tr>
<td><span>180.00 美元 - 189.99 美元 (1)</span></td>
<td></td>
</tr>
<tr>
<td><span>420.00 美元 - 429.99 美元 (1)</span></td>
<td></td>
</tr>
<tr>
<td><span>440.00 美元 - 449.99 美元 (1)</span></td>
<td></td>
</tr>
<tr>
<td><span>$710.00 及以上 (1)</span></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<h2 id="configure-price-navigation"><span>配置价格导航</span></h2>
<div class="extension important">
<div><span><span>重要的</span></span></div>
<div>
<p><span></span><em>要根据分层导航中的价格过滤器</em><span><span>正确显示产品及其价格</span><span>，请确保</span></span><a href="https://docs.magento.com/user-guide/configuration/sales/tax.html">销售税配置</a><span>中的价格显示设置具有相同的值（</span><code>Excluding Tax</code>&nbsp;<span>或</span>&nbsp;<code>Including Tax</code><span><span>）。</span><span>对于</span></span><em>Calculation Settings</em><span>，检查</span><span>Catalog Prices</span><span><span>值。</span><span>对于</span></span><em>Price Display Settings</em><span>，选中</span><span>Display Product Prices in Catalog</span><span><span>值。</span><span>如果它们具有不同的值，分层导航中的价格过滤器可能无法按价格正确过滤和排序产品。</span></span></p>
</div>
</div>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><em><span>分层导航</span></em></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><em><span></span></em><span></span></p>
<p><span>默认情况下，</span><span>显示产品计数</span><span>设置为</span><code>Yes</code><span><span>。</span><span>如有必要，取消选中</span></span><span>使用系统值</span><span>复选框以更改此设置。</span></p>
<p><img alt="分层导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/layered-navigation.png?lang=en" /></p>
<p><span>有关这些配置选项的信息，请参阅</span><a href="https://docs.magento.com/user-guide/configuration/catalog/catalog.html#layered-navigation">分层导航</a></p>
</li>
<li>
<p><span>为以下部分中的其中一种方法设置</span><span>价格导航步骤计算</span><span>。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h3 id="method-1%3A-automatic-(equalize-price-ranges)"><span>方法 1：自动（均衡价格范围）</span></h3>
<p><span>将</span><span>价格导航步骤计算</span><span>设置为</span><code>Automatic (Equalize Price Ranges)</code><span><span>（默认）。</span><span>此设置使用标准算法进行价格导航。</span></span></p>
<h3 id="method-2%3A-automatic-(equalize-product-counts)"><span>方法 2：自动（均衡产品计数）</span></h3>
<div class="extension tip">
<div><span><span>提示</span></span></div>
<div>
<p><span>如有必要，请先取消选中</span><span>使用系统值</span><span>复选框以更改这些设置。</span></p>
</div>
</div>
<ol>
<li>
<p><span>将</span><span>价格导航步骤计算</span><span>设置为</span><code>Automatic (equalize product counts)</code><span>。</span></p>
</li>
<li>
<p><span>多个商品同价时显示单个价格，将</span><span>显示价格间隔设置为 一个价格</span><span>为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>对于</span><span>Interval Division Limit</span><span>，输入价格范围内产品数量的阈值。</span></p>
<p><span><span>范围不能进一步分割超出此限制。</span><span>默认值为</span></span><code>9</code><span>。</span></p>
<p><img alt="自动（均衡产品数量）" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/equalize-product-counts.png?lang=en" /></p>
</li>
</ol>
<h3 id="method-3%3A-manual"><span>方法三：手动</span></h3>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>如有必要，请先取消选中</span><span>使用系统值</span><span>复选框以更改这些设置。</span></p>
</div>
</div>
<ol>
<li>
<p><span>将</span><span>价格导航步骤计算</span><span>设置为</span><code>Manual</code><span>。</span></p>
</li>
<li>
<p><span>输入一个值以确定</span><span>默认价格导航步骤</span><span>。</span></p>
</li>
<li>
<p><span>输入允许的</span><span>最大价格区间</span><span>数，最多</span><code>100</code><span>.</span></p>
<p><img alt="手动的" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/layered-navigation-manual.png?lang=en" /></p>
</li>
</ol>
<h2 id="configure-layered-navigation"><span>配置分层导航</span></h2>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>此页面中描述的标准配置与</span><a href="https://experienceleague.adobe.com/docs/commerce-merchant-services/live-search/overview.html?lang=en">Live Search</a><span>不同。</span></p>
</div>
</div>
<p><span>分层导航配置确定产品计数是否出现在每个属性后的括号中，以及价格导航中使用的步长计算的大小。</span></p>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><em>目录</em><span>部分并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>展开</span><em>分层导航</em><span>部分。</span></p>
<p><img alt="分层导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/layered-navigation.png?lang=en" /></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>如有必要，请先取消选中</span><span>使用系统值</span><span>复选框以更改这些设置。</span></p>
</div>
</div>
</li>
<li>
<p><span>要显示为每个属性找到的产品数量，请将</span><span>Display Product Count</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>将</span><span>价格导航步骤计算</span><span>设置为</span><code>Automatic (equalize price ranges)</code><span>。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Sat, 17 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2顶部导航]]></title>
      <link>https://www.360magento.com/blog/Top-navigation/</link>
      <description><![CDATA[<p><span><span>商店的主菜单就像商店中不同部门的目录。</span><span>每个选项代表不同类别的产品。</span><span>顶部导航的位置和呈现可能因主题而异，但其工作方式基本相同。</span></span></p>
<p><img alt="顶部导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-top-navigation.png?lang=en" /></p>
<p><span><span>目录的类别结构会影响您的站点被搜索引擎编入索引的程度。</span><span>类别嵌套越深，被彻底索引的可能性就越小。</span><span>通常，使用一到三个可见级别是最有效的。</span><span>根</span></span>类别<span><span>算作第一级，尽管它没有出现在菜单中。</span><span>顶部导航中可用的最大级别数由配置决定。</span><span>此外，您的商店主题支持的菜单级别数量可能有限制。</span><span>例如，示例 Luma 主题最多支持五个级别，包括根。</span></span></p>
<h2 id="counting-menu-levels"><span>计算菜单级别</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>物品</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>1级</span></td>
<td><span><span>第一层是根类别，在样本数据中被命名为&ldquo;默认类别&rdquo;。</span><span>根目录是菜单的容器，其名称不会作为选项出现在菜单中。</span></span></td>
</tr>
<tr>
<td><span>2级</span></td>
<td><span><span>在桌面显示器上，顶部导航是出现在页面顶部的主菜单。</span><span>在移动设备上，主菜单通常显示为选项的弹出菜单。</span><span>Luma 商店的二级选项是</span></span><em>What's New</em><span>、</span><em>Women</em><span>、</span><em>Men</em><span>、</span><em>Gear</em><span>、</span><em>Training</em><span>和</span><em>Sale</em><span>。</span></td>
</tr>
<tr>
<td><span>3级</span></td>
<td><span><span>第三级显示在每个主菜单选项下方。</span><span>例如，在</span></span><em>Women</em><span>下，第三级选项是</span><em>Tops</em><span>和</span><em>Bottoms</em><span>。</span></td>
</tr>
<tr>
<td><span>4级</span></td>
<td><span><span>第四级选项是从第三级选项飞出的子类别。</span><span>例如，在</span></span><em>Tops</em><span>下，第四级菜单选项是</span><em>Jackets</em><span>、</span><em>Hoodies &amp; Sweatshirts</em><span>、</span><em>Tees</em><span>和</span><em>Bras &amp; Tanks</em><span>。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="set-the-top-navigation"><span>设置顶部导航</span></h2>
<p><span>要使类别显示在商店的顶部导航中，请完成以下步骤：</span></p>
<h3 id="step-1%3A-create-a-category"><span>第 1 步：创建类别</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>设置</span><span>商店视图</span><span>以确定新类别的可用位置。</span></p>
</li>
<li>
<p><span>在类别树中，选择新类别的父类别。</span></p>
<p><span>如果您从头开始，没有任何数据，则列表中可能只有两个类别：</span><em>默认类别</em><span>（根）和</span><em>示例类别</em><span>。</span></p>
</li>
<li>
<p><span>单击</span><span>添加子类别</span><span>。</span></p>
</li>
<li>
<p><span>使用以下设置完成基本信息：</span></p>
<ul>
<li><span>启用类别</span><span>设置为</span><code>Yes</code></li>
<li><span>包含在菜单中</span><span>设置为</span><code>Yes</code></li>
</ul>
</li>
<li>
<p><span>在 Display Setting 中将</span><span>Anchor</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>完成任何其他必需的</span>类别设置<span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<p><span><span>对于多商店安装，可以将不同的主菜单指定</span><span>为每个</span><span>商店的</span></span>根类别<span>。</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/stores-sales/site-store/stores.html?lang=en#add-stores"><span></span></a><span></span></p>
<h3 id="step-2%3A-set-the-depth-of-the-top-navigation"><span>第二步：设置顶部导航的深度</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
<p><span>有关这些配置选项的信息，请参阅</span>类别顶部导航</p>
</li>
<li>
<p><span>展开</span><span>类别顶部导航</span><span>部分。</span></p>
<p><img alt="类别顶部导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-category-top-navigation.png?lang=en" /></p>
<p><span>因为顶部导航的深度具有全局</span>配置范围<span><span>，所以该设置适用于 Commerce 安装中的所有网站、商店和商店视图。</span><span>只有在左上角的</span><em><span>Store View</span></em><span>设置为 时，</span></span><em>Category Top Navigation</em><span><span>配置部分才可用</span><span>。</span></span><em><span></span></em><span></span><code>Default Config</code><span></span></p>
<p><img alt="默认配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/configuration-store-view-default-config.png?lang=en" /></p>
</li>
<li>
<p><span>要限制出现在顶部导航中的子类别数量，请输入</span><span>Maximal Depth</span><span>的数字。</span></p>
<p><span>默认值为</span><code>0</code><span>，它不限制子类别级别的数量。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Fri, 16 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2面包屑路径]]></title>
      <link>https://www.360magento.com/blog/Breadcrumb-trails/</link>
      <description><![CDATA[<p><em>面包屑路径</em><span><span>是一</span><span>组链接，显示您相对于商店中其他页面的位置。</span><span>您可以单击面包屑路径中的任何链接以返回到上一页。</span></span></p>
<p><span><span>面包屑路径可以配置为显示在内容页面和目录页面上。</span><span>面包屑路径的格式和位置因主题而异，但通常位于标题下方。</span><span>默认情况下，面包屑路径显示在 CMS 页面上。</span></span></p>
<p><img alt="店面中显示的面包屑路径" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-breadcrumb-trail.png?lang=en" /></p>
<h2 id="general-types-of-bread-crumbs"><span>一般类型的面包屑</span></h2>
<p><span><span>面包屑可分为三种主要类型，它们的用途不同。</span><span>下面分别介绍各类型面包屑的实现本质和主要原理。</span></span></p>
<h3 id="hierarchy-based-breadcrumbs"><span>基于层次结构的面包屑</span></h3>
<p><span><span>这种类型的面包屑基于站点上设置的类别层次结构。</span><span>显示的链告诉用户它们在结构中的位置。</span><span>在这种情况下，每个文本链接都用于比前一个页面高一级的页面。</span></span></p>
<p><span>例子：</span><code>Men &gt; Tops &gt; Hoodies &amp; Sweatshirts</code></p>
<p><span>这种类型的优点是用户可以很容易地看到他们处于哪个类别级别，并且可以轻松访问目录页面之间的导航。</span></p>
<h3 id="history-based-breadcrumbs"><span>基于历史的面包屑</span></h3>
<p><span><span>基于历史（或路径）的导航类似于浏览器中的后退按钮。</span><span>这使用户可以快速返回到他们访问过的先前页面而无需更改。</span></span></p>
<p><span>这种类型的优点是，当客户在类别页面上选择多个过滤器后想要返回到上一页时，它最有帮助。</span></p>
<p><span>例子：</span><code>Home &gt; What's New &gt; Gear &gt; Bags</code></p>
<h3 id="attribute-based-breadcrumbs"><span>基于属性的面包屑</span></h3>
<p><span><span>这种类型的面包屑显示在类别页面上选择的属性。</span><span>与其他类型的主要区别在于，基于属性的面包屑表示客户在导航层中为某些产品（例如价格、质量和颜色）选择的过滤器和选项。</span></span></p>
<p><span>例子：</span><code>Home &gt; Suits &gt; All Suits &gt; Refined by &gt; Slim Fit</code></p>
<h2 id="add%2Fremove-the-breadcrumbs-from-cms-pages"><span>从 CMS 页面添加/删除面包屑</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在</span><em>General</em><span>下的左侧面板中，选择</span><span>Web</span><span>并执行以下操作：</span></p>
<ul>
<li>
<p><span>展开</span><em>默认页面</em><span>部分。</span></p>
</li>
<li>
<p><span>取消选中</span><span>使用系统值</span><span>复选框。</span></p>
</li>
<li>
<p><span>将</span><span>CMS 页面的&ldquo;显示面包屑&rdquo;</span><span>设置为</span><code>No</code><span>或</span><code>Yes</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
<p><img alt="显示 CMS 页面的面包屑" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/web-default-pages_c1.png?lang=en" /></p>
</li>
</ol>]]></description>
      <pubDate>Thu, 15 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品列表]]></title>
      <link>https://www.360magento.com/blog/Product-listings/</link>
      <description><![CDATA[<p><span><span>产品列表可以设置为默认显示为列表或网格。</span><span>您还可以确定每页显示多少产品，以及使用哪个属性对列表进行排序。</span><span>产品列表包括一组控件，可用于对产品进行排序、更改列表格式、按属性排序以及从一页前进到下一页。</span></span></p>
<p><img alt="显示为网格的产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-catalog-page.png?lang=en" /></p>
<h2 id="configure-product-listings"><span>配置产品列表</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>店面</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分</span><span>。</span></span><span><span></span></span><span></span></p>
<p><img alt="店面配置选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-storefront.png?lang=en" /></p>
<p><span><span>有关这些选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span>Storefront<span>。</span><em><span></span></em><span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span></span><em>要根据按价格排序的</em><span><span>产品正确显示产品及其价格</span><span>，请确保</span></span>销售税配置<span>中的价格显示设置具有相同的值（</span><code>Excluding Tax</code>&nbsp;<span>或</span>&nbsp;<code>Including Tax</code><span><span>）。</span><span>对于</span></span><em>Calculation Settings</em><span>，检查</span><span>Catalog Prices</span><span><span>值。</span><span>对于</span></span><em>Price Display Settings</em><span>，选中</span><span>Display Product Prices in Catalog</span><span><span>值。</span><span>如果它们具有不同的值，分层导航中的价格过滤器可能无法按价格正确过滤和排序产品。</span></span></p>
</div>
</div>
</li>
<li>
<p><span>将默认</span><span>列表模式</span><span>设置为以下之一：</span></p>
<ul>
<li><code>Grid Only</code></li>
<li><code>List Only</code></li>
<li><code>Grid (default) / List</code></li>
<li><code>List (default / Grid</code></li>
</ul>
</li>
<li>
<p><span>对于</span><span>网格允许值上</span><span>的每页产品数，输入您希望在以网格格式显示时每页显示的产品数。</span></p>
<p><span>要输入一系列值，请用逗号分隔每个数字。</span></p>
</li>
<li>
<p><span>对于每页网格产品</span><span>默认值</span><span>，输入每页网格中显示的默认产品数。</span></p>
</li>
<li>
<p><span>对于</span><span>List Allowed Values per Page 上的 Products per Page</span><span>，输入您希望在以列表格式显示时每页显示的产品数量。</span></p>
<p><span>要输入一系列值，请用逗号分隔每个数字。</span></p>
</li>
<li>
<p><span>对于</span><span>列表默认值上的每页产品数</span><span>，输入列表中每页显示的默认产品数。</span></p>
</li>
<li>
<p><span>将</span><span>产品列表排序方式</span><span>设置为最初用于对列表进行排序的默认属性。</span></p>
</li>
<li>
<p><span>要为客户提供列出所有产品的选项，请将</span><span>&ldquo;允许页面上的所有</span><span>产品&rdquo;设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>如果您想在客户浏览目录列表时保留所有分页设置，请将</span><span>记住类别分页</span><span>设置为</span><code>Yes</code><span>。</span></p>
<p><span><span>启用此设置可确保在购物者从一个类别浏览到另一个类别时保留列表或网格中显示的产品数量。</span><span>默认情况下，此字段设置为，</span></span><code>No</code><span>因为它使用更多的缓存存储空间，并且会影响页面被搜索引擎索引的方式。</span></p>
</li>
<li>
<p><span>如果使用</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/catalog/catalog-flat.html?lang=en">平面目录</a><span>（</span><span>不推荐</span><span>），请执行以下操作：</span></p>
<ul>
<li>
<p><span>要显示产品的平面类别列表，请将</span><span>使用平面目录类别</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>要显示平面产品列表，请将</span><span>Use Flat Catalog Product</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>如果要允许动态引用类别和产品 URL 中的媒体资产，请将&ldquo;</span><span>允许产品和类别中的动态媒体 URL</span><span>&nbsp;&rdquo;设置为</span><code>Yes</code><span>。</span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>
<h2 id="page-controls"><span>页面控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>查看方式</span></td>
<td><span>以网格或列表格式显示产品。</span></td>
</tr>
<tr>
<td><span>排序方式</span></td>
<td><span>更改列表的排序顺序。</span></td>
</tr>
<tr>
<td><span>每页显示</span></td>
<td><span>确定每页显示多少产品。</span></td>
</tr>
<tr>
<td><span>分页链接</span></td>
<td><span>导航链接到其他页面。</span></td>
</tr>
</tbody>
</table>
</div>
<h2 id="pagination-controls"><span>分页控件</span></h2>
<p><span><span>分页设置显示在列表的顶部和底部，并控制产品列表的分页链接的格式。</span><span>您可以设置控件中显示的链接数，并配置 Next 和 Previous 链接。</span><span>要显示分页链接，列表中的产品数量必须多于产品列表配置中每页允许的数量。</span></span></p>
<p><img alt="分页控件" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-pagination-controls.png?lang=en" /></p>
<h3 id="storefront-pagination-controls"><span>店面分页控件</span></h3>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><img alt="显示网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/controls-pagination-list-grid.png?lang=en" /></td>
<td><span>查看方式 - 以网格或列表格式显示列表。</span></td>
</tr>
<tr>
<td><img alt="排序方式" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/control-pagination-sort-by.png?lang=en" /></td>
<td><span>排序依据 - 更改列表的排序顺序。</span><em>Used for Sorting in Product Listing</em><span>店面属性确定哪些</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/product-attributes/product-attributes.html?lang=en">产品属性</a><span><span>可用于对列表进行排序</span><span>。</span></span></td>
</tr>
<tr>
<td><img alt="每页显示" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/control-pagination-show-per-page.png?lang=en" /></td>
<td><span>每页显示 - 确定每页显示多少产品。</span></td>
</tr>
<tr>
<td><img alt="分页链接" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/control-pagination.png?lang=en" /></td>
<td><span>分页链接 - 指向其他页面的导航链接。</span></td>
</tr>
</tbody>
</table>
</div>
<h3 id="configure-the-pagination-controls"><span>配置分页控件</span></h3>
<ol>
<li>
<p><span>在</span><em>Admin</em><span>侧边栏上，转到</span><span>Content</span><span>&nbsp;&gt;&nbsp;</span><em>Design</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>找到您要配置的商店视图，然后在</span><span>操作</span><span>列中单击</span><span>编辑</span><span>。</span></p>
</li>
<li>
<p><span>在</span><span>其他设置</span><span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>下</span><span>，展开</span></span><span>分页</span><span>部分。</span></p>
<p><img alt="分页" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/config-design-pagination.png?lang=en" /></p>
</li>
<li>
<p><span>对于</span><span>Pagination Frame</span><span>，输入您希望在分页控件中显示的链接数。</span></p>
</li>
<li>
<p><span>对于</span><span>Pagination Frame Skip</span><span>，输入在分页控件中显示下一组链接之前要向前跳过的链接数。</span></p>
<p><span><span>比如分页框有5个链接，你想跳转到后面5个链接，你想往前跳多少个链接？</span><span>如果将其设置为四，则上一组中的最后一个链接将成为下一组中的第一个链接。</span></span></p>
</li>
<li>
<p><span>对于</span><span>Previous 的锚文本</span><span>，输入您希望为 Previous 链接显示的文本。</span></p>
<p><span>留空以使用默认箭头。</span></p>
</li>
<li>
<p><span>对于</span><span>Next 的锚文本</span><span><span>，输入您希望为 Next 链接显示的文本。</span><span>留空以使用默认箭头。</span></span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存配置</span><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Wed, 14 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2平面目录]]></title>
      <link>https://www.360magento.com/blog/sections-nav-sections/</link>
      <description><![CDATA[<p><span><span>Commerce 通常根据实体-属性-值 (EAV) 模型将目录数据存储在多个表中。</span><span>由于产品属性存储在许多表中，因此 SQL 查询有时又长又复杂。</span></span></p>
<p><span><span>相比之下，平面目录会动态创建表格，其中每一行都包含有关产品或类别的所有必要数据。</span><span>平面目录会自动更新&mdash;&mdash;每分钟更新一次，或者根据您的 cron 作业更新一次。</span><span>平面目录索引还可以加快目录和购物车价格规则的处理。</span><span>包含多达 500,000 个 SKU 的目录可以作为平面目录快速编入索引。</span></span></p>
<h2 id="step-1%3A-enable-the-flat-catalog"><span>第 1 步：启用平面目录</span></h2>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>展开</span><em>店面</em><span>部分并执行以下操作：</span></p>
<ul>
<li>
<p><span>将</span><span>使用平面目录类别</span><span>设置为</span><code>Yes</code><span><span>。</span><span>（如有必要，取消选择</span></span><span>使用系统值</span><span>复选框。）</span></p>
</li>
<li>
<p><span>将</span><span>使用平面目录产品</span><span>设置为</span><code>Yes</code><span>。</span></p>
</li>
</ul>
<p><img alt="平面目录配置" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/use-flat-catalog.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>当提示更新缓存时，点击系统消息中的</span><span>缓存管理</span><span>，按照提示刷新缓存。</span></p>
</li>
</ol>
<h2 id="step-2%3A-verify-the-results"><span>第 2 步：验证结果</span></h2>
<p><span>您可以使用两种方法来验证结果。</span></p>
<h3 id="method-1%3A-verify-the-results-for-a-single-product"><span>方法 1：验证单个产品的结果</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧栏上，转到</span><span>目录</span><span>&gt;</span><span>产品</span><span>。</span></p>
</li>
<li>
<p><span>在编辑模式下打开产品。</span></p>
</li>
<li>
<p><span>对于</span><span>Name</span><span>，将文本添加</span><code>_TEST</code><span>到产品名称的末尾。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span>在新的浏览器选项卡上，导航到您商店的主页并执行以下操作：</span></p>
<ul>
<li>
<p><span>搜索您编辑的产品。</span></p>
</li>
<li>
<p><span>使用导航浏览到其指定类别下的产品。</span></p>
<p><span><span>如有必要，刷新页面以查看结果。</span><span>更改会在一分钟内或根据您的</span></span><a href="https://docs.magento.com/user-guide/system/cron.html">Cron</a><span>计划出现。</span></p>
</li>
</ul>
<p><img alt="带有平面目录的店面" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-flat-catalog-enabled.png?lang=en" /></p>
</li>
</ol>
<h3 id="method-2%3A-verify-the-results-for-a-category"><span>方法 2：验证类别的结果</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在左上角，确认</span><span>Store View</span><span>设置为</span><code>All Store Views</code><span>。</span></p>
<p><span>如果出现提示，请单击&ldquo;</span><span>确定</span><span>&rdquo;进行确认。</span></p>
</li>
<li>
<p><span>在类别树中，选择现有类别，单击</span><span>添加子类别</span><span>，然后执行以下操作：</span></p>
<ul>
<li>
<p><span>对于</span><span>类别名称</span><span>，输入</span><code>Test Category</code><span>。</span></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
<p><img alt="测试子类" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-flat-test-category.png?lang=en" /></p>
</li>
<li>
<p><span><span>展开</span><span><span>类别</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分的产品</span><span>并单击</span><span><span>重置过滤器</span></span><span>以显示所有产品。</span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
</li>
<li>
<p><span>选中多个产品的复选框以将它们添加到新类别。</span></p>
</li>
<li>
<p><span>单击</span><span>保存</span><span>。</span></p>
</li>
</ul>
<p><img alt="测试类产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-flat-test-category-products.png?lang=en" /></p>
</li>
<li>
<p><span>在新的浏览器选项卡上，导航到商店的主页并使用商店导航浏览到您创建的类别。</span></p>
<p><span><span>如有必要，刷新页面以查看结果。</span><span>更改会在一分钟内或根据您的 cron 计划出现。</span></span></p>
</li>
</ol>
<h2 id="step-3%3A-remove-the-test-data"><span>第三步：移除测试数据</span></h2>
<p><span>执行以下操作以删除测试数据并恢复原始产品名称和目录配置。</span></p>
<h3 id="remove-the-test-category"><span>删除测试类别</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在类别树中，选择您创建的测试子类别。</span></p>
</li>
<li>
<p><span>在右上角，单击&ldquo;</span><span>删除</span><span>&rdquo; 。</span></p>
</li>
<li>
<p><span>当提示确认时，单击</span><span>确定</span><span>。</span></p>
<p><span>这不会删除分配给该类别的产品。</span></p>
</li>
</ol>
<h3 id="restore-the-original-product-name"><span>恢复原产品名称</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Catalog</span><span>&nbsp;&gt;&nbsp;</span><span>Categories</span><span>。</span></p>
</li>
<li>
<p><span>在编辑模式下打开测试产品。</span></p>
</li>
<li>
<p><span>删除</span><code>_TEST</code><span>您添加到</span><span>Product Name</span><span>的文本。</span></p>
</li>
<li>
<p><span>在右上角，点击</span><span>保存</span><span>。</span></p>
</li>
</ol>
<h3 id="restore-the-original-catalog-configuration"><span>恢复原始目录配置</span></h3>
<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span>展开</span><em>店面</em><span>部分并执行以下操作：</span></p>
<ul>
<li>
<p><span>将</span><span>使用平面目录类别</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
<li>
<p><span>将</span><span>使用平面目录产品</span><span>设置为</span><code>No</code><span>。</span></p>
</li>
</ul>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>出现提示时，刷新缓存。</span></p>
</li>
</ol>]]></description>
      <pubDate>Tue, 13 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品属性概览]]></title>
      <link>https://www.360magento.com/blog/Product-attributes-overview/</link>
      <description><![CDATA[<p><span><span>属性是产品目录的构建块，描述了产品的特定特征。</span><span>产品属性可以组织成</span></span>属性集<span>，然后用作创建产品的模板。</span></p>
<p><span><span>属性确定用于产品选项的输入控件的类型，并为产品页面提供附加信息。</span><span>它们还用作分层导航、产品比较报告和促销的搜索参数和标准。</span><span>您可以根据需要创建尽可能多的属性和属性集来描述目录中的产品。</span><span>除了您可以创建的属性之外，价格等系统属性内置于核心 Commerce 平台中，无法更改。</span></span></p>
<p><img alt="在编辑产品时创建新属性" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/attribute-new-product.png?lang=en" /></p>
<p><span>规划和创建产品属性时，请使用以下部分中描述的最佳实践。</span></p>
<h2 id="attribute-names"><span>属性名称</span></h2>
<p><span><span>建立一致的属性命名约定，包括字母大小写和标点符号。</span><span>例如，</span></span><code>Color:Green</code><span>和</span><code>Color:green</code><span><span>可能被不同的系统视为两个不同的属性值。</span><span>数据中的此类噪音会影响业务规则、搜索结果以及将产品与规则相匹配的应用程序的数据过滤器。</span></span></p>
<h2 id="attribute-use"><span>属性使用</span></h2>
<p><span><span>考虑在分配属性和值时如何使用属性。</span><span>识别用作展示标签的属性，例如产品名称、图像、价格和描述，以及哪些属性用于数据输入。</span><span>考虑属性如何在整个站点的不同页面上表示，以及它们如何出现在类别页面、产品详细信息页面、类别网格和缩略图滑块上。</span></span></p>
<h2 id="color"><span>颜色</span></h2>
<p><span><span>从数据库操作的角度来看，临时颜色描述可能会带来挑战。</span><span>&ldquo;Azure Skies&rdquo;或&ldquo;Robin Egg Blue&rdquo;等颜色名称很有吸引力，但当用作搜索条件时，或者如果营销要求您指定 ，可能不会返回最佳结果</span></span><code>Color_Family:Blue</code><span><span>。</span><span>考虑颜色在搜索结果和分层导航中的表示方式，并为您的业务需求制定一些准则。</span><span>然后，在整个目录中分配颜色属性值时保持一致。</span></span></p>
<h2 id="variations-management"><span>变体管理</span></h2>
<p><span>使用产品</span>配置选项<span>和</span>可配置产品<span><span>来管理产品供应的变化。</span><span>这些功能使产品分类、创建购物车价格规则和动态类别规则以及提供具有各种文本、选择和日期输入类型的选项选择变得更加容易。</span></span></p>
<h2 id="weighted-search"><span>加权搜索</span></h2>
<p><span></span>可以为目录搜索<span><span>启用的产品属性</span><span>分配权重，以便在搜索结果中赋予它们更高的价值。</span><span>权重较大的属性在权重较低的属性之前返回。</span><span>例如，考虑系统中的两个属性，搜索权重为 3 的</span></span><em>颜色</em><span>和搜索权重为 1 的</span><em>描述</em><span>。搜索单词</span><em>red</em><span>会返回颜色属性值为 的产品列表</span><code>red</code><span>，但不会返回具有包含单词</span><em>red</em><span><span>的描述。</span><span>在此示例中，</span></span><code>color</code><span>属性具有比</span><code>description</code><span>属性更大的定义权重。</span></p>
<h2 id="unused-properties"><span>未使用的属性</span></h2>
<p><span>删除未使用的产品属性以获得更好的结构和更快的索引。</span></p>]]></description>
      <pubDate>Mon, 12 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2产品列表]]></title>
      <link>https://www.360magento.com/blog/Products-list/</link>
      <description><![CDATA[<p><span>目录中的所有产品都可以从管理员的</span><em>产品</em><span><span>页面访问，您可以在其中创建产品和编辑现有产品。</span><span>对于多站点安装，每个网站都可以从同一目录中提供不同的待售产品选择。</span></span></p>
<p><span></span><em>产品</em><span><span>列表包括目录中的</span><span>所有产品，指示它们可用的网站，以及它们当前是否可以销售。</span></span>在启用了共享目录<span><span>的 Adob​​e Commerce B2B 安装中</span><span>，网格包含一个列，指示哪些产品在共享目录中具有替代折扣定价。</span></span></p>
<p><span><span>您可以逐页浏览列表，或搜索特定产品。</span><span>使用标准</span></span>控件<span><span>对列表进行排序和过滤，并对</span><span>选定产品应用</span></span>操作。<span></span></p>
<p><img alt="产品网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/products-grid.png?lang=en" /></p>
<h2 id="page-controls"><span>页面控件</span></h2>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>添加产品</span></td>
<td><span><span>启动创建新的简单产品的流程。</span><span>要选择特定的产品类型，请单击向下箭头。</span><span>选项：</span></span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-simple.html?lang=en">简单产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-configurable.html?lang=en">可配置产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-grouped.html?lang=en">分组产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-virtual.html?lang=en">虚拟产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-bundle.html?lang=en">捆绑产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-create-downloadable.html?lang=en">可下载产品</a><span>/</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/types/product-gift-card-create.html?lang=en">礼品卡</a></td>
</tr>
<tr>
<td><span>导出完整目录</span></td>
<td><span>（需要</span><a href="https://docs.magento.com/user-guide/mcom.html">MCOM 连接器</a><span>）手动请求从 Adob​​e Commerce</span><a href="https://docs.magento.com/user-guide/catalog/export-full-catalog.html">导出完整目录</a><span><span>。</span><span>外发消息批量导出到 .csv 文件。</span></span></td>
</tr>
<tr>
<td><span>动作</span></td>
<td><span><span>列出可应用于列表中选定产品的所有操作。</span><span>要对一个产品或一组产品应用操作，请选中每个产品第一列中的复选框。</span><span>选项：</span></span><code>Delete</code><span>/&nbsp;</span><code>Change Status</code><span>/&nbsp;</span><code>Update Attributes</code><span>/&nbsp;</span><code>Assign Inventory Source</code><span>/&nbsp;</span><code>Unassign Inventory Source</code><span>/</span><code>Transfer Inventory To Source</code></td>
</tr>
<tr>
<td><span>过滤器</span></td>
<td><span>根据当前过滤器启动目录搜索。</span></td>
</tr>
<tr>
<td><span>默认视图</span></td>
<td><span><span>指示当前网格列布局。</span><span>如果有保存的网格列视图，您可以选择另一个。</span></span></td>
</tr>
<tr>
<td><span>列</span></td>
<td><span><span>列出可应用于列表中选定产品的所有操作。</span><span>要对一个产品或一组产品应用操作，请选中每个产品第一列中的复选框。</span></span></td>
</tr>
<tr>
<td><span>按关键字搜索</span></td>
<td><span>左上角的搜索框用于按关键字查找产品。</span></td>
</tr>
<tr>
<td><span>编辑</span></td>
<td><span><span>在编辑模式下打开产品。</span><span>您可以通过单击行中的任意位置来完成相同的操作。</span></span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Sun, 11 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2类别概览]]></title>
      <link>https://www.360magento.com/blog/Categories-overview/</link>
      <description><![CDATA[<p><span><span>在将产品添加到目录之前，您需要建立目录的基本类别结构。</span><span>产品可以分配给零个或多个类别。</span><span>通常，类别是在产品添加到目录之前预先创建的。</span><span>但是，您也可以</span><span>在创建产品时</span></span><em>即时添加类别。</em><span><span>目录的类别结构反映</span><span>在商店的主菜单或</span></span>顶部导航中。<span></span></p>
<p><img alt="类别树" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-selected.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>控制</span></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>添加根目录</span></td>
<td><span>创建根类别。</span></td>
</tr>
<tr>
<td><span>添加子类别</span></td>
<td><span>在当前类别或子类别下添加子类别。</span></td>
</tr>
<tr>
<td><span>全部折叠</span><span>/全部</span><span>展开</span></td>
<td><span>折叠或展开类别树。</span></td>
</tr>
<tr>
<td><span>删除</span></td>
<td><span>从树中删除当前类别或子类别。</span></td>
</tr>
<tr>
<td><span>救球</span></td>
<td><span>保存对类别所做的任何更改。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Sat, 10 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2目录搜索概述]]></title>
      <link>https://www.360magento.com/blog/Catalog-search-overview/</link>
      <description><![CDATA[<p><span><span>研究表明，使用搜索的人比仅依赖导航的人更有可能进行购买。</span><span>事实上，根据一些研究，使用搜索的人进行购买的可能性几乎是其他人的两倍。</span></span></p>
<p><span>以下部分介绍了客户如何在您的目录中搜索产品，以及您如何配置目录搜索。</span></p>
<h2 id="quick-search"><span>快速搜索</span></h2>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span></span>安装Live Search<span><span>后，搜索框会在弹出窗口中返回&ldquo;键入时搜索&rdquo;结果</span><span>。</span></span></p>
</div>
</div>
<p><span><span>商店标题中的搜索框可帮助访问者在您的目录中查找产品。</span><span>搜索文本可以是完整或部分产品名称或描述产品的任何其他词或短语。</span><span>人们用来查找产品的搜索词可以从管理员管理。</span></span></p>
<ol>
<li>
<p><span>对于</span><span>搜索</span><span>，客户输入他们想要查找的内容的前几个字母。</span></p>
<p><span>目录中的所有匹配项以及找到的结果数显示在下方。</span></p>
</li>
<li>
<p><span>客户按下 Enter 键或单击匹配产品列表中的结果。</span></p>
<p><img alt="搜索" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-box.png?lang=en" /></p>
</li>
</ol>
<h2 id="advanced-search"><span>高级搜索</span></h2>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>此处描述的高级表单搜索功能不适用于</span>Live Search<span>。</span></p>
</div>
</div>
<p><span><span>高级搜索让购物者可以根据输入到表单中的值搜索目录。</span><span>因为表单包含多个字段，所以一次搜索可以包含多个参数。</span><span>结果是目录中符合条件的所有产品的列表。</span><span>高级搜索的链接位于您商店的页脚中。</span></span></p>
<p><img alt="高级搜索" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-advanced.png?lang=en" /></p>
<p><span><span>表单中的每个字段对应于您产品目录中的一个属性。</span><span>要添加字段，请将属性的前端属性设置为</span></span><code>Include in Advanced Search</code><span><span>。</span><span>作为最佳做法，请仅包括客户最有可能用来查找产品的字段，因为太多会减慢搜索速度。</span></span></p>
<ol>
<li>
<p><span>在商店的底部，客户单击</span><span>Advanced Search</span><span>。</span></p>
</li>
<li>
<p><span>在</span><em>高级搜索</em><span>表单中，根据需要在尽可能多的字段中添加完整或部分值。</span></p>
</li>
<li>
<p><span>单击</span><span>搜索</span><span>以显示结果。</span></p>
<p><img alt="搜索结果" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-search-advanced-results-modify.png?lang=en" /></p>
</li>
<li>
<p><span>如果他们在搜索结果中看不到他们要查找的内容，客户会单击&ldquo;</span><span>修改您的搜索</span><span>&rdquo;并尝试其他条件组合。</span></p>
</li>
</ol>]]></description>
      <pubDate>Fri, 09 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2目录导航]]></title>
      <link>https://www.360magento.com/blog/Catalog-navigation/</link>
      <description><![CDATA[<p><span>术语</span><em>导航</em><span><span>是指购物者在整个商店中从一个页面移动到另一个页面的方法。</span><span>您商店的主菜单或顶部导航实际上是一个类别链接列表，可让您轻松访问目录中的产品。</span><span>在出现在大多数页面顶部的面包屑路径中以及出现在某些两列或三列页面左侧的分层导航中也有类别。</span><span><br /></span></span></p>
<p><span>对于要在您的商店中可见的产品，必须将其分配到至少一个类别</span><span><span>。</span><span>每个类别都可以有一个专用的登录页面，其中包含图像、静态块、描述和类别中的产品列表。</span><span>您还可以为仅在特定时间段（例如假期或促销）活动的类别页面创建特殊设计。</span></span></p>
<p><img alt="店面目录导航" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/storefront-menu-levels.png?lang=en" /></p>]]></description>
      <pubDate>Thu, 08 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2配置目录媒体 URL 格式]]></title>
      <link>https://www.360magento.com/blog/Configure-catalog-media-URL-format/</link>
      <description><![CDATA[<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>General</span><span>并选择</span><span>Web</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>Url Options</span></span><span>部分并设置选项</span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span>：</span><span><span></span></span><span></span></p>
</li>
</ol>
<p><img alt="网页 &gt; 常规选项" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/web-url-options.png?lang=en" /></p>
<div class="table-container">
<table>
<thead>
<tr><th><span>场地</span></th><th><a href="https://experienceleague.adobe.com/docs/commerce-admin/start/setup/websites-stores-views.html?lang=en#scope-settings">范围</a></th><th><span>描述</span></th></tr>
</thead>
<tbody>
<tr>
<td><span>将商店代码添加到 URL</span></td>
<td><span>全球的</span></td>
<td><span><span>如果启用了 Web 服务器重写，则会在 URL 中插入当前视图的商店代码。</span><span>选项：是/否</span></span></td>
</tr>
<tr>
<td><span>自动重定向到基本 URL</span></td>
<td><span>全球的</span></td>
<td><span><span>（对于单一商店设置）如果您的网站上有损坏的链接，这会将流量重定向到基本 URL，而不是带有&ldquo;404 页面未找到&rdquo;消息的页面。</span><span>选项：No / Yes (302 Found) / Yes (301 Moved Permanently)</span></span><br /><br /><span><em>重要！</em></span><span>不要使用自动重定向到多商店设置的基本 URL。</span></td>
</tr>
<tr>
<td><span>目录媒体 URL 格式</span></td>
<td><span>全球的</span></td>
<td><span><span>定义分配给产品和类别的 URL 格式。</span><span>选项：</span></span><br /><span>每个图像变体的唯一哈希值（传统模式）</span><span>&nbsp;- 将转换后的文件名定义为唯一的哈希值。</span><br /><span>基于查询参数的</span><span>图像优化- 根据查询参数定义</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/content-design/media/gallery/media-gallery-image-optimization.html?lang=en">图像优化</a><span>过程。</span></td>
</tr>
</tbody>
</table>
</div>]]></description>
      <pubDate>Wed, 07 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2配置目录 URL]]></title>
      <link>https://www.360magento.com/blog/Configure-catalog-URLs/</link>
      <description><![CDATA[<ol>
<li>
<p><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>Stores</span><span>&nbsp;&gt;&nbsp;</span><em>Settings</em><span>&nbsp;&gt;&nbsp;</span><span>Configuration</span><span>。</span></p>
</li>
<li>
<p><span>在左侧面板中，展开</span><span>目录</span><span>并选择下面的</span><span>目录</span><span>。</span></p>
</li>
<li>
<p><span><span>展开</span><span><span>搜索引擎优化</span></span></span><img alt="扩展选择器" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/icon-display-expand.png?lang=en" /><span><span>部分并</span><span>设置选项：</span></span><span><span></span></span><span></span></p>
<ul>
<li>
<p><span>将</span><span>产品 URL 后缀</span><span>设置为</span><code>html</code><span>或</span><code>htm</code><span><span>。</span><span>输入不带句点的后缀，因为它是自动应用的。</span></span></p>
</li>
<li>
<p><span>将</span><span>类别 URL 后缀</span><span>设置为</span><code>html</code><span>或</span><code>htm</code><span><span>。</span><span>输入不带句点的后缀，因为它是自动应用的。</span></span></p>
</li>
<li>
<p><span><span>根据您的喜好</span><span>设置</span></span><span>产品 URL 的使用类别路径。</span><span></span></p>
</li>
</ul>
<p><img alt="搜索引擎优化" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/catalog-search-engine-optimization_c1.png?lang=en" /></p>
<p><span><span>有关这些选项的更多信息，请参阅</span><em><span>配置参考</span></em><span>中的</span></span><a href="https://docs.magento.com/user-guide/configuration/catalog/catalog.html#search-engine-optimization">搜索引擎优化</a><span>。</span><em><span></span></em><span></span></p>
</li>
<li>
<p><span>完成后，单击</span><span>保存配置</span><span>。</span></p>
</li>
<li>
<p><span>出现提示时，单击系统消息中的</span><span>缓存管理</span><span>链接并刷新无效缓存。</span></p>
<p><img alt="刷新缓存" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/msg-cache-management.png?lang=en" /></p>
<p><span>有关这些选项的更多信息，请参阅</span><a href="https://docs.magento.com/user-guide/system/cache-management.html">刷新缓存</a><span>。</span></p>
</li>
</ol>]]></description>
      <pubDate>Tue, 06 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2网址组件]]></title>
      <link>https://www.360magento.com/blog/URL-components/</link>
      <description><![CDATA[<h3 id="url-key"><span>网址键</span></h3>
<p><span><span>URL 键是描述产品或类别的静态 URL 的一部分。</span><span>当您创建产品或类别时，会根据名称自动生成初始 URL 密钥。</span><span>要更改 URL 密钥，请参阅产品信息的</span></span>搜索引擎优化<span>部分。</span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span><span>带重音的特殊字符会自动替换为 URL 键中的常规非重音版本。</span><span>例如，</span></span><code>&ntilde;</code><span>自动替换为</span><code>n</code><span>。</span></p>
</div>
</div>
<p><span><span>URL 键应由小写字符组成，这些字符之间有非尾随连字符以分隔单词。</span><span>不允许在 URL 键的开头或结尾使用连字符。</span><span>一个设计良好、&ldquo;搜索引擎友好&rdquo;的 URL 键可能包括产品名称和关键词，以改进它被搜索引擎索引的方式。</span><span>URL 键可以配置为在 URL 键更改时创建自动重定向。</span></span></p>
<div class="extension note">
<div><span><span>笔记</span></span></div>
<div>
<p><span>要扩展 URL 自定义，例如本地化 URL，请参阅</span>URL 重写<span>以获取更多信息。</span></p>
</div>
</div>
<h3 id="html-suffix"><span>后缀</span></h3>
<p><span><span>您的目录可以配置为包含或排除后缀作为类别和产品 URL 的一部分。</span><span>人们可能选择使用或省略后缀的原因有多种。</span><span>有些人认为后缀不再有任何用处，没有后缀的页面可以更有效地被搜索引擎索引。</span><span>但是，您的公司可能有需要后缀的标准化 URL 格式。</span></span></p>
<p><span><span>由于后缀由系统配置控制，因此您永远不应将其直接输入到类别或产品的 URL 键中。</span><span>（这样做会导致 URL 末尾出现双后缀。）无论您是否决定使用后缀，都要保持一致，并为所有产品和类别页面使用相同的设置。</span><span>以下是带有和不带有后缀的 URL 示例。</span></span></p>
<h4 id="url-with-html-suffix"><span>带有 HTML 后缀的 URL</span></h4>
<ul>
<li><code>http://mystore.com/helena-hooded-fleece.html</code></li>
<li><code>http://mystore.com/helena-hooded-fleece.htm</code></li>
</ul>
<h4 id="url-without-html-suffix"><span>没有 HTML 后缀的 URL</span></h4>
<ul>
<li><code>http://mystore.com/helena-hooded-fleece</code></li>
</ul>
<h3 id="category-path"><span>类别路径</span></h3>
<p><span><span>您可以将 URL 配置为包含或排除类别路径。</span><span>默认情况下，类别路径包含在所有类别和产品页面中。</span><span>以下示例显示了带有和不带有类别路径的相同产品 URL。</span></span></p>
<h4 id="url-with-category-path"><span>带有类别路径的 URL</span></h4>
<ul>
<li><code>http://mystore.com/women/tops-women/hoodies-and-sweatshirts-women/helena-hooded-fleece.html</code></li>
</ul>
<h4 id="url-without-category-path"><span>没有类别路径的 URL</span></h4>
<ul>
<li><code>http://mystore.com/helena-hooded-fleece.html</code></li>
</ul>
<p><span><span>为防止搜索引擎索引指向相同内容的多个 URL，您可以从 URL 中排除类别路径。</span><span>另一种方法是使用规范的元标记让搜索引擎知道要索引哪些 URL 以及要忽略哪些 URL。</span><span>默认情况下，Commerce 不在产品 URL 中包含类别路径。</span></span></p>]]></description>
      <pubDate>Mon, 05 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2网址格式]]></title>
      <link>https://www.360magento.com/blog/URL-formats/</link>
      <description><![CDATA[<h3 id="dynamic-url"><span>动态网址</span></h3>
<p><span>动态 URL 是</span><em>即时创建的</em><span><span>，可能包含一个查询字符串，其中包含产品 ID、排序顺序和发出请求的页面的变量。</span><span>当客户在您的商店中搜索产品时，生成的 URL 可能如下所示：</span></span></p>
<ul>
<li><code>http://mystore.com/catalogsearch/result/?q=racer+back</code></li>
<li><code>http://mystore.com/women/tops-women.html?style_general=135</code></li>
</ul>
<h3 id="static-url"><span>静态网址</span></h3>
<p><span><span>静态 URL 是特定页面的固定地址。</span><span>静态 URL 可以以搜索引擎友好的格式或按 ID 引用产品和类别的格式显示。</span><span>搜索引擎友好的 URL 包括人们可能用来查找产品的词，并且需要启用 Web 服务器重写。</span><span>具有静态 URL 的文件通常用于产品和类别页面、内容页面和</span></span>主题资产<span>。</span></p>
<ul>
<li><code>http://mystore.com/antonia-racer-tank.html</code></li>
</ul>]]></description>
      <pubDate>Sun, 04 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2目录菜单]]></title>
      <link>https://www.360magento.com/blog/Catalog-menu/</link>
      <description><![CDATA[<p><span>目录菜单提供对产品创建、类别和库存管理工具的轻松访问，以及用于</span>B2B 商店<span>自定义定价的共享目录。</span></p>
<p><img alt="目录菜单" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/admin-menu-catalog.png?lang=en" /></p>
<p><span>在</span><em>管理</em><span>侧边栏上，单击</span><span>目录</span><span>。</span></p>
<h2 id="products"><span>产品</span></h2>
<p><span>创建各种类型的</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/products/products-list.html?lang=en">产品</a><span>并管理您的库存。</span></p>
<p><img alt="产品网格" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/products-grid.png?lang=en" /></p>
<h2 id="categories"><span>类别</span></h2>
<p><span>创建作为商店导航基础的</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/catalog/categories/categories.html?lang=en">类别</a><span>结构。</span></p>
<p><img alt="类别工作区" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/category-workspace.png?lang=en" /></p>
<h2 id="shared-catalogs"><span>共享目录</span></h2>
<p><span>对于安装并启用了 B2B for Adob​​e Commerce 的商店，</span><a href="https://experienceleague.adobe.com/docs/commerce-admin/b2b/shared-catalogs/catalog-shared.html?lang=en">共享目录</a><span>使您能够为不同的公司提供自定义定价。</span></p>
<p><img alt="共享目录产品" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/shared-catalog-select-products-step-1.png?lang=en" /></p>]]></description>
      <pubDate>Sat, 03 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2为不同的视图编辑产品]]></title>
      <link>https://www.360magento.com/blog/Edit-a-product-for-a-different-view/</link>
      <description><![CDATA[<p><span>对于具有多个网站、商店和视图的安装，</span>范围<span><span>设置确定产品可用于销售的位置，以及可用于每个商店视图的产品信息。</span><span>最初，您创建的所有产品都发布到默认网站、商店和商店视图。</span></span></p>
<ol>
<li></li>
<ol>
<li>
<p><span>在左上角，将</span><span>Store View</span><span>设置为要编辑的具体视图。</span></p>
</li>
<li>
<p><span>单击</span><span>确定</span><span>以确认范围更改。</span></p>
<p><img alt="商店视图" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-store-view-spanish-racer-tank.png?lang=en" /></p>
</li>
<li>
<p><span>使用商店视图的新值更新该字段。</span></p>
<p><span><span>可以为商店视图编辑的任何字段下方都会出现一个复选框。</span><span>要覆盖默认值，请取消选择&ldquo;</span></span><span>使用默认值</span><span>&rdquo;复选框。</span></p>
<p><img alt="为西班牙语商店视图翻译产品名称" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-translate-field-spanish.png?lang=en" /></p>
</li>
<li>
<p><span>完成后，点击</span><span>保存</span><span>。</span></p>
</li>
<li>
<p><span>在左上角，将</span><span>商店视图</span><span>选择器设置回默认值。</span></p>
</li>
<li>
<p><span>要验证商店中的更改，请执行以下操作：</span></p>
</li>
<ul>
<li>
<p><span>在右上角，单击</span><em>管理</em><span>菜单箭头并选择</span><span>客户视图</span><span>。</span></p>
<p><img alt="客户观" src="https://experienceleague.adobe.com/docs/commerce-admin/assets/product-admin-menu-customer-view.png?lang=en" /></p>
</li>
<li>
<p><span>在商店的右上角，将</span><span>语言</span><span>选择器设置为您编辑的产品的商店视图，并找到您为该视图编辑的产品。</span></p>
</li>
<li><span><img src="https://www.360magento.com/media/wysiwyg/blog_1229/4.png" width="860" /></span></li>
</ul>
</ol></ol>]]></description>
      <pubDate>Fri, 02 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置默认​​页面布局]]></title>
      <link>https://www.360magento.com/blog/configure-default-page-layout-magento-2/</link>
      <description><![CDATA[<p><span><span><span>你知道吗？</span><span>使用默认的 Magento，您可以更改商店布局。</span><span>这可以直接从 Magento 后端完成。</span></span></span></p>
<p><span><span><span>建立电子商务商店最重要的步骤之一是决定它的外观和感觉。</span><span>根据您的设计思路优化正确的页面布局将产生最佳的客户体验。</span></span></span></p>
<p><span><span><span>商店页面的页眉、页脚和内容区域由部分或容器分隔。</span><span>每页的列数取决于布局。</span></span></span></p>
<p></p>
<h2><span id="How_To_Configure_Default_Page_Layout_In_Magento_2">如何在 Magento 2 中配置默认​​页面布局？</span></h2>
<p><span><img src="https://www.360magento.com/media/wysiwyg/default-layout.png" /></span></p>
<ul>
<li><span>登录到 Magento 管理员。</span></li>
<li><span>前往</span><span>商店 &rarr; 设置 &rarr; 配置。</span></li>
<li><span>转到</span><span>Web &rarr; 默认布局</span></li>
<li><span>您可以在此处从下拉菜单中更改默认产品布局和类别布局。</span></li>
<li><span>选择您选择的页面布局以显示在前端。</span></li>
<li><span>保存配置。</span></li>
</ul>]]></description>
      <pubDate>Thu, 01 Dec 2022 08:32:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中安装和设置 Varnish 缓存]]></title>
      <link>https://www.360magento.com/blog/How-to-Install-and-Setup-Varnish-cache-in-Magento2/</link>
      <description><![CDATA[<p><span><span>缓存是任何网站的关键部分。</span><span>对于像 Magento 2 这样的重型平台，缓存变得更加重要。通过使用缓存，商家可以减少页面加载时间，加快页面响应，从而创造更好的用户体验。</span></span></p>
<p><span><span>Magento 2 中最流行的缓存技术之一是 Varnish。</span><span>Varnish 作为一个完整的页面缓存机制来减少 Magento 2 服务器的工作量。</span><span>因此，性能得到改善。</span></span></p>
<p><span><span>Varnish Cache 是一个开源的 Web 应用程序加速器（HTTP 代理）。</span><span>Varnish 将数据存储在内存中。</span><span>这使 Varnish 能够减少期货的响应时间和网络带宽消耗。</span><span>与 Apache 和 Nginx 等 Web 服务器不同，Varnish 专为与 HTTP 协议一起使用而设计。</span></span></p>
<h2><span>如何在 Magento 2 中安装 Varnish</span></h2>
<p><span>Magento 有自己的缓存机制（读取、写入数据到文件），但效率不够高。</span><br /><span><span>Magento 本身强烈推荐 Varnish 为其用户。</span><span>要在 Magento 2 上运行 Varnish，您需要安装 Varnish 并将 Varnish 配置文件（VCL 文件）部署到系统中的 Varnish 实现中。</span></span></p>
<p><span>以 root 用户 (sudo su) 运行以下一系列命令。</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">apt<span class="token operator">-</span>get install apt<span class="token operator">-</span>transport<span class="token operator">-</span>https
curl https<span class="token punctuation">:</span><span class="token comment">//repo.varnish-cache.org/GPG-key.txt | apt-key add -</span>
<span class="token keyword">echo</span> <span class="token double-quoted-string string">"deb https://repo.varnish-cache.org/ubuntu/ trusty varnish-4.1"</span> \
     <span class="token operator">&gt;</span><span class="token operator">&gt;</span> <span class="token operator">/</span>etc<span class="token operator">/</span>apt<span class="token operator">/</span>sources<span class="token punctuation">.</span><span class="token keyword">list</span><span class="token punctuation">.</span>d<span class="token operator">/</span>varnish<span class="token operator">-</span>cache<span class="token punctuation">.</span><span class="token keyword">list</span>
apt<span class="token operator">-</span>get update
apt<span class="token operator">-</span>get install varnish</pre>
<p><span>如果一切顺利，您应该能够看到 Varnish 版本：</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">varnishd <span class="token operator">-</span><span class="token constant">V</span></pre>
<h2><span>如何在 Magento 2 中配置 Varnish</span></h2>
<h3><span>第一步：修改webserver监听端口</span></h3>
<p><span>安装 Varnish 后，您需要配置当前的 Web 服务器。</span></p>
<p><span>将您的网络服务器配置为侦听默认端口 (80) 以外的端口 (8080)。</span></p>
<p><span>找到您当前的&ldquo;服务器&rdquo;指令并将监听端口更改为 8080。</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">server <span class="token punctuation">{</span>
    listen <span class="token number">8080</span> default_server<span class="token punctuation">;</span>
    server_name  your<span class="token operator">-</span>magento2<span class="token operator">-</span>store<span class="token punctuation">.</span>dev<span class="token punctuation">;</span>
    <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span></pre>
<h3><span>第二步：修改default.vcl</span></h3>
<p><span>备份旧的默认值</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">cp <span class="token operator">/</span>etc<span class="token operator">/</span>varnish<span class="token operator">/</span><span class="token keyword">default</span><span class="token punctuation">.</span>vcl <span class="token operator">/</span>etc<span class="token operator">/</span>varnish<span class="token operator">/</span><span class="token keyword">default</span><span class="token punctuation">.</span>vcl<span class="token punctuation">.</span>bak</pre>
<p><span>从 Magento 2 后端下载默认 VCL 配置。</span></p>
<p><span><span>转到商店 &gt; 配置 &gt; 高级 &gt; 系统 &gt; 整页缓存。</span><span>单击&ldquo;缓存应用程序&rdquo;下拉框。</span><span>从列表中选择&ldquo;清漆缓存&rdquo;。</span></span></p>
<p><span>下载与您在系统中安装的清漆等效的清漆文件版本。</span></p>
<p><img alt="" class="wp-image-3508" src="https://store.magenest.com/wp/wp-content/uploads/2019/08/Varnish-cache-magento-2-download-default-vcl.png" /><span>Magento 2 中的清漆配置</span></p>
<p><span>复制这个你刚刚导出的文件到 /etc/varnish/default.vcl</span></p>
<p><span>查找并编辑下面的行</span><code>backend default</code></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token shell-comment comment"># Default backend definition. Set this to point to your content server.</span>
backend <span class="token keyword">default</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span>host <span class="token operator">=</span> <span class="token double-quoted-string string">"127.0.0.1"</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span>port <span class="token operator">=</span> <span class="token double-quoted-string string">"8080"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></pre>
<p><span>在哪里</span></p>
<ul>
<li><span><span>.host &ndash; Varnish 后端或源服务器的完全限定主机名或 IP 地址和监听端口；</span><span>也就是说，提供内容 Varnish 的服务器会加速。</span><span>通常，这是您的 Web 服务器。</span></span></li>
<li><span>.port &ndash; Web 服务器的监听端口（本例中为 8080）</span></li>
</ul>
<h3><span>第三步：配置Nginx端口80（或443）传给Varnish</span></h3>
<p><span>打开 Nginx 配置文件（位于 /path/to/nginx/sites-enabled/default）</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">server <span class="token punctuation">{</span>
    listen <span class="token number">80</span><span class="token punctuation">;</span>
    location <span class="token operator">/</span> <span class="token punctuation">{</span>
          proxy_pass http<span class="token punctuation">:</span><span class="token comment">//127.0.0.1:6081/;</span>
          proxy_set_header Host <span class="token variable">$host</span><span class="token punctuation">;</span>  
    	proxy_set_header <span class="token constant">X</span><span class="token operator">-</span>Forwarded<span class="token operator">-</span>Host <span class="token variable">$http_host</span><span class="token punctuation">;</span>
	proxy_set_header <span class="token constant">X</span><span class="token operator">-</span>Real<span class="token operator">-</span><span class="token constant">IP</span> <span class="token variable">$remote_addr</span><span class="token punctuation">;</span>
	proxy_set_header <span class="token constant">X</span><span class="token operator">-</span>Forwarded<span class="token operator">-</span><span class="token keyword">For</span> <span class="token variable">$proxy_add_x_forwarded_for</span><span class="token punctuation">;</span>
		proxy_set_header Ssl<span class="token operator">-</span>Offloaded <span class="token double-quoted-string string">"1"</span><span class="token punctuation">;</span>
		proxy_set_header      <span class="token constant">X</span><span class="token operator">-</span>Forwarded<span class="token operator">-</span>Port <span class="token number">443</span><span class="token punctuation">;</span>
		proxy_set_header <span class="token constant">X</span><span class="token operator">-</span>Forwarded<span class="token operator">-</span>Proto https<span class="token punctuation">;</span>
		proxy_set_header <span class="token constant">X</span><span class="token operator">-</span>Forwarded<span class="token operator">-</span>Ssl on<span class="token punctuation">;</span>

<span class="token punctuation">}</span></pre>
<p><span>6081 是 varnish 的默认端口。</span></p>
<p><span>最后，重启 Varnish &amp; Nginx（或 apache）</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">service nginx restart
service varnish restart</pre>
<h2><span>如何在 Magento 2 中验证清漆</span></h2>
<h3><span>第一步：检查 Varnish 是否监听 6081 端口</span></h3>
<p><span>netstat -tulpn | grep varnished</span></p>
<h3><span>第二步：验证var/cache中的内容，var/page_cache文件夹没有重新生成</span></h3>
<p><span>由于 FPC 配置为从 Varnish 提供内容，因此一旦清除，缓存文件夹（var/cache、var/page_cache）应始终为空。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Tue, 08 Nov 2022 08:24:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中更改产品图片尺寸]]></title>
      <link>https://www.360magento.com/blog/Change-product-image-sizes-in-Magento2/</link>
      <description><![CDATA[<p><span><span>产品图片是电子商务商店的重要视觉元素，因为它不仅提供了有关产品的更多信息，而且在客户第一次访问时就给他们留下了良好的印象。</span><span>吸引人的图像通过将文本中的所有功能显示为可视化来满足产品描述。</span><span>通过这种方式，转化率显着提高。</span></span></p>
<p><span><span>让我们谈谈图像大小。</span><span>在 Magento 产品图像中，缩略图图像等可以轻松调整大小以获得更好的视觉体验。</span><span>它还可以潜在地提高网站的加载速度。<br /></span></span></p>
<p><span>假设您要将类别网格产品图像的大小调整为&nbsp;</span><span>300px</span><span>&nbsp;x&nbsp;</span><span>450px</span><span>（原始：</span><span>240px</span><span>&nbsp;x&nbsp;</span><span>300px</span><span>），如下所示。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/1.png" width="800" /></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/2.png" width="800" /></span></p>
<p><span>在本博客中，我们将向您展示如何在 Magento 2 中更改产品图像大小。</span></p>
<h2><span>第 1 步 - 查找 view.xml 文件</span></h2>
<p><span>几乎所有产品图片的配置都包含在</span><span>view.xml 中</span><span><span>（包括宽度和高度）。</span><span>因此，如果您想在 Magento 2 中更改 resize 产品图像，则需要调整</span></span><span>view.xml</span><span>文件。</span></p>
<p><span>主题 的</span><span>view.xml</span><span>的常规位置是</span><span>&lt;theme_dir&gt;/etc/view.xml</span><span>。</span></p>
<p><span>例如：</span><span>app/design/Magenest/beauty/etc/view.xml</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/3.png" width="800" /></div>
<p><span>如果您的主题没有</span><span>view.xml</span><span><span>文件，只需在您的父主题 etc/ 文件夹中找到它并复制到您的主题文件夹。</span><span>这遵循 Magento 的后备机制。</span></span></p>
<p><span></span><span>view.xml</span><span><span>的位置</span><span>因您使用</span></span><span>Magento Blank</span><span>主题或</span><span>Magento Luma</span><span>主题而异：</span></p>
<ul>
<li><span>Magento/Blank：</span><span>供应商/magento/theme-frontend-blank/etc/view.xml</span></li>
<li><span>Magento/Luma：</span><span>供应商/magento/theme-frontend-luma/etc/view.xml</span></li>
</ul>
<p><span><span>Magento 不推荐覆盖核心的代码，所以你不应该修改这些文件。</span><span>最好复制到</span></span><span>app/</span><span>文件夹中的一个新的来修改它。</span></p>
<h2><span>第 2 步 - 找到正确的图像 ID 并输入</span></h2>
<p><span>在</span><span>view.xml 中，图像属性在</span><span></span><span>&lt;images&gt;</span><span><span>元素</span><span>的范围内配置：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>view</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:Config/etc/view.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>media</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>images</span> <span class="token attr-name">module</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento_Catalog<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
           <span class="token comment">&lt;!-- Product images are configured within this element scope --&gt;</span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>bundled_product_customization_page<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>thumbnail<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span>140<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span>140<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>cart_cross_sell_products<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>thumbnail<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span>152<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span>188<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>cart_page_product_thumbnail<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>small_image<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span>110<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span>160<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>category_page_grid<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>small_image<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span>275<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span>275<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>category_page_list<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>small_image<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span>275<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span>275<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span></pre>
<p><span><span>Magento 中的每个产品图像都有一个 id 和 type 属性。</span><span>它们在</span></span><span>view.xml</span><span>内的 &lt;image&gt; 节点中定义：</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>images</span> <span class="token attr-name">module</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento_Catalog<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>unique_image_id<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>image_type<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
	...
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>images</span><span class="token punctuation">/&gt;</span></span></pre>
<p><span>查找包含产品图像定义的图像唯一 ID。</span></p>
<p><span>在我们的情况下，图像 id 是</span><span>&lt;image id="category_page_grid" type="small_image"&gt;</span><span>。</span></p>
<p><span>提示</span><span><span>：要查找图像 id，请找到宽度和高度与输出图像完全相同的节点。</span><span>假设您的图像是 700px x 700px 。</span><span>找到具有 &lt;width&gt;700&lt;/width&gt; 和 &lt;height&gt;700&lt;/height&gt; 的节点</span></span></p>
<h2><span>第 3 步 - 在 Magento 2 中配置产品图片</span></h2>
<p><span>找到包含产品图片配置的元素后，更改 &lt;&nbsp;</span><span>width</span><span>&nbsp;&gt; 和 &lt;&nbsp;</span><span>height</span><span>&nbsp;&gt; 节点的值</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>images</span> <span class="token attr-name">module</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento_Catalog<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>image</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>category_page_grid<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>small_image<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>width</span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!-- Replace this with width in px : 300--&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>width</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>height</span><span class="token punctuation">&gt;</span></span><span class="token comment">&lt;!-- Replace this with height in px: 450 --&gt;</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>height</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>image</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>images</span><span class="token punctuation">&gt;</span></span></pre>
<h2><span>第 4 步 - 清理缓存</span></h2>
<p><span>清理 Magento 缓存以应用配置。</span></p>
<ul>
<li><span><span>您可以转到系统 -&gt; 工具 -&gt; 缓存管理。</span><span>然后单击 Flush Magento Cache 按钮以清除 Magento Cache。</span></span></li>
</ul>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/4.png" width="800" /></div>
<ul>
<li><span>或者您可以使用命令行执行此操作：</span><span>php bin/magento cache:flush</span></li>
</ul>
<p><span>在某些情况下，您可能希望调整店面上所有图像的大小，以便立即提供它们，这将加快第一次加载时的页面加载速度。</span></p>
<p><span>这可能是必要的情况可能是：</span></p>
<ul>
<li><span>导入产品后，可能有各种尺寸的图像</span></li>
<li><span>如果图像尺寸发生变化</span></li>
<li><span>图像缓存已刷新</span></li>
</ul>
<p><span>从 Magento 根文件夹运行此命令：&nbsp;</span><span>php bin/magento catalog:images:resize</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/5.png" width="800" /></div>
<p><span>之后，您的所有类别网格图像都已调整大小。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1026/6.png" width="800" /></div>
<h2><span>包起来</span></h2>
<p><span><span>Magento 提供了许多有用的功能来处理产品及其图像。</span><span>今天，我们学习了配置产品视觉外观方面最重要的功能之一。</span></span></p>
<p></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Mon, 07 Nov 2022 08:32:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[覆盖 Magento 2 布局：基本布局和主题布局]]></title>
      <link>https://www.360magento.com/blog/Override-Magento2-Layout-Base-Layout-Theme-Layout/</link>
      <description><![CDATA[<h2><span>1 Magento 2 核心布局是什么？</span></h2>
<p><span><span>页面的基本组件是布局、容器和块。</span><span>布局表示网页的结构。</span><span>容器代表该网页结构中的占位符。</span><span>块代表容器占位符内的 UI 控件或组件。</span></span></p>
<p><span><span>在这篇博客中，我们将解释如何覆盖 Magento 2 布局。</span><span>Magento 2 中的布局 xml 文件描述了页面结构。</span></span></p>
<p><span>强烈建议您在想要完全取消使用核心的布局文件并定义自己的布局时覆盖布局文件。</span></p>
<p><span><span>不要重写 Magento 2 核心文件。</span><span>为了保证您的修改安全，您应该覆盖或扩展自定义主题中的布局文件。</span></span></p>
<h2><span>2 2 种 Magento 2 核心布局：基础布局和主题布局</span></h2>
<p><span>Magento 2 布局分为两种类型的布局：</span><span>基本布局</span><span>和</span><span>主题布局</span><span><span>。</span><span>这是它们之间的主要区别。</span></span></p>
<h3><span>2.1 基地布局</span></h3>
<p><span><span>基本布局文件由模块提供。</span><span>我们可以在这个路径上找到这些文件：&nbsp;</span></span></p>
<ul>
<li><span>配置和一般布局文件：</span><span>&nbsp;{module_dir}/view/frontend/layout/</span></li>
<li><span>页面布局文件：</span><span>&nbsp;{module_dir}/view/frontend/page_layout/</span></li>
</ul>
<h3><span>2.2 主题布局</span></h3>
<p><span><span>主题布局由 Magento 主题提供。</span><span>我们可以在这条路径上找到它们：</span></span></p>
<ul>
<li><span>配置和一般布局文件：</span><span>&nbsp;{theme_dir}/Namespace_Module/layout/</span></li>
<li><span>页面布局文件：</span><span>&nbsp;{theme_dir}/Namespace_Module/page_layout/</span></li>
</ul>
<h2><span>3 覆盖核心布局</span></h2>
<p><span>当我们执行自定义时，我们可以覆盖布局，这意味着您放置在主题中的新文件将被使用，而不是父主题布局文件或基础布局文件。</span></p>
<h3><span>3.1 覆盖基础布局</span></h3>
<p><span>添加覆盖的基本布局文件（覆盖模块提供的基本布局）：</span></p>
<p><span>将同名的布局文件放在以下位置：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;theme_dir&gt; </span><span>
  |__/&lt;Namespace_Module&gt; </span><span>
     |__/layout </span><span>
       |__/override </span><span>
          |__/base </span><span>
            |--&lt;layout1&gt;.xml </span><span>
            |--&lt;layout2&gt;.xml</span></pre>
<p><span>这些文件覆盖以下布局：</span></p>
<ul>
<li><span>&lt;module_dir&gt;/view/frontend/layout/&lt;layout1&gt;.xml</span></li>
<li><span>&lt;module_dir&gt;/view/frontend/layout/&lt;layout2&gt;.xml</span></li>
</ul>
<p><span>例如：</span></p>
<ul>
<li><span>&lt;theme_dir&gt;/Magento_Customer/layout/override/base/default.xml 将覆盖</span></li>
<li><span>vendor/magento/module-customer/view/frontend/layout/default.xml （或 app/code/Magento/Customer/view/frontend/layout/default.xml 如果您使用 github 版本）</span></li>
</ul>
<h3><span>3.2 覆盖主题布局</span></h3>
<p><span>要覆盖父主题布局：</span></p>
<p><span>将同名的布局文件放在以下位置：</span></p>
<p><em>&lt;theme_dir&gt;</em></p>
<p><em>&nbsp;&nbsp;|__/&lt;Namespace_Module&gt;</em></p>
<p><em>&nbsp;&nbsp;&nbsp; &nbsp;|__/layout</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;|__/override</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;|__/theme</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |__/&lt;Parent_Vendor&gt;</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;|__/&lt;parent_theme&gt;</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;|--&lt;layout1&gt;.xml</em></p>
<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;|--&lt;layout2&gt;.xml</em></p>
<p><span>这些文件覆盖以下布局：</span></p>
<ul>
<li><span>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout1&gt;.xml</span></li>
<li><span>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout2&gt;.xml</span></li>
</ul>
<p><span>要覆盖页面布局文件，请使用 page_layout 目录名称而不是布局。</span></p>
<h2><span>4 结论</span></h2>
<p><span><span>覆盖布局文件为主题定制创造了有利条件。</span><span>但是，您需要记住，覆盖的布局文件不受对主文件的任何更改的影响，如果您不仔细检查正在更新的文件，这反过来可能会导致将来升级 Magento 2 时出现问题。</span></span></p>
<p><span>因此，应该非常小心地使用覆盖，并且只在真正需要并且不能没有它的情况下使用。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Sun, 06 Nov 2022 08:29:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中为购物车中的产品设置自定义价格]]></title>
      <link>https://www.360magento.com/blog/How-to-set-custom-Price-for-Products-in-Cart-in-Magento2/</link>
      <description><![CDATA[<p><span><span>为了在产品页面或小部件上显示产品价格，Magento 从基本价格、特价、等级价格或目录规则价格之一计算最低价格。</span><span>可配置产品可以为子产品设置自己的价格，捆绑产品可以对捆绑应用固定价格。</span><span>然后，当将产品添加到购物车时，其价格也会受到购物车价格规则的影响。</span></span></p>
<p><span><span>在本文中，我们将展示如何将您的自定义价格添加到购物车中的产品中。</span><span>此操作将覆盖 Magento 计算的价格。</span></span></p>
<h2><span>购物车中产品的自定义价格</span></h2>
<p><span>以下是可以帮助您实现这一目标的 2 个简单步骤：</span></p>
<p><span>首先，安装自定义模块后，您声明一个名为 events.xml 的文件以捕获在将产品添加到购物车后发生的事件。</span></p>
<p><span>&lt;供应商名称&gt;/&lt;模块名称&gt;/etc/frontend/events.xml</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>config</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:Event/etc/events.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>event</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>checkout_cart_product_add_after<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>observer</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>customPriceInCart<span class="token punctuation">"</span></span> <span class="token attr-name">instance</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>VendorName\ModuleName\Observer\CustomPriceInCart<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>event</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>config</span><span class="token punctuation">&gt;</span></span></pre>
<p><span>在这里，您声明了一个名为 customPriceInCart 的观察者，它将处理每次将产品添加到购物车时 Magento 调度的事件 checkout_cart_product_add_after。&nbsp;</span></p>
<p><span>接下来，我们创建观察者类：&nbsp;</span></p>
<p><span>&lt;供应商名称&gt;/&lt;模块名称&gt;/Observer/customPriceInCart.php</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
namespace VendorName\ModuleName\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;

class CustomPriceInCart implements ObserverInterface
{
	public function execute(\Magento\Framework\Event\Observer $observer)
	{
		//get the item just added to cart
		$item = $observer-&gt;getEvent()-&gt;getData('quote_item');
		//(optional) get the parent item, if exists
		$item = ($item-&gt;getParentItem() ? $item-&gt;getParentItem() : $item);
		// set your custom price
		$customPrice = 101;
		$item-&gt;setCustomPrice($customPrice);
		$item-&gt;setOriginalCustomPrice($customPrice);
		$item-&gt;getProduct()-&gt;setIsSuperMode(true);
	}
}</pre>
<p><span>通过函数</span><span>setIsSuperMode(true)</span><span>为产品打开超级模式，您可以停止系统生成价格，然后设置您的自定义价格。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/1_2.png" width="800" /></span></p>
<p><span>结果是每当将产品添加到购物车时，您的自定义价格都会替换原始价格。<br /></span></p>
<h2><span>结论</span></h2>
<p><span><span>当产品出现在客户的购物车中时，本教程已成功修复了产品的价值。</span><span>除了设置固定数字外，您还可以添加自己的函数并将其他类注入到观察者中以实现自定义定价逻辑。</span></span></p>
<p><span><span>感谢您阅读这篇文章。</span><span>如果您在上面的代码中运行良好或在实现该方法时遇到任何问题，请告诉我们。</span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Sat, 05 Nov 2022 08:26:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置多个网站、多个商店视图]]></title>
      <link>https://www.360magento.com/blog/How-to-configure-multiple-websites-multiple-store-views-in-Magento2/</link>
      <description><![CDATA[<p><span><span>Magento 允许我们在一次安装中创建多个网站并存储使用不同属性和内容的视图。</span><span>本博客将向您展示如何在 Magento 2 中配置多个网站、多个商店视图。</span></span></p>
<h2><span>第 1 步：创建网站</span></h2>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; All Stores</span><span>。</span></p>
<p><span>2. 在店铺页面，点击</span><span>创建网站</span><span>。</span></p>
<ul>
<li><span>名称 - 输入名称以识别网站。</span></li>
<li><span>代码 - 输入唯一代码以避免冲突。</span></li>
</ul>
<ul>
<li><span>排序顺序 - 输入可选的数字排序顺序。</span></li>
</ul>
<p><span>3. 单击</span><span>保存网站</span><span>。</span></p>
<h2><span>第 2 步：创建商店</span></h2>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; All Stores</span><span>。</span></p>
<p><span>2. 在店铺页面，点击</span><span>创建店铺</span><span>。</span></p>
<ul>
<li><span><span>网站 - 单击要与此商店关联的网站的名称。</span><span>一个网站可以有多个商店。</span></span></li>
<li><span>名称 - 输入名称以识别商店。</span></li>
<li><span>代码 - 输入唯一代码以识别商店。</span></li>
<li><span>根类别 - 单击此商店的根类别的名称。</span></li>
</ul>
<p><span>3. 点击</span><span>保存商店</span><span>。</span></p>
<h2><span>第 3 步：创建商店视图</span></h2>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; All Stores</span><span>。</span></p>
<p><span>2. 在店铺页面，点击</span><span>创建店铺视图</span><span>。</span></p>
<ul>
<li><span><span>商店 - 单击商店名称以关联此商店视图。</span><span>每个商店可以有多个商店视图。&nbsp;</span></span></li>
<li><span>名称 - 输入名称以标识此商店视图。&nbsp;</span></li>
<li><span>代码 - 输入唯一名称以标识此商店视图。</span></li>
<li><span>状态 - 选择启用。</span></li>
<li><span>排序顺序 - 输入可选的数字排序顺序。</span></li>
</ul>
<p><span>3.点击</span><span>保存商店视图</span></p>
<h2><span>第 4 步：更改网站基本 URL</span></h2>
<p><span>要使用 http://mysite.local 等唯一 URL 访问网站，您必须在 Magento Admin 中更改每个站点的基本 URL。</span></p>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; Configuration &gt;&gt; General &gt;&gt; Web</span><span><span>&nbsp;.</span></span></p>
<p><span><span>2。</span><span>选择</span><span>左上角的</span></span><span>Store View以检查您添加的新网站视图，选择</span><span></span><span>OK</span><span>确认操作。</span></p>
<p><span>3. 展开</span><span>基本 URL</span><span>部分。</span></p>
<p><span><span>4. 清除 Base URL 和 Base Link URL 字段旁边的</span><span>Use&nbsp;</span><span>Default 复选框</span></span><span>。在</span><span><span>Base URL</span></span><span>和</span><span>Base&nbsp;</span><span>Link&nbsp;</span><span><span><span>URL</span></span><span>字段中输入网站的 URL&nbsp;</span><span>。</span><span>确保以正斜杠结束 URL，以便可以使用商店中的其他 URL 密钥对其进行扩展。</span><span>例如：http://mysite.local/</span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
<div class="wp-block-image"><img alt="" class="wp-image-5488" src="https://store.magenest.com/wp/wp-content/uploads/2019/12/Configure-multiple-websites-multiple-store-views-change-URL-1-1024x477.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/1.jpg" width="800" /></div>
<p><span>5. 重复</span><span>基本 URL（安全）</span><span>部分中的上一步。</span></p>
<p><span>6. 如果您有两个以上的网站，请像第 1 步一样添加新网站，并使用</span><span>商店视图</span><span>部分切换网站（商店）并为新网站配置新网址：</span></p>
<p><span>例子：</span></p>
<div class="wp-block-image"><img alt="" class="wp-image-5489" src="https://store.magenest.com/wp/wp-content/uploads/2019/12/Configure-multiple-websites-multiple-store-views-change-URL-2-1024x298.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/2.jpg" width="800" /></div>
<p><span>7. 单击</span><span>保存配置。</span></p>
<h2><span>第 5 步：将商店代码添加到基本 URL（可选）</span></h2>
<p><span>Magento 为您提供了将商店代码添加到站点基本 URL 的选项，这简化了设置多个商店的过程。</span></p>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; Configuration &gt;&gt; General &gt;&gt; Web</span><span>。</span></p>
<p><span><span>2. 选择</span><span>左上角的</span></span><span>Store View ，点击</span><span></span><span>Default Config</span><span>。</span></p>
<p><span>3. 展开</span><span>URL 选项</span><span><span>.</span></span></p>
<p><span><span>4.&nbsp;</span><span>清除将</span><span><span>商店代码添加到 URL</span></span><span>字段</span><span>旁边的</span></span><span>使用系统值复选框。</span><span><span>从将</span><span><span>商店代码添加到 URL</span></span><span>列表中，单击</span><span><span>是</span></span><span>。</span></span></p>
<p><span>5. 点击</span><span>保存配置</span><span>。</span></p>
<h2><span>第 6 步：更改默认商店视图基本 URL</span></h2>
<p><span>完成此步骤后，您将失去对 Magento Admin 的访问权限，您的访问权限会在您设置虚拟主机后返回。</span></p>
<p><span>1. 在 Magento 2 面板中，转到</span><span>Stores &gt;&gt; Settings &gt;&gt; Configuration &gt;&gt; General &gt;&gt; Web</span><span>。</span></p>
<p><span><span>2. 选择</span><span>左上角的</span></span><span>Store View ，点击</span><span></span><span>Default Config。</span></p>
<p><span>3. 展开</span><span>基本 URL</span><span><span>&nbsp;.4。</span><span>清除</span><span><span>Base Link URL</span></span><span>字段</span><span>旁边的</span></span><span>Use Default复选框。</span><span><span>在</span><span><span>基本 URL</span></span><span>和</span><span><span>基本链接 URL</span></span><span>字段中输入所需的 URL。</span><span>例如：http://exam.com/</span></span></p>
<p><span>5. 重复</span><span>基本 URL（安全）</span><span>部分中的上一步。</span></p>
<p><span>6. 单击</span><span>保存配置。</span></p>
<p></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Fri, 04 Nov 2022 08:33:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置 Table Rate Shipping Method]]></title>
      <link>https://www.360magento.com/blog/How-to-configure-Table-Rate-Shipping-Method-in-Magento2/</link>
      <description><![CDATA[<p><em>什么是表率</em><span>？</span><em>它是一种运输方法，它引用数据表以根据重量与目的地</em><span>、</span><em>价格</em><span>与目的地和</span><em>物品数量与</em><span><span>目的地等维度的融合来估算运输成本</span><span>。</span></span></p>
<p><span><span>例如，您可以使用表费率来向您的客户收取 100 磅订单的费用，该费用高于运送到同一地点的 50 磅订单。</span><span>当客户要求报价时，结果将出现在购物车的运费估算中。</span></span></p>
<p><span>按照以下步骤在</span><span>Magento 2</span><span>中配置 Table Rates Shipping Method 。</span></p>
<h2><span>步骤 1：配置默认设置</span></h2>
<p><span>在管理面板上，转到</span><span>商店 &gt; 设置 &gt; 配置 &gt; 销售 &gt; 运输方式，</span><span>然后放大</span><span>表费率</span><span>部分，您将看到以下部分：</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/1_1.png" width="800" /></div>
<ul>
<li><span></span><span>将启用</span><span><span>更改</span><span>为</span></span><span>是</span></li>
<li><span>您可以更改</span><span>标题</span><span>和</span><span>方法名称</span><span><span>或保留默认值。</span><span>这些值将显示为结帐页面中估计费率旁边的标签。&nbsp;</span></span></li>
<li><span>Condition</span><span><span>包含 3 种计算方法选项：Weight v. Destination；</span><span>价格诉目的地；</span><span>项目数量与目的地</span></span></li>
</ul>
<ul>
<li><span>如果您想在估算中包含虚拟产品，请在&ldquo;</span><span>在价格计算中包含虚拟产品</span><span>&rdquo;中选择&ldquo;是&rdquo; 。</span></li>
<li><span>如果您收取手续费，请将计算手续费设置</span><span>为</span><span>固定或百分比并输入</span><span>手续费。</span><span>此金额将按订单收取。</span><span>&nbsp;</span></li>
<li><span>在</span><span>Displayed Error Message 框中</span><span>，键入此方法不可用时出现的消息</span></li>
<li><span><span>您可以</span><span>在所有允许的国家或特定国家之间&nbsp;选择</span></span><span>运送到适用国家。</span><span></span></li>
<li><span>如果您选择特定国家，&ldquo;</span><span>运送到特定国家</span><span>&rdquo;将被启用，让您选择您想应用表费率的国家。</span></li>
<li><span>最后一个字段</span><span>排序顺序</span><span>定义了费率在结帐页面中显示的顺序</span></li>
<li><span>单击</span><span>保存配置</span><span>以完成。</span></li>
</ul>
<h2><span>第 2 步：填写预计运费</span></h2>
<p><span>在左上角，选择&ldquo;</span><span>商店视图</span><span>&rdquo;到&ldquo;主网站&rdquo;或配置适用的任何其他网站。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/2_1.png" width="800" /></div>
<p><span>将出现 2 个新按钮</span></p>
<div class="wp-block-image"><img alt="" class="wp-image-5550" src="https://store.magenest.com/wp/wp-content/uploads/2020/01/configure-table-rates-shipping-method-in-Magento-2-import-export-files-1024x198.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/3_1.png" width="800" /></div>
<p><span>单击</span><span>导出 CSV</span><span><span>并将 CSV 文件保存到您的计算机。</span><span>打开 CSV 文件，填写运费计算条件值的表格</span></span></p>
<ul>
<li><span>使用星号 (*) 作为通配符来表示任何类别中的所有可能值。</span></li>
<li><span>Country 列中的每一行都应该有一个有效的三字符代码。</span></li>
</ul>
<p><span>示例：价格与目的地</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/4_1.png" width="800" /></div>
<p><span>完成后，保存 csv 文件。</span></p>
<h2><span>第 3 步：导入表格费率数据</span></h2>
<p><span>转到</span><span>Table Rates Shipping</span><span>部分，在左上角，选择</span><span>Store View</span><span>&nbsp;to &ldquo;Main website&rdquo; 或配置适用的任何其他网站。&nbsp;</span></p>
<p><span><span>单击</span><span><span>导入字段中的</span></span></span><span>选择文件</span><span><span>按钮</span><span>，然后选择要导入的前一个 csv 文件。</span><span>单击</span><span><span>保存配置</span></span><span>。</span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
<h2><span>第 4 步：检查结果</span></h2>
<p><span><span>要测试表运费，请将产品添加到购物车。</span><span>然后，转到结帐页面。</span><span>完成所有运输信息后，查看运输估算部分，您将看到您之前配置的值。</span></span></p>
<p><span>示例</span><span>：将 45 美元的产品添加到购物车</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/5_1.png" width="800" /></div>
<p><span>在结帐页面中，您可以看到运费将根据我们在步骤 2 中添加的规则进行更改。</span></p>
<ul>
<li><span>未选择发货状态时，运费为 15 美元。</span></li>
</ul>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/6_1.png" width="800" /></div>
<ul>
<li><span>将运输状态更改为阿拉斯加/夏威夷，运费为 20 美元。</span></li>
</ul>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/7_1.png" width="800" /></div>
<p><span>注意</span><span>：您可以使用表格费率来创建免费送货条件。</span></p>
<p><span>我们希望通过这些简单的步骤可以帮助您轻松理解和配置 Table Rate Shipping Method。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Thu, 03 Nov 2022 08:21:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Paypal 如何在 Magento 2 中工作？]]></title>
      <link>https://www.360magento.com/blog/How-does-Paypal-work-within-Magento2/</link>
      <description><![CDATA[<p><span>Magento 中可用的支付方式是</span><span>Paypal Express Checkout</span><span>，它支持客户使用 Paypal 账户或信用卡支付。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/1.png" width="800" /></div>
<p><span>本文将帮助您如何在</span><span>Magento 2</span><span><span>中配置 PayPal 。</span><span>在设置 Paypal 付款之前，请确保您拥有真实或沙盒 Paypal 商家帐户。</span></span></p>
<h2><span>1.从新配置开始</span></h2>
<p><span>1. 前往</span><span>商店</span><span>&gt;</span><span>配置</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/2.png" width="800" /></div>
<p><span>2. 向下滚动到</span><span>销售</span><span>选项卡，展开它并单击</span><span>付款方式</span><span>选项卡。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/3.png" width="800" /></div>
<p><span>3. 如您所见，</span><span>Merchant Location</span><span><span>就在此处。</span><span>您可以为 Paypal 付款选择一个国家，或者如果您不选择，付款将使用 General Config 中的 Default Country。</span></span></p>
<p><span>此设置决定了配置中出现的 PayPal 解决方案的选择。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/4.png" width="800" /></div>
<p><span>4. 之后，单击</span><span>配置</span><span>按钮以展开</span><span>Paypal Express Checkout</span><span>部分。</span></p>
<p><span></span><span>5. 然后，在必填 Paypal 设置</span><span>&gt;</span><span>快速结账</span><span><span>部分</span><span>填写信息。</span></span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/5.png" width="800" /></div>
<p><span>如果您将任何字段（可选字段除外）留空，则</span><span>启用此解决方案</span><span><span>字段将被禁用。</span><span>在填写所有必填字段之前，您无法启用它。</span></span></p>
<ul>
<li><span>与 PayPal 商家帐户关联的电子邮件：</span><span><span>电子邮件地址区分大小写。</span><span>要接收付款，您输入的电子邮件地址必须与您的 PayPal 商家帐户中指定的电子邮件地址相匹配。</span><span>此字段是可选的，您可以将其留空。</span></span></li>
</ul>
<ul>
<li><span>API 身份验证方法：</span><span>这里有两种类型的身份验证方法。</span></li>
</ul>
<ol>
<li><span>API 签名。</span></li>
<li><span>API 证书。</span></li>
</ol>
<ul>
<li><span>API 用户名/API 密码：</span><span>输入 Paypal 为您提供的用户名/密码。</span></li>
<li><span>API 签名/API 证书：</span><span>取决于</span><span>&nbsp;</span><span>身份验证方法，您必须完成它。&nbsp;</span></li>
<li><span>沙盒模式：</span><span>确定您正在使用的环境。&nbsp;</span></li>
</ul>
<ul>
<li><span>API 使用代理：</span><span>如果您使用代理连接 Magento 和 Paypal，则将此字段设置为是，并填写以下两个字段：</span></li>
</ul>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/6.png" width="800" /></div>
<p><span><span>6. 完成这些字段后，您可以</span><span>在</span><span><span>启用此解决方案字段中选择</span></span></span><span>是</span><span>。</span><span><span></span></span><span></span></p>
<p><span>7. 如果您希望客户在商店付款，请启用</span><span>Enable In-Context Checkout Experience</span><span>字段并输入</span><span><span><span>Merchant Account</span></span><span><span>&nbsp;ID</span></span></span><span>的值。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/7.png" width="800" /></div>
<p><span>移至</span><span>基本设置 - PayPal Express Checkout</span><span>部分以设置付款的一些基本信息。</span></p>
<p><span>在这里，您可以指定</span><span>标题、排序顺序、付款操作</span><span>（此字段包括授权/销售/订单操作）。</span></p>
<p><span>顺便说一句，如果您希望在每个产品页面上显示付款，则将&ldquo;</span><span>在产品详细信息页面上显示&rdquo;</span><span>字段设置为&ldquo;是&rdquo;。</span></p>
<h2><span>2. 获取 API 凭证</span></h2>
<p><span>您可以通过单击</span><span>Get Credentials from Paypal</span><span>&nbsp;/&nbsp;</span><span>Sandbox Credentials</span><span>按钮来获取信息。</span></p>
<p><span>如果您想从沙盒模式更改为实时模式，只需将您输入的所有凭据替换为实时凭据即可。</span></p>
<p><span>1. 登录您的 Paypal 商家帐户。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/8.png" width="800" /></div>
<p><span>2. 进入</span><span>设置</span><span>&gt;</span><span>账户设置</span></p>
<p><span>3. 转到</span><span>帐户访问</span><span>&gt;&nbsp;</span><span>API 访问</span><span>&gt;</span><span>更新</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/9.png" width="800" /></div>
<p><span>4. 向下滚动到</span><span>自定义结帐体验</span><span>，然后单击</span><span>管理 API 凭据。</span></p>
<p><span>5. 然后，选择身份验证方法</span><span>&nbsp;</span><span>（签名或证书）并提交您的选择。</span></p>
<p><span>6. 现在，您可以获得 Paypal 付款方式的凭据。</span></p>
<p><span>完成 Paypal 支付方式的所有基本设置后，前往 Store Front 并尝试购买东西。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/10.png" width="800" /></div>
<p><span>现在，您将看到 Paypal 付款出现在产品详细信息、迷你购物车和结帐页面上。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1025/11.png" width="800" /></div>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Wed, 02 Nov 2022 08:28:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何检查客户是否登录 Magento 2]]></title>
      <link>https://www.360magento.com/blog/How-To-Check-If-Customer-Is-Logged-Into-Magento2/</link>
      <description><![CDATA[<p><span><span>众所周知，在很多情况下，我们需要检查客户当前是否在您的网站上登录。</span><span>例如，有一些针对已登录客户的特殊促销活动。</span><span>今天，这篇博客将向您展示如何在 Magento 2 中检查客户的登录状态。</span></span></p>
<p><span><span>在 Magento 中，会话在增强用户体验方面发挥着重要作用，它们在收集有关用户访问的重要统计数据方面也很有用。</span><span>会话的特点是在服务器端存储与用户交互相关的信息。</span></span>我为您推荐此解决方案：</p>
<p><span>使用</span><code>Magento\Customer\Model\Session::isLoggedIn()</code><span>方法。</span></p>
<p><code>isloggedIn()</code><span><span>方法返回一个布尔值，指示登录客户的状态。</span><span>访客客户或未登录的客户浏览该网站将返回 false，反之亦然。</span></span></p>
<p><span>要在控制器、助手或观察者中使用此类......您可以按照以下步骤操作：</span></p>
<p><span>首先，您需要在构造函数方法中注入以下类：</span><code>/Magento/Customer/Model/Session</code><span>.</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token keyword">protected</span> <span class="token variable">$_session</span><span class="token punctuation">;</span>

<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
\<span class="token package">Magento<span class="token punctuation">\</span>Customer<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Session</span> <span class="token variable">$session</span><span class="token punctuation">,</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_session</span> <span class="token operator">=</span> <span class="token variable">$session</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token punctuation">}</span></pre>
<p><span>然后在您的班级中，在任何函数中使用以下代码来检查客户是否已登录：</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_session</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">isLoggedIn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Customer is logged in</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token comment">// Customer is not logged in</span>
<span class="token punctuation">}</span></pre>
<p><span>使用控制器类的代码示例：</span></p>
<p><em>将 [Vendor] 和 [Module] 替换为您的供应商和模块名称</em></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>
<span class="token keyword">namespace</span> <span class="token punctuation">[</span>Vendor<span class="token punctuation">]</span>\<span class="token punctuation">[</span>Module<span class="token punctuation">]</span>\<span class="token package">Controller<span class="token punctuation">\</span>Index</span><span class="token punctuation">;</span>

<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>Action<span class="token punctuation">\</span>Context</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>Action<span class="token punctuation">\</span>Action</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Customer<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Session</span><span class="token punctuation">;</span>

<span class="token keyword">class</span> <span class="token class-name">ClassName</span> <span class="token keyword">extends</span> <span class="token class-name">Action</span>
<span class="token punctuation">{</span>
    <span class="token keyword">protected</span> <span class="token variable">$_session</span><span class="token punctuation">;</span>

    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>Context <span class="token variable">$context</span><span class="token punctuation">,</span> Session <span class="token variable">$session</span><span class="token punctuation">)</span> 
    <span class="token punctuation">{</span>
        <span class="token keyword">parent</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">__construct</span><span class="token punctuation">(</span><span class="token variable">$context</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_session</span> <span class="token operator">=</span> <span class="token variable">$session</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">execute</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token comment">// by using Session model</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_session</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">isLoggedIn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token comment">//customer has logged in</span>
            <span class="token comment">// your code in here</span>
        <span class="token punctuation">}</span><span class="token keyword">else</span><span class="token punctuation">{</span>
            <span class="token comment">//Customer is not logged in</span>
            <span class="token comment">// your code in here</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></pre>
<p><span>我们希望本文能帮助您检查客户是否已登录 Magento 2。祝您编码愉快！</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Tue, 01 Nov 2022 08:22:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加客户属性 - Magenest]]></title>
      <link>https://www.360magento.com/blog/How-to-add-customer-attribute-in-Magento2-Magenest/</link>
      <description><![CDATA[<p><span><span>了解客户是所有电子商务业务成功的关键。</span><span>在 Magento 2 中，商家可以通过注册表单、帐户仪表板等中的各个字段收集客户属性。为了更好地了解您的客户，需要在客户网格中添加自定义属性。</span><span>在此博客中，我们将指导您如何通过 2 个简单的步骤在 Magento 2 中创建自定义客户属性。</span></span></p>
<p><span>为您提供智能解决方案</span><span>：使用</span><span>Magento 2 的客户属性</span><span>有效地收集客户信息。</span></p>
<h2><span>步骤 1：创建数据补丁</span></h2>
<p><span>Magento 的最新版本引入了一种在 Magento 2 数据库中修改数据的新方法：</span><span><span>数据/模式补丁</span></span><span>（更多信息在这里：</span><span>Magento 文档</span><span>）。</span></p>
<p><span>我们将实施一个</span><span>数据补丁</span><span>来将客户的属性添加到数据库中。</span></p>
<p><span></span><em><code>CustomerAttributePatcher</code></em><span><span>首先，按照这个目录约定在你的模块目录中</span><span>创建一个名为：的类：</span></span><em><code>&lt;your-module&gt;/Setup/Patch/Data/CustomerAttributePatcher.php</code></em></p>
<p><span>注意</span><span>：</span><em>所有数据补丁都必须在此目录</em><span>中。</span></p>
<p><span>必须实施</span><em><code>Magento\Framework\Setup\Patch\DataPatchInterface</code></em></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>
<span class="token keyword">namespace</span> <span class="token package">Magenest<span class="token punctuation">\</span>Customer<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>Patch<span class="token punctuation">\</span>Data</span><span class="token punctuation">;</span>

<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Customer<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Customer</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Eav<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Config</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Customer<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>CustomerSetupFactory</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>ModuleDataSetupInterface</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>Patch<span class="token punctuation">\</span>DataPatchInterface</span><span class="token punctuation">;</span>

<span class="token keyword">class</span> <span class="token class-name">AccountPurposeCustomerAttribute</span> <span class="token keyword">implements</span> <span class="token class-name">DataPatchInterface</span>
<span class="token punctuation">{</span>
    <span class="token comment">/**
     * @var CustomerSetupFactory
     */</span>
    <span class="token keyword">private</span> <span class="token variable">$customerSetupFactory</span><span class="token punctuation">;</span>

    <span class="token comment">/**
     * @var ModuleDataSetupInterface
     */</span>
    <span class="token keyword">private</span> <span class="token variable">$setup</span><span class="token punctuation">;</span>

    <span class="token comment">/**
     * @var Config
     */</span>
    <span class="token keyword">private</span> <span class="token variable">$eavConfig</span><span class="token punctuation">;</span>

    <span class="token comment">/**
     * AccountPurposeCustomerAttribute constructor.
     * @param ModuleDataSetupInterface $setup
     * @param Config $eavConfig
     * @param CustomerSetupFactory $customerSetupFactory
     */</span>
    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>
        ModuleDataSetupInterface <span class="token variable">$setup</span><span class="token punctuation">,</span>
        Config <span class="token variable">$eavConfig</span><span class="token punctuation">,</span>
        CustomerSetupFactory <span class="token variable">$customerSetupFactory</span>
    <span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">customerSetupFactory</span> <span class="token operator">=</span> <span class="token variable">$customerSetupFactory</span><span class="token punctuation">;</span>
        <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">setup</span> <span class="token operator">=</span> <span class="token variable">$setup</span><span class="token punctuation">;</span>
        <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">eavConfig</span> <span class="token operator">=</span> <span class="token variable">$eavConfig</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token comment">/** We'll add our customer attribute here */</span>
    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">apply</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token variable">$customerSetup</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">customerSetupFactory</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token single-quoted-string string">'setup'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">setup</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$customerEntity</span> <span class="token operator">=</span> <span class="token variable">$customerSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getEavConfig</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getEntityType</span><span class="token punctuation">(</span>Customer<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">ENTITY</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$attributeSetId</span> <span class="token operator">=</span> <span class="token variable">$customerSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getDefaultAttributeSetId</span><span class="token punctuation">(</span><span class="token variable">$customerEntity</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getEntityTypeId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$attributeGroup</span> <span class="token operator">=</span> <span class="token variable">$customerSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getDefaultAttributeGroupId</span><span class="token punctuation">(</span><span class="token variable">$customerEntity</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getEntityTypeId</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token variable">$attributeSetId</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$customerSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">addAttribute</span><span class="token punctuation">(</span>Customer<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">ENTITY</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'new_attribute'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>
            <span class="token single-quoted-string string">'type'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'int'</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'input'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'select'</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'label'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'New Attribute'</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'required'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'default'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'visible'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'user_defined'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'system'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">false</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'is_visible_in_grid'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'is_used_in_grid'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'is_filterable_in_grid'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'is_searchable_in_grid'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'position'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token number">300</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$newAttribute</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">eavConfig</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getAttribute</span><span class="token punctuation">(</span>Customer<span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">ENTITY</span><span class="token punctuation">,</span> <span class="token single-quoted-string string">'new_attribute'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$newAttribute</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">addData</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
            <span class="token single-quoted-string string">'used_in_forms'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">[</span><span class="token single-quoted-string string">'adminhtml_checkout'</span><span class="token punctuation">,</span><span class="token single-quoted-string string">'adminhtml_customer'</span><span class="token punctuation">,</span><span class="token single-quoted-string string">'customer_account_edit'</span><span class="token punctuation">,</span><span class="token single-quoted-string string">'customer_account_create'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'attribute_set_id'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token variable">$attributeSetId</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'attribute_group_id'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token variable">$attributeGroup</span>
        <span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token variable">$newAttribute</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function">getDependencies</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">getAliases</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></pre>
<h2><span>第二步：安装数据补丁</span></h2>
<p><span>运行升级命令为了数据补丁采取行动：</span><code>php bin/magento setup:upgrade</code></p>
<p><span>现在我们的客户属性已安装。</span></p>
<p><span><span>我们希望这些简单的步骤可以帮助您在 Magento 2 中添加您需要的自定义客户属性。</span><span>如果您有任何问题，请在评论中提出。</span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Mon, 31 Oct 2022 08:28:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加自定义 CSS 文件]]></title>
      <link>https://www.360magento.com/blog/How-to-add-Custom-CSS-File-in-Magento2/</link>
      <description><![CDATA[<p><span>在本文中，我们将讨论</span><span>&ldquo;如何在 Magento 2 中自定义 CSS&rdquo;</span><span>，它可以帮助您自定义 Magento 中的所有样式，例如布局、字体粗细、颜色、背景等。它可以加载一些文件，如 URL、 CDN、库等。</span></p>
<p><span><span>在 Magento 2 中，您可以在 Module 或 Theme 中包含自定义 CSS。</span><span>通常，您包含的样式表应该适用于所有商店页面，您将在布局</span></span><code>default_head_blocks.xml</code><span>或特定加载样式中包含一个 CSS 文件，每个页面都有一个布局。</span></p>
<h2><span>在模块中包含 CSS</span></h2>
<p><span><span>在本例中，我们将创建模块，并</span><span>在模块的</span><span><span>view/frontend/layout</span></span></span><code>Magenest_CustomCss</code><span>文件夹中添加一个</span><span>default_head_blocks.xml</span><span><span>文件，对于特定布局的自定义 CSS，我们将从</span><span><span>default_head_block.xml</span></span><span>布局开始。</span><span>它将适用于 Magento 中的所有页面。</span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span>  <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>css</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magenest_CustomCss::css/css-module.css<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span>

After that, add the web/css/source/less-custom.less file.

body {
    background: pink;
}</pre>
<p><span>这是使用以下命令清除缓存后的结果：</span><code>php bin/magento cache:flush</code></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/1_1.jpg" width="800" /></div>
<p><span><span>如果您想为特定布局自定义 CSS，则需要页面的布局，这与模块或主题中的 less 文件类似的步骤。</span><span>这是</span></span><span>catalog_product_view.xml</span><span>的一个例子：</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;page</span></span></span><span><span></span></span></span> <span class="token attr-name"><span class="token namespace"><span><span>xmlns:</span></span></span><span><span> xsi </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> http://www.w3.org/2001/XMLSchema-instance </span></span><span class="token punctuation"><span><span>"</span></span></span></span>
      <span class="token attr-name"><span><span> layout </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> 2columns-left </span></span><span class="token punctuation"><span><span>" </span></span></span></span>
     <span class="token attr-name"><span class="token namespace"><span><span>xsi:</span></span></span><span><span> noNamespaceSchemaLocation </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> urn:magento:framework:View/Layout/etc/page_configuration.xsd </span></span><span class="token punctuation"><span><span>"</span></span></span></span><span class="token punctuation"><span><span> &gt; </span></span></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> head </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> css </span></span></span> <span class="token attr-name"><span><span>src </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> css/local.css </span></span><span class="token punctuation"><span><span>"</span></span></span></span> <span class="token punctuation"><span><span> /&gt; </span></span></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> head </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> page </span></span></span><span class="token punctuation"><span><span>&gt;</span></span></span></span></pre>
<p><span>结果将如下图所示：</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/2_1.jpg" width="800" /></div>
<p><span>我们可以进入带有布局主页的页面或</span><code>catalog_product_view.xml</code></p>
<p><span>和</span><code>catalog_product_view</code></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/3_1.jpg" width="800" /></div>
<p><span>最后，我们将检查页面是否有布局</span><code>catalog_category_view.xml</code></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/4_1.jpg" width="800" /></div>
<h2><span>在主题中包含 CSS</span></h2>
<p><span><span>Theme 添加 CSS 的方式与 Module 类似，但这里有一点不同。</span><span>它是目录的结构。</span></span></p>
<p><span><span class="tadv-color">第一步：</span></span><span><span><span>您需要在/app/design/frontend/&lt;Vendor&gt;/&lt;Theme_Name&gt;/web/css/local.css</span></span><span>中创建一个 css 文件&nbsp;</span></span><span><span></span></span></p>
<p><span><span class="tadv-color">第二步：</span></span><span>在这一步中，创建</span><span>default_head_blocks.xml</span><span>文件</span></p>
<p><span>app/design/frontend/&lt;供应商&gt;/&lt;Theme_Name&gt;/&lt;Module_NameSpace&gt;/layout/</span></p>
<p><span><span class="tadv-color">第三步：</span></span><span>在</span><code>default_head_blocks.xml</code><span>中，使用</span><span>css 标签 (&lt;css&gt;)</span><span>包含我们在第 2 步创建的 css 文件。</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml"><span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;page</span></span></span><span><span></span></span></span> <span class="token attr-name"><span class="token namespace"><span><span>xmlns:</span></span></span><span><span> xsi </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> http://www.w3.org/2001/XMLSchema-instance </span></span><span class="token punctuation"><span><span>"</span></span></span></span>
      <span class="token attr-name"><span><span> layout </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> 2columns-left </span></span><span class="token punctuation"><span><span>" </span></span></span></span>
      <span class="token attr-name"><span class="token namespace"><span><span>xsi:</span></span></span><span><span> noNamespaceSchemaLocation </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> urn:magento:framework:View/Layout/etc/page_configuration.xsd </span></span><span class="token punctuation"><span><span>"</span></span></span></span><span class="token punctuation"><span><span> &gt; </span></span></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> head </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> css </span></span></span> <span class="token attr-name"><span><span>src </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> css/local.css </span></span><span class="token punctuation"><span><span>"</span></span></span></span> <span class="token punctuation"><span><span> /&gt; </span></span></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> head </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> page </span></span></span><span class="token punctuation"><span><span>&gt;</span></span></span></span><span><br /></span></pre>
<p><span><span class="tadv-color">第四步：在local.css文件中添加以下代码。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">body {
    background: blue;
}</pre>
<p><span><span class="tadv-color">第五步：</span></span><span>在 Magento 根目录下运行 clear cache 命令。&nbsp;</span></p>
<p><span>结果会是这样：背景变成了蓝色：</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/5_1.jpg" width="800" /></div>
<p><span><span>在 Magento 2 中创建自定义 CSS 文件很容易，对吧？</span><span>我们希望您可以使用 CSS 来修改 Magento 店面，以获得更好的用户体验。</span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Sun, 30 Oct 2022 08:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何以编程方式在 Magento 2 中将产品添加到愿望清单]]></title>
      <link>https://www.360magento.com/blog/How-to-Add-Product-to-Wishlist-in-Magento2-Programmatically/</link>
      <description><![CDATA[<p><span><span>Magento 2 Wishlist 允许用户将产品添加到他们的收藏夹中，这将为下次购买节省时间。</span><span>此外，愿望清单也可以通过电子邮件与任何人共享。</span></span></p>
<p><span>本文将指导您如何以编程方式将产品添加到 Magento 2 的愿望清单中。</span></p>
<h2><span>如何将产品添加到愿望清单</span></h2>
<p><span>要将产品添加到愿望清单，我们需要两个参数：</span><span>产品对象</span><span>和</span><span>客户 ID</span><span>。</span></p>
<ul>
<li><span>Product Object</span><span><span>：可以通过Product SKU或者Id获取。</span><span>例如，使用此方法从</span></span><span>SKU</span><span>获取产品：</span><em><code>Magento\Catalog\Api\ProductRepositoryInterface::get($sku)</code></em></li>
<li><span>客户 ID</span><span><span>。</span><span>可以使用此方法为当前登录的客户获取前端客户 ID：</span></span><em><code>Magento\Customer\Model\Session::getId()</code></em></li>
</ul>
<p><span>要保存产品，首先加载客户的愿望清单，然后通过愿望清单模型添加产品。</span></p>
<p><span>编码示例：</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>

<span class="token keyword">class</span> <span class="token class-name">AddProductToWishlist</span>
<span class="token punctuation">{</span>
   <span class="token keyword">protected</span> <span class="token variable">$_wishlistFactory</span><span class="token punctuation">;</span>
   <span class="token keyword">protected</span> <span class="token variable">$_wishlistResource</span><span class="token punctuation">;</span>

   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>
       Magento\<span class="token package">Wishlist<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>WishlistFactory</span> <span class="token variable">$wishlistFactory</span><span class="token punctuation">,</span>
       Magento\<span class="token package">Wishlist<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>ResourceModel<span class="token punctuation">\</span>Wishlist</span> <span class="token variable">$wishlistResource</span>
   <span class="token punctuation">)</span> <span class="token punctuation">{</span>
       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_wishlistFactory</span>  <span class="token operator">=</span> <span class="token variable">$wishlistFactory</span><span class="token punctuation">;</span>
       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_wishlistResource</span> <span class="token operator">=</span> <span class="token variable">$wishlistResource</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>

   <span class="token comment">/**
    * @param $product
    * @param $customerId
    *
    * @throws \Magento\Framework\Exception\AlreadyExistsException
    * @throws \Magento\Framework\Exception\LocalizedException
    */</span>
   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">saveProductToWishlist</span><span class="token punctuation">(</span><span class="token variable">$product</span><span class="token punctuation">,</span> <span class="token variable">$customerId</span><span class="token punctuation">)</span>
   <span class="token punctuation">{</span>
       <span class="token comment">//load wishlist by customer id</span>
       <span class="token variable">$wishlist</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_wishlistFactory</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">loadByCustomerId</span><span class="token punctuation">(</span><span class="token variable">$customerId</span><span class="token punctuation">,</span> <span class="token boolean constant">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

       <span class="token comment">//add product for wishlist</span>
       <span class="token variable">$wishlist</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">addNewItem</span><span class="token punctuation">(</span><span class="token variable">$product</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

       <span class="token comment">//save wishlist</span>
       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">_wishlistResource</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token variable">$wishlist</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></pre>
<p><span>结果如下：该产品已在前端成功添加到用户的收藏列表中。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/3.png" width="800" /></div>
<h2><span>结论</span></h2>
<p><span><span>Magento 2 Wishlist 是一种方便的方式来跟踪您喜欢但尚未准备好购买的产品。</span><span>您的愿望清单中的物品可以与他人共享或添加到购物车中。</span><span>为用户带来更好的体验。</span></span></p>
<p><span><span>默认情况下，Magento 仅支持每个客户的一个愿望清单。</span><span>对于</span></span><span>多个愿望清单，您可以</span><span></span><span>在这里</span><span><span>查看我们的免费扩展</span><span>。</span></span></p>
<p><span><span>我们希望您从这篇文章中学到了一些有用的东西。</span><span>如果出现任何问题，请在评论中告诉我们。</span></span></p>
<p><span>感谢您的阅读！</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Sat, 29 Oct 2022 08:32:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 页面的布局中移动块、容器]]></title>
      <link>https://www.360magento.com/blog/How-to-move-block-container-in-a-layout-in-a-Magento2-page/</link>
      <description><![CDATA[<p><span>今天，我们将了解如何使用layout.xml</span><span><span>将 Magento 2 中的元素（块、容器等）移动到页面的不同部分</span><span>。</span></span></p>
<h2><span>如何</span><span>在 Magento 2 中移动块</span></h2>
<p><span>首先，我们需要编辑布局 xml 文件以移动块。&nbsp;</span></p>
<p><span>布局 xml 可用于：&nbsp;</span></p>
<ul>
<li><span>将元素移动到另一个元素</span></li>
<li><span>添加或删除一些元素&nbsp;</span></li>
</ul>
<p><span>但在本篇博客的范围内，我们将重点关注如何将元素移动到另一个元素。</span></p>
<p><span>要将块移动到另一个目的地，我们需要使用</span><code>&lt;move&gt;</code><span>带有特定元素名称和目的地位置的标签。</span></p>
<p><code>&lt;move&gt;</code><span>标记将按指定顺序将声明的块或容器元素设置为另一个元素的子元素。</span></p>
<p><span>例子</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>move element<span class="token operator">=</span><span class="token double-quoted-string string">"page.main.title"</span> destination<span class="token operator">=</span><span class="token double-quoted-string string">"product.info.main"</span> before<span class="token operator">=</span><span class="token double-quoted-string string">"product.info.price"</span><span class="token operator">/</span><span class="token operator">&gt;</span></pre>
<p><span><span>在这个例子中。</span><span>我将块名称&ldquo;&nbsp;</span></span><span>page.main.title</span><span>&nbsp;&rdquo;移动到&ldquo;&nbsp;</span><span>product.info.price</span><span><span>&nbsp;&rdquo;元素</span><span>之前的&ldquo;&nbsp;</span></span><span>product.info.main &rdquo;。</span><span></span></p>
<p><span>使用</span><code>&lt;move&gt;</code><span>标签时，这些属性是必需的：</span><span>元素</span><span>、</span><span>目的地</span><span>。</span></p>
<p><span>这些属性： before 和 after 用于指定元素应该放在目标元素之前或之后。</span></p>
<p><span><span>使用可以使用破折号 (-) 将块定位在其嵌套级别的所有其他同级之前或之后。</span><span>如果省略这些属性，则该元素将放置在所有兄弟元素之后。</span></span></p>
<p><span>请记住：</span></p>
<ul>
<li><code>&lt;move&gt;</code><span>如果要移动的元素未定义，则跳过。</span></li>
<li><span><span>如果未定义 as 属性，则使用元素别名的当前值。</span><span>如果这不可能，则使用 name 属性的值。</span></span></li>
<li><span><span>在布局生成期间，&lt;move&gt; 指令在移除之前处理​​（使用 remove 属性设置）。</span><span>这意味着如果任何元素被移动到计划删除的元素，它们也将被删除</span></span></li>
</ul>
<p class="has-medium-font-size"><span><span class="tadv-color">动手吧！</span></span></p>
<p><span>在此博客中，我将指导您如何将价格块移动到产品详细信息页面上的另一个位置。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/1.png" width="800" /></div>
<p><span><span>如上图所示，红色矩形是价格块。</span><span>我们将把那个块移到另一个地方：</span></span><span>product.info.main</span></p>
<p><span>步骤 1：</span><span><span>您需要在</span><span><span>module/view/frontend/layout/中创建</span></span></span><span>catalog_product_view.xml</span><span>文件</span><span><span></span></span></p>
<p><span><span>因为产品详情页面是前端页面并且它使用这个布局文件catalog_product_view.xml。</span><span>这样我们就需要在正确的前端范围和正确的布局xml文件名中创建。</span></span></p>
<p><span>步骤 2：为</span><span><span><span>catalog_product_view.xml</span></span><span>添加内容</span></span><span><span></span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>move</span> <span class="token attr-name">element</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>product.info.price<span class="token punctuation">"</span></span> <span class="token attr-name">destination</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>product.info.main<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span></pre>
<p><span>第 3 步：</span><span>通过以下命令清理布局缓存：</span><code>php bin/magento cache:clean</code><span>layout.</span></p>
<p><span>这是结果：</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/2.png" width="800" /></div>
<p><span>如您所见，价格块已成功移动到</span><span>product.info.main</span><span>部分。</span></p>
<h2><span><span>如何</span><span>在 Magento 2中</span></span><span>移动容器</span><span></span></h2>
<p><span>移动容器与移动块非常相似，如果需要，您还需要指定元素名称、目的地、之前或之后。</span></p>
<p><span><span>这就是通过布局 XML 文件移动 Magento 2 中的元素的全部内容。</span><span>如果您有任何疑问或问题，请随时与我们联系。</span><span>谢谢！</span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Fri, 28 Oct 2022 08:29:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中删除块、容器、静态资源]]></title>
      <link>https://www.360magento.com/blog/How-to-remove-block-container-static-resource-in-Magento2/</link>
      <description><![CDATA[<p><span><span>Magento 2 使店主能够在各个方面为客户提供最佳体验。</span><span>自定义前端以吸引和吸引用户很容易。</span><span>在本文中，我们将展示 Magento 2 开发人员的基本自定义之一：删除</span></span><span>块</span><span>、</span><span>容器</span><span>和</span><span>静态资源</span><span>。</span></p>
<h2><span>1.如何删除块</span></h2>
<p><span>块是一个页面输出单元，它呈现一些独特的内容（对最终用户来说是视觉上可见的任何内容），例如一条信息或用户界面元素。</span></p>
<p><span>在 Magento 2 中从布局中删除块的步骤：</span></p>
<p><span>您的代码将如下所示：</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>referenceBlock</span> <span class="token attr-name">&lt;em</span><span class="token punctuation">&gt;</span></span>name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>em</span><span class="token punctuation">&gt;</span></span>="product.info.overview" <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>em</span><span class="token punctuation">&gt;</span></span>remove<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>em</span><span class="token punctuation">&gt;</span></span>="true"/&gt; </pre>
<p><span>例如，从产品页面中删除描述块：</span></p>
<p><span>在</span><span>catalog_product_view.xml</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>referenceBlock</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>product.info.overview<span class="token punctuation">"</span></span> <span class="token attr-name">remove</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span></pre>
<p><span>在此，我使用</span><code>&lt;referenceBlock&gt;</code><span>删除块。</span></p>
<p><code>Name</code><span>是要删除的块的名称。</span></p>
<p><code>Remove</code><span><span>设置为 true 以删除。</span><span>刷新</span></span><span>缓存</span><span>后，整个描述将从产品页面中删除。</span></p>
<h2><span>2. 如何移除容器</span></h2>
<p><span><span>容器在视图输出生成期间呈现子元素。</span><span>它可以是空的，也可以包含任意一组 &lt;container&gt; 和 &lt;block&gt; 元素。</span><span>如果 &lt;container&gt; 为空，并且没有子 &lt;block&gt; 可用，则不会在前端源代码中显示。</span></span></p>
<p><span>在 Magento 2 中从布局中删除容器的步骤：</span></p>
<p><span>您的代码将如下所示：</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> referenceContainer</span></span></span> <span class="token attr-name"><span><span>名称</span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>&ldquo;</span></span></span><span><span>内容</span></span><span class="token punctuation"><span><span>&rdquo;</span></span></span></span> <span class="token attr-name"><span><span>移除</span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>&ldquo;</span></span></span><span><span>真</span></span><span class="token punctuation"><span><span>&rdquo;</span></span></span></span><span class="token punctuation"><span><span> /&gt;</span></span></span></span></pre>
<p><span>例如，从产品页面中删除内容：</span></p>
<p><span>在</span><span>catalog_product_view.xml</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt; </span>

<span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;page</span></span></span><span><span></span></span></span> <span class="token attr-name"><span class="token namespace"><span><span>xmlns:</span></span></span><span><span> xsi </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> http://www.w3.org/2001/XMLSchema-instance </span></span><span class="token punctuation"><span><span>" </span></span></span></span> <span class="token attr-name"><span class="token namespace"><span><span>xsi:</span></span></span><span><span> noNamespaceSchemaLocation </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> urn:magento:framework:View/Layout/etc/ page_configuration.xsd </span></span><span class="token punctuation"><span><span>"</span></span></span></span><span class="token punctuation"><span><span> &gt; </span></span></span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> body </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;</span></span></span><span><span> referenceContainer </span></span></span> <span class="token attr-name"><span><span>name </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> content </span></span><span class="token punctuation"><span><span>"</span></span></span></span> <span class="token attr-name"><span><span> remove </span></span></span><span class="token attr-value"><span class="token punctuation"><span><span>= </span></span></span><span class="token punctuation"><span><span>"</span></span></span><span><span> true </span></span><span class="token punctuation"><span><span>"</span></span></span></span><span class="token punctuation"><span><span> /&gt; </span></span></span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> body </span></span></span><span class="token punctuation"><span><span>&gt; </span></span></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><span><span>&lt;/</span></span></span><span><span> page </span></span></span><span class="token punctuation"><span><span>&gt;</span></span></span></span></pre>
<p><span>除了移除块之外，我曾经</span><code>&lt;referenceContainer&gt;</code><span>移除容器。</span></p>
<p><code>Name</code><span>是我要删除的容器的名称。</span></p>
<p><code>Remove</code><span><span>设置为 true 以删除。</span><span>刷新缓存后，内容将从</span></span><span>产品页面</span><span>中删除。</span></p>
<h2><span>3. 如何移除静态资源（JavaScript、CSS、字体）</span></h2>
<p><span><span>要删除页面中链接的静态资源，请在扩展</span><span><span>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml</span></span></span><code>&lt;head&gt;</code><span><span>的主题中进行类似以下的更改</span><span>：</span></span><span><span></span></span><span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
       <span class="token comment">&lt;!-- Remove local resources --&gt;</span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>css/styles-m.css<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>my-js.js<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento_Catalog::js/compare.js<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
       <span class="token comment">&lt;!-- Remove external resources --&gt;</span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js<span class="token punctuation">"</span></span><span class="token punctuation">/&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>remove</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://fonts.googleapis.com/css?family=Montserrat<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span></pre>
<p><span>请注意，如果在初始布局中添加了带有模块路径（例如 Magento_Catalog::js/sample.js）的静态资产，则在删除资产时也需要指定模块路径。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Thu, 27 Oct 2022 08:27:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置税收规则、税率]]></title>
      <link>https://www.360magento.com/blog/How-to-setup-Tax-Rules-Tax-Rates-in-Magento2/</link>
      <description><![CDATA[<p><span>为了帮助企业轻松扩展到国际市场，Magento 2 允许您为每个地区和产品创建和设置不同的税率。</span></p>
<p><span>我们希望本文能帮助您更好地了解 Magento 2 中的税收。</span></p>
<h2><span>创建税率</span></h2>
<p><span>登录到您的管理页面，点击</span><span>商店-&gt;税区</span><span><span>和税率</span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/1.jpg" width="800" /></p>
<p><span>点击</span><span>添加新税率</span></p>
<div class="wp-block-image wp-image-7115"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/2.jpg" width="800" /></div>
<p><span>现在，您可以配置税率</span></p>
<ul>
<li><span>Tax Identifier&nbsp;</span><span>- 用于内部识别的税的名称</span></li>
<li><span>邮编/邮政是范围</span><span>- 如果选中，您将能够在此下方的两个字段中设置邮政编码范围</span></li>
<li><span>州</span><span>- 您希望征收税率的州（如果您的国家没有州，此选项将显示为灰色）</span></li>
<li><span>国家</span><span>- 您希望对其征收税率的国家</span></li>
<li><span>税率百分比</span><span>- 客户需要支付的税率百分比</span></li>
</ul>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/3.jpg" width="800" /></div>
<p><span>单击&ldquo;</span><span>保存税率&rdquo;</span><span>按钮以保存税率。</span></p>
<h2><span>创建税收规则</span></h2>
<p><span>点击</span><span>税收规则</span></p>
<div class="wp-block-image"><img alt="创建税收规则 Magento 2" class="wp-image-7118" src="https://store.magenest.com/wp/wp-content/uploads/2020/07/creat-a-tax-rules.jpg" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/4.jpg" width="800" /></div>
<p><br /><span>点击</span><span>添加新的税收规则</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/5.jpg" width="800" /><img alt="添加新的税收规则 Magento 2" class="wp-image-7119" src="https://store.magenest.com/wp/wp-content/uploads/2020/07/add-new-tax-rules.jpg" /></div>
<h3><span>税收规则信息</span></h3>
<ul>
<li><span>名称</span><span>- 您的税则名称</span></li>
<li><span>税率</span><span>- 选择您想要的税率</span></li>
<li><span>添加新税率</span><span>- 创建新税率</span></li>
</ul>
<div class="wp-block-image wp-image-7120"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/6.jpg" width="800" /></div>
<h3><span>其他设置</span></h3>
<ul>
<li><span>客户税类</span><span>&ndash; 您可以从现有的税类中进行选择、编辑或按添加新税类来创建新的客户税类。</span></li>
<li><span>产品税级</span><span>&mdash;&mdash;从现有的列表中选择、编辑它们或通过按下下面的按钮创建一个全新的产品税级。</span></li>
<li><span>优先级</span><span><span><span>- 指明规则优先级，以防适用不止一种税。</span><span>优先级相同的税收会加起来，不同优先级的税收会复合。</span></span></span></li>
<li><span>仅计算小计</span><span>- 选中复选框以根据订单小计计算税金。</span></li>
<li><span>排序顺序</span><span>&ndash; 列表中税收规则的顺序。</span></li>
</ul>
<div class="wp-block-image wp-image-7121"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1024/7.jpg" width="800" /></div>
<p><span>您可以导入税率和出口税率</span></p>
<p><span>单击</span><span>保存规则</span><span>按钮以保存税收规则。</span></p>
<p><span><span><span>感谢您阅读这篇文章。</span><span>如果出现任何问题，请在评论中告诉我们</span></span></span><span>。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Wed, 26 Oct 2022 08:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在侧边栏列 Magento 2 中添加静态块？]]></title>
      <link>https://www.360magento.com/blog/How-to-add-a-static-block-in-a-sidebar-column-Magento2/</link>
      <description><![CDATA[<p><span>今天，我们将展示一种在侧边栏列中添加静态块的简单方法，您可以使用该块向客户显示重要通知。&nbsp;</span></p>
<h2><span>使用 Magento 2 的默认功能创建静态块</span></h2>
<p><span>首先，您必须在管理端创建一个 CMS 静态块，这是 Magento 2 的一个很棒的默认功能。</span></p>
<p><span>访问后端 &gt; 内容 &gt; 块 &gt; 添加新块</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/6_1.png" width="800" /></div>
<h2><span>另一种使用 DataPatch 创建静态块 CSM 的方法。</span></h2>
<p><span>您必须在此路径中添加以下代码：'&nbsp;</span><em>Magenest/StaticBlock/Setup/Patch/Data/CreateStaticBlock.php</em><span><span>&nbsp;'。</span><span>您可以将名称编辑为您想要的任何名称。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>

<span class="token keyword">namespace</span> <span class="token package">Magenest<span class="token punctuation">\</span>StaticBlock<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>Patch<span class="token punctuation">\</span>Data</span><span class="token punctuation">;</span>

<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>Patch<span class="token punctuation">\</span>DataPatchInterface</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Setup<span class="token punctuation">\</span>ModuleDataSetupInterface</span><span class="token punctuation">;</span>
<span class="token keyword">use</span> <span class="token package">Magento<span class="token punctuation">\</span>Cms<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>BlockFactory</span><span class="token punctuation">;</span>
<span class="token comment">/**
* Class UpdateTest2Block
* @package Test\CmsExport\Setup\Patch\Data
*/</span>
<span class="token keyword">class</span> <span class="token class-name">CreateStaticBlock</span> <span class="token keyword">implements</span> <span class="token class-name">DataPatchInterface</span>
<span class="token punctuation">{</span>
   <span class="token comment">/**
    * @var ModuleDataSetupInterface
    */</span>
   <span class="token keyword">private</span> <span class="token variable">$moduleDataSetup</span><span class="token punctuation">;</span>

   <span class="token comment">/**
    * @var BlockFactory
    */</span>
   <span class="token keyword">private</span> <span class="token variable">$blockFactory</span><span class="token punctuation">;</span>

   <span class="token comment">/**
    * AddAccessViolationPageAndAssignB2CCustomers constructor.
    * @param ModuleDataSetupInterface $moduleDataSetup
    * @param BlockFactory $blockFactory
    */</span>
   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">__construct</span><span class="token punctuation">(</span>
       ModuleDataSetupInterface <span class="token variable">$moduleDataSetup</span><span class="token punctuation">,</span>
       BlockFactory <span class="token variable">$blockFactory</span>
   <span class="token punctuation">)</span> <span class="token punctuation">{</span>
       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">moduleDataSetup</span> <span class="token operator">=</span> <span class="token variable">$moduleDataSetup</span><span class="token punctuation">;</span>
       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">blockFactory</span> <span class="token operator">=</span> <span class="token variable">$blockFactory</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>

   <span class="token comment">/**
    * {@inheritdoc}
    */</span>
   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">apply</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">{</span>
       <span class="token variable">$newCmsStaticBlock</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
           <span class="token single-quoted-string string">'title'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'Static Block created by using DataPatch'</span><span class="token punctuation">,</span>
           <span class="token single-quoted-string string">'identifier'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'static-block-created-by-datapatch'</span><span class="token punctuation">,</span>
           <span class="token single-quoted-string string">'content'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token single-quoted-string string">'&lt;h3&gt;Static Block created by using DataPatch&lt;/h3&gt;'</span><span class="token punctuation">,</span>
           <span class="token single-quoted-string string">'is_active'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token number">1</span><span class="token punctuation">,</span>
           <span class="token single-quoted-string string">'stores'</span> <span class="token operator">=</span><span class="token operator">&gt;</span> \<span class="token package">Magento<span class="token punctuation">\</span>Store<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Store</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">DEFAULT_STORE_ID</span>
       <span class="token punctuation">]</span><span class="token punctuation">;</span>

       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">moduleDataSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">startSetup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

       <span class="token comment">/** @var \Magento\Cms\Model\Block $block */</span>
       <span class="token variable">$block</span> <span class="token operator">=</span> <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">blockFactory</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token variable">$block</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setData</span><span class="token punctuation">(</span><span class="token variable">$newCmsStaticBlock</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">save</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

       <span class="token variable">$this</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token property">moduleDataSetup</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">endSetup</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>

   <span class="token comment">/**
    * {@inheritdoc}
    */</span>
   <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">function</span> <span class="token function">getDependencies</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">{</span>
       <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>

   <span class="token comment">/**
    * {@inheritdoc}
    */</span>
   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">getAliases</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
   <span class="token punctuation">{</span>
       <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></pre>
<p><span>运行命令</span><span>php bin/magento setup:upgrade</span><span>将静态块添加到数据库中。</span></p>
<p><span><span>其次，我们需要创建一个新模块 (Magenest_StaticBlock) 和一个您想要添加 CMS 静态块的布局。</span><span>在我们的模块中，我们将此块添加到默认布局中，以便它可以显示在每个具有容器名称'&nbsp;</span></span><em>sidebar.additional</em><span>&nbsp;'路径的页面中：</span><em>Magentest/StaticBlock/view/frontend/layout/default.xml</em></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>referenceContainer</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sidebar.additional<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>block</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Magento\Cms\Block\Block<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sidebar_custom_static_block<span class="token punctuation">"</span></span> <span class="token attr-name">as</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sidebar_custom_static_block<span class="token punctuation">"</span></span> <span class="token attr-name">after</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>catalog.compare.sidebar<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>arguments</span><span class="token punctuation">&gt;</span></span>
                   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>argument</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>block_id<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>string<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>sidebar-customer-static-block<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>argument</span><span class="token punctuation">&gt;</span></span>
               <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>arguments</span><span class="token punctuation">&gt;</span></span>
           <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>block</span><span class="token punctuation">&gt;</span></span>
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>referenceContainer</span><span class="token punctuation">&gt;</span></span>
   <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span></pre>
<p><span><span>block_id 是我们自定义 CMS 静态块中的标识符值。</span><span>上述 CMS 静态块的 block_id 是&ldquo;&nbsp;</span></span><em>sidebar-customer-static-block</em><span>&nbsp;&rdquo;，它是通过 Backend 或&ldquo;&nbsp;</span><em>static-block-created-by-datapatch</em><span>&nbsp;&rdquo;（由代码创建）创建的。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/7_1.png" width="800" /></div>
<p><span>最后，您可以看到 CMS 静态块的内容出现在侧边栏中。</span></p>
<p><span>希望本指南对您有用。&nbsp;</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为英语</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将英语翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译英语</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Tue, 25 Oct 2022 08:23:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中以客户身份登录 - 分步指南]]></title>
      <link>https://www.360magento.com/blog/How-to-login-as-customer-in-Magento2-A-Step-by-Step-Guide/</link>
      <description><![CDATA[<p><span><span>有时客户需要订单帮助，这需要商店管理员在客户的视图下调查问题。</span><span>从</span></span><span>Magento 2.4</span><span>开始，Magento 2 以客户身份登录功能已可用于 Magento 的开源和企业版本。</span></p>
<h2><span>启用 Magento 2 以客户身份登录</span></h2>
<h3><span>启用该功能</span></h3>
<ol>
<li><span>在管理页面中单击</span><span>Stores -&gt; Settings -&gt; Configuration</span><span>。</span></li>
<li><span>在左侧面板中，展开</span><span>客户</span><span>并选择</span><span>Login as Customer</span><span>。</span></li>
</ol>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/1_1.png" width="800" /></div>
<p><span>描述配置中的字段</span></p>
<div class="table-wrapper">
<div>
<table class="wp-block-table">
<tbody>
<tr>
<td><span>选项</span></td>
<td><span>价值</span></td>
<td><span>描述</span></td>
</tr>
<tr>
<td><span>启用以客户身份登录</span></td>
<td><span>是/否</span></td>
<td><span>启用/禁用以客户身份登录功能</span></td>
</tr>
<tr>
<td><span>为管理员用户禁用页面缓存</span></td>
<td><span>是/否</span></td>
<td><span>如果是，将为管理员用户禁用页面缓存。</span></td>
</tr>
<tr>
<td><span>要登录的商店视图</span></td>
<td><span>自动检测（默认）/手动选择</span></td>
<td><span><span>自动使用该公司用户的默认商店设置。</span><span>如果您希望管理员用户在以客户身份登录时选择商店视图，请使用手动选择。</span></span></td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>3. 完成后，点击</span><span>保存配置</span><span>并</span><span>清除缓存</span></p>
<h3><span>以客户身份登录</span></h3>
<p><span><span>以客户身份登录允许您以客户身份查看网站，并允许您以客户身份进行故障排除和采取其他操作。</span><span>此功能需要管理员帐户有权访问客户 &gt; 以客户身份登录。</span></span></p>
<p><span>从</span><span>Magento 2.4.1</span><span><span>开始，客户还必须</span><span>在管理员登录之前从他们的仪表板启用</span></span><em>允许远程购物帮助：</em><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/2_1.png" width="800" /></p>
<p><span>如果客户未启用此选项，则当管理员尝试登录其帐户时，将显示错误消息：&ldquo;</span><span><span><span>用户未启用&ldquo;允许远程购物协助&rdquo;功能。</span><span>联系客户讨论此用户配置。</span></span></span><span>&rdquo;</span></p>
<p><span><span>要跳过这个额外的步骤，商店管理员可以</span><span>通过命令行禁用模块</span></span><span>LoginAsCustomerAssistance ：</span><span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">php bin<span class="token operator">/</span>magento module<span class="token punctuation">:</span>disable Magento_LoginAsCustomerAssistance</pre>
<p><span>然后重新部署站点。</span></p>
<p><span>以客户身份登录</span><span>出现在以下页面上：</span></p>
<ul>
<li><span>客户编辑页面</span></li>
</ul>
<ol>
<li><span>在</span><em>管理</em><span>侧边栏上，转到</span><span>客户 -&gt; 所有客户。</span></li>
<li><span>在网格中找到客户，然后单击</span><em>操作</em><span>列中的编辑。</span></li>
<li><span>在顶部控制栏上，单击&ldquo;</span><span>以客户身份登录</span><span>&rdquo;</span></li>
</ol>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/3_1.png" width="800" /></div>
<ul>
<li><span>订单查看页面</span></li>
</ul>
<ol>
<li><span>在</span><em>Admin</em><span>侧边栏上，转到</span><span>Sales</span><span>&nbsp;-&gt;&nbsp;</span><span>Orders</span><span>。</span></li>
<li><span>在网格中查找顺序。</span></li>
<li><span>在</span><em>操作</em><span>列中，单击</span><span>查看</span><span>。</span></li>
<li><span>点击&ldquo;</span><span>以客户身份登录</span><span>&rdquo;</span></li>
</ol>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/4_1.png" width="800" /></div>
<ul>
<li><span>发票查看页面</span></li>
<li><span>货件查看页面</span></li>
<li><span>贷项凭单查看页面</span></li>
</ul>
<p><span>管理员连接将显示在标题上。</span><span>关闭会话</span><span>按钮将结束登录会话清除相关缓存</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/5_1.png" width="800" /></div>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Mon, 24 Oct 2022 08:27:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置店内取货功能]]></title>
      <link>https://www.360magento.com/blog/How-to-configure-in-store-pickup-function-in-Magento2/</link>
      <description><![CDATA[<p><span><span>Magento 2.4 于 7 月底发布，具有许多出色的功能，可以帮助店主优化电子商务网站的客户体验。</span><span>这个新版本最强大的功能之一是</span></span><span>Magento 店内取货</span><span>，为买家提供了另一种下订单后获取商品的方式：到实体店取货。</span></p>
<p><span>在本文中，我们将为您提供配置 Magento 店内取货的分步指南。</span></p>
<h2><span>Magento 店内取货功能是什么？</span></h2>
<p><span>店内取货 (ISPU) 是</span><span>Magento 2.4</span><span><span>中的一项新功能，允许客户在线下订单并从实体店取货。</span><span>Magento 中的订单管理系统 (OMS) 提供了一个基于 Web 的界面，允许商店员工挑选和准备商品以供客户取货。</span></span></p>
<h2><span>您什么时候需要使用店内取货？</span></h2>
<p><span>客户在网上购物以尽量减少接触，但他们想要那种熟悉的实体店体验。</span></p>
<h2><span>如何设置 Magento 店内取货功能</span></h2>
<h3><span>第 1 步：启用多源库存 (MSI)</span></h3>
<p><span>首先，您的网站必须启用 MSI 功能。&nbsp;</span></p>
<p><span>请按照以下步骤添加新来源：</span></p>
<ul>
<li><span>在管理侧边栏上，转到</span><span>商店 &gt; 库存 &gt; 来源</span></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/6.png" width="800" /></p>
<ul>
<li><span>单击</span><span>添加新源</span><span>按钮。</span></li>
</ul>
<ul>
<li><span>现在您将填写表格以配置新源的一些信息：</span></li>
</ul>
<p><span>&gt;</span><span>一般部分</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/7.png" width="800" /></p>
<p><span><em>名称</em></span><em>：</em><span>标识库存源的唯一名称</span><br /><span><em>代码</em></span><em>：</em><span>源代码是分配给库存和导出/导入数据时使用的唯一 ID 已</span><br /><span><em>启用</em></span><span>：如果此库存源可以使用，则将其设置为是</span><br /><span><em>描述</em></span><span>：简要说明此位置用于快速参考或其他详细信息</span><br /><span><em>纬度和经度</em></span><span>：这里是设施位置的 GPS 坐标</span><br /><span><em>用作取件位置</em></span><span>：我们将在下一步中设置。</span></p>
<p><span>&gt;</span><span>联系方式</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/8.png" width="800" /></p>
<p><span><em>联系人姓名</em></span><span>：输入该位置主要联系人的全名。</span><br /><span><em>电子邮件</em></span><span>：输入用于联系该位置的电子邮件地址。</span><br /><span><em>电话</em></span><span>：输入区号和电话号码。</span><br /><span><em>传真</em></span><span>：输入传真的区号和电话号码（如果有）。</span></p>
<p><span>&gt;</span><span>地址数据</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/9.png" width="800" /></p>
<p><span><em>国家</em></span><span>：选择国家。</span><br /><span><em>州/省</em></span><span>：输入州或省的标准缩写。</span><br /><span><em>城市</em></span><span>：输入城市。</span><br /><span><em>街道</em></span><span>：输入实际街道地址。</span><br /><span><em>邮政编码</em></span><span>：输入邮政编码。</span></p>
<ul>
<li><span>按</span><span>保存</span><span>按钮完成工作。</span></li>
</ul>
<h3><span>第 2 步：启用 Magento 店内取货功能</span></h3>
<p><span><span>* 要在结帐页面上显示选择商店取货的选项，您必须</span><span>在</span><span><span>送货方式</span></span><span>设置中启用</span></span><span>店内送货。</span><span><span>转到</span><span><span>商店 &gt; 配置 &gt; 销售 &gt; 交货方式</span></span></span><span><span></span></span><span></span><span><span></span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/10.png" width="800" /></p>
<p><span>* 要将来源设为取货地点，请按照以下步骤操作：</span></p>
<ul>
<li><span><span>转到</span><span><span>商店 &gt; 库存 &gt; 来源下的</span></span></span><span>管理来源</span><span>页面</span><span><span></span></span></li>
</ul>
<ul>
<li><span>编辑将被设置为取货地点的来源</span></li>
</ul>
<ul>
<li><span>启用&ldquo;</span><span><em>用作取货地点</em></span><span><span>&rdquo;字段。</span><span>之后，&ldquo;</span></span><span>取货地点</span><span>&rdquo;部分将出现并提供有关该地点的描述信息</span>
<ul>
<li><span><em>Frontend Name</em></span><span>&nbsp;: 取货地点的名称</span></li>
<li><span><em>前端描述</em></span><span>：您可以输入有关位置的更多详细信息，例如商店营业时间、相对于其他地标的位置，或任何有助于客户选择正确取货位置的有用信息</span></li>
</ul>
</li>
</ul>
<ul>
<li><span>最后，单击</span><span>保存</span><span>按钮。</span></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/11.png" width="800" /></p>
<h2><span>店面代表</span></h2>
<p><span>完成店内取货配置后，客户可以在结账时选择</span><em>配送</em><span>和店内取货</span><em>。</em></p>
<p><span><span>如果客户选择店内取货方式，则会根据他们保存的送货地址的位置自动选择取货地点。</span><span>客户还可以更改选择的取货地点。&nbsp;</span></span></p>
<p><span>对于访客用户，客户必须手动选择取货地点。&nbsp;&nbsp;</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/12.png" width="800" /></p>
<p><span>此外，商家还可以通过店内取货选项从后端下单：</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/13.png" width="800" /></p>
<p class="has-medium-font-size"><span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Sun, 23 Oct 2022 08:22:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取库存状态警报不足]]></title>
      <link>https://www.360magento.com/blog/How-to-get-stock-status-alert-deficient-in-Magento2/</link>
      <description><![CDATA[<p><span>今天，我们将展示在 Magento 2 中获取库存状态警报不足的方法。如果产品的数量下降到设置中的</span><span>Notify for Quantity below 之下</span><span>，系统将通知管理员产品处于低库存状态。</span></p>
<p><em lang="zh">例子：</em></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/1.png" width="800" /></div>
<p><span lang="zh">产品数量为 3</span><br /><span lang="zh">下面的数量通知是 3</span><br /><span lang="zh">客户购买此产品，库存为 1</span><br /><span lang="zh">管理员为此订单创建发货，因此数量降至 2</span><br /><span><span><span>系统将通知管理员该产品的库存状态。</span><span>您可以通过访问</span></span><em><span><span><span>报告 &gt; 产品 &gt; 低库存查看通知</span></span></span></em></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/2.png" width="800" /></p>
<p><span lang="zh"><span><span>有 3 种方法可以设置</span></span><span><span><span>以下数量通知</span></span></span></span><span>：</span></p>
<ul>
<li lang="zh"><span>为所有产品设置。</span></li>
<li lang="zh"><span>为特定产品设置。</span></li>
<li lang="zh"><span>针对特定的产品来源进行设置。</span></li>
</ul>
<h2><span lang="zh">3 种设置以下数量通知的方法</span></h2>
<h3><span lang="zh">1 - 为所有产品设置</span></h3>
<p lang="zh"><span>访问</span><em><span>商店 &gt; 设置 &gt; 配置 &gt; 目录 &gt; 库存 &gt; 产品库存选项 &gt; 通知以下数量</span></em></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/3.png" width="800" /></p>
<p><span>注意：</span><span>此配置为整个网站/商店的所有产品全局设置默认值。</span></p>
<h3><span lang="zh">2 - 为特定产品设置</span></h3>
<p lang="zh"><span>访问</span><span><em>目录 &gt; 产品 &gt; 特定产品 &gt; 高级库存 &gt; 通知以下数量</em></span></p>
<p><img alt="" class="wp-image-9747" src="https://store.magenest.com/wp/wp-content/uploads/2020/11/image2-1024x537.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/4.png" width="800" /></p>
<p><span>注意：</span><span><span>此配置会覆盖在网站/商店级别设置的值。</span><span>该值适用于产品的所有来源。</span></span></p>
<h3><span lang="zh">3 - 设置特定的产品来源</span></h3>
<p lang="zh"><span>访问</span><span><em>目录 &gt; 产品 &gt; 特定产品 &gt; 来源 &gt; 通知数量</em></span></p>
<p><span><span>如果您的站点有多个来源，则会为特定来源设置数量和通知数量。</span><span>如果不是，它将获得默认值。</span></span></p>
<p><img alt="" class="wp-image-9748" src="https://store.magenest.com/wp/wp-content/uploads/2020/11/image4-1024x538.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1014/5.png" width="800" /></p>
<p><span>注意：</span><span><span>此配置会覆盖所有其他设置。</span><span>商家可以为特定产品的每个来源分配不同的阈值。</span></span></p>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Sat, 22 Oct 2022 08:29:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取产品库存]]></title>
      <link>https://www.360magento.com/blog/How-to-get-Product-Stock-in-Magento2/</link>
      <description><![CDATA[<p><span><span>库存管理是电子商务管理中不可或缺的一部分。</span><span>在某些情况下，出于许多不同的原因，我们需要获取产品的库存信息。</span><span>例如，您需要检查产品是否有库存以将其显示在类别页面上，或者防止客户将缺货的产品添加到购物车等许多情况。&nbsp;</span></span></p>
<p><span>在本文中，我们将逐步指导您获取产品库存 Magento 2。</span></p>
<h2><span>从管理页面获取产品库存信息</span></h2>
<p><span>作为管理员，您可以在分类产品网格中获取产品的库存信息：</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/1_3.png" width="800" /></div>
<p><span>或者在产品创建/编辑表单中，您可以编辑数量（每个来源）或查看产品的可销售数量。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/2_3.png" width="800" /></div>
<h2><span>对于开发人员</span></h2>
<p><span><span>作为开发人员，您还需要了解产品库存信息，例如缺货状态、库存状态、剩余数量、最大数量、最小数量&hellip;&hellip;以及许多其他信息。</span><span>Magento 2 支持开发人员获取产品库存信息的一些方法。</span></span></p>
<p><span><span><span>使用StockItemRepository</span></span><span>获取特定产品的库存信息</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token variable">$productId</span> <span class="token operator">=</span> <span class="token number">620</span><span class="token punctuation">;</span>
<span class="token comment">/** @var \Magento\CatalogInventory\Model\Stock\StockItemRepository $stockItem */</span>

<span class="token variable">$stockItem</span> <span class="token operator">=</span> \<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>ObjectManager</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">get</span><span class="token punctuation">(</span>\<span class="token package">Magento<span class="token punctuation">\</span>CatalogInventory<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>Stock<span class="token punctuation">\</span>StockItemRepository</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span>

<span class="token comment">// Retrieve backorders status</span>
<span class="token keyword">echo</span> <span class="token variable">$stockItem</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getBackorders</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Get quantity of item remaining in stock</span>
<span class="token keyword">echo</span> <span class="token double-quoted-string string">"qty: "</span><span class="token punctuation">.</span><span class="token variable">$stockItem</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getQty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Get stock status</span>
<span class="token keyword">echo</span> <span class="token variable">$stockItem</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getIsInStock</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Retrieve Maximum Qty Allowed in Shopping Cart data wrapper</span>
<span class="token keyword">echo</span> <span class="token double-quoted-string string">"max sale qty: "</span><span class="token punctuation">.</span><span class="token variable">$stockItem</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getMaxSaleQty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></pre>
<p><span><span><span>使用GetSourceItemsDataBySku</span></span><span>检索产品多源数量</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token comment">// To retrieve product multi-source quantities, you can use GetSourceItemsDataBySku</span>

<span class="token comment">/** @var \Magento\InventoryCatalogAdminUi\Model\GetSourceItemsDataBySku $sourceDataBySku */</span>
<span class="token comment">//use ObjectManager to get \Magento\InventoryCatalogAdminUi\Model\GetSourceItemsDataBySku instance</span>

<span class="token variable">$sku</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"24-MB01"</span><span class="token punctuation">;</span> <span class="token comment">//sku of product</span>

<span class="token variable">$sourceDataBySku</span> <span class="token operator">=</span> \<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>ObjectManager</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">get</span><span class="token punctuation">(</span>\<span class="token package">Magento<span class="token punctuation">\</span>InventoryCatalogAdminUi<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>GetSourceItemsDataBySku</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//load quantities of assigned source</span>
<span class="token variable">$data</span> <span class="token operator">=</span> <span class="token variable">$sourceDataBySku</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">execute</span><span class="token punctuation">(</span><span class="token variable">$sku</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// the returned data should be an array including source name, source code, qty of the product in source, source status</span>
<span class="token comment">// data = array(</span>
<span class="token comment">//  array(</span>
<span class="token comment">//      'source_code' =&gt; "example",</span>
<span class="token comment">//      'quantity' =&gt; 100,</span>
<span class="token comment">//      'status' =&gt; 1</span>
<span class="token comment">//      'name' =&gt; "Example"</span>
<span class="token comment">//      'source_status' =&gt; true</span>
<span class="token comment">//)</span>

<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></pre>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token punctuation"><span></span></span><span class="token punctuation"><span></span></span><span class="token punctuation"><span></span></span></pre>
<p><span><span>产品存储库用于加载特定产品的所有信息。</span><span>因此，它也用于获取股票信息。&nbsp;</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
   <span class="token comment">//use product repository to get stock data</span>
  <span class="token variable">$sku</span> <span class="token operator">=</span> <span class="token double-quoted-string string">"883985891715"</span><span class="token punctuation">;</span>
<span class="token comment">/** @var Magento\Catalog\Model\ProductRepository $productRepository */</span>
   <span class="token variable">$productRepository</span> <span class="token operator">=</span> \<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>ObjectManager</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">get</span><span class="token punctuation">(</span>Magento\<span class="token package">Catalog<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>ProductRepository</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token variable">$product</span> <span class="token operator">=</span> <span class="token variable">$productRepository</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token variable">$sku</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$product</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
       <span class="token keyword">echo</span> <span class="token variable">$product</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">isSalable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Check is product available for sale</span>
       <span class="token keyword">echo</span> <span class="token variable">$product</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">isAvailable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Check whether the product type or stock allows to purchase the product</span>
       <span class="token keyword">echo</span> <span class="token variable">$product</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">getQty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> get quantity of product

   <span class="token punctuation">}</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></pre>
<p><span><span>产品集合对于获取产品列表中的库存信息也很有用。</span><span>您还可以使用库存属性来过滤或从集合中获取数据。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span>
<span class="token comment">/** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */</span>
<span class="token variable">$productCollection</span> <span class="token operator">=</span> \<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>App<span class="token punctuation">\</span>ObjectManager</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">get</span><span class="token punctuation">(</span>\<span class="token package">Magento<span class="token punctuation">\</span>Catalog<span class="token punctuation">\</span>Model<span class="token punctuation">\</span>ResourceModel<span class="token punctuation">\</span>Product<span class="token punctuation">\</span>Collection</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">//use  salable option to filter product in collection</span>
<span class="token variable">$data</span> <span class="token operator">=</span>  <span class="token variable">$productCollection</span>
<span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">addAttributeToFilter</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"is_saleable"</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setPageSize</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span>
<span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">toArray</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span></pre>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Fri, 21 Oct 2022 08:24:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中使用多个送货地址]]></title>
      <link>https://www.360magento.com/blog/How-to-use-multiple-shipping-addresses-in-Magento2/</link>
      <description><![CDATA[<h3><span>先决条件：设置通讯录</span></h3>
<p><span>第 1 步：</span><span>转到</span><em>我的帐户 &gt; 通讯录</em></p>
<p><span>第 2 步：</span><span>输入您的默认送货地址</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/14_1.png" width="800" /></div>
<p><span>第 3 步：</span><span>添加新地址</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/15_1.png" width="800" /></div>
<h3><span>多个送货地址</span></h3>
<p><span>第 1 步：</span><span>选择您的产品并添加到购物车</span></p>
<p><span>第 2 步：</span><span>选择</span><em>查看和编辑购物车</em></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/1_2.png" width="800" /></div>
<p><span>第 3 步：</span><span>选择</span><em>多地址结帐</em></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/2_2.png" width="800" /></div>
<p><span>第 4 步：</span><span>选择购物车中每件商品的送货地址，然后选择</span><span>前往送货信息</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/3_1.png" width="800" /></div>
<p><span>第 5 步：</span><span><span>您可以查看按送货地址过滤的所有商品及其详细信息。</span><span>选择 Continue to Billing Information 继续下订单。&nbsp;</span></span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/4_1.png" width="800" /></div>
<p><span>下订单后，您将有 2 个具有 2 个不同送货地址的订单。</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/5_1.png" width="800" /></div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Thu, 20 Oct 2022 08:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置多个送货地址]]></title>
      <link>https://www.360magento.com/blog/How-to-Configure-Multiple-Shipping-Addresses-in-Magento2/</link>
      <description><![CDATA[<p><span><span>一个非常实际的情况是&ldquo;如果您需要将订单运送到 2 个或更多不同的地址，则必须创建具有不同送货地址的不同订单&rdquo;。</span><span>这个解决方案会导致一个问题，如果您有多个收货地址，您必须创建各种订单，多次结帐......这给客户带来了不便。</span></span></p>
<p><span>因此，Magento 2 创建了多个送货地址功能，可将您的订单划分为每个商品的多个地址。</span></p>
<h2><span>店主如何在 Magento 2 中配置多个送货地址</span></h2>
<p><span>第 1 步：</span><span>登录 Magento 2 管理页面</span></p>
<p><span>第 2 步：</span><span>选择</span><em>商店 &gt; 配置</em></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/1_1.png" width="800" /></div>
<p><span>第 3 步：</span><span>在选项卡</span><span>Configuration</span><span>中，展开</span><span>Sales</span><span>面板并选择</span><span>Multishiping Settings</span></p>
<div class="wp-block-image"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/2_1.png" width="800" /></div>
<p><span>第 4 步：</span><span>在</span><span>选项</span><span>部分，将</span><em>允许运送到多个地址</em><span>更改为是或勾选</span><em>使用系统值</em><span>（默认为是）并输入</span><em>允许运送到多个地址的最大数量</em><span>的数量或勾选</span><em>使用系统值</em><span>（默认为 100）。</span></p>
<ul>
<li><em>允许送货到多个地址：</em><span>配置客户是否可以在店面使用多个送货地址。</span></li>
<li><em>允许运送到多个地址</em><span><span>的最大数量：配置订单中可用于多个运送地址的最大商品数量。</span><span>例如，此配置设置为 10 件商品，而您的购物车中有 11 件商品，则不能使用多收货地址功能。</span></span></li>
</ul>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Wed, 19 Oct 2022 08:35:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建色板属性]]></title>
      <link>https://www.360magento.com/blog/How-to-Create-Swatches-Properties-in-Magento2/</link>
      <description><![CDATA[<p><span><span>在本文中，我们将介绍</span><span>使用内置产品属性管理系统&nbsp;在</span></span><span>Magento 2上为产品创建样本的步骤。</span><span></span></p>
<p><span><span>Magento 支持颜色样本和基于文本的样本。</span><span>无法选择的选项被划掉或模糊。</span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/1.png" width="800" /></span></p>
<p><span>Magento 2 色板：基于颜色和文本的色板</span></p>
<h2><span>在 Magento</span><span>&nbsp;2中配置色板</span></h2>
<p><span>要创建色板，请转到</span><em>Admin &gt; Stores &gt; Attributes &gt; Product</em><span>，单击</span><em>Add New Attribute</em><span>。</span></p>
<h3><span>完成基本属性</span></h3>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/2.png" width="800" /></p>
<p>插入<em>默认标签</em>来描述属性。</p>
<p><span>在</span><em>Store Owner 的目录输入类型中</em><span>，选择类型是文本样本或视觉样本。</span></p>
<ul>
<li><span>带文字色板</span>
<ul>
<li><span>在管理色板下，单击</span><em>添加色板</em><span>。</span></li>
<li><span><span>为列表中显示的第一个值命名，同时，当您有多个商店视图时，您可以在 Admin 下命名该值，并为每个商店视图命名不同的值。</span><span>如果只有一个商店视图，则管理员值会自动应用于店面。</span></span></li>
<li><span>单击</span><em>添加</em><span>色板并再次执行上述指南以获取下一个色板。</span></li>
<li><span><span>如果要将其用作默认值，请</span><span>标记为</span></span><em>默认值复选框。</em><span></span></li>
</ul>
</li>
</ul>
<p><img alt="" class="wp-image-10607" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image9-1024x175.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/3.png" width="800" /></p>
<ul>
<li><span>使用视觉样本：</span>
<ul>
<li><span>在管理色板下，单击</span><em>添加色板</em><span>。</span></li>
<li><span>为样本选择颜色或上传文件。</span></li>
<li><span>默认商店视图是在前端显示的样本的名称。</span></li>
<li><span>单击</span><em>添加</em><span>色板并再次执行上述指南以获取下一个色板。</span></li>
<li><span><span>如果要将其用作默认值，请</span><span>标记为</span></span><em>默认值复选框。</em><span></span></li>
</ul>
</li>
</ul>
<p><span></span><em>为所需的值</em><span><span>选择是，</span><span>以要求客户在购买前选择选项。</span></span></p>
<p><span></span><em>在选择不同的色板时，为更新产品预览图像</em><span><span>选择是以更新</span><span>目录页面和产品页面上的产品图像。</span></span></p>
<p><span></span><em>对于视觉样本，如果可能，请为样本使用产品图像</em><span><span>选择是，</span><span>以允许使用后备逻辑将样本图像替换为产品样本或基本图像。</span></span></p>
<h3><span>完成高级属性（可选）</span></h3>
<p><img alt="" class="wp-image-10609" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image12-1024x474.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/4.png" width="800" /></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/5.png" width="800" /></p>
<ul>
<li><span><span>插入</span><span>少于 60 个符号的</span></span><em>属性代码，不要使用空格。</em><span></span></li>
<li><span></span><em>范围</em><span><span>包括商店视图、网站和全球</span><span>。</span><span>您将在商店系统中选择属性外观被批准的三个位置之一。</span></span></li>
<li><span></span><em>如果您</em><span><span>不想与其他产品共享，请</span><span>应用唯一值。</span></span></li>
<li><span></span><em>为&ldquo;添加到列选项</em><span><span>&rdquo;选择&ldquo;是&rdquo;</span><span>以将此属性添加到产品网格中的列选项列表中。</span></span></li>
<li><span></span><em>为在过滤器选项</em><span><span>中使用选择是，</span><span>以将此属性添加到产品网格中的过滤器选项列表中。</span></span></li>
</ul>
<h3><span>管理标签部分</span></h3>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/6.png" width="800" /></p>
<p><span><span>插入</span><span>为字段标签显示的</span></span><em>标题。</em><span>如果您的商店支持多种语言，请为每个视图插入标题的翻译。</span></p>
<h3><span>店面属性</span></h3>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/7.png" width="800" /></p>
<ul>
<li><span></span><em>为&ldquo;在搜索中使用</em><span><span>&rdquo;选择&ldquo;是&rdquo;</span><span>以准备好搜索属性。</span></span></li>
<li><span></span><em>如果您在&ldquo;店面可比&rdquo;</em><span><span>字段</span><span>中选择&ldquo;是&rdquo;，则允许在&ldquo;产品比较&rdquo;中比较产品属性。</span></span></li>
<li><span></span><em>在&ldquo;用于促销规则条件&rdquo;</em><span><span>字段中选择&ldquo;是&rdquo;</span><span>以将产品属性应用于价格规则。</span></span></li>
<li><span>要使该属性在目录页面列表中可见，请在&ldquo;</span><em>在店面目录页面上可见&rdquo;</em><span>字段中选择&ldquo;是&rdquo;。</span></li>
<li><span><span>如果您的商店支持产品列表，则可以显示该属性并将其用作排序参数。</span><span>从&ldquo;</span></span><em>用于产品列表</em><span>&rdquo;和&ldquo;用于在产品列表</span><em>中排序&rdquo;</em><span>字段中配置它。</span></li>
<li><span>保存属性以完成所有操作。</span></li>
</ul>
<h2><span>更新产品</span></h2>
<p><span>在管理侧边栏上，选择</span><em>目录 &gt; 产品</em><span>并选择可配置产品。</span></p>
<p><span>在配置部分中，单击</span><span>编辑配置</span><span>。</span></p>
<p><img alt="" class="wp-image-10615" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image3-1-1024x460.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/8.png" width="800" /></p>
<p><span>选择要添加到可配置产品的属性，然后单击</span><span>下一步</span><span>。</span></p>
<p><img alt="" class="wp-image-10617" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image2-1-1024x480.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/9.png" width="800" /></p>
<p><span>然后，选择属性值。</span></p>
<p><img alt="" class="wp-image-10618" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image6-1-1024x486.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/10.png" width="800" /></p>
<p><span>接下来，选择图像、价格和数量选项。</span></p>
<p><img alt="" class="wp-image-10616" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image1-1-1024x485.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/11.png" width="800" /></p>
<p><span>接下来，您将显示所有新产品，在其中单击</span><em>Generate Product</em><span>。</span></p>
<p><img alt="" class="wp-image-10619" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image15-1024x482.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/12.png" width="800" /></p>
<p><span>设置价格和数量，然后点击</span><em>保存</em><span>。</span></p>
<p><img alt="" class="wp-image-10620" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image16-1024x484.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/13.png" width="800" /></p>
<p><span>选择</span><em>Affected Attribute Set</em><span>然后点击</span><em>Confirm</em><span>。</span></p>
<p><img alt="" class="wp-image-10621" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image10-1024x275.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/14.png" width="800" /></p>
<p><span>最后，刷新缓存，然后重新加载编辑页面并查看结果。</span></p>
<p><img alt="" class="wp-image-10622" src="https://store.magenest.com/wp/wp-content/uploads/2020/12/image14-1024x482.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1013/15.png" width="800" /></p>
<p><span></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Tue, 18 Oct 2022 08:27:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中使用 Modal 小部件创建弹出窗口]]></title>
      <link>https://www.360magento.com/blog/How-to-create-a-popup-using-Modal-widget-in-Magento2/</link>
      <description><![CDATA[<p><span>在使用 Magento 2 时，我们尝试利用 Magento 支持的所有实用程序，以避免不得不重新设计现有功能，这会耗费时间和精力。</span></p>
<p><span>在这篇文章中，我将解释如何在 Magento 2 中创建和调用模态弹出窗口小部件。</span></p>
<p><span><span><span>首先，我们有一个按钮。</span><span>单击它将显示一个弹出窗口。</span></span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>button id<span class="token operator">=</span><span class="token double-quoted-string string">"modal-btn"</span><span class="token operator">&gt;</span>Open Modal<span class="token operator">&lt;</span><span class="token operator">/</span>button<span class="token operator">&gt;</span></pre>
<h2><span>为弹出窗口创建内容</span></h2>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>div id<span class="token operator">=</span><span class="token double-quoted-string string">"modal-content"</span><span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token double-quoted-string string">"modal-inner-content"</span><span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>h2<span class="token operator">&gt;</span>Modal Title<span class="token operator">&lt;</span><span class="token operator">/</span>h2<span class="token operator">&gt;</span>
        <span class="token operator">&lt;</span>p<span class="token operator">&gt;</span>Modal content<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token operator">&lt;</span><span class="token operator">/</span>p<span class="token operator">&gt;</span>
    <span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>div<span class="token operator">&gt;</span></pre>
<h2><span>使用 Magento 2 模态小部件</span></h2>
<p><span><span><span>我们现在需要同时需要 jQuery 和 jQuery UI。</span><span>为此，在您的 JS 脚本中，添加以下代码：</span></span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
    <span class="token keyword">require</span><span class="token punctuation">(</span>
        <span class="token punctuation">[</span>
            <span class="token single-quoted-string string">'jquery'</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'Magento_Ui/js/modal/modal'</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token keyword">function</span><span class="token punctuation">(</span>$<span class="token punctuation">,</span> modal<span class="token punctuation">)</span> <span class="token punctuation">{</span> 
            <span class="token comment">// Your JS</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span></pre>
<h2><span>设置模式</span>&nbsp;<span>小部件的选项</span></h2>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token keyword">var</span> options <span class="token operator">=</span> <span class="token punctuation">{</span>
    	type<span class="token punctuation">:</span> <span class="token single-quoted-string string">'popup'</span><span class="token punctuation">,</span>
    	responsive<span class="token punctuation">:</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
      innerScroll<span class="token punctuation">:</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
    	title<span class="token punctuation">:</span> <span class="token single-quoted-string string">'Pop-up title'</span><span class="token punctuation">,</span>
      buttons<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
         text<span class="token punctuation">:</span> $<span class="token punctuation">.</span>mage<span class="token punctuation">.</span><span class="token function">__</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'Close'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
         <span class="token keyword">class</span><span class="token punctuation">:</span> <span class="token single-quoted-string string">'modal-close'</span><span class="token punctuation">,</span>
         click<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
             this<span class="token punctuation">.</span><span class="token function">closeModal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>
    	<span class="token punctuation">}</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></pre>
<h2><span>初始化模态</span>&nbsp;<span>小部件</span></h2>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token function">modal</span><span class="token punctuation">(</span>options<span class="token punctuation">,</span> $<span class="token punctuation">(</span><span class="token single-quoted-string string">'#modal-content'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre>
<p><span>单击按钮时创建事件将显示一个弹出窗口：</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">$<span class="token punctuation">(</span><span class="token double-quoted-string string">"#modal-btn"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'click'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    $<span class="token punctuation">(</span><span class="token double-quoted-string string">"#modal-content"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">modal</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"openModal"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre>
<h2><span>结束</span></h2>
<p><span>完成上述所有步骤后，您的脚本应如下所示：</span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
    <span class="token keyword">require</span><span class="token punctuation">(</span>
        <span class="token punctuation">[</span>
            <span class="token single-quoted-string string">'jquery'</span><span class="token punctuation">,</span>
            <span class="token single-quoted-string string">'Magento_Ui/js/modal/modal'</span>
        <span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token keyword">function</span><span class="token punctuation">(</span>$<span class="token punctuation">,</span> modal<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">var</span> options <span class="token operator">=</span> <span class="token punctuation">{</span>
                type<span class="token punctuation">:</span> <span class="token single-quoted-string string">'popup'</span><span class="token punctuation">,</span>
                responsive<span class="token punctuation">:</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
                innerScroll<span class="token punctuation">:</span> <span class="token boolean constant">true</span><span class="token punctuation">,</span>
                title<span class="token punctuation">:</span> <span class="token single-quoted-string string">'Pop-up title'</span><span class="token punctuation">,</span>
                buttons<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
                    text<span class="token punctuation">:</span> $<span class="token punctuation">.</span>mage<span class="token punctuation">.</span><span class="token function">__</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'Close'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
                    <span class="token keyword">class</span><span class="token punctuation">:</span> <span class="token single-quoted-string string">'modal-close'</span><span class="token punctuation">,</span>
                    click<span class="token punctuation">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                        this<span class="token punctuation">.</span><span class="token function">closeModal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                <span class="token punctuation">}</span><span class="token punctuation">]</span>
            <span class="token punctuation">}</span><span class="token punctuation">;</span>

            <span class="token function">modal</span><span class="token punctuation">(</span>options<span class="token punctuation">,</span> $<span class="token punctuation">(</span><span class="token single-quoted-string string">'#modal-content'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            $<span class="token punctuation">(</span><span class="token double-quoted-string string">"#modal-btn"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'click'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
                $<span class="token punctuation">(</span><span class="token double-quoted-string string">"#modal-content"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">modal</span><span class="token punctuation">(</span><span class="token double-quoted-string string">"openModal"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span></pre>
<h2><span>结果</span></h2>
<p><span>单击按钮时，我们会弹出一个弹出窗口</span><span>：</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/1_3.png" width="800" /></p>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Mon, 17 Oct 2022 08:28:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中验证表单的完整指南]]></title>
      <link>https://www.360magento.com/blog/The-Complete-Guide-on-How-to-Validate-Forms-in-Magento2/</link>
      <description><![CDATA[<p><span><span>Magento 应用程序提供了多种验证表单输入的方法。</span><span>在本文中，我将向您展示如何使用 javascript 在 Magento 2 中验证表单。</span></span></p>
<h2><span>要向表单添加验证，您需要启动验证</span></h2>
<p><span>有几种方法可以启动表单验证：</span><br /><span>- 使用 data-mage-init 属性</span></p>
<pre class="EnlighterJSRAW line-numbers language-js" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator"><span>&lt;</span></span><span> form id </span><span class="token operator"><span>= </span></span><span class="token string">"my-form"</span><span> data </span><span class="token operator"><span>-</span></span><span> mage </span><span class="token operator"><span>-</span></span><span> init </span><span class="token operator"><span>= </span></span><span class="token string">'{"validation": {}}' </span><span class="token operator"><span>&gt; </span></span>
    <span class="token operator"><span>... </span></span>
<span class="token operator"><span>&lt; </span></span><span class="token operator"><span>/</span></span><span> form </span><span class="token operator"><span>&gt;</span></span></pre>
<p><span>- 使用 text/x-magento-init 脚本类型标签</span></p>
<pre class="EnlighterJSRAW line-numbers language-js" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator"><span>&lt;</span></span><span> script type </span><span class="token operator"><span>= </span></span><span class="token string">"text/x-magento-init" </span><span class="token operator"><span>&gt; </span></span>
    <span class="token punctuation">{ </span>
        <span class="token string">"#my-form" </span><span class="token operator"><span>: </span></span> <span class="token punctuation">{ </span>
            <span class="token string">"validation" </span><span class="token operator"><span>: </span></span> <span class="token punctuation">{ </span><span class="token punctuation">} </span>
        <span class="token punctuation">} </span>
    <span class="token punctuation">} </span>
<span class="token operator"><span>&lt; </span></span><span class="token operator"><span>/</span></span><span> script </span><span class="token operator"><span>&gt;</span></span></pre>
<h2><span>将验证规则应用于您的输入字段</span></h2>
<p><span>在您的自定义表单中，您可以使用此处列出的以下方法之一为您的字段设置验证规则：</span><br /><span>- 方法 #1：使用&ldquo;data-validate&rdquo;属性</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;input id="field-name" type="text" data-validate='{"required":true}'/</span></pre>
<p><span>- 方法#2：使用规则名称作为属性</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;input id="field-1" ... required="true"/&gt;</span></pre>
<p><span>- 方法#3：使用规则名作为类名</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;input id="field-1" ... class="input-text required-entry"/&gt;</span></pre>
<p><span>- 方法#4：在表单标签的 data-mage-init 属性中设置规则</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;form ... data-mage-init='{"validation": {"rules": {"field-1": {"required":true}}}}'&gt; </span><span>
    ... </span><span>
&lt;/form&gt;</span></pre>
<h2><span>一些表单验证规则列表</span></h2>
<ul>
<li><span>验证密码</span></li>
<li><span>字母数字</span></li>
<li><span>仅限字母</span></li>
<li><span>无空格</span></li>
<li><span>最大字数</span></li>
<li><span>确认电邮</span></li>
<li><span>验证网址</span></li>
<li><span>验证数字</span></li>
<li><span>验证范围</span></li>
<li><span>验证标识符</span></li>
<li><span>仅限字母</span></li>
<li><span>字母数字</span></li>
<li><span>无空格</span></li>
<li><span>电话美国</span></li>
<li><span>英国电话</span></li>
<li><span>等等，...</span><br /><span>您可以在文件中检查这些所有验证逻辑：</span><em>lib/web/mage/validation.js</em></li>
</ul>
<p><span>示例</span><br /><span><span>我们创建一个自定义表单并为表单字段添加验证。</span><span>在这个表单中，我们使用&ldquo;data-mage-init&rdquo;属性来启动表单验证。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;form class="form" id="custom-form" method="post" autocomplete="off" data-mage-init='{"validation": {}}'&gt;
   &lt;fieldset class="fieldset"&gt;
       &lt;legend class="legend"&gt;
        &lt;span&gt;Form Information&lt;/span&gt;
       &lt;/legend&gt;
       &lt;div class="field required"&gt;
           &lt;label for="email_address" class="label"&gt;
           &lt;span&gt;Email&lt;/span&gt;
           &lt;/label&gt;
       &lt;div class="control"&gt;
            &lt;input type="email" name="email" id="email" value=" "  title="Email"       data-validate="{required:true,  'validate-email':true}"&gt;
        &lt;/div&gt;
       &lt;/div&gt;
       &lt;div class="field name required"&gt;
           &lt;label class="label" for="name"&gt;&lt;span&gt;Name&lt;/span&gt;&lt;/label&gt;
           &lt;div class="control"&gt;
               &lt;input name="name" id="field-2" title="Name" value="" class="input-text" type="text" data-validate="{required:true}"/&gt;
           &lt;/div&gt;
       &lt;/div&gt;
   &lt;/fieldset&gt;
   &lt;div class="actions-toolbar"&gt;
       &lt;div class="primary"&gt;
           &lt;button type="submit" class="action submit primary" title="Submit"&gt;&lt;span&gt;Submit&lt;/span&gt;&lt;/button&gt;
       &lt;/div&gt;
   &lt;/div&gt;
&lt;/form&gt;</pre>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/13_1.png" width="800" /></span></pre>
<p><span>因此，我们已经学习了如何使用 javascript 和 Magento 2 的 validation.js 库来验证表单。希望这篇文章可以帮助您解决您的问题。</span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Sun, 16 Oct 2022 08:26:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中获取和设置 cookie]]></title>
      <link>https://www.360magento.com/blog/How-to-get-and-set-cookies-in-Magento2/</link>
      <description><![CDATA[<p><span>Cookie 是网络工作方式的必要组成部分。</span><span>网站使用 cookie 来跟踪用户并启用用户特定的功能。</span><span>因此，在本文中，我们将向大家展示如何在 Magento 2 中从 cookie 中获取和设置数据。</span></p>
<h2><span>创建类以管理 cookie</span></h2>
<p><span><span>第一步是在 app/code/Magentest/Helper 中设置一个 ExampleCookie.php 类。</span><span>ExampleCookie.php 包含以下内容：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
namespace Magenest\ManagerCookie\Helper;

use Magento\Framework\Session\SessionManagerInterface;

class ExampleCookie {

   protected $cookieManager;
   protected $cookieMetadataFactory;

   public function __construct(
       \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager,
       \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
       )
   {
       $this-&gt;cookieManager = $cookieManager;
       $this-&gt;cookieMetadataFactory = $cookieMetadataFactory;
    }

   /**
    * get cookie by name
    */
   public function getCookie($cookieName) {
       return $this-&gt;cookieManager-&gt;getCookie($cookieName);

   }

   /**
    * set public cookie
    */
   public function setPublicCookie($cookieName, $value) {

   $metadata = $this-&gt;cookieMetadataFactory
       -&gt;createPublicCookieMetadata()
       -&gt;setDuration(86400) // Cookie will expire after one day (86400 seconds)
       -&gt;setSecure(true) //the cookie is only available under HTTPS
       -&gt;setPath('/subfolder')// The cookie will be available to all pages and subdirectories within the /subfolder path
       -&gt;setHttpOnly(false); // cookies can be accessed by JS
  
   $this-&gt;_cookieManager-&gt;setPublicCookie(
       $cookieName,
       $value,
       $metadata
   );
}
   
   /**
    * set sensitive cookie
    */
 public function set Sensitive Cookie($cookieName, $value) {

   $metadata = $this-&gt;cookieMetadataFactory
       -&gt;createSensitiveCookieMetadata()
       -&gt;setPath('')// for global
       -&gt;setDomain('.example.com');// cookie will be available for www.example.com, example.com and will not be available for anotherexample.com

   $this-&gt;_cookieManager-&gt;setSensitiveCookie(
       $cookieName,
       $value,
       $metadata
   );
}

}</pre>
<p><span><span>关于在 Magento 中设置 cookie，首先，你们需要记住，我们在 Magento 中有两种类型的 cookie。</span><span>它们是公共和敏感 cookie：</span></span></p>
<ul>
<li><span>公共</span>&nbsp;<span>cookie</span><span><span>可以通过 JS 访问。</span><span>默认情况下，这些 cookie 的 HttpOnly 将设置为 false。</span></span></li>
<li><span>敏感的cookies</span><span><span>不能被客户端的JS访问，它只能在你的服务器上访问。</span><span>对于这些 cookie，HttpOnly 将始终设置为 true。&nbsp;</span></span></li>
</ul>
<p><span><span>设置 cookie 时，您设置了原始 cookie 数据和一些元数据。</span><span>此元数据包括cookie 的有效</span></span><span>路径</span><span>、cookie 过期时间的</span><span>Duration</span><span>等。</span></p>
<h2><span>在 Javascript 中使用 cookie</span></h2>
<p><span>在 javascript 中，您只需要包含</span><span>jquery/jquery.cookie</span><span>即可使用 cookie</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;script type="text/javascript"&gt;
   require([
       'jquery',
       'jquery/jquery.cookie'
   ], function ($) {
       $(document).ready(function () {

           var simple_cookie = $.cookie('name_cookie'); // Get Cookie Value, note: You can only get a cookie if it is public
           if(!simple_cookie) {
               $.cookie('name_cookie', 'value of cookie', {expires: 86400}); // Set Cookie with metadata (note the cookies set here are public)
           }else {
               console.log(simple_cookie);
           }
       });
&lt;/script&gt;</pre>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="z-index: 2; width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为中文（简体）</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将中文（简体）翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译中文（简体）</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Sat, 15 Oct 2022 08:29:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置联系我们表格和联系电子邮件]]></title>
      <link>https://www.360magento.com/blog/How-to-configure-Contact-Us-form-Contact-Email-in-Magento2/</link>
      <description><![CDATA[<p><span><span>联系我们表单为客户提供了一种与您的业务保持联系的简便方法。</span><span>更重要的是，联系我们表格还有助于让客户放心，有人在倾听他们的查询、投诉和反馈。</span></span></p>
<p><span>因此，在本博客中，我们将向您展示如何在 Magento 2 商店中配置联系我们表单。</span></p>
<h1><span>I.启用联系我们表格</span></h1>
<p><span>第 1 步：</span><span>在管理面板中，选择</span><span>Stores&gt;Configuration：</span></p>
<ul class="wp-block-gallery columns-1 is-cropped">
<li class="blocks-gallery-item"><img alt="" class="wp-image-13338" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_4-1024x549.png" data-id="13338" data-link="https://store.magenest.com/blog/?attachment_id=13338" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/8.png" width="800" /></li>
</ul>
<p><span>第 2 步：</span><span>在&ldquo;</span><span>常规</span><span>&rdquo;选项卡中导航到&ldquo;</span><span>联系人&rdquo;</span></p>
<ul class="wp-block-gallery columns-1 is-cropped">
<li class="blocks-gallery-item"><img alt="" class="wp-image-13339" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_5-1024x137.png" data-id="13339" data-link="https://store.magenest.com/blog/?attachment_id=13339" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/9.png" width="800" /></li>
</ul>
<p><span><span>为字段</span><span>设置</span></span><span>是</span><span></span><span>启用联系我们</span></p>
<p><span>第 3 步：</span><span><span>将您的联系电子邮件放入&ldquo;发送电子邮件至&rdquo;字段中。</span><span>在电子邮件发件人选项中选择将在电子邮件中设置的发件人姓名：</span></span></p>
<ul class="wp-block-gallery columns-1 is-cropped">
<li class="blocks-gallery-item"><img alt="" class="wp-image-13340" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_6-1024x217.png" data-id="13340" data-link="https://store.magenest.com/blog/?attachment_id=13340" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/10.png" width="800" /></li>
</ul>
<p><span><span>您可以在&ldquo;电子邮件模板&rdquo;选项中选择要用于消息的模板。</span><span>然后点击&nbsp;</span></span><span>保存配置</span><span>按钮</span></p>
<p><span>第 4 步：</span><span>在前端检查结果，查看默认的&ldquo;联系我们&rdquo;表单是否已显示：</span></p>
<p><span><img alt="" class="wp-image-13341" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_7-1024x566.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/11.png" width="800" /></span></p>
<h2><span>II.配置联系我们表格</span></h2>
<p><span>第 1 步：</span><span>转到</span><span>内容&gt;块：</span></p>
<p><span><img alt="" class="wp-image-13342" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_8-1024x543.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/12.png" width="800" /></span></p>
<p><span>第 2 步：</span><span>找到带有 Title&nbsp;</span><span>Contact us info</span><span><span>的块，然后在 Select 下拉菜单中</span><span>选择</span></span><span>Edit ：</span><span></span></p>
<p><span><img alt="" class="wp-image-13343" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_9-1024x551.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/13.png" width="800" /></span></p>
<p><span></span><span>您可以通过在内容</span><span>框中输入您的联系信息并</span><span>保存</span><span><span>块</span><span>来自定义您的联系我们表单。</span></span></p>
<p><span>第 3 步：</span><span>将</span><span>CAPTCHA</span><span>添加到&ldquo;</span><span>联系我们&rdquo;</span><span>表单</span></p>
<p><span>转到</span><span>商店 &gt; 配置 &gt; 客户 &gt; 客户配置</span></p>
<p><span><img alt="" class="wp-image-13344" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_10-1024x513.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/1_1.png" width="800" /></span></p>
<p><span>在选项卡验证码中&nbsp;</span></p>
<p><span><img alt="" class="wp-image-13345" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_11-1024x379.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/2_1.png" width="800" /></span></p>
<p><span></span><span>将&ldquo;在店面启用验证码&rdquo;</span><span><span>字段</span><span>设置为&ldquo;是&rdquo; 。</span><span>然后为字段表单选择联系我们以在此表单上添加验证码。</span><span>之后单击&ldquo;</span></span><span>保存配置</span><span><span>&rdquo;按钮。</span><span>StoreFront 中的结果：CAPTCHA 将添加到您的联系我们表单中：</span></span></p>
<p><span><img alt="" class="wp-image-13346" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_12.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/3_1.png" width="800" /></span></p>
<h2><span>III.自定义电子邮件联系表&nbsp;</span></h2>
<p><span>第 1 步：</span><span><span>在 app/code/YourVendor/YourModule/view/frontend/templates 中创建文件 form.phtml。</span><span>您可以在下面查看我们的示例代码：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;form class="form contact"
      action="&lt;?= $block-&gt;escapeUrl($block-&gt;getFormAction()) ?&gt;"
      id="contact-form"
      method="post"
      data-hasrequired="&lt;?= $block-&gt;escapeHtmlAttr(__('* Required Fields')) ?&gt;"
      data-mage-init='{"validation":{}}'&gt;
 
    &lt;fieldset class="fieldset"&gt;
        &lt;legend class="legend"&gt;&lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('Write Us')) ?&gt;&lt;/span&gt;&lt;/legend&gt;&lt;br /&gt;
        &lt;div class="field note no-label"&gt;&lt;?= $block-&gt;escapeHtml(__('Jot us a note and we&rsquo;ll get back to you as quickly as possible.')) ?&gt;&lt;/div&gt;
        &lt;div class="field name required"&gt;
            &lt;label class="label" for="name"&gt;&lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('Name')) ?&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="control"&gt;
                &lt;input name="name" id="name" title="&lt;?= $block-&gt;escapeHtmlAttr(__('Name')) ?&gt;" value="&lt;?= $block-&gt;escapeHtmlAttr($this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getPostValue('name') ?: $this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getUserName()) ?&gt;" class="input-text" type="text" data-validate="{required:true}"/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
 
       &lt;--New field customize--&gt;
        &lt;div class="field subject required"&gt;
             &lt;label class="label" for="subject"&gt;&lt;span&gt;&lt;?php /* @escapeNotVerified */ echo __('Subject') ?&gt;&lt;/span&gt;&lt;/label&gt;
             &lt;div class="control"&gt;
                  &lt;input name="subject" id="subject" title="&lt;?php /* @escapeNotVerified */ echo __('Subject') ?&gt;" value="" class="input-text" type="text" data-validate="{required:true}"/&gt;
             &lt;/div&gt;
        &lt;/div&gt;
 
        &lt;div class="field email required"&gt;
            &lt;label class="label" for="email"&gt;&lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('Email')) ?&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="control"&gt;
                &lt;input name="email" id="email" title="&lt;?= $block-&gt;escapeHtmlAttr(__('Email')) ?&gt;" value="&lt;?= $block-&gt;escapeHtmlAttr($this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getPostValue('email') ?: $this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getUserEmail()) ?&gt;" class="input-text" type="email" data-validate="{required:true, 'validate-email':true}"/&gt;
            &lt;/div&gt;
        &lt;/div&gt;
 
        &lt;div class="field telephone"&gt;
            &lt;label class="label" for="telephone"&gt;&lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('Phone Number')) ?&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="control"&gt;
                &lt;input name="telephone" id="telephone" title="&lt;?= $block-&gt;escapeHtmlAttr(__('Phone Number')) ?&gt;" value="&lt;?= $block-&gt;escapeHtmlAttr($this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getPostValue('telephone')) ?&gt;" class="input-text" type="text" /&gt;
            &lt;/div&gt;
        &lt;/div&gt;
 
        &lt;div class="field comment required"&gt;
            &lt;label class="label" for="comment"&gt;&lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('What&rsquo;s on your mind?')) ?&gt;&lt;/span&gt;&lt;/label&gt;
            &lt;div class="control"&gt;
                &lt;textarea name="comment" id="comment" title="&lt;?= $block-&gt;escapeHtmlAttr(__('What&rsquo;s on your mind?')) ?&gt;" class="input-text" cols="5" rows="3" data-validate="{required:true}"&gt;&lt;?= $block-&gt;escapeHtml($this-&gt;helper('Magento\Contact\Helper\Data')-&gt;getPostValue('comment')) ?&gt;&lt;/textarea&gt;
            &lt;/div&gt;
        &lt;/div&gt;
 
        &lt;?= $block-&gt;getChildHtml('form.additional.info') ?&gt;
    &lt;/fieldset&gt;
 
    &lt;div class="actions-toolbar"&gt;
        &lt;div class="primary"&gt;
            &lt;input type="hidden" name="hideit" id="hideit" value="" /&gt;
            &lt;button type="submit" title="&lt;?= $block-&gt;escapeHtmlAttr(__('Submit')) ?&gt;" class="action submit primary"&gt;
                &lt;span&gt;&lt;?= $block-&gt;escapeHtml(__('Submit')) ?&gt;&lt;/span&gt;
            &lt;/button&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/form&gt;</pre>
<p><span>第 2 步：</span><span><span>接下来，</span><span>在 app/code/YourVendor/YourModule/view/frontend/layout 中创建</span></span><span>contact_index_index.xml以用新的 form.phtml 文件覆盖之前的</span><span></span><span>form.phtml</span><span><span>文件。</span><span>看看我们下面的示例代码：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;?xml version="1.0"?&gt; </span><span>
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View /Layout/etc/page_configuration.xsd"&gt;     </span><span>
   &lt;body&gt;      </span><span>
      &lt;referenceBlock name="contactForm" remove="true"/&gt;    </span><span>
       &lt;referenceContainer name="content"&gt; </span><span>
           &lt;block class="Magento\Contact\Block\ContactForm" name= "customContactForm" template="Magenticians_Modulecontact::form.phtml" /&gt; </span><span>
       &lt;/referenceContainer&gt; </span><span>
   &lt;/body&gt; </span><span>
&lt;/page&gt;</span></pre>
<p><span>第 3 步：</span><span>转到</span><span>MARKETING &gt; Email Templates</span><span>并单击</span><span>Add New Template</span><span>按钮：</span></p>
<p><span><img alt="" class="wp-image-13347" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_13-1024x502.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/1_2.png" width="800" /></span></p>
<p><span><span>从</span><span><span>模板</span></span><span>字段中</span><span>选择</span></span><span>联系表格，然后单击</span><span><span><span>加载模板</span></span><span>按钮。</span><span>然后单击</span><span><span>保存模板</span></span><span>按钮。</span></span><span><span></span></span><span></span><span><span></span></span><span></span><span><span></span></span><span></span></p>
<p><span>第 4 步：</span><span>转到</span><span>商店 &gt; 配置 &gt; 常规 &gt; 联系人</span><span>选项卡：</span></p>
<p><span><img alt="" class="wp-image-13348" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_14-1024x461.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/2_2.png" width="800" /></span></p>
<p><span><span>选择</span><span>您为电子邮件模板字段创建的</span></span><span>我的自定义表单。</span><span>然后单击</span><span>保存配置</span><span>。</span></p>
<p><span>如果您已正确完成所有步骤，您的结果将是带有新字段主题的联系我们表单，如下面的屏幕截图：</span></p>
<p><span><img alt="" class="wp-image-13349" src="https://store.magenest.com/wp/wp-content/uploads/2021/04/Screenshot_15-1024x674.png" /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/3_2.png" width="800" /></span></p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>
<div class="TnITTtw-fp-collapsed-button" style="display: block;"></div>
<div class="TnITTtw-mate-fp-bar" style="width: 0px; height: 0px; opacity: 0; display: none;">
<div class="TnITTtw-hide-fp-bar" style="display: none;"></div>
<div class="TnITTtw-current-page-lang" style="display: none;">此页面的语言为英语</div>
<div class="TnITTtw-cta-button-layout" style="display: none;">
<div class="TnITTtw-spinner">
<div class="TnITTtw-bounce1"></div>
<div class="TnITTtw-bounce2"></div>
<div class="TnITTtw-bounce3"></div>
</div>
<div class="TnITTtw-mw-button TnITTtw-fp-translate TnITTtw-high-cta" style="display: none;">翻译为</div>
</div>
<div class="TnITTtw-change-language TnITTtw-select" style="display: none;" data-for-serial="3"></div>
<div class="TnITTtw-stop-fp"></div>
<div class="TnITTtw-toggle-iphone-settings" style="display: none;"></div>
<div class="TnITTtw-ui_selector" style="display: none;">
<div class="TnITTtw-options-arrow" style="display: none;"></div>
<div class="TnITTtw-options TnITTtw-opt-3 TnITTtw-standalone" style="display: none; z-index: 998;" data-serial="3">
<div class="TnITTtw-dd-search"><input class="TnITTtw-dd-input" type="text" data-dir="to" data-width="NaN" /></div>
<div id="selVisibleScroll-3">
<div id="selEntireScroll-3">
<div class="TnITTtw-inner-options-layout">
<ul class="TnITTtw-list">
<li class="lang-zh-CN TnITTtw-option"><span class="lang-zh-CN" id="lang-zh-CN">中文（简体）</span></li>
<li class="lang-zh-TW TnITTtw-option"><span class="lang-zh-TW" id="lang-zh-TW">中文（繁体）</span></li>
<li class="lang-da TnITTtw-option"><span class="lang-da" id="lang-da">丹麦语</span></li>
<li class="lang-uk TnITTtw-option"><span class="lang-uk" id="lang-uk">乌克兰语</span></li>
<li class="lang-ur TnITTtw-option"><span class="lang-ur" id="lang-ur">乌尔都语</span></li>
<li class="lang-hy TnITTtw-option"><span class="lang-hy" id="lang-hy">亚美尼亚语</span></li>
<li class="lang-ru TnITTtw-option"><span class="lang-ru" id="lang-ru">俄语</span></li>
<li class="lang-bg TnITTtw-option"><span class="lang-bg" id="lang-bg">保加利亚语</span></li>
<li class="lang-hr TnITTtw-option"><span class="lang-hr" id="lang-hr">克罗地亚语</span></li>
<li class="lang-is TnITTtw-option"><span class="lang-is" id="lang-is">冰岛语</span></li>
<li class="lang-ca TnITTtw-option"><span class="lang-ca" id="lang-ca">加泰罗尼亚语</span></li>
<li class="lang-hu TnITTtw-option"><span class="lang-hu" id="lang-hu">匈牙利语</span></li>
<li class="lang-kn TnITTtw-option"><span class="lang-kn" id="lang-kn">卡纳达语</span></li>
<li class="lang-hi TnITTtw-option"><span class="lang-hi" id="lang-hi">印地语</span></li>
<li class="lang-id TnITTtw-option"><span class="lang-id" id="lang-id">印尼语</span></li>
<li class="lang-gu TnITTtw-option"><span class="lang-gu" id="lang-gu">古吉拉特语</span></li>
<li class="lang-kk TnITTtw-option"><span class="lang-kk" id="lang-kk">哈萨克语</span></li>
<li class="lang-tr TnITTtw-option"><span class="lang-tr" id="lang-tr">土耳其语</span></li>
<li class="lang-cy TnITTtw-option"><span class="lang-cy" id="lang-cy">威尔士语</span></li>
<li class="lang-bn TnITTtw-option"><span class="lang-bn" id="lang-bn">孟加拉语</span></li>
<li class="lang-ne TnITTtw-option"><span class="lang-ne" id="lang-ne">尼泊尔语</span></li>
<li class="lang-af TnITTtw-option"><span class="lang-af" id="lang-af">布尔语(南非荷兰语)</span></li>
<li class="lang-iw TnITTtw-option"><span class="lang-iw" id="lang-iw">希伯来语</span></li>
<li class="lang-el TnITTtw-option"><span class="lang-el" id="lang-el">希腊语</span></li>
<li class="lang-ku TnITTtw-option"><span class="lang-ku" id="lang-ku">库尔德语</span></li>
<li class="lang-de TnITTtw-option"><span class="lang-de" id="lang-de">德语</span></li>
<li class="lang-it TnITTtw-option"><span class="lang-it" id="lang-it">意大利语</span></li>
<li class="lang-lv TnITTtw-option"><span class="lang-lv" id="lang-lv">拉脱维亚语</span></li>
<li class="lang-no TnITTtw-option"><span class="lang-no" id="lang-no">挪威语</span></li>
<li class="lang-cs TnITTtw-option"><span class="lang-cs" id="lang-cs">捷克语</span></li>
<li class="lang-sk TnITTtw-option"><span class="lang-sk" id="lang-sk">斯洛伐克语</span></li>
<li class="lang-sl TnITTtw-option"><span class="lang-sl" id="lang-sl">斯洛文尼亚语</span></li>
<li class="lang-pa TnITTtw-option"><span class="lang-pa" id="lang-pa">旁遮普语</span></li>
<li class="lang-ja TnITTtw-option"><span class="lang-ja" id="lang-ja">日语</span></li>
<li class="lang-ps TnITTtw-option"><span class="lang-ps" id="lang-ps">普什图语</span></li>
<li class="lang-mi TnITTtw-option"><span class="lang-mi" id="lang-mi">毛利语</span></li>
<li class="lang-fr TnITTtw-option"><span class="lang-fr" id="lang-fr">法语</span></li>
<li class="lang-pl TnITTtw-option"><span class="lang-pl" id="lang-pl">波兰语</span></li>
<li class="lang-fa TnITTtw-option"><span class="lang-fa" id="lang-fa">波斯语</span></li>
<li class="lang-te TnITTtw-option"><span class="lang-te" id="lang-te">泰卢固语</span></li>
<li class="lang-ta TnITTtw-option"><span class="lang-ta" id="lang-ta">泰米尔语</span></li>
<li class="lang-th TnITTtw-option"><span class="lang-th" id="lang-th">泰语</span></li>
<li class="lang-ht TnITTtw-option"><span class="lang-ht" id="lang-ht">海地克里奥尔语</span></li>
<li class="lang-et TnITTtw-option"><span class="lang-et" id="lang-et">爱沙尼亚语</span></li>
<li class="lang-sv TnITTtw-option"><span class="lang-sv" id="lang-sv">瑞典语</span></li>
<li class="lang-lt TnITTtw-option"><span class="lang-lt" id="lang-lt">立陶宛语</span></li>
<li class="lang-my TnITTtw-option"><span class="lang-my" id="lang-my">缅甸语</span></li>
<li class="lang-ro TnITTtw-option"><span class="lang-ro" id="lang-ro">罗马尼亚语</span></li>
<li class="lang-lo TnITTtw-option"><span class="lang-lo" id="lang-lo">老挝语</span></li>
<li class="lang-fi TnITTtw-option"><span class="lang-fi" id="lang-fi">芬兰语</span></li>
<li class="lang-en TnITTtw-option"><span class="lang-en" id="lang-en">英语</span></li>
<li class="lang-nl TnITTtw-option"><span class="lang-nl" id="lang-nl">荷兰语</span></li>
<li class="lang-sm TnITTtw-option"><span class="lang-sm" id="lang-sm">萨摩亚语</span></li>
<li class="lang-pt TnITTtw-option"><span class="lang-pt" id="lang-pt">葡萄牙语</span></li>
<li class="lang-es TnITTtw-option"><span class="lang-es" id="lang-es">西班牙语</span></li>
<li class="lang-vi TnITTtw-option"><span class="lang-vi" id="lang-vi">越南语</span></li>
<li class="lang-az TnITTtw-option"><span class="lang-az" id="lang-az">阿塞拜疆语</span></li>
<li class="lang-am TnITTtw-option"><span class="lang-am" id="lang-am">阿姆哈拉语</span></li>
<li class="lang-sq TnITTtw-option"><span class="lang-sq" id="lang-sq">阿尔巴尼亚语</span></li>
<li class="lang-ar TnITTtw-option"><span class="lang-ar" id="lang-ar">阿拉伯语</span></li>
<li class="lang-ko TnITTtw-option"><span class="lang-ko" id="lang-ko">韩语</span></li>
<li class="lang-mg TnITTtw-option"><span class="lang-mg" id="lang-mg">马尔加什语</span></li>
<li class="lang-mr TnITTtw-option"><span class="lang-mr" id="lang-mr">马拉地语</span></li>
<li class="lang-ml TnITTtw-option"><span class="lang-ml" id="lang-ml">马拉雅拉姆语</span></li>
<li class="lang-ms TnITTtw-option"><span class="lang-ms" id="lang-ms">马来语</span></li>
<li class="lang-mt TnITTtw-option"><span class="lang-mt" id="lang-mt">马耳他语</span></li>
<li class="lang-km TnITTtw-option"><span class="lang-km" id="lang-km">高棉语</span></li>
</ul>
</div>
</div>
<div id="sel-scrollbar-3">
<div id="sel-track-3">
<div id="sel-dragBar-3"></div>
</div>
</div>
</div>
</div>
</div>
<div class="TnITTtw-fp-options" style="display: none;"><input id="TnITTtw-always-translate" readonly="readonly" style="display: none;" type="checkbox" /><label class="TnITTtw-always-translate-label TnITTtw-not-pro" for="TnITTtw-always-translate" style="display: none;"><span class="TnITTtw-always-translate-inner-label" style="display: none;">随时将英语翻译为</span><span class="TnITTtw-pro-label" style="display: none;">PRO</span></label> <br style="display: none;" /> <input id="TnITTtw-never-translate-lang" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-lang-label" for="TnITTtw-never-translate-lang" style="display: none;">一律不翻译英语</label> <br style="display: none;" /> <input id="TnITTtw-never-translate-site" style="display: none;" type="checkbox" /><label class="TnITTtw-never-translate-site-label" for="TnITTtw-never-translate-site" style="display: none;">一律不翻译www.360magento.com</label></div>
</div>]]></description>
      <pubDate>Fri, 14 Oct 2022 08:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 UI 表单中创建图像上传器]]></title>
      <link>https://www.360magento.com/blog/How-to-Create-an-Image-Uploader-in-Magento2-UI-Form/</link>
      <description><![CDATA[<p><span><span>上传文件是每个开发人员在使用 UI 表单时都会遇到的流行过程。</span><span>虽然它很受欢迎，但这个过程比看起来要复杂得多。</span><span>因此，在今天来自 Magenest 的技术指南文章中，我们将逐步指导您如何在 Magento 2 UI 表单中创建图像上传器。&nbsp;</span></span></p>
<h2><span>在 UI 表单中创建图片上传器的步骤</span></h2>
<h3><span>第 1 步：添加字段 UI 表单</span>&nbsp;</h3>
<p><span><span>让我们在您的 UI 表单 XML 文件中添加一个字段来呈现图像上传器。</span><span>请注意，您需要如下定义 formElement、elementTmpl、previewTmpl、uploaderConfig 配置，以确保图像上传器可以正确显示。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;field name="logo"&gt;
   &lt;argument name="data" xsi:type="array"&gt;
       &lt;item name="config" xsi:type="array"&gt;
           &lt;item name="dataType" xsi:type="string"&gt;string&lt;/item&gt;
           &lt;item name="label" xsi:type="string" translate="true"&gt;Logo&lt;/item&gt;
           &lt;item name="formElement" xsi:type="string"&gt;fileUploader&lt;/item&gt;
           &lt;item name="elementTmpl" xsi:type="string"&gt;ui/form/element/uploader/uploader&lt;/item&gt;
           &lt;item name="previewTmpl" xsi:type="string"&gt;ui/form/element/uploader/preview&lt;/item&gt;
           &lt;item name="sortOrder" xsi:type="number"&gt;10&lt;/item&gt;
           &lt;item name="required" xsi:type="boolean"&gt;true&lt;/item&gt;
           &lt;item name="allowedExtensions" xsi:type="string"&gt;jpg jpeg gif png svg&lt;/item&gt;
           &lt;item name="uploaderConfig" xsi:type="array"&gt;
               &lt;item name="url" xsi:type="url" path="magenest_upload/index/upload"/&gt;
           &lt;/item&gt;
           &lt;item name="notice" xsi:type="string"&gt;&lt;![CDATA[Allowed file types:jpg, jpeg, png.]]&gt;&lt;/item&gt;
       &lt;/item&gt;
   &lt;/argument&gt;
&lt;/field&gt;</pre>
<h3><span>第 2 步：创建 ImageUploader 模型</span></h3>
<p><span>创建一个模型 ImageUploader 来处理您的上传逻辑，例如从请求正文在临时目录中创建文件，将文件从临时目录复制到目标文件夹。</span></p>
<p><span><span>Magenest / ImageUpload / Model / ImageUploader</span><br /></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
namespace Magenest\ImageUpload\Model;
...
class ImageUploader extends \Magento\Catalog\Model\ImageUploader {
public function __construct(
   Database $coreFileStorageDatabase,
   Filesystem $filesystem,
   UploaderFactory $uploaderFactory,
   StoreManagerInterface $storeManager,
   LoggerInterface $logger, $baseTmpPath,
   $basePath,
   $allowedExtensions,
   $allowedMimeTypes = [],
   Name $fileNameLookup = null)
{
   parent::__construct($coreFileStorageDatabase, $filesystem, $uploaderFactory, $storeManager, $logger, $baseTmpPath, $basePath, $allowedExtensions, $allowedMimeTypes, $fileNameLookup);
}
//todo: for later logic override use
...
}</pre>
<h3><span>第三步：创建控制器上传图片</span></h3>
<p><span>当您上传图片时，控制器将响应</span><span>&nbsp;</span><span>使用 ImageUploader 模型将您的图片移动到目标目录。</span></p>
<p><span>Magenest / ImageUpload / Controller / Adminhtml / Index / Upload</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""> public function __construct(
       Context $context, 
       \Magenest\ImageUpload\Model\ImageUploader $imageUploader
   ){
       $this-&gt;imageUploader = $imageUploader;
       parent::__construct($context);
   }
   public function execute()
   {
       $imageId = $this-&gt;_request-&gt;getParam('param_name', 'image');

       try {
           $result = $this-&gt;imageUploader-&gt;saveFileToTmpDir($imageId);
       } catch (Exception $e) {
           $result = ['error' =&gt; $e-&gt;getMessage(), 'errorcode' =&gt; $e-&gt;getCode()];
       }
       return $this-&gt;resultFactory-&gt;create(ResultFactory::TYPE_JSON)-&gt;setData($result);
   }
</pre>
<h3><span>第 4 步：使用依赖注入配置 ImageUploader 和 Upload 控制器构造函数</span></h3>
<p><span><span>现在在 di.xml 中添加您的配置。</span><span>这些配置包括上传基本路径和上传图片上传的基本临时路径。</span><span>类型名称将是您的上传控制器。</span></span></p>
<p><span>现在在</span><span>Magenest/ImageUpload/etc/di.xml中添加配置</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>&lt;type name="Magenest\ImageUpload\TestImageUpload"&gt; </span><span>
   &lt;arguments&gt; </span><span>
       &lt;argument name="baseTmpPath" xsi:type="string"&gt;test/tmp&lt;/argument&gt; </span><span>
       &lt;argument name="basePath" xsi:type="string "&gt;test&lt;/argument&gt; </span><span>
   &lt;/arguments&gt; </span><span>
&lt;/type&gt;</span></pre>
<h2><span>检查结果</span></h2>
<p><span>如果所有步骤都已完成，请清除缓存并查看您的 UI 表单以查看结果。</span></p>
<div class="wp-block-image"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/7.png" width="800" /></span></div>
<div class="wp-block-image"><span>如果您已成功创建图片上传器，结果将如下所示</span></div>
<p><span><span>现在客户端可以将图像上传到文件系统。</span><span>但是，要将图像从 tmpl 文件夹移动到所需文件夹以及保存文件路径以供进一步处理，您需要在 UI 表单的操作保存中添加一些脚本：&nbsp;</span></span></p>
<p><span>Magenest / ImageUpload / Controller / Adminhtml / Index / Save</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">if ($data) 
{
           if (isset($data['logo'][0]['name']) &amp;&amp; isset($data['logo'][0]['tmp_name'])) {
               $data['image'] =$data['logo'][0]['name'];
               /** @var \Magenest\ImageUpload\Model\ImageUploader $this-&gt;imageUploader */
               $this-&gt;imageUploader-&gt;moveFileFromTmp($data['image']);
           } elseif (isset($data['logo'][0]['image']) &amp;&amp; !isset($data['logo'][0]['tmp_name'])) {
               $data['image'] = $data['logo'][0]['image'];
           } else {
               $data['image'] = null;
           }
}</pre>]]></description>
      <pubDate>Thu, 13 Oct 2022 08:31:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中安装 ElasticSearch]]></title>
      <link>https://www.360magento.com/blog/How-to-install-ElasticSearch-within-Magento2/</link>
      <description><![CDATA[<p><span><span>为什么要安装 Elasticsearch？</span><span>Elasticsearch 是一个实时分布式搜索引擎，能够执行各种类型的搜索。</span><span>它在您的 Web 服务器上运行，其灵活的特性使其能够搜索各种类型的文档，无论其数据类型如何，包括结构化、非结构化、地理和指标数据类型。</span><span>通过安装 Elasticsearch，您可以提高电子商务网站搜索查询的性能和准确性。</span></span></p>
<p><span><span>从 2.4 版本开始，Magento 使用 Elasticsearch 进行搜索，而不是使用 Mysql。</span><span>在这篇博客中，我将向您介绍如何安装 Elasticsearch，然后在 Magento 2 中进行设置。</span></span></p>
<h2><span>1.安装Java（依赖需要）</span></h2>
<p><span><span>因为 Elasticsearch 是基于 Java 开发的开源软件，所以首先设置 Java 至关重要。</span><span>如您所知，Java 是一种编程语言和平台。</span><span>Java 是一种高级、健壮、面向对象和安全的编程语言。</span><span>因此，您可以将注意力从安全问题上移开，并按照以下说明进行操作。</span></span></p>
<p><span>运行以下命令来安装 Java。</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">sudo apt-get update</pre>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">sudo apt install openjdk-8-jdk-y</pre>
<p><span>接下来，使用以下命令验证 java 是否已正确安装：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">java -version</pre>
<p><span>输出应如下所示：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>openjdk version "1.8.0_292" </span><span>
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10) </span><span>
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)</span></pre>
<h2><span>2. 安装 Elasticsearch</span></h2>
<p><span>首先，您必须添加 Elasticsearch 的签名密钥来验证下载的包（如果您已经从 Elasticsearch 安装了包，则跳过此步骤）：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add</pre>
<p><span>接下来，您需要安装 apt-transport-https 包：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>sudo apt-get install apt-transport-https</span></pre>
<p><span>现在将 Elasticsearch 存储库添加到系统中。</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span><span>echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | </span><span>sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list</span></span></pre>
<p><span>接下来，更新 apt 包的列表并安装 Elasticsearch 引擎。</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>sudo apt-get update &amp;&amp; sudo apt-get install elasticsearch</span></pre>
<p><span>启动 Elasticsearch 服务。</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>sudo systemctl enable elasticsearch.service </span><span>
sudo systemctl start elasticsearch.service</span></pre>
<p><span>您可以通过使用以下 curl 命令将 HTTP 请求发送到 localhost 上的端口 9200 来验证 Elasticsearch 是否正在运行：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>curl -X GET "localhost:9200/"</span></pre>
<p><span>结果与此类似：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{
  "name" : "P5wiUFd",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "WfQWVkBvSUam5sD708C6_w",
  "version" : {
    "number" : "6.8.14",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "dab5822",
    "build_date" : "2021-02-02T19:58:04.182039Z",
    "build_snapshot" : false,
    "lucene_version" : "7.7.3",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}</pre>
<h2><span>3. 在 Magento 2 中配置 Elasticsearch</span></h2>
<p><span><span>获得 Elasticsearch 后，您现在就可以在您的电子商务网站中配置这个强大的搜索引擎了。</span><span>让我们潜入吧！</span></span></p>
<p><span>从管理侧边栏中，导航到</span><em>商店 &gt; 设置 &gt; 配置 &gt; 目录 &gt; 目录 &gt; 目录搜索。</em></p>
<p><span>在 Search Engine 字段中，清除 Use system value 复选框并选择安装在您的服务器上的 Elasticsearch 版本。</span></p>
<p><span>配置 Elasticsearch 连接</span></p>
<ul>
<li><span><span>输入 Elasticsearch 服务器主机名。</span><span>默认是本地主机</span></span></li>
<li><span>输入 Elasticsearch 服务器端口。</span></li>
<li><span><span>在 Elasticsearch Index Prefix 字段中输入前缀以确定 Elasticsearch 索引。</span><span>例如：Magento2。</span></span></li>
<li><span>在 Enable Elasticsearch HTTP Auth 字段中，选择 Yes 选项以使用 HTTP 身份验证来建议用户名和密码访问 Elasticsearch Server。</span></li>
<li><span><span>在 Elasticsearch Server Timeout 字段中输入系统超时前的秒数。</span><span>默认数字为 15。</span></span></li>
</ul>
<p><span><span>要验证配置，请单击测试连接按钮。</span><span>如果成功，按钮文本将变为&ldquo;</span></span><span><em><span><span>成功！</span><span>再次测试</span></span></em></span><em>？</em><span>'</span></p>
<p><span>你的配置应该是这样的</span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/6.png" width="800" /></span></span></p>
<p><span>完成后，点击&ldquo;保存配置&rdquo;。</span></p>]]></description>
      <pubDate>Wed, 12 Oct 2022 08:27:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何以编程方式将产品添加到购物车]]></title>
      <link>https://www.360magento.com/blog/How-to-add-products-to-cart-programmatically/</link>
      <description><![CDATA[<p><span>在本文中，我们将向您展示如何在 Magento 2 中以编程方式将产品添加到购物车。这在您想要向购物车中的商品添加额外数据、添加需要自定义逻辑的产品或只是为购物车添加礼物时最有用。购买您的产品的客户。</span></p>
<p><span>本文假设：</span></p>
<ul>
<li><span>我们正在将代码添加到名为 Magenest\Example 的自定义模块中，路径为&ldquo;example&rdquo;</span></li>
<li><span>自定义添加到购物车功能在 Magenest\Example\Controller\Product 的控制器中执行</span></li>
</ul>
<h2><span>如何</span><span>使用报价模型将产品添加到购物车</span></h2>
<p><span>控制器 AddToCart 处理发送到路径&ldquo;example/product/addToCart&rdquo;的 GET 请求，并使用存储在请求参数中的信息将产品添加到购物车。</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?php
namespace Magenest\Example\Controller\Product;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;

/**
* Class AddToCart
* @package Magenest\BookingReservation\Controller\Product
*/
class AddToCart extends Action implements HttpGetActionInterface
{
   /** @var \Magento\Checkout\Model\SessionFactory */
   private $checkoutSession;

   /** @var \Magento\Quote\Api\CartRepositoryInterface */
   private $cartRepository;

   /** @var \Magento\Catalog\Api\ProductRepositoryInterface */
   private $productRepository;

   /** @var \Magento\Framework\Serialize\Serializer\Json */
   private $json;

   /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable */
   private $configurableType;

   /**
     * AddToCart constructor.
     * @param Context $context
     * @param \Magento\Framework\Serialize\Serializer\Json $json
     * @param \Magento\Checkout\Model\SessionFactory $checkoutSession
     * @param \Magento\Quote\Api\CartRepositoryInterface $cartRepository
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
     */
   public function __construct(
       Context $context,
       \Magento\Framework\Serialize\Serializer\Json $json,
       \Magento\Checkout\Model\SessionFactory $checkoutSession,
       \Magento\Quote\Api\CartRepositoryInterface $cartRepository,
       \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
       \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
   ) {
       $this-&gt;checkoutSession = $checkoutSession;
       $this-&gt;cartRepository = $cartRepository;
       $this-&gt;productRepository = $productRepository;
       $this-&gt;json = $json;
       $this-&gt;configurableType = $configurableType;
       parent::__construct($context);
   }

   /**
    * @return ResultInterface
    * @throws LocalizedException
    */
   public function execute()
   {
       $product = $this-&gt;productRepository-&gt;getById($this-&gt;getRequest()-&gt;getParam('id'));
       $qty = $this-&gt;getRequest()-&gt;getParam('qty');

       $session = $this-&gt;checkoutSession-&gt;create();
       $quote = $session-&gt;getQuote();
       $quote-&gt;addProduct($product, $qty);

       $this-&gt;cartRepository-&gt;save($quote);
       $session-&gt;replaceQuote($quote)-&gt;unsLastRealOrderId();
   }
}</pre>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span><br /></span><span></span></pre>
<p><span><span>您可以仅使用产品 ID 将产品添加到购物车。</span><span>数量参数是可选的：如果参数为空，报价模型将假定数量为 1。</span></span></p>
<h3><span>如何使用其他选项将产品添加到购物车</span></h3>
<p><span><span>addProduct 函数可以适应简单参数格式和高级参数格式。</span><span>这允许您向购物车项目添加其他选项和数据。</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">/**
* @throws LocalizedException
*/
public function addProductWithOptions()
{
   $productSku = $this-&gt;getRequest()-&gt;getParam('sku');
   $qty       = $this-&gt;getRequest()-&gt;getParam('qty');

   /**
    * You can specify custom options for a product before adding it to cart
    */
   $product = $this-&gt;productRepository-&gt;get($productSku);
   $product-&gt;addCustomOption('additional_options', $this-&gt;json-&gt;serialize([
       'custom_option_1' =&gt; [
           'label' =&gt; __("Custom Option 1"),
           'value' =&gt; 10
       ],
       'custom_option_2' =&gt; [
           'label' =&gt; __("Custom Option 2"),
           'value' =&gt; 20
       ]
   ]));

   /**
    * The second parameter of addProduct function can either be an integer, or a Magento DataObject
    * An integer will be interpreted as quantity added
    * Using a DataObject will allow adding custom data to cart items; these data will be saved and can be retrieved as info_buyRequest of quote/order items
    */
   $buyRequest = new \Magento\Framework\DataObject([
       'qty' =&gt; $qty,
       'related_product' =&gt; '',
       'custom_option' =&gt; '?'
   ]);

   $session = $this-&gt;checkoutSession-&gt;create();
   $quote = $session-&gt;getQuote();
   $quote-&gt;addProduct($product, $buyRequest);

   $this-&gt;cartRepository-&gt;save($quote);
   $session-&gt;replaceQuote($quote)-&gt;unsLastRealOrderId();
}</pre>
<p><span>Product 的&ldquo;additional_options&rdquo;将显示在购物车页面上：</span></p>
<h2><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/4.png" width="800" /></span></h2>
<h2><span>购物车页面上的产品附加选项</span></h2>
<h3><span>如何将特殊类型的产品添加到购物车</span></h3>
<p><span><span>将一些具有特殊类型的产品添加到购物车可能需要提供额外的选项。</span><span>假设您知道所需的具体参数值，您还可以将这些产品添加到购物车中。</span><span>以下是将捆绑产品添加到购物车的一般格式：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span>/** </span><span>
* @throws LocalizedException </span><span>
*/ </span><span>
public function addSpecialProduct() </span><span>
{ </span><span>
   $productId = $this-&gt;getRequest()-&gt;getParam('id'); </span><span>
   $product = $this-&gt;productRepository-&gt;getById($productId); </span>
<span>
   $buyRequest = new \Magento\Framework\DataObject([ </span><span>
       // super_group 用于设置分组产品中子项目的数量</span><span>
       'super_group' =&gt; [ </span><span>
           10 =&gt; "1", // value is pass as $sub-productId =&gt; $qty </span><span>
           20 =&gt; "2" </span><span>
       ], </span>
<span>
       // 添加捆绑产品需要两个选项：'bundle_option' 和 'bundle_option_qty' </span><span>
       // 两个选项都作为索引数组传递，</span><span>
       'bundle_option' =&gt; ["2", "4", "5"], // 使用捆绑产品 'selection_id' 添加项目，而不是实际产品 ID </span><span>
       'bundle_option_qty' =&gt; ["1", "2", " 3"], </span>
<span>
       // 可配置的产品选项使用 'super_attribute' 传递 option </span><span>
       'super_attribute' =&gt; [ </span><span>
           143 =&gt; "168", // 格式为 $optionId =&gt; $optionValue </span><span>
           93 =&gt; "58" </span><span>
       ] </span><span>
   ]); </span>
<span>
   $session = $this-&gt;checkoutSession-&gt;create(); </span><span>
   $quote = $session-&gt;getQuote(); </span><span>
   $quote-&gt;addProduct($product, $buyRequest); </span>
<span>
   $this-&gt;cartRepository-&gt;save($quote); </span><span>
   $session-&gt;replaceQuote($quote)-&gt;unsLastRealOrderId(); </span><span>
}</span></pre>
<p><span><span>每种特殊产品类型都有自己的功能来获取特殊属性。</span><span>请参阅这些产品的类型模型以了解如何手动添加它们。</span></span></p>
<p><span><span>例如，可以使用函数 getConfigurableAttributes() 或 getConfigurableAttributesAsArray() 提取可配置产品属性。</span><span>这使我们可以使用其简单的 SKU 将可配置的产品添加到购物车：</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">/**
* @throws LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
private function addConfigurableProduct()
{
   $childId = $this-&gt;getRequest()-&gt;getParam('id');
   $childProduct = $this-&gt;productRepository-&gt;getById($childId);

   /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable configurableType */
   $parentId = $this-&gt;configurableType-&gt;getParentIdsByChild($childId);
   if (($parentId = reset($parentId)) !== false) {
       $parentProduct = $this-&gt;productRepository-&gt;getById($parentId);
       $productAttributeOptions = $this-&gt;configurableType-&gt;getConfigurableAttributesAsArray($parentProduct);

       $options = [];
       foreach ($productAttributeOptions as $option) {
           $options[$option['attribute_id']] =  $childProduct-&gt;getData($option['attribute_code']);
       }
       $buyRequest = new \Magento\Framework\DataObject(['super_attribute' =&gt; $options]);

       $session = $this-&gt;checkoutSession-&gt;create();
       $quote = $session-&gt;getQuote();
       $quote-&gt;addProduct($parentProduct, $buyRequest);

       $this-&gt;cartRepository-&gt;save($quote);
       $session-&gt;replaceQuote($quote)-&gt;unsLastRealOrderId();
   }
}</pre>
<p><span>应始终将可配置产品添加为具有自定义选项的可配置 SKU，而不是其简单的 SKU：</span></p>
<h2><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/5.png" width="800" /></span></h2>
<h2><span>可配置产品的可配置 SKU</span></h2>
<h3><span>以编程方式添加到购物车时触发迷你购物车更新</span></h3>
<p><span>与每次访问时都请求最新数据的购物车页面不同，迷你购物车内容使用 Magento 的 customer-data.js 库缓存在客户端。</span></p>
<p><span><span>这个缓存只能通过在客户端机器上执行Javascript来清除；</span><span>因为服务器通常不能请求清除客户端上保存的数据。</span><span>因此，customer-data.js 的缓存失效和重新加载通常发生在客户端触发事件时，例如成功的 AJAX 请求。</span></span></p>
<p><span>迷你购物车可以配置为在对 addToCart 端点的 AJAX 请求完成时更新：</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">require([
   'jquery',
   'mage/url',
   'Magento_Customer/js/customer-data'
], function ($, urlBuilder, customerData) {
   $.ajax({
       type: 'POST',
       data: {
           product_id: ...,
           qty: ...
       },
       url: urlBuilder.build('example/product/addToCart'),
       complete: function () {
           // you might not need this section if you're using sections.xml instead
           customerData.invalidate(['cart']);
           customerData.reload(['cart'], true);
       },
       success: ...,
       error: ...
   })
});</pre>
<p><span><span>但是，每次都直接调用这些函数效率不是很高。</span><span>Magento 允许使用sections.xml 配置文件来配置这些端点服务器端：</span></span></p>
<p><span>Magenest/Example/etc/frontend/sections.xml</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd"&gt;
   &lt;action name="example/product/addToCart"&gt;
       &lt;section name="cart"/&gt;
   &lt;/action&gt;
&lt;/config&gt;</pre>
<p><span>现在，使用 Magento 2 AJAX 库发送到&ldquo;example/product/addToCart&rdquo;的所有 AJAX 请求都将触发重新加载&ldquo;购物车&rdquo;数据，而无需手动向 AJAX 请求添加回调。</span></p>]]></description>
      <pubDate>Tue, 11 Oct 2022 08:27:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 - 2022 完整指南中创建日期字段]]></title>
      <link>https://www.360magento.com/blog/How-to-create-a-date-field-in-Magento2-2022-Full-Guide/</link>
      <description><![CDATA[<p><span><span>当需要在上下文中为特定事件选择未知日期或安排某些计划时，主要需要日期字段。</span><span>它不仅减少了打字错误，而且还标准化了格式。</span><span>它还通过允许用户简单地选择而不是使用键盘输入来帮助改善用户体验。</span></span></p>
<p><span>在本文中，我们将向您展示如何在 Magento 2 中创建日期字段，尤其是在自定义表单中</span></p>
<h2><span>在 UI 组件中创建日期字段</span></h2>
<p><span>在这个代码片段中，我们将看到如何使用 UI 组件在 Magento 2 管理表单中添加日期字段。&nbsp;</span></p>
<p><span>先决条件：</span></p>
<ul>
<li><span>设置模块</span></li>
<li><span>设置表</span></li>
<li><span>设置3个文件：model、resourcemodel和collection</span></li>
<li><span><span>设置控制器和布局文件。</span><span>在布局文件中，对文件 ui 组件的引用是 ui_component/my_form.xml</span></span></li>
</ul>
<p><span>1.</span><span>创建文件内容&lt;routes&gt;_&lt;controller&gt;_&lt;action&gt;.xml</span></p>
<p><span>这是一个示例：magenest_myform_index.xml</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token prolog">&lt;?xml version="1.0"?&gt;</span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>page</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>urn:magento:framework:View/Layout/etc/page_configuration.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>referenceContainer</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>content<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>uiComponent</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>my_form<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>referenceContainer</span><span class="token punctuation">&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span> 
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>page</span><span class="token punctuation">&gt;</span></span><br /><br /></pre>
<p><span>2.&nbsp;<span>创建对应的ui_component文件，命名为my_form.xml</span></span></p>
<p><span>3.&nbsp;<span>将示例代码添加到 my_form.xml</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span><span class="token punctuation">&gt;</span></span>
    ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>fieldset</span><span class="token punctuation">&gt;</span></span>
        ...
       <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>field</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>start_date<span class="token punctuation">"</span></span> <span class="token attr-name">formElement</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>date<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>argument</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>data<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>array<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>item</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>config<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>array<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>item</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>options<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>array<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>item</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>showsTime<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>boolean<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>item</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>item</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>item</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>source<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>string<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>start_date<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>item</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>item</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>argument</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>settings</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>validation</span><span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>rule</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>validate-date<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>boolean<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>rule</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>validation</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dataType</span><span class="token punctuation">&gt;</span></span>timestamp<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dataType</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">translate</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>true<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>Start Date<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>visible</span><span class="token punctuation">&gt;</span></span>true<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>visible</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dataScope</span><span class="token punctuation">&gt;</span></span>start_date<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dataScope</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>settings</span><span class="token punctuation">&gt;</span></span>
     <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>field</span><span class="token punctuation">&gt;</span></span>
 ...
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>fieldset</span><span class="token punctuation">&gt;</span></span>
    ...
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span><br /><br /><span>将代码添加到正确位置后，清理缓存，您的日期字段将开始显示您设置的位置：</span><br /><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/1.png" width="800" /></pre>
<h2><span>初始化日历小部件</span></h2>
<p><span>1.</span><span>创建模板文件（.phtml）</span></p>
<p><span>2.</span><span>要显示日期字段，首先我们需要添加字段名称为&ldquo;example-date&rdquo;</span></p>
<pre class="EnlighterJSRAW line-numbers language-generic" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;div class="field"&gt;
    &lt;label&gt;Date : &lt;/label&gt;
    &lt;input type="text" class="input-text" id="example-date" style="width: auto" name="example-date" /&gt;
&lt;/div&gt;<br /><br /><span>现在，我们可以简单地在 for 结束标记之后添加 Javascript 代码：&nbsp;</span></pre>
<pre class="EnlighterJSRAW line-numbers language-js" data-enlighter-language="js" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token operator">&lt;</span>script<span class="token operator">&gt;</span>
  <span class="token function">require</span><span class="token punctuation">(</span><span class="token punctuation">[</span>
    <span class="token string">'jquery'</span><span class="token punctuation">,</span>
    <span class="token string">'mage/translate'</span><span class="token punctuation">,</span>
    <span class="token string">'mage/calendar'</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">$<span class="token punctuation">,</span> $t</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'#example-date'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">calendar</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        changeMonth<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
        changeYear<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
        showButtonPanel<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
        currentText<span class="token operator">:</span> <span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'Go Today'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        closeText<span class="token operator">:</span> <span class="token function">$t</span><span class="token punctuation">(</span><span class="token string">'Close'</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
        showWeek<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
    showOn<span class="token operator">:</span> <span class="token string">"both"</span><span class="token punctuation">,</span>
         showsTime<span class="token operator">:</span> <span class="token boolean">true</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token operator">&lt;</span><span class="token operator">/</span>script<span class="token operator">&gt;</span></pre>
<ul>
<li><span>showOn</span><span><span>：日期选择器应该出现的时间。</span><span>日期选择器可以在字段获得焦点（&ldquo;焦点&rdquo;）、单击按钮（&ldquo;按钮&rdquo;）或任一事件发生（&ldquo;两者&rdquo;）时出现。</span></span></li>
<li><span>显示</span><span>时间：如果需要，显示时间</span></li>
</ul>
<p><span>日历小部件的大多数选项、方法和事件对应于</span><a class="is-plain-link" href="https://api.jqueryui.com/datepicker/" rel="noreferrer nofollow noopener" target="_blank"><span>jQuery Datepicker 小部件</span></a><span>选项。</span></p>
<p><span>结果如下：</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/2.png" width="800" /></span></p>
<h2><span>使用 system.xml 在 Magento 2 配置部分创建日期字段</span></h2>
<p><span>1.</span><span>在app/code/NameSpace/ModuleName/etc/adminhtml中创建system.xml文件</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>config</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>xsi</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://www.w3.org/2001/XMLSchema-instance<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xsi:</span>noNamespaceSchemaLocation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>../../../Config/etc/system_file.xsd<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>system</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>section</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>yoursectionid<span class="token punctuation">"</span></span> <span class="token attr-name">translate</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>label<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">sortOrder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token attr-name">showInDefault</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInWebsite</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInStore</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">&gt;</span></span>Custom Label<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>tab</span><span class="token punctuation">&gt;</span></span>tab name<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>tab</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>resource</span><span class="token punctuation">&gt;</span></span>NameSpace_ModuleNmae::config_modulename<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>resource</span><span class="token punctuation">&gt;</span></span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>group</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>general<span class="token punctuation">"</span></span> <span class="token attr-name">translate</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>label<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">sortOrder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInDefault</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInWebsite</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInStore</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">&gt;</span></span>General Settings<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
                <span class="token comment">&lt;!-- date field code start--&gt;</span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>field</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>start_date<span class="token punctuation">"</span></span> <span class="token attr-name">translate</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>label comment<span class="token punctuation">"</span></span> <span class="token attr-name">sortOrder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>4<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">showInDefault</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name">showInStore</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">&gt;</span></span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span><span class="token punctuation">&gt;</span></span>Start Date<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
                    <span class="token comment">&lt;!-- here we pass class where we create date picker--&gt;</span>
                    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>frontend_model</span><span class="token punctuation">&gt;</span></span>NameSpace\ModuleName\Block\DateField<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>frontend_model</span><span class="token punctuation">&gt;</span></span>
                <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>field</span><span class="token punctuation">&gt;</span></span>
                <span class="token comment">&lt;!-- date field code end--&gt;</span>
            <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>group</span><span class="token punctuation">&gt;</span></span>
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>section</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>system</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>config</span><span class="token punctuation">&gt;</span></span></pre>
<p><span><span>2.</span><span>创建 app/code/NameSpace/ModuleName/Block/DateField.php 我们在其中创建日期字段元素</span></span></p>
<pre class="EnlighterJSRAW line-numbers language-php" data-enlighter-language="php" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><span class="token php language-php"><span class="token delimiter important">&lt;?php</span>
<span class="token keyword">namespace</span> <span class="token package">NameSpace<span class="token punctuation">\</span>ModuleName<span class="token punctuation">\</span>Block</span><span class="token punctuation">;</span>

<span class="token keyword">class</span> <span class="token class-name">DateField</span> <span class="token keyword">extends</span> <span class="token class-name"><span class="token punctuation">\</span>Magento<span class="token punctuation">\</span>Config<span class="token punctuation">\</span>Block<span class="token punctuation">\</span>System<span class="token punctuation">\</span>Config<span class="token punctuation">\</span>Form<span class="token punctuation">\</span>Field</span>
<span class="token punctuation">{</span>
   <span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function">render</span><span class="token punctuation">(</span>\<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Data<span class="token punctuation">\</span>Form<span class="token punctuation">\</span>Element<span class="token punctuation">\</span>AbstractElement</span> <span class="token variable">$element</span><span class="token punctuation">)</span>
   <span class="token punctuation">{</span>
       <span class="token variable">$element</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setDateFormat</span><span class="token punctuation">(</span>\<span class="token package">Magento<span class="token punctuation">\</span>Framework<span class="token punctuation">\</span>Stdlib<span class="token punctuation">\</span>DateTime</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token constant">DATE_INTERNAL_FORMAT</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token variable">$element</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setTimeFormat</span><span class="token punctuation">(</span><span class="token single-quoted-string string">'HH:mm:ss'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//set date and time as per your need</span>
       <span class="token variable">$element</span><span class="token operator">-</span><span class="token operator">&gt;</span><span class="token function">setShowsTime</span><span class="token punctuation">(</span><span class="token boolean constant">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
       <span class="token keyword">return</span> <span class="token keyword">parent</span><span class="token punctuation">:</span><span class="token punctuation">:</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token variable">$element</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span></span></pre>
<p><span>有四种日期格式可供使用：</span></p>
<ul>
<li><span>DATETIME_INTERNAL_FORMAT: yyyy-MM-dd HH:mm:ss</span></li>
<li><span>DATE_INTERNAL_FORMAT：yyyy-MM-dd</span></li>
<li><span>DATETIME_PHP_FORMAT: Ymd H:i:s</span></li>
<li><span>DATE_PHP_FORMAT：Ymd</span></li>
</ul>
<p><span>此日期选择器元素将显示在商店配置下，如下所示：</span></p>
<pre class="EnlighterJSRAW line-numbers language-xml" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1012/3.png" width="800" /></pre>]]></description>
      <pubDate>Mon, 10 Oct 2022 08:31:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 允许内存耗尽错误]]></title>
      <link>https://www.360magento.com/blog/Magento2-Allowed-Memory-exhausted-error/</link>
      <description><![CDATA[<div class="votecell post-layout--left">
<div class="js-voting-container grid jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="141003">
<div class="js-accepted-answer-indicator grid--cell fc-green-500 py6 mtn8" title="接受此答案时正在加载..." data-s-tooltip-placement="right">
<div>
<p><span>在本文中，我们将了解问题的原因以及如何解决 Magento2 中&ldquo;允许的内存耗尽错误&rdquo;的问题。</span></p>
<p><span><span>&ldquo;allowed memory size of bytes exhausted&rdquo;错误的原因与内存不足有关。</span><span>如果您尝试使用比您通过&ldquo;memory_limit&rdquo;在 php.ini 文件中指定的更多的 RAM 资源，则会发生错误。</span></span></p>
<p><span>解决方案1：</span></p>
<p><span>在 php.ini 文件中，搜索并更改以下值，如下所示</span></p>
<pre><span>max_execution_time=18000 </span><span>
max_input_time=1800 </span><span>
memory_limit=4G</span></pre>
</div>
<div><span>并重新启动 Apache。</span></div>
</div>
</div>
</div>
<div></div>
<div><span>解决方案2：&nbsp;</span></div>
<div class="votecell post-layout--left">
<div class="js-voting-container grid jc-center fd-column ai-stretch gs4 fc-black-200" data-post-id="141003">
<div class="js-accepted-answer-indicator grid--cell fc-green-500 py6 mtn8" title="接受此答案时正在加载..." data-s-tooltip-placement="right">
<div class="ta-center"><span>Magento 2 命令中内存限制的快速解决方案是直接在命令中添加内存限制。</span></div>
</div>
</div>
</div>
<div class="answercell post-layout--right">
<div class="s-prose js-post-body">
<p><span>对于编译命令，</span></p>
<pre class="default s-code-block hljs python"><code>php -dmemory_limit=4G <span class="hljs-built_in">bin</span>/magento setup:di:<span class="hljs-built_in">compile</span>
</code></pre>
<p><span>用于部署</span></p>
<pre class="default s-code-block hljs csharp"><code>php -dmemory_limit=<span class="hljs-number">4</span>G bin/magento setup:<span class="hljs-keyword">static</span>-content:deploy
</code></pre>
<p><span>如果问题没有解决，您可以根据 4G 更改为最大。</span></p>
<p><span>解决方案3： -</span></p>
<p><span>您可以使用此命令而不是 bin/magento 轻松修复它</span><span>：</span></p>
<pre><span>php -dmemory_limit=-1 bin/magento ....</span></pre>
<p><span>例子：</span></p>
<pre><span>php -dmemory_limit=-1 bin/magento 设置：升级</span></pre>
<pre><span>php -dmemory_limit=-1 bin/magento setup:di:compile</span></pre>
<p><span><span>此错误与 PHP 中的内存限制配置有关。</span><span>参数&nbsp;</span></span><span>-dmemory_limit=-1</span><span>允许在没有内存限制的命令行中运行 PHP。</span></p>
<p><span>希望这些解决方案可以帮助您解决问题。</span></p>
</div>
</div>]]></description>
      <pubDate>Sun, 09 Oct 2022 08:26:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：向特定客户群免运费]]></title>
      <link>https://www.360magento.com/blog/Magento2-Free-shipping-for-specific-Customer-Group/</link>
      <description><![CDATA[<p class="p">为了向特定客户群免运费<a href="https://www.thecoachsmb.com/free-shipping-for-specific-customer-group/"></a>，我们将不得不创建促销规则。</p>
<p class="p">前题：</p>
<p class="p">我只想为登录用户显示免费送货方式。</p>
<p class="p"><strong><span style="font-family: sans-serif;">登录管理面板</span> - 转到营销 -&gt; 促销 -&gt; 购物车价格规则</strong><strong></strong></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1008/1.png" width="800" /></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1008/2.png" width="800" /></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1008/3.png" width="800" /></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1008/4.png" width="800" /></p>
<p class="p"><span style="font-family: sans-serif;"><span style="font-family: sans-serif;">然后单击</span><span style="font-family: sans-serif;">&ldquo;保存&rdquo;按钮以保存更改。</span></span></p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1008/5.png" width="800" /></p>
<p class="p">&ndash; 网站：主要网站</p>
<p class="p">&ndash; 客户群：Group X（选择客户群，我希望它申请登录用户）</p>
<p class="p">&ndash; 优惠券：无优惠券（我希望在他们登录帐户时自动应用）</p>
<p class="p">&ndash; 条件：空白（因此应适用于所有产品）</p>
<p class="p">&ndash; 行动：</p>
<p class="p">&ndash; 折扣金额：0</p>
<p class="p">&ndash; 适用于运费：是</p>
<p class="p">&ndash; 丢弃后续规则：否</p>
<p class="p">&ndash; 如果所有这些条件都为真：空白</p>
<p class="p">&ndash; 免费送货：适用于匹配物品的运输</p>]]></description>
      <pubDate>Sat, 08 Oct 2022 08:25:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中创建访问密钥]]></title>
      <link>https://www.360magento.com/blog/How-to-create-Access-Keys-in-Magento2/</link>
      <description><![CDATA[<p class="p"><span style="font-family: sans-serif;">在本文中，我们将看到访问密钥的详细信息：</span></p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/1_2.png" width="800" /></p>
<p class="p"><strong>获取访问密钥：</strong></p>
<p class="p"><span style="font-family: sans-serif;">在</span> Magento 市场上创建一个帐户并转到&nbsp;<a href="https://marketplace.magento.com/customer/accessKeys/">https://marketplace.magento.com/customer/accessKeys/</a>&nbsp;以获取私有和公共访问密钥</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/2_2.png" width="800" /></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/3_1.png" width="800" /></p>
<p class="p">在此处创建访问密钥。如果您有访问密钥，则可以使用它们。</p>
<p class="p"><span style="font-family: sans-serif;">现在输入</span>&nbsp;Username&nbsp;&nbsp;并&nbsp;password&nbsp;开始下载</p>
<ul>
<li><strong>用户</strong><span style="font-family: sans-serif;">名：您的公钥</span> 2fc966a913d4e83b28041eeb3c3b72e5</li>
<li><strong>密码</strong><span style="font-family: sans-serif;">：您的私钥。</span>48e05400d17ca1bcb4e693825c45416e</li>
</ul>
<p class="p">在您的项目中使用您的访问密钥。</p>]]></description>
      <pubDate>Fri, 07 Oct 2022 08:32:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在静态块 Magento2 中调用时事通讯]]></title>
      <link>https://www.360magento.com/blog/How-to-call-Newsletter-in-static-block-Magento2/</link>
      <description><![CDATA[<p class="p"><span style="font-family: sans-serif;">在本文中，我们将学习如何在</span> Magento2 的静态块中调用时事通讯。</p>
<ol>
<li>首先，您需要决定在哪个<span style="font-family: sans-serif;">静态块</span><span style="font-family: sans-serif;">中显示</span>newsetter。</li>
<li>在那个静态块中，像下面这样调用时事通讯。将下面的代码粘贴到该块内。</li>
</ol>
<p class="pre"></p>
<p class="p"><span style="font-family: sans-serif;">您需要使用</span> html 代码选项将此代码放在静态块中。</p>
<p class="p">3.我已经给出了在主页块上显示它的示例。</p>
<p class="p"><span style="font-family: sans-serif;">在主页静态块中，我选择了静态块，在那里我拖了</span>html代码</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/1_1.png" width="800" /></p>
<p class="p">4.保存并清除缓存。在前端查看您的时事通讯，如下所示：</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/2_1.png" width="800" /></p>]]></description>
      <pubDate>Thu, 06 Oct 2022 08:33:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中显示最新产品]]></title>
      <link>https://www.360magento.com/blog/How-to-Display-Latest-Products-in-Magento2/</link>
      <description><![CDATA[<p class="p"><br />Magento 2 拥有大量的产品属性，可以让我们过滤状态、新品、creat_at 等产品。但如果店主想在主页上展示数千种产品中的最新产品以增加销量，如何他们应该这样做吗？</p>
<p class="p"><span style="font-family: sans-serif;">查看以下文章，了解如何在</span> Magento 2 中创建最新产品。</p>
<p class="p"><span style="font-family: sans-serif;">我们可以将最新产品放在</span> Magento 2 网站的任何位置，但最简单的方法是创建一个 CMS 页面。</p>
<p class="p">首先，您转到<strong><span style="font-family: sans-serif;">内容</span> &gt; 页面</strong>并在网格表中选择主页。然后选择<strong>编辑</strong></p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/1.jpg" width="800" /></p>
<ul>
<li><strong>小部件类型</strong>：从下拉列表中选择目录新产品列表。</li>
<li><strong>显示类型</strong>：选择所有产品以获取所有产品。如果您选择新产品，您只能获取属性为新的产品。</li>
<li><strong>显示页面控制</strong><span style="font-family: sans-serif;">：如果要调整页面上的产品数量，请选择是。否则，选择否。</span>&nbsp;&nbsp;</li>
<li><strong>要显示的产品</strong>数量：输入要显示的产品数量。</li>
<li><strong>模板</strong>：选择要显示的模板。</li>
<li><strong>Cache Lifetime (Seconds)&nbsp;</strong><span style="font-family: sans-serif;">：</span>&nbsp;选择您希望刷新新产品列表的频率。默认情况下，缓存设置为 86400 秒或 24 小时。清理缓存将帮助小部件在保存内容后立即工作。</li>
</ul>
<p class="p">内容选项卡中的内容如下图所示：</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/2.jpg" width="800" /></p>
<p class="p">然后单击保存页面并在前端检查最终结果。</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/3.jpg" width="800" /></p>
<p class="p"><span style="font-family: sans-serif;">以上是在</span> Magento 2 中展示最新产品的 1 分钟指南。希望对您的工作有所帮助。</p>]]></description>
      <pubDate>Wed, 05 Oct 2022 08:29:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[自定义 Magento 2 布局插图的分步教程]]></title>
      <link>https://www.360magento.com/blog/Step-by-Step-Tutorial-to-Customize-Magento2-Layout-Illustrations/</link>
      <description><![CDATA[<p class="p"><br /><span style="font-family: sans-serif;">嗨，大家好，</span>&nbsp;今天的这篇文章将为您提供如何在实践中进行自定义布局的分步说明，特别是说明 Magento 页面标题中客户帐户链接的布局更改。</p>
<p class="p"><span style="font-family: sans-serif;">我刚刚创建了一个新主题</span><span style="font-family: sans-serif;">&mdash;&mdash;Bss 主题，它继承自一个空白主题，并且与下图中的风格相似：&nbsp;</span></p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/1.png" width="800" /></p>
<p class="p">我想将客户帐户链接移至下拉列表，如下所示：</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/2.png" width="800" /></p>
<p class="p">要获得上述结果，您需要执行以下步骤：</p>
<h2><strong><span style="font-family: sans-serif;">第</span> 1 步：定义布局块</strong><strong></strong></h2>
<p class="p">Bss 主题应用 Luma 主题：使用描述性方法确定模板、布局和样式位置。该文件负责显示文件中指定的标题链接：<strong>&lt;Magento_Theme_module_dir&gt;/view/frontend/layout/default.xml</strong>：</p>
<p class="pre">&nbsp;&lt;container name="header.panel" label="Page Header Panel" htmlTag="div" htmlClass="panel "&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;...</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Framework\View\Element\Html\Links" name="top.links"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt;</p>
<p class="pre">&lt;/container&gt;</p>
<p class="p">其他模块使用此块使用<strong>referenceBlock</strong>将其特定链接添加到标头。</p>
<p class="p">例如：亮度主题</p>
<p class="p">Luma 主题中的客户模块：使用 move top.links 来阻止客户。</p>
<p class="p"><strong>&lt;Magento_luma_theme_dir&gt;/Magento_Theme/layout/default.xml</strong></p>
<p class="pre">&lt; <strong>referenceBlock</strong>&nbsp;name="header.links"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Customer\Block\Account\Customer" name="customer" template="account/customer.phtml" before="-"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;...</p>
<p class="pre">&lt; <strong>/referenceBlock</strong>&nbsp;&gt;</p>
<p class="pre">...</p>
<p class="pre">&lt; <strong>move</strong>&nbsp;element="top.links" destination="customer"/&gt;</p>
<p class="pre">...</p>
<p class="p"><span style="font-family: sans-serif;">在下拉菜单外的</span> Luma 主题文件中，添加了一个新块 - header.links。</p>
<p class="p"><strong>&lt;Magento_luma_theme_dir&gt;/Magento_Theme/layout/default.xml</strong></p>
<p class="pre">&nbsp;&lt;referenceContainer name="header.panel"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt;</p>
<p class="pre">&lt;/referenceContainer&gt;</p>
<h2><strong><span style="font-family: sans-serif;">第</span> 2 步：定义模板</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">与上一步一样，</span>Bss 主题使用位于目录中的下拉菜单来识别模板：</p>
<p class="p"><strong>&lt;Magento_Customer_module_dir&gt;/view/frontend/templates/account/customer.phtml</strong></p>
<p class="pre">&lt;?php if($block-&gt;customerLoggedIn()): ?&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;li class="customer-welcome"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;span class="customer-name"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;role="link"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabindex="0"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data-mage-init ='{"dropdown":{}}'</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data-toggle="dropdown"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data-trigger-keypress-button="true"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data-bind="scope: 'customer'"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;span data-bind="text: customer().fullname"&gt;&lt;/span&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;button type="button"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class="action switch"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tabindex="-1"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data-action="customer-menu-toggle"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;span&gt;&lt;?php /* @escapeNotVerified */ echo __('Change')?&gt;&lt;/span&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/button&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/span&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;script type="text/x-magento-init"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"*": {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Magento_Ui/js/core/app": {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"components": {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"customer": {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"component": "Magento_Customer/js/view/customer"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/script&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php if($block-&gt;getChildHtml()):?&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;div class="customer-menu" data-target="dropdown"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php echo $block-&gt;getChildHtml();?&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/div&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php endif; ?&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/li&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;?php endif; ?&gt;</p>
<h2><strong><span style="font-family: sans-serif;">第</span> 3 步：扩展基本布局以添加块</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">在</span> Bss 主题中创建扩展布局文件。</p>
<p class="p"><strong>app/design/frontend/Bss/default/Magento_Theme/layout/default.xml</strong></p>
<p class="pre">&lt;?xml version="1.0"?&gt;</p>
<p class="pre">&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/ page_configuration.xsd"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;referenceContainer name="header.panel"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/referenceContainer&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt;</p>
<p class="pre">&lt;/page&gt;</p>
<h2><strong><span style="font-family: sans-serif;">第</span> 4 步：移动链接</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">要将链接移动到块</span> header.links，我们需要将扩展​​布局文件添加到主题中：</p>
<p class="p"><strong><span style="font-family: sans-serif;">应用程序</span>/设计/前端/Bss/default/Magento_Customer/layout/default.xml</strong></p>
<p class="pre">&nbsp;&lt;?xml version="1.0"?&gt;</p>
<p class="pre">&lt;!--</p>
<p class="pre">/**</p>
<p class="pre">&nbsp;* Copyright &copy; Magento, Inc. All rights reserved.</p>
<p class="pre">&nbsp;* See COPYING.txt for license details.</p>
<p class="pre">&nbsp;*/</p>
<p class="pre">--&gt;</p>
<p class="pre">&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<strong>referenceBlock</strong>&nbsp;name="header.links"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Customer\Block\Account\Customer" name="customer" template="Magento_Customer::account/customer.phtml" before="-"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Customer\Block\Account\AuthorizationLink" name="authorization-link-login" template="Magento_Customer::account/link/authorization.phtml"&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="sortOrder" xsi:type="number"&gt;10&lt;/argument&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/<strong>referenceBlock</strong>&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;move element="header" destination="header.links" before="-"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<strong>move</strong>&nbsp;element="register-link" destination="header.links"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<strong>move</strong>&nbsp;element="top.links" destination="customer"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;<strong>move</strong>&nbsp;element="authorization-link" destination="top.links" after="-"/&gt;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt;</p>
<p class="pre">&lt;/page&gt;</p>
<p class="p">接下来，清除缓存并获取结果：</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/3.png" width="800" /></p>
<h2><strong><span style="font-family: sans-serif;">第</span> 5 步：使用 Css 设置下拉菜单样式</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">在</span>Bss主题的文件夹中，创建文件：<strong>app/design/frontend/Bss/default/web/css/source/&nbsp;_extend.les</strong></p>
<p class="pre">//</p>
<p class="pre">// Common</p>
<p class="pre">// ______________________________________________</p>
<p class="pre">&amp; when (@media-common = true) {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;.header.panel .header.links {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.customer-welcome + .authorization-link {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display: none;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">}</p>
<p class="pre">//</p>
<p class="pre">// Mobile</p>
<p class="pre">// _____________________________________________</p>
<p class="pre">.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;.customer-name,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;.customer-welcome + .authorization-link {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display: none;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">}</p>
<p class="pre">//</p>
<p class="pre">// Desktop</p>
<p class="pre">// _____________________________________________</p>
<p class="pre">.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;.customer-welcome {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.lib-dropdown(</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_toggle-selector: ~'.action.switch ',</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_options-selector: ~'.customer-menu .header.links',</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_dropdown-actions-padding: 0,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_icon-font-text-hide: true,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_icon-font-size: 22px,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_icon -font-line-height：22px，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_dropdown-list-min-width：160px，</p>
<p class="pre">&nbsp;&nbsp;@_dropdown-list-item-hover：transparent，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_dropdown-list-pointer-position：right，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_dropdown-list-position-right : 0</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-family: Courier;">L</span><span style="font-family: Courier;">i</span>{</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-family: Courier;">a</span>{</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.lib-link( @_link</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-color: #333,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-text-decoration: none,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-color-visited: #333,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-text-decoration-visited: none,</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-color-hover: #333，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-text-decoration-hover：<span style="font-family: Courier;">none</span>，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-color-active：#333，</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@_link-text-decoration-active：<span style="font-family: Courier;">none</span></p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;）；</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;display: block;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;line-height: 1.4;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;padding: 8px;</p>
<p class="pre">&nbsp;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;.action {</p>
<p class="pre">&nbsp;&amp;.switch {</p>
<p class="pre">&nbsp;background: transparent;</p>
<p class="pre">&nbsp;border: none;</p>
<p class="pre">&nbsp;}</p>
<p class="pre">&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">}</p>
<h2><strong><span style="font-family: sans-serif;">第</span> 6 步：运行命令行并检查结果</strong><strong></strong></h2>
<p class="p">运行命令：</p>
<p class="pre">php bin/magento s:up</p>
<p class="pre">php bin/magento setup:static-content:deploy -f</p>
<p class="p">重新加载页面并检查结果：</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog1004/4.png" width="800" /></p>]]></description>
      <pubDate>Tue, 04 Oct 2022 08:24:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加/删除 JavaScript、CSS、字体]]></title>
      <link>https://www.360magento.com/blog/How-to-Add-Remove-JavaScript-CS-Fonts-in-Magento2/</link>
      <description><![CDATA[<p class="p"></p>
<h2><strong>1.在&lt;head&gt;中包含静态资源</strong></h2>
<p class="p"><span style="font-family: sans-serif;">在</span> Magento 2 中使用外部库自定义页面是很常见的，但如果您想使用外部库，则需要添加 JavaScript 和 CSS 文件。</p>
<p class="p"><span style="font-family: sans-serif;">在页面配置文件的</span> &lt;head&gt; 部分中添加了 JavaScript、CSS 和其他静态文件。&lt;head&gt; 页面的默认视图在 vendor /magento/module-theme/view/frontend/layout/default_head_blocks.xml 中定义。&nbsp;</p>
<p class="p">如果要添加外部文件，可以将此文件扩展为自定义主题。</p>
<p class="p">示例：在自定义主题中创建文件：</p>
<p class="p">app/code/Bss/default/Magento_Theme/layout/default_head_blocks.xml</p>
<p class="pre">&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"</p>
<p class="pre">xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc</p>
<p class="pre">/page_configuration.xsd"&gt; &nbsp;&nbsp;&lt;head&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;! -- 添加本地资源 --&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;css src="css/my-styles.css"/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- 下面两种添加本地JavaScript文件的方法是对等的 --&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script src="Magento_Catalog::js /sample1.js"/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;link src="js/sample.js"/&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- 添加外部资源 --&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;css</p>
<p class="pre">src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4 /css/bootstrap-theme.min.css" src_type="url" /&gt; &nbsp;&nbsp;&nbsp;&nbsp;&lt;script</p>
<p class="pre">src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" src_type="url" /&gt; &nbsp;&nbsp;&nbsp;&lt;link rel="stylesheet" type="text/css"</p>
<p class="pre">src="http://fonts.googleapis.com/css?family=Montserrat"</p>
<p class="pre">src_type="url" /&gt; &nbsp;&nbsp;&lt;/head&gt; &lt;/page&gt;</p>
<p class="pre">&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">添加外部资源时，值</span> src_type = &ldquo;url&rdquo; 是必需的。</p>
<p class="p">资产的路径指定到以下位置之一：</p>
<ul>
<li>&lt;theme_dir&gt;/web-</li>
<li>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web-</li>
</ul>
<p class="p"><span style="font-family: sans-serif;">让我们再举一个例子来了解更多细节：</span>&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">如果您想将</span> owl.carousel.css 文件添加到网站中，请按照以下说明操作：&nbsp;将此行添加到 &lt;head&gt; 中：</p>
<p class="pre">&lt;css src = "css / owl.carousel.css" /&gt;</p>
<h2><strong>2.去除静态资源</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">当您根据设计的变化修改页面时，需要对页面进行编辑。但是，如果您不想使用</span> CSS、JavaScript 或字体文件，您完全可以删除它们。&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">要删除这些静态资源，并且链接位于页面</span> &lt;head&gt; 上，您应该在扩展主题中更改以下内容：</p>
<p class="p"><span style="font-family: sans-serif;">应用程序</span>/设计/前端/&lt;供应商&gt;/&lt;主题&gt;/Magento_Theme/layout/default_head_blocks.xml&nbsp;：</p>
<p class="pre">&lt;page &nbsp;xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" &nbsp;xsi:noNamespaceSchemaLocation= "urn:magento:framework:View/Layout/etc/page_configuration.xsd</p>
<p class="pre">" &gt; &lt;head&gt; &lt; !-- 删除本地资源 --&gt; &lt;remove src= "css/styles-m.css" /&gt; &lt;remove src= "my-js.js" /&gt; &lt;remove src= "Magento_Catalog::js/compare.js " /&gt; &lt;!-- 移除外部资源 --&gt; &lt;remove src= "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" /&gt; &lt;remove src=&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" /&gt; &lt;remove src= "http://fonts.googleapis.com/css?family=Montserrat" /&gt; &lt;/head&gt; &lt;/page&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">例如：您希望删除</span> calendar.css 文件，因为您不使用此文件。calendar.css 文件是从文件中添加的</p>
<p class="p"><span style="font-family: sans-serif;">供应商</span>\magento\module-theme\view\frontend\layout\default_head_blocks.xml。</p>
<p class="p"><span style="font-family: sans-serif;">您可以使用</span> &lt;remove src = &ldquo;mage/calendar.css&rdquo; /&gt; 删除文件。</p>]]></description>
      <pubDate>Mon, 03 Oct 2022 08:26:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何修改 Magento 2 页面布局]]></title>
      <link>https://www.360magento.com/blog/How-to-modify-Magento2-page-layou/</link>
      <description><![CDATA[<p><span>在探索本教程之前，我们想提醒一下，Magento 2 支持 4 种基本页面布局类型，例如</span><span><span><span>1 列、2 列左、2 列右和 3 列。</span><span>这些页面布局用于页面配置文件中的特定页面，在 &lt;page&gt; 的属性布局中。</span></span></span></p>
<p><span><span><span><span>例如</span></span></span><span><span>：默认类别页面的布局是左两列。</span><span>如果要更改为设计中的 3 列，则必须在主题中扩展布局文件 catalog_category_view.xml。</span></span></span></p>
<p><span><span><span><span>第 1 步</span></span></span><span><span>：在以下文件夹中创建 catalog_category_view.xml 文件：</span></span></span></p>
<p><span>app/design/frontend/Bss/default/Magento_Catalog/layout/.</span></p>
<p><span><span><span><span>第 2 步</span></span></span><span><span>：将内容添加到 catalog_category_view.xml 文件并保存。</span></span></span></p>
<pre><span>&lt;?xml version="1.0"?&gt; </span>
<span>&lt;page layout="3columns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </span>
<span>xsi:noNamespaceSchemaLocation="urn:magento:framework:View /Layout/etc/page_configuration.xsd"&gt; </span>
<span>... </span>
<span>&lt;/page&gt;</span></pre>
<p><span><span><span><span>第 3 步</span></span></span><span><span>：刷新缓存并检查结果：&nbsp;</span></span></span></p>
<p><span><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/3_2.png" width="800" /></span></span></span></p>]]></description>
      <pubDate>Sun, 02 Oct 2022 08:33:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何设置 Magento 2 报价设置运费]]></title>
      <link>https://www.360magento.com/blog/How-to-Set-up-Magento2-Quote-Set-Shipping-Amount/</link>
      <description><![CDATA[<p class="p">今天，我们将讨论<strong>M&nbsp;agento 2 报价</strong>集运费。</p>
<p class="p">Magento 2 目前正在使用前端处理库 Knockout JS (KO)。购物车页面 KO 将用于呈现带有 JSON 格式数据的 HTML 块，包括块总数。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/1_3.png" width="800" />&nbsp;</p>
<p class="p">在许多情况下，您需要获取购物车报价的完整信息来解决问题，例如：</p>
<ul>
<li>将当前购物车页面信息发送给客户（如果客户尚未准备好下订单）</li>
<li>根据购物车报价等信息自定义购物车页面界面。</li>
</ul>
<p class="p">通过以下简单的方法，您可以获取报价的完整数据，重点是块<strong>运输估算</strong>数据。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/2_3.png" width="800" /></p>
<h2><strong><span style="font-family: sans-serif;">如何设置</span> Magento 2 报价集运费</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">想知道</span><span style="font-family: sans-serif;">&ldquo;Estimate shipping&rdquo;区块的值保存在哪里，可以使用Chrome浏览器进行调试。</span></p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 1 步：</strong><span style="font-family: sans-serif;">在购物车页面</span> (http://yourdomain.com/checkout/cart)，按<strong>F12</strong>显示调试选项卡。</p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 2 步：</strong>导航到<strong><span style="font-family: sans-serif;">应用程序</span> -&gt; 本地存储 (yourdomain.com) -&gt; 值列（右列）。</strong></p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 3 步：</strong>复制<strong>Value 列</strong><span style="font-family: sans-serif;">中的文本（来自第</span> 2 步）并粘贴到网站 http://json.parser.online.fr/ 的左侧列中（以便轻松读取 Json 结构数据）。</p>
<p class="p"><span style="font-family: sans-serif;">您将看到存储在此</span> json 文本中的所有<strong>报价信息。</strong><span style="font-family: sans-serif;">但我只关注</span><span style="font-family: sans-serif;">&ldquo;预估运费&rdquo;的主要数据，block。</span></p>
<p class="p"><span style="font-family: sans-serif;">您需要关注两个主要对象，即</span><span style="font-family: sans-serif;">&ldquo;结帐数据&rdquo;和&ldquo;购物车数据&rdquo;（请查看下面的屏幕截图以获取这些对象的详细数据）。</span></p>
<p class="p">其中：</p>
<p class="p"><strong>结帐数据：结帐</strong>时有任何操作时保存值：<em><span style="font-family: sans-serif;">更改送货方式（</span>Magento 2 刷新送货方式），在国家字段中切换值，邮政编码，地址，城市......</em></p>
<p class="p"><strong>Cart-data：</strong><span style="font-family: sans-serif;">保存报价的概览信息（报价存储的更详细信息，您可以展开</span><span style="font-family: sans-serif;">&ldquo;cart-data&rdquo;部分查看更多信息）。</span></p>
<p class="p">根据具体情况，您可以相应地获取数据。</p>
<p class="p"><span style="font-family: sans-serif;">从</span> Json（字符串）获得数据后，我将指导如何获取 Magento 2 报价表的数据并处理您的要求。</p>
<p class="p"><span style="font-family: sans-serif;">在您自己创建的模块中创建一个</span> JS 文件。</p>
<p class="p"><strong>示例：</strong>&nbsp;app/code/Bss/QuoteData/view/frontend/web/js/quote-data.js。</p>
<p class="pre">define([</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;'jquery',</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;"Magento_Customer/js/customer-data",</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;'Magento_Checkout/js/checkout-data',</p>
<p class="pre">], function ($, customerData, checkoutData) {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;'use strict';</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;$.widget('bss.quote_data', {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_create: function () {</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$("#click-button").on('click', function(){</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var cartData = customerData.get('cart-data')(); // Data from "cart-data"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var checkout = checkoutData.getShippingAddressFromData(); // data from "checkout-data"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var selectedShippingMethod = checkoutData.getSelectedShippingRate(); // your selected shipping method from "checkout-data"</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*Log data in console tab of browser*/</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(cartData); // you can remove this after check</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(checkout); // you can remove this after check</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(selectedShippingMethod); // you can remove this after check</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Log data in console tab of browser */</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false;</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;});</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;});</p>
<p class="pre">&nbsp;&nbsp;&nbsp;&nbsp;return $.bss.quote_data;</p>
<p class="pre">});</p>
<p class="p"><span style="font-family: sans-serif;">希望本文对您在处理</span> M&nbsp;agento 2 报价集运费或 Magento 2 报价表时有用。</p>]]></description>
      <pubDate>Sat, 01 Oct 2022 08:35:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中使块可见性动态化]]></title>
      <link>https://www.360magento.com/blog/Dynamize-block-visibility-in-Magento2/</link>
      <description><![CDATA[<p class="p"><span style="font-family: sans-serif;">如您所知，我们可以使用</span> ifconfig 参数根据 Magento / Config / Model / Config / Source / Yesno 配置字段配置任何块是否显示。对于值，我们可以将 XPath 用于必填字段：&nbsp;</p>
<p class="pre">&lt;block class="Namespace\Module\Block\Type" name="block.example" ifconfig="my/yesno/field"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;... <br />&lt;/block&gt;</p>
<p class="p"><span style="font-family: sans-serif;">例如：您使用</span> ifconfig 在核心联系人模块中检查演示：&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">供应商</span>/magento/module-contact/view/frontend/layout/default.xml</p>
<p class="pre">&lt;referenceBlock name="footer_links"&gt; <br />&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Framework\View\Element\Html\Link\Current" <br /><strong>ifconfig="contact/contact/enabled"</strong>&nbsp;name="contact-us-link"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt; argument name="label" xsi:type="string" <br />translate="true"&gt;联系我们&lt;/argument&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="path" xsi:type="string"&gt;联系方式&lt;/argument&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; <br />&nbsp;&nbsp;&nbsp;&lt; /block&gt; <br />&lt;/referenceBlock&gt;</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/3_1.png" width="800" /></p>
<p class="p"><span style="font-family: sans-serif;">我们还通过</span> ACL 资源调整可见性。虽然它主要用于管理区域，但类似的方法也适用于网站的前端。</p>
<p class="pre">&lt;block class="Namespace\Module\Block\Type" name="block.example" <br />aclResource="Vendor_ModuleName::acl_name"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- ... --&gt; <br />&lt;/block&gt;</p>
<p>&nbsp;</p>]]></description>
      <pubDate>Fri, 30 Sep 2022 08:30:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 的 Head Block 中添加元标记]]></title>
      <link>https://www.360magento.com/blog/Add-meta-tags-to-Magento2-s-Head-Block/</link>
      <description><![CDATA[<p><span><span><span>将元标签添加到 Magento 2 中的头块？</span><span>如何更快更容易地做到这一点？</span></span></span></p>
<p><span>大家好，&nbsp;</span></p>
<p><span><span><span>HTML 页面的 &lt;head&gt; 元素包含不同的元标记、JS 和 CSS 文件定义以及 JS 代码片段。</span><span>在 Magento 2 中，如果您希望在 &lt;head&gt; 中插入元标记，则需要使用一些自定义代码片段。&nbsp;</span></span></span></p>
<p><span>现在就开始！</span></p>
<h2 class="ftwp-heading" id="quick-guide-to-add-meta-tags-to-the-head-block-in-magento-2"><span>在 Magento 2 的 Head Block 中添加元标记的快速指南</span></h2>
<p><span>您需要从自定义主题创建扩展文件，以将 &lt;meta&gt; 标记添加到布局中的 &lt;head&gt; 元素中。</span></p>
<pre><span>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml.</span></pre>
<p><span>或者您可以使用 head.additional 添加具有自定义类和自定义 phtml 的新块：</span></p>
<pre><span>&lt;referenceBlock name="head.additional"&gt; &lt;block </span>
<span>class="Vendor\Module\Block\CustomHead" name="custom_head" </span>
<span>template="Vendor_Module::custom_head.phtml"/&gt; &lt;/referenceBlock&gt;</span></pre>
<p><span>在</span><span>默认类中</span><span>呈现标记元</span><span>：</span><span>\Magento\Framework\View\Page\Config\Renderer。</span></p>
<h2 class="ftwp-heading" id="5-types-of-meta"><span><span>5 种元类型</span></span></h2>
<p><span>这个类可以渲染 5 种类型的元数据并将它们全部捕获：&nbsp;</span></p>
<ul>
<li><span><span><span>og：是一种用于在您的网站和社交网络之间进行通信的协议。</span><span>比如开放图的一些属性Og：title，Og：type，Og：description，Og：image，Og：url&hellip;&hellip;</span></span></span></li>
<li><span>charset：用于指定 HTML 文档的字符编码</span></li>
<li><span>content_type：用于声明网站的语言显示代码</span></li>
<li><span>x_ua_compatible</span></li>
<li><span>media_type：用于指定要链接的元类型</span></li>
<li><span><span>&ldquo;Default&rdquo; case</span>：使用 Magento 的默认元标记，如元标题、元描述。</span></li>
</ul>
<p><span>尝试使用以下代码添加到您的主题布局中：&nbsp;</span></p>
<pre><span><span><span>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </span></span><span><span>
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt; </span></span></span>
<span> &nbsp;&nbsp;&lt;head&gt; </span>
<span><span><span> &nbsp;&nbsp;&nbsp;&lt;! -- 这将创建一个类似 '&lt;meta </span></span><span><span>
http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"&gt;' 的标签 --&gt; </span></span></span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name="x_ua_compatible" content="IE= edge,chrome=1"/&gt; </span>
<span><span><span> &nbsp;&nbsp;&nbsp;&lt;!-- 这将创建一个类似 '&lt;meta property="og:type" </span></span><span><span>
content="article"/&gt;'' 的标签 --&gt; </span></span></span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name="og:type" content ="article"/&gt; </span>
<span> &nbsp;&nbsp;&nbsp;&lt;!-- 这将创建一个类似 '&lt;meta charset="UTF-8"&gt;' 的标签 --&gt; </span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name="charset" content="UTF-8"/&gt; </span>
<span><span><span> &nbsp;&nbsp;&nbsp;&lt;!-- 这将创建一个类似 '&lt;meta http-equiv="Content-Type" </span></span><span><span>
content="content-type-value"/&gt;' 的标签 - -&gt;</span></span></span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name="content_type" content="content-type-value"/&gt; </span>
<span><span><span> &nbsp;&nbsp;&nbsp;&lt;!-- 这个标签不会渲染（详见</span></span><span><span>
\Magento\Framework\View\Page\Config\Renderer） --&gt; </span></span></span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name ="media_type" content="any-value"/&gt; </span>
<span><span><span> &nbsp;&nbsp;&nbsp;&lt;!-- 这将创建一个标签，如 '&lt;meta name="my_custom_type" </span></span><span><span>
content="my_custom_value"/&gt;' --&gt; </span></span></span>
<span> &nbsp;&nbsp;&nbsp;&lt;meta name="my_custom_type" content ="my_custom_value"/&gt; </span>
<span> &nbsp;&nbsp;&lt;/head&gt; </span>
<span>&lt;/page&gt;
</span></pre>
<h2 class="ftwp-heading" id="conclusion"><span>结论</span></h2>
<p><span>这就是我们在 Magento 2 的 head 块中添加元标记的快速指南。</span></p>]]></description>
      <pubDate>Thu, 29 Sep 2022 08:27:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[引用 Magento 2 中的容器：包含的示例]]></title>
      <link>https://www.360magento.com/blog/Referencing-containers-in-Magento2-Examples-of-included/</link>
      <description><![CDATA[<ul>
<li><strong><span style="font-family: sans-serif;">要更新容器，您可以使用</span> &lt;referenceContainer&gt;。&nbsp;</strong></li>
</ul>
<p class="p">例如：向页眉面板添加链接。</p>
<p class="pre">&lt;referenceContainer name="header.panel"&gt; <br />&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="css_class" xsi:type=" string"&gt;标题链接&lt;/argument&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; <br />&nbsp;&nbsp;&nbsp;&lt;/block&gt; <br />&lt;/referenceContainer&gt;</p>
<ul>
<li><strong><span style="font-family: sans-serif;">要创建包装</span> div 或块，您可以使用容器。</strong>&nbsp;</li>
</ul>
<p class="p">例如：将容器添加到页脚容器中并在前端显示。</p>
<p class="pre">&lt;referenceContainer name="footer"&gt; <br />&nbsp;&nbsp;&nbsp;&lt;container name="some.container" as="someContainer" label="Some Container" htmlTag="div" htmlClass="some-container"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;block class="Magento\Cms\ Block\Block" name="footer_top"&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="block_id" xsi:type="string"&gt;footer_top&lt;/argument&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/block&gt; <br />&nbsp;&nbsp;&lt;/container&gt; <br />&lt;/referenceContainer&gt;</p>
<ul>
<li><strong><span style="font-family: sans-serif;">要将类添加到现有容器中：</span>&nbsp;</strong></li>
</ul>
<p class="pre">&lt;referenceContainer name="page.wrapper" htmlClass="my-new-page-wrapper-class second-class"/&gt;</p>
<p class="p"><strong>*注意</strong><span style="font-family: sans-serif;">：</span>referenceContainer 部分将覆盖被引用容器的类。</p>
<p class="p"><span style="font-family: sans-serif;">要为现有容器添加</span> id，您可以使用 htmlID 标记，如下所示：&nbsp;</p>
<p class="pre">&lt;referenceContainer name="page.wrapper" htmlId="MyWrapper"/&gt;</p>
<p>&nbsp;</p>]]></description>
      <pubDate>Wed, 28 Sep 2022 08:28:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中优化资源文件]]></title>
      <link>https://www.360magento.com/blog/Optimize-resource-files-in-Magento2/</link>
      <description><![CDATA[<p>如果您是拥有网站的店主，则不应忽略<strong>优化资源文件。</strong>做这个动作是非常重要和必要的。</p>
<p class="p"><span style="font-family: sans-serif;">与优化网站内容不同，您可以通过更简单的步骤直接在</span> Magento 2 后端优化资源文件。让我们阅读并遵循我们的指南！</p>
<h2><strong>什么是资源文件？</strong><strong></strong></h2>
<p class="p">您希望优化您的资源文件，但您清楚地知道资源文件是什么吗？</p>
<p class="p"><span style="font-family: sans-serif;">资源文件包含图标、菜单、对话框、字符串表、用户定义的二进制数据和其他类型的项目的集合。</span>&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">资源文件可以在编译成兼容的格式后直接嵌入到可执行文件中，从而形成一个包含代码和资源的</span>EXE。应用程序可以在运行时利用嵌入文件中的资源对象。</p>
<p class="p">资源文件允许您更改应用程序显示的文本和视觉效果，而无需更新应用程序的代码。</p>
<h2><strong>有多少种方法可以减少资源文件的加载时间？</strong><strong></strong></h2>
<p class="p">优化资源文件与减少资源文件的加载时间相同。</p>
<p class="p"><span style="font-family: sans-serif;">我们有</span> 3 种方法可以更快地加载资源文件：合并和捆绑文件，以及最小化代码。</p>
<ul>
<li>合并是将多个相同类型的文件合并为一个文件的过程。</li>
<li><span style="font-family: sans-serif;">捆绑是一种组合许多文件以减少加载页面所需的</span> HTTP 请求数量的技术。</li>
<li>缩小会删除空格、换行符和注释，但代码的功能不受影响。由于无法修改最小化文件，因此您应该仅在准备开始生产时使用此方法。</li>
</ul>
<p class="p"><span style="font-family: sans-serif;">但是，默认情况下，</span>Adobe Commerce 和 Magento Open Source 不会合并、捆绑或最小化文件，因此项目开发人员必须决定使用哪种文件优化方法。</p>
<p class="p">不用担心，我们在下面展示了快速且合适的方法。查看我们的详细指南！</p>
<h2><strong><span style="font-family: sans-serif;">优化资源文件的</span> 4 个步骤</strong><strong></strong></h2>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 1 步</strong>：在<strong><em>管理</em></strong>侧边栏上，转到<strong><em><span style="font-family: sans-serif;">商店</span> &gt; 设置 &gt; 配置 &gt;高级&gt; 开发人员</em></strong>。</p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 2 步</strong><span style="font-family: sans-serif;">：要优化</span> CSS 文件，请单击<strong><em>CSS 设置</em></strong><span style="font-family: sans-serif;">部分。如果要合并或缩小</span> CSS 文件，请选择<strong><em>是。</em></strong></p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/1_2.png" width="800" /></p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 3 步</strong><span style="font-family: sans-serif;">：要优化</span> JavaScript 文件，请单击<strong>JavaScript 设置</strong><span style="font-family: sans-serif;">部分。如果要合并或缩小</span> JS 文件，请选择<strong><em>是。</em></strong></p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/2_2.png" width="800" /></p>
<p class="p"><strong><span style="font-family: sans-serif;">第</span> 4 步</strong><span style="font-family: sans-serif;">：要缩小</span> PHTML 模板文件，请单击<strong>模板设置</strong>部分并选择<strong><em>是以</em></strong><span style="font-family: sans-serif;">缩小</span> HTML。</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/3.png" width="800" /></p>
<p class="p"><span style="font-family: sans-serif;">完成所有</span> 4 个步骤后，您不要忘记保存配置以完成该过程。现在，您已成功优化资源文件。</p>]]></description>
      <pubDate>Tue, 27 Sep 2022 08:25:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：使用静态文件签名]]></title>
      <link>https://www.360magento.com/blog/Magento2-Use-static-file-signing/</link>
      <description><![CDATA[<p><span style="font-family: sans-serif;">当您的</span> Magento 网站具有多个版本并且浏览器需要发现它们时，常用的开发工具之一是使用静态文件签名。</p>
<h2><strong>关于静态文件签名</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">可以通过更改数字签名（包括</span> JavaScript、CSS、图像和字体）来监控静态文件。签名附加到基本 URL 之后的路径。如果文件的签名与浏览器中当前缓存的签名不同，则使用该文件的最新版本。</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/1_1.png" width="800" /></p>
<p class="p"><span style="font-family: sans-serif;">例如，当您运行命令时</span>&nbsp;</p>
<p class="pre">php bin/magento 设置：静态内容：部署&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">要部署静态内容，</span>Magento 会自动更改部署的版本。</p>
<h2><strong>使用静态文件签名的配置</strong><strong></strong></h2>
<p class="p">要启用<strong>签名静态文件，</strong>您应该按照以下步骤操作：</p>
<ol>
<li>访问后端并登录到管理员帐户。</li>
<li>在<strong>管理</strong>侧边栏上，转到<strong>商店</strong>&gt;<strong>配置</strong>&gt;<strong>高级</strong>&nbsp;&gt;<strong>开发人员</strong>&gt;<strong>静态文件设置</strong>。</li>
<li>选择<strong>是以</strong>启用此配置。</li>
</ol>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/2_1.png" width="800" /></p>
<p class="p">除此之外，您还可以使用命令行来启用或禁用上述配置。</p>
<p class="pre">php bin/magento 配置：设置 dev/static/sign &lt;值&gt;</p>
<p class="p"><span style="font-family: sans-serif;">值为</span> 1（启用）或 0（禁用）。</p>
<p class="p"><span style="font-family: sans-serif;">例如，当您启用时，</span>URL 将显示为&nbsp;</p>
<table border="0" cellspacing="0">
<tbody>
<tr>
<td valign="top">
<p class="pre">http://magento2.com/pub/static/version1591840430/frontend/Magento/luma/en_US/mage/calendar.css</p>
</td>
</tr>
</tbody>
</table>
<p class="p"><span style="font-family: sans-serif;">或者在另一种情况下，当您禁用时，</span>URL 将是</p>
<table border="0" cellspacing="0">
<tbody>
<tr>
<td valign="top">
<p>http://magento2.com/pub/static/frontend/Magento/luma/en_US/mage/calendar.css</p>
</td>
</tr>
</tbody>
</table>
<p class="p"><strong><em>注意：配置静态文件设置仅在开发人员模式下可用。</em></strong></p>
<h2><strong>结论</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">这是关于在</span> Magento 中启用使用静态文件签名的指南。</p>
<p class="p">希望您会对这些有用的信息感到满意。</p>]]></description>
      <pubDate>Mon, 26 Sep 2022 08:29:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中设置开发者客户端限制]]></title>
      <link>https://www.360magento.com/blog/How-to-set-developer-client-restrictions-in-Magento2/</link>
      <description><![CDATA[<p><span style="font-family: sans-serif;">作为店主，您应该对您的网站有所了解：您的网站有多少元素，您可以使用哪些工具来影响网站的功能以及您如何使用它等等</span><span style="font-family: sans-serif;">&hellip;&hellip;</span></p>
<p class="p"><span style="font-family: sans-serif;">如果您正在运行一个</span> Magento 网站，您可能知道并希望找到一种使用高级开发工具的方法。它们用于在前端开发过程中建立编译模式、构建 IP 地址允许列表、提供模板路径提示以及在店面和管理界面中执行现场文本更改。</p>
<h2><strong>为什么需要限制开发者客户端？</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">在激活模板路径提示配置之前使用开发者客户端限制配置。您需要添加您希望他们看到路径提示的</span> IP 地址。&nbsp;</p>
<p class="p">有关模板路径提示的额外信息。它是一种诊断工具，可通过路径为页面上使用的每个模板添加符号，您可以为店面或管理员启用它。</p>
<p class="p"><span style="font-family: sans-serif;">回到</span> Developer Client Restrictions，您应该使用此功能，因为它将最大限度地减少对客户在商店购物体验的干扰。&nbsp;</p>
<p class="p">除此之外，当您拥有允许列表时，路径提示的检查和自定义将更简单、更快、更正确，因为有一些资源可以做到这一点。因此，您的客户不会因为可以访问错误链接而感到不愉快。</p>
<h2><strong>逐步配置开发者客户端限制</strong><strong></strong></h2>
<p class="p">有关帮助您理解受限开发人员客户端的好处的详细示例：您想要启用路径提示但只有您可以看到而其他人看不到，是时候激活此配置了。</p>
<p class="p">请按照以下步骤完成此操作：</p>
<p class="p">1. 登录管理员帐户。</p>
<p class="p">2. 在<strong>管理</strong><span style="font-family: sans-serif;">侧边栏上，单击商店</span> &gt;<strong>设置</strong>&gt;<strong>配置</strong>&gt;<strong>高级</strong>&gt;<strong>开发人员</strong>。</p>
<p class="p">3. 单击<strong>开发者客户端限制</strong>部分。</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/1.png" width="800" /></p>
<p class="p"><strong><em>注意：开发者客户端限制仅在启用开发者模式后出现。</em></strong></p>
<p class="p">4. 在<strong>Allow IPs中输入您的 IP 地址</strong><span style="font-family: sans-serif;">。如果要添加多个</span> IP 地址，请用逗号分隔每个地址。</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0924/2.png" width="800" /></p>
<p class="p">5.不要忘记保存配置并刷新任何无效缓存，以便此操作处于活动状态。</p>
<h2><strong>结论</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">它非常简单整洁，对吧？按照上面的详细说明，您将更有效地获得一切。</span>&nbsp;</p>
<p class="p"><span style="font-family: sans-serif;">我们希望它对您有所帮助。</span>&nbsp;</p>]]></description>
      <pubDate>Sun, 25 Sep 2022 08:33:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中创建产品属性集]]></title>
      <link>https://www.360magento.com/blog/Create-a-product-property-set-in-Magento2/</link>
      <description><![CDATA[<p align="justify" class="p">Magento 2 产品属性集是某种产品的一组属性特征，并在创建它们时使用<em><span>（例如，</span>&nbsp;</em><strong><em>Top</em></strong><em>有颜色、尺寸、材料、天气，</em><strong><em>Bag</em></strong><em>有颜色、重量、材料）。</em></p>
<p align="justify" class="p">Magento 2&nbsp;中使用产品属性集主要是为了简化您的产品管理，这样您就不需要将每个<span class="16"><span>属性</span></span>单独分配给产品。</p>
<h2><strong>创建属性集</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">为了在</span> Magento 2 中创建产品属性集，请按照下列步骤操作：</p>
<ol>
<li>导航到<strong>Admin Panel &gt; Stores &gt; Attributes &gt; Attribute Set</strong>.</li>
</ol>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_10.png" width="800" />&nbsp;</p>
<p class="p">&nbsp; &nbsp; &nbsp; 2. 选择您要编辑的属性集或按<strong>添加属性集</strong><strong>Add Attribute Set</strong>以添加一个</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_11.png" width="800" /></p>
<p class="p">&nbsp; &nbsp; &nbsp; &nbsp; 3. 填写属性集信息：</p>
<ul>
<li><strong>在名称</strong><strong>Name</strong>字段中插入属性集的名称。</li>
<li><span style="font-family: Arial;">在</span><span style="font-family: Arial;">&ldquo;</span><strong>基于</strong><strong>Based On</strong><strong>&rdquo;</strong>字段中，选择已经存在的属性集，新属性集将基于。</li>
<li>按<strong>保存</strong><strong>Save</strong>按钮。</li>
</ul>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_12.png" width="800" /></p>
<h2><strong>编辑属性集</strong><strong></strong></h2>
<p align="justify" class="p">创建新属性后，您将看到属性集编辑页面，其中包含可编辑的<strong>属性集名称</strong>&nbsp;<strong>Attribute Set Name</strong>、分配给该属性集的属性组以及<strong>未分配</strong><strong>Unassigned Attributes</strong>的属性。</p>
<p align="justify" class="p">要将属性添加到现有组，您只需将其拖放到所选组中即可。</p>
<p align="justify" class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_13.png" width="800" /></p>
<p align="justify" class="p">您可以通过按<strong>添加新</strong><strong>Add New</strong>按钮来添加新组。此外，您只需单击属性组并按<strong>Delete Selected Group</strong>按钮即可删除该属性组。</p>
<p align="justify" class="p">完成后不要忘记按<strong>保存</strong><strong>Save</strong>按钮。</p>]]></description>
      <pubDate>Sat, 24 Sep 2022 08:28:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中添加产品属性]]></title>
      <link>https://www.360magento.com/blog/Add-product-attributes-in-Magento2/</link>
      <description><![CDATA[<p align="justify" class="p">Magento 2 产品属性通常是 Magento 2 产品的属性，可帮助客户在产品变体之间进行选择并找到最合适的选项。它可能是颜色，尺寸，重量，材料等。</p>
<p align="justify" class="p"><span style="font-family: Arial;">产品属性不仅用于定义</span> Magento 2 产品特性，还用于帮助客户缩小结果范围并提高客户参与度的搜索。Magento 2产品属性也可以用于各种规则，如<span style="font-family: Arial;">动态分类规则</span>、cms显示规则等。</p>
<h2 align="justify"><strong><span style="font-family: Arial;">在</span> Magento 2 中添加产品属性的步骤如下：</strong><strong></strong></h2>
<ol>
<li>转到<strong>Admin Panel</strong><strong>&nbsp;&gt;&nbsp;Stores&nbsp;&gt;&nbsp;Attributes&nbsp;&gt;&nbsp;Product.</strong></li>
</ol>
<p><strong><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_1_2.png" width="800" /></strong></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 2. 按<strong>添加新属性</strong><strong>Add New Attribute</strong>按钮。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_2_2.png" width="800" /></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 3. 填写<strong>属性属性</strong><strong>Attribute Properties</strong>部分。</p>
<ul>
<li>输入属性的<strong>默认标签</strong><strong>Default Label</strong>&nbsp;。它将显示在管理面板上。</li>
<li><strong>在商店所有者的目录输入类型</strong><strong>Catalog Input Type for Store Owner</strong>字段中选择一种属性类型。这里有这样的可用值：<em><span style="font-family: Arial;">文本字段、文本区域、日期、是</span>/否、</em>多<em>选、下拉菜单、价格、媒体图像、固定产品税、视觉样本</em>、文本<em>样本。</em></li>
<li><strong><span style="font-family: Arial;">在</span>Values Required</strong><span style="font-family: Arial;">字段中选择</span> yes以使该属性对产品是必需的。在这种情况下，如果您不设置其值，您将无法使用该属性保存产品。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_3_1.png" width="800" /></p>
<p align="justify" class="p">&nbsp; &nbsp; &nbsp; &nbsp; 4. 填写<strong>高级属性属性</strong><strong>Advanced Attribute Properties</strong>部分。</p>
<ul>
<li>设置<strong>属性代码</strong><strong>Attribute Code</strong>。如果将此字段留空，则属性代码将自动从默认标签生成。</li>
<li>在<strong>Scope</strong><span style="font-family: Arial;">中，您选择将在其上编辑属性的级别。就</span> Magento 2 是一个多语言和多网站平台而言，最好将文本字段属性留在<em>商店视图</em>级别。如果属性值不依赖于站点或语言，则选择<em>Global 会更明智。</em></li>
<li>设置属性的<strong>默认值</strong><strong>Default Value</strong>。请注意，默认值不会自动设置所有现有产品。只有在产品重新保存后才会添加。</li>
<li>在<strong>唯一值</strong><strong>Unique Value</strong><span style="font-family: Arial;">字段中设置是，如果您不希望将相同的属性值应用于不同的产品，例如</span> SKU 属性应该是唯一的。</li>
</ul>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_4_1.png" width="800" /></p>
<p align="justify" class="p">&nbsp; &nbsp; &nbsp; &nbsp; 5. 在<strong>商店所有者的输入验证中</strong><strong>Input Validation for Store Owner</strong><strong>，</strong>选择框集过滤器，该过滤器将在保存产品之前用于验证属性值。</p>
<p align="justify" class="p">&nbsp; &nbsp; &nbsp; &nbsp; 6.在<strong>添加到列选项字段中过滤</strong><strong>Add to Column Options</strong><em>是</em>，以便将属性添加到产品网格中的列选项列表中。</p>
<p align="justify" class="p"><span style="font-family: Arial;">您需要启用此选项，以便该属性出现在</span>&nbsp;<strong>产品网格列</strong><strong>Product Grid Columns</strong>中，您可以将其添加到产品网格中。</p>
<p align="justify" class="p">&nbsp; &nbsp; &nbsp; &nbsp; 7. 如果您希望在过滤产品时使用此属性，<strong>请在过滤选项</strong><strong>Use in Filter Options</strong>字段的使用中选择<em>是。</em></p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_5.png" width="800" /></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 8. 设置<strong>默认商店视图</strong><strong>Default Store View</strong>&nbsp;，该视图将在<strong>管理标签</strong><strong>Manage Labels</strong>部分的店面中显示。如果您有一个多语言网站，您可以为每种语言设置一个标签。</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_6.png" width="800" /></p>
<p align="justify" class="p">&nbsp; &nbsp; &nbsp; &nbsp; 9. 配置<strong>店面属性</strong><strong>Storefront Properties</strong>。</p>
<ul>
<li><span style="font-family: Arial;">如果您希望在搜索中使用该属性，请在</span><span style="font-family: Arial;">&ldquo;在搜索中</span><strong><span style="font-family: Arial;">使用</span><span style="font-family: Arial;">&rdquo;</span></strong><strong>Use in Search</strong>字段中选择<em>&ldquo;是&rdquo;。</em></li>
<li><span style="font-family: Arial;">如果您希望在</span>&nbsp;Magento 2 目录搜索中使用该属性，则必须设置<strong>Search Weight</strong>。</li>
<li>决定您是否希望该属性<strong>在高级搜索中可见</strong><strong>Visible in Advanced Search</strong>。</li>
<li>在<strong>店面的可比较</strong><strong>Comparable on Storefront</strong>字段中，您可以选择是否在比较产品页面上使用此属性。</li>
<li>在<strong>用于分层导航中</strong><strong>Used in Layered Navigation</strong>，您选择要在分层导航中使用的属性。</li>
<li><strong><span style="font-family: Arial;">您可以在</span><span style="font-family: Arial;">&ldquo;在搜索结果</span></strong><span style="font-family: Arial;">中使用分层导航</span><span style="font-family: Arial;">&rdquo;中选择是否将属性用于分层导航搜索。</span></li>
</ul>
<p class="p"><strong>注意：</strong><span style="font-family: Arial;">详细了解</span>&nbsp;Magento 2 中的<span style="font-family: Arial;">分层导航配置</span>。</p>
<ul>
<li>在<strong>位置</strong><strong>Position</strong>字段中，您可以设置属性在分层导航中的位置。</li>
</ul>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_7.png" width="800" /></p>
<ul>
<li>如果您希望此属性也用于<span style="font-family: Arial;">购物车价格规则</span>cart price rules&nbsp;和<span style="font-family: Arial;">目录价格规</span>catalog price rule<span style="text-decoration: underline;"><span style="font-family: Arial;">则</span></span><span style="font-family: Arial;">的规则条件，请在</span><span style="font-family: Arial;">&ldquo;</span><strong><span style="font-family: Arial;">用于促销规则条件</span><span style="font-family: Arial;">&rdquo;</span></strong><strong>Use for Promo Rule Conditions</strong><span style="font-family: Arial;">字段中选择</span><span style="font-family: Arial;">&ldquo;</span><em>是</em>&rdquo; 。<a href="https://magefan.com/blog/create-cart-price-rule-in-magento-2" title="如何在 Magento 2 中创建购物车价格规则？"></a><a href="https://magefan.com/blog/magento-2-catalog-price-rules" title="创建 Magento 2 目录价格规则"></a></li>
<li>为了使属性在附加选项中显示在产品页面上，请<strong>在店面目录页面上可见</strong><strong>Visible on Catalog Pages on Storefront</strong>字段中选择<em>是。</em></li>
<li><span style="font-family: Arial;">选择</span> Yes in&nbsp;<strong>Use in Product Listing</strong><span style="font-family: Arial;">以将此属性值添加到产品列表（产品集合）中的</span> PHP 产品对象。</li>
<li><span style="font-family: Arial;">如果您希望该属性用于排序过程，请在</span><span style="font-family: Arial;">&ldquo;</span><strong>用于产品列表中的排序</strong><strong>Used for Sorting in Product Listing</strong><strong>&rdquo;</strong>字段中选择<strong>&ldquo;是&rdquo;。</strong></li>
</ul>
<p><strong><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_8.png" width="800" /></strong></p>
<ul>
<li>完成后不要忘记按<strong>保存属性</strong>按钮。</li>
</ul>
<h2><strong>分配给属性集</strong><strong></strong></h2>
<p class="p">Magento 允许您根据需要创建任意数量的产品属性，每个属性都有自己的输入类型，并将它们分配给<span style="font-family: Arial;">属性集</span>，这些属性集是某种产品的一组属性特征。</p>
<p align="justify" class="p">因此，转到<strong>Admin Panel&nbsp;&gt;&nbsp;Stores&nbsp;&gt;&nbsp;Attributes&nbsp;&gt;&nbsp;Attribute Set ，选择您需要的属性，将其从Unassigned Attributes</strong>拖放到<strong>Groups。</strong></p>
<p align="justify" class="p"><strong><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_9.png" width="800" /></strong></p>
<p align="justify" class="p">完成后不要忘记保存属性集。</p>
<p align="justify" class="p">因此，属性和属性集可帮助您管理产品并保持其信息结构化且易于查找。</p>
<p align="justify" class="p">但是，有时更新属性可能是一项具有挑战性的任务，尤其是在您有很多产品的情况下。</p>
<p>&nbsp;</p>]]></description>
      <pubDate>Fri, 23 Sep 2022 08:27:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中禁用页面构建器]]></title>
      <link>https://www.360magento.com/blog/Disable-Page-Builder-in-Magento2/</link>
      <description><![CDATA[<p class="p">Magento Page Builder 是 Commerce 版本 2.3.1 和 Open Source 2.4.3 中提供的高级内容创建工具。它使您可以更快地创建丰富的内容。这是由于 Page Builder 具有广泛的功能集，例如：整页布局、不同的内容类型、自定义产品属性输入类型、拖放页面设计等。</p>
<p class="p"><span style="font-family: Arial;">尽管它是一个非常方便的工具，可以显着改善多个</span> Magento 商店页面的内容创建，但有些人仍然更喜欢使用所见即所得的编辑器。</p>
<p class="p"><span style="font-family: Arial;">因此，我们将向您展示如何在</span> Magento 2 管理面板中禁用 Page Builder 的 2 种不同方法。</p>
<p class="p">在您询问之前，不建议通过命令行禁用它，因为它可能会破坏多个布局。</p>
<p class="p"><span style="font-family: Arial;">要在</span> Magento 2 中禁用 Page Builder，请导航到<strong>Stores &gt; Configuration &gt; General &gt; Content Management &gt; Advanced Content Tools</strong>并禁用<strong>Page Builder</strong>选项。</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_1_1.png" width="800" /></p>
<p class="p"><span style="font-family: Arial;">通过此方法禁用</span> Page Builder 后，您将无法在任何产品、类别、CMS 页面、动态块或博客上使用它。</p>
<p class="p"><span style="font-family: Arial;">但是，如果您只想为</span> CMS 页面或博客禁用它，则可以使用另一种方法 -&nbsp;Magento 2 Advanced WYSIWYG Extension<span style="font-family: Arial;">。</span>&nbsp;</p>
<p class="p"><span style="font-family: Arial;">它允许您在特定页面上禁用</span> Page Builder，并在它们上使用 WYSIWYG 编辑器。</p>
<p class="p"><span style="font-family: Arial;">确保安装最新的</span> 2.0.11 版本。然后，要禁用 Page Builder，请转到<strong>Stores &gt; Configuration &gt; Magefan Extensions &gt; WYSIWYG Advanced</strong><span style="font-family: Arial;">并为</span> CMS、博客、类别或产品页面完全禁用它。&nbsp;</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_2_1.png" width="800" /></p>
<p><span style="font-family: Arial;">解决方案使您能够同时继续从方便的</span> Page Builder 和 WYSIWYG 编辑器中受益。<span style="font-family: Arial;">通过最合适和最方便的方法在</span> Magento 2 中创建内容。</p>]]></description>
      <pubDate>Thu, 22 Sep 2022 08:26:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：修复 Google PageSpeed 上的“延迟离屏图像]]></title>
      <link>https://www.360magento.com/blog/Magento2-Fix-delayed-off-screen-image-on-Google-PageSpeed/</link>
      <description><![CDATA[<p><span>这不是秘密</span>&nbsp;<span>网站速度是最重要的</span>&nbsp;SEO&nbsp;排名因素之一，不仅因为加载本身，还因为它对客户体验的影响。这就是为什么您必须使用不同的工具不断<span class="15"><span>测试网站速度</span></span><span>以确定减慢</span>&nbsp;Magento 2 商店的问题。</p>
<p class="p"><span style="font-family: Arial;">每个人都熟悉的最常见的工具是</span> Google PageSpeed Insights 或 PSI。它通过 Google 的服务器运行您的 URL，并提供有关您网站运行情况的报告。</p>
<p class="p"><span style="font-family: Arial;">今天，我们希望将您的注意力转向</span><span style="font-family: Arial;">&ldquo;延迟屏幕外图像&rdquo;，它通常会阻止您的网站进入 PSI 绿区。我们将讨论它的含义以及如何修复它以</span><span style="font-family: Arial;">加速</span> Magento。</p>
<p class="p">&nbsp;</p>
<h2><strong><span style="font-family: Arial;">什么是</span><span style="font-family: Arial;">&ldquo;延迟离屏图像&rdquo;消息？</span></strong><strong></strong></h2>
<p class="p">&ldquo;Defer Offscreen Images&rdquo;是 Google PageSpeed Insights 中显示的消息，其中<strong><span style="font-family: Arial;">列出了应在请求的</span> URL 上延迟加载的所有图像</strong><span style="font-family: Arial;">。它还显示了延迟加载这些图像可能会节省的大小。来自</span> Google 的完整描述如下所示：&nbsp;</p>
<p class="p"><em>&ldquo;考虑在所有关键资源完成加载后延迟加载屏幕外和隐藏图像，以缩短交互时间。&rdquo;</em></p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_1.png" width="800" /></p>
<p class="p">一旦网站访问者打开它，您的<strong>网页就会分为两部分</strong>- 首屏 (ATF) 和首屏以下。前者是指 Googlebots 在 PSI 屏幕截图中向您显示的屏幕上可见的区域。换句话说，它是访问者视口内的区域。</p>
<p class="p">然后后者指的是初始加载时不可见的区域或开始滚动页面后显示的所有内容。</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_2.png" width="800" /></p>
<p class="p">如果没有延迟加载，所有页面图像都会在页面呈现之前加载。它会导致延迟，尤其是在您加载包含大量图像的类别页面或产品页面时。</p>
<p class="p"><span style="font-family: Arial;">这就是为什么</span> Google 的<strong>&ldquo;延迟屏幕外图像&rdquo;消息建议您最初加载仅在首屏上方可见的媒体文件并延迟加载，延迟加载其余文件</strong>。</p>
<p class="p"><span style="font-family: Arial;">在这种情况下，一次加载所有图像不会成为问题，因为只会首先加载视口中的图像。</span>&nbsp;</p>
<p class="p"><span style="font-family: Arial;">还需要注意的是，</span><span style="font-family: Arial;">&ldquo;延迟离屏图像&rdquo;问题出现在移动网站上的次数多于桌面网站。这一点至关重要，因为</span><strong>移动体验更依赖于加载时间</strong>，而移动用户可能根本不愿意等待那么长时间来呈现页面。</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_3.png" width="800" /></p>
<h2><strong>&ldquo;延迟离屏图像&rdquo;的原因是什么？&nbsp;</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">出现</span> Google Page Speed Insights&ldquo;延迟离屏图像&rdquo;消息的主要原因是您根本没有在商店中使用图像延迟加载。</p>
<p class="p">您需要加载所有页面资产供用户浏览，这似乎是合乎逻辑的，但它并没有严格定义。正如我们之前开始的那样，只要您在视口中加载所有重要资产，其余部分的加载就可以延迟。</p>
<p class="p"><em>如果访问者只是单击顶部的某个位置并转到另一个页面，那么加载所有页面图像根本没有意义，是吗？</em></p>
<p class="p"><span style="font-family: Arial;">这就是为什么</span> Google 建议您实施延迟加载或延迟加载图像的原因。因此，除非用户开始滚动，否则不会加载图像文件。它有助于相应地提高您的 PSI 分数和用户体验。&nbsp;</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0917/_4.png" width="800" /></p>
<h2><strong><span style="font-family: Arial;">如何修复</span><span style="font-family: Arial;">&ldquo;延迟离屏图像&rdquo;？</span></strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">从</span> PSI 中出现&ldquo;延迟离屏图像&rdquo;的原因来看，要解决此通知，您必须为您的商店实施延迟加载。&nbsp;</p>
<p class="p"><span style="font-family: Arial;">您可以采用</span><span style="font-family: Arial;">&ldquo;硬&rdquo;的方式并将相应的属性添加到&ldquo;首屏&rdquo;图像的 HTML 代码中：</span></p>
<p>&lt;img src="https://yourwebsite.com/images/image-title.jpg" alt="Image Alt Tag" style="width:100%" loading="lazy"&gt;</p>
<p class="p"><span style="font-family: Arial;">但请注意，它不适用于旧版浏览器或任何版本的</span> Safari，这是此方法未被广泛使用的原因之一。&nbsp;</p>
<p class="p">忽略此方法的另一个原因是有像Magento 2 Image Lazy Load这样的强大工具可以自动解决这个问题。您只需要定义<strong>延迟加载块</strong>，模块将覆盖其余部分</p>]]></description>
      <pubDate>Wed, 21 Sep 2022 08:34:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[配置 MAGENTO 2 多语言商店]]></title>
      <link>https://www.360magento.com/blog/Configure-MAGENTO2-multilingual-store/</link>
      <description><![CDATA[<p>创建在线商店是推动创建和运营国际商店的一件好事。<span style="font-family: sans-serif;">随着创建在线商店的举措，如果您会说他们的语言，您将接触到世界上许多国家的客户。以客户的语言接触客户是本文的主题。因此，要以他们的母语接触客户，需要配置</span> Magento 2 多语言商店。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_1_4.png" width="800" />&nbsp;</p>
<p><span style="font-family: sans-serif;">使用</span> Magento 2 多语言商店将文本立即翻译成客户的母语很容易实现目标。<span style="font-family: sans-serif;">从客户的角度来看，需要选择他们的语言环境，客户将以他们的母语看到商店。此外，</span>Magento 2 不会逐字翻译，相反，您可以创建一个包含标题、标签、按钮和链接的含义表，以便让客户感觉商店很自然。因此，本文将分享以客户的母语提供给客户的最简单方法。&nbsp;</p>
<h2><strong>下载语言包</strong><strong></strong></h2>
<p class="p"><span style="font-family: sans-serif;">启用翻译功能后，您必须先下载并安装语言包。为此，请访问</span> Magento Marketplace 并找到所需语言的语言包。安装将由扩展管理器进行。下载和安装的过程通常与您已经使用过的类似。选择下载后，您将获得 .gzip 格式的文件，其中将包含所选语言包。该包包含您选择的语言的独特文件。&nbsp;</p>
<p>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_2_2.png" width="800" /></p>
<h2><strong><span style="font-family: sans-serif;">添加新的商店视图</span>&nbsp;</strong><strong></strong></h2>
<p class="p">下载语言包后，您需要指定在此视图中显示商店。对于每种语言，您都需要添加一个商店视图。安装<a href="https://soft-loft.com/why-migrate-to-magento-2/"><span style="text-decoration: underline;">Magento 2</span></a>时，默认语言为英语，并带有示例数据，您将看到法语、德语和英语。因此，下载语言包后，需要设置特定语言的前端。为此，需要转到您的管理面板，转到<strong>System</strong>，然后是<strong>Configuration</strong>和<strong>Manage stores</strong>。在菜单中，需要选择<strong>Create Store View</strong>，选择<strong>New Store View</strong><span style="font-family: sans-serif;">，并输入其字段名称和代码。最后，需要保存商店视图，并创建新的商店视图。</span>&nbsp;</p>
<h2><strong><span style="font-family: sans-serif;">安装和配置语言包</span>&nbsp;</strong><strong></strong></h2>
<p class="p">安装和配置语言包是下载后需要执行的下一步。为此，您需要进入管理面板，然后进入<strong>Store View</strong>、<strong>Configuration</strong>和<strong>General</strong>。然后，选择<strong>区域设置</strong>并设置您想要更改的语言。一旦你设置了<strong>Locale</strong>，<strong>Save Config</strong><span style="font-family: sans-serif;">，并清除缓存以使更改立即生效。</span>&nbsp;</p>
<p class="p">&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_3_2.png" width="800" /></p>
<h2><strong>更改产品描述和类别</strong><strong></strong></h2>
<p class="p">添加并保存新语言的配置后，需要更改产品的描述和类别。为此，请转到<strong>目录</strong>菜单并选择选项<strong>管理产品</strong>。之后，找到产品，然后单击按钮<strong>Edit</strong>。在打开的菜单中，从菜单中<strong><span style="font-family: sans-serif;">选择视图</span> <span style="font-family: sans-serif;">选择商店视图</span></strong>并更改选项的值，取消选中<strong>使用默认值</strong>选项。然后，单击<strong>保存</strong>或<strong>保存并继续编辑</strong>按钮。如果您需要编辑类别，您可以使用选项<strong>Manage Categories</strong>来完成。</p>
<h2><strong><span style="font-family: sans-serif;">在</span> MAGENTO 2 中设置多种货币</strong><strong></strong></h2>
<p class="p">&nbsp;最后，当您已经在商店中添加并激活了不同的语言时，您将需要添加当地货币。此举将有助于完成更多销售。通过设置多种货币，您将帮助客户了解产品价格与当地商品价格的比较。反过来，购物过程越方便，客户完成结账的可能性就越大。实际上，要在 Magento 2 中开启多币种功能，需要前往<strong>Stores</strong>，然后前往<strong>Settings</strong>、<strong>Configuration</strong>和<strong>General</strong>。然后，导航到<strong>Currency Setup</strong>。您将需要更改该部分中的<strong>默认配置当前配置范围</strong>。最后，填写必填字段并单击<strong>Save Configuration</strong><span style="font-family: sans-serif;">。</span>&nbsp;</p>]]></description>
      <pubDate>Tue, 20 Sep 2022 08:30:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[修复 Magento 2 中的死锁问题]]></title>
      <link>https://www.360magento.com/blog/Fix-the-deadlock-problem-in-Magento2/</link>
      <description><![CDATA[<p><span style="font-family: Arial;">死锁问题是</span> Magento 2 上最大和最难解决的问题之一，每个 Magento 开发人员迟早都会遇到它。<span style="font-family: Arial;">一旦您开始搜索如何解决</span> Magento 中的死锁问题，您将很难找到最终的答案。&nbsp;</p>
<h2><strong>1.测量产品节省执行时间</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">为此，请在</span> Magento 2 根目录中创建<strong>脚本文件夹。</strong>然后使用以下代码将<strong>test.php文件添加到其中：</strong></p>
<p>&lt;?php</p>
<p>error_reporting(E_ALL);</p>
<p>ini_set('display_errors', 1);</p>
<p>use Magento\Framework\App\Bootstrap;</p>
<p>require __DIR__ . '/../app/bootstrap.php';</p>
<p>$bootstrap = Bootstrap::create(BP, $_SERVER);</p>
<p>$obj = $bootstrap-&gt;getObjectManager();</p>
<p>$state = $obj-&gt;get(Magento\Framework\App\State::class);</p>
<p>$state-&gt;setAreaCode('adminhtml');</p>
<p>$startTime = microtime(true);</p>
<p>$productRepo = $obj-&gt;get(Magento\Catalog\Api\ProductRepositoryInterface::class);</p>
<p>$product = $productRepo-&gt;getById(39);</p>
<p>$product-&gt;setName($product-&gt;getName() . ' - test');</p>
<p>$product-&gt;setStoreId(0);</p>
<p>$productRepo-&gt;save($product);</p>
<p>$endTime = microtime(true);</p>
<p>$executionTime = ($endTime - $startTime);</p>
<p>echo " Execution time of script = ".$executionTime." sec";</p>
<p>?&gt;</p>
<p>然后运行<strong>​​php scripts/test.php</strong>以测量通过产品存储库保存一个产品所需的时间。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_1_3.png" width="800" /></p>
<p class="p">Magento 2.4.4 上，它需要不到一秒的时间。对于常规 Magento 2 商店，可接受的值最多为 2 秒。</p>
<p class="p"><span style="font-family: Arial;">如果产品保存在</span> 2 秒内执行，您可以跳过此部分并转到下一部分。</p>
<p class="p">如果您需要找出导致此问题的扩展名，最简单的方法是：</p>
<ol>
<li>禁用所有第三方<a href="https://magefan.com/magento-2-extensions" title="Magento 2 扩展"><span style="text-decoration: underline;">Magento 2 扩展</span></a>并测量保存产品所需的时间。</li>
<li>将所有扩展一一启用，衡量产品保存速度。</li>
</ol>
<p class="p">为每个扩展逐步执行此操作，您会发现哪个扩展对您的性能影响最大。</p>
<h2><strong>2.检查数据库配置</strong><strong></strong></h2>
<p class="p">Magento 建议使用以下<a href="https://experienceleague.adobe.com/docs/commerce-operations/performance-best-practices/software.html" title="Magento 软件推荐"><span style="text-decoration: underline;"><span style="font-family: Arial;">数据库配置</span></span></a><span style="font-family: Arial;">以获得更好的性能。因此，如果您遇到</span> Magento 死锁问题，请检查一下。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_2_1.png" width="800" /></p>
<p class="p"><span style="font-family: Arial;">您可能还面临以下问题：</span>&nbsp;</p>
<p class="p">SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction, query was...</p>
<p class="p">您可以尝试更改<strong>app/etc/env.php文件</strong><a href="https://www.naguel.com/magento-and-a-deadlock-found-when-trying-to-get-lock/" title="Magento 和尝试获取锁时发现死锁"><span style="text-decoration: underline;"><span style="font-family: Arial;">中的锁定节点</span></span></a>并更改内部配置节点中的前缀。</p>
<p>&lt;?php</p>
<p>return [</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;'lock' =&gt; [</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'provider' =&gt; 'db',</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'config' =&gt; [</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'prefix' =&gt; 'new-prefix-here'</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;]</p>
<p>];</p>
<p>然后只需重置索引器并尝试再次重新<a href="https://magefan.com/blog/how-to-reindex-magento-2-via-cli" title="如何使用 CLI 重新索引 Magento 2"><span style="text-decoration: underline;"><span style="font-family: Arial;">索引</span></span></a>。</p>
<h2><strong>3. 监控 Cron 执行</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">如果在执行</span> cron 作业期间发生 Magento 死锁问题，我们强烈建议安装一些 Magento 2 cron 计划扩展。</p>
<p class="p"><span style="font-family: Arial;">它们允许您查看</span> cron 作业执行图表并更改 cron 作业计划以减少对 CPU 的影响以及同时对数据库的请求数。</p>
<p class="p"><span style="font-family: Arial;">如果您发现同时执行了一些扩展进程（超过</span> 10 分钟），请尝试重新安排它们以平均分配负载。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_3_1.png" width="800" /></p>]]></description>
      <pubDate>Mon, 19 Sep 2022 08:24:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中配置统一运费方式]]></title>
      <link>https://www.360magento.com/blog/Configure-uniform-freight-method-in-Magento2/</link>
      <description><![CDATA[<p class="p"><span class="15"><span>统一</span></span>运费配送方式是在您的商店<span class="15"><span>配置配送方式</span></span>的简单解决方案。对于任何具有不同尺寸或重量或任何送货地址的订单，它都会收取固定的运费。由于易于配置和应用，统一运费受到许多携带者的欢迎。</p>
<p class="p">如果您需要在您的商店收取不同的运费，您可以使用<span class="15">Free Shipping Method</span>和<span class="15">Table Rate Shipping Method</span><span>来完成。现在，我们将一起学习如何在</span>&nbsp;Magento 2 中配置统一运费方式。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_1_2.png" width="800" /></p>
<h2><strong><span style="font-family: Outfit;">在</span> Magento 2 中配置统一运费方式的 4 个步骤：</strong><strong></strong></h2>
<ol>
<li>在管理面板上，Stores &gt; Settings &gt; Configuration.</li>
<li><span style="font-family: Outfit;">在左侧面板的</span> <span style="font-family: Outfit;">下</span>Sales，选择Shipping Methods选项卡。</li>
<li>打开Flat Rate栏目，</li>
</ol>
<ul>
<li>Enable<strong>通过选择是</strong><span style="font-family: Outfit;">的运输方式。当时，统一费率可在购物车的</span><span style="font-family: Outfit;">&ldquo;估计运费和税款&rdquo;部分以及结帐时的&ldquo;运费&rdquo;部分中使用。</span></li>
<li>在结帐页面上设置Title统一运费。</li>
<li>Method Name<span style="font-family: Outfit;">在购物车中与计算的运费一起显示的字段中描述方法。方法名称默认为</span><span style="font-family: Outfit;">&ldquo;固定&rdquo;。</span></li>
<li><span style="font-family: Outfit;">要阐明应用统一运费配送方式的条款，请将</span> <span style="font-family: Outfit;">设置为</span>Type以下选项之一：</li>
<li>无：此类型的运费为零，类似于<span style="font-family: Outfit;">免费送货方式</span>。</li>
<li>每个订单：为整个订单设置统一运费</li>
<li><span style="font-family: Outfit;">每件商品：为每件商品设置统一运费。费率乘以购物车中的商品数量，无论是否有多个数量相同或不同的商品。</span>* 提供Price<span style="font-family: Outfit;">您要收取的统一运费。</span>* 如果您要求收取额外的手续费，请设置Calculate Handling Fee<span style="font-family: Outfit;">为</span><span style="font-family: Outfit;">&ldquo;固定&rdquo;或&ldquo;百分比&rdquo;，然后在</span>Handling Fee字段中输入您要设置的数字。Displayed Error Message*如果统一运费不可用，请键入短文本。* 设置Ship to Applicable Countries为两个选项之一：</li>
<li><span style="font-family: Outfit;">所有允许的国家</span>/地区：每个国家/地区都支持免费送货。</li>
<li><span style="font-family: Outfit;">特定国家：仅选定国家</span>/地区支持统一运费。Sort Order在结帐页面的运输方式上设置。</li>
</ul>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 4. Save Config去完成。</p>
<p>&nbsp;</p>
<p class="p"></p>]]></description>
      <pubDate>Sun, 18 Sep 2022 08:28:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 的发票中添加订单 ID、客户 IP 地址]]></title>
      <link>https://www.360magento.com/blog/Add-order-ID-and-customer-IP-address-to-Magento2-s-invoice/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_1_1.png" width="800" /></p>
<h2><strong><span style="font-family: Outfit;">如何显示订单</span> ID</strong><strong></strong></h2>
<ul>
<li>在管理面板上，单击Stores &gt; Settings &gt; Configuration。</li>
<li>在左侧下方的面板中Sales，选择PDF Print-outs。</li>
<li>打开Invoice部分。</li>
<li>选择Yes_Display Order ID in Header</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_2.png" width="800" /></p>
<ul>
<li>打开Shipment部分</li>
<li>选择Yes_Display Order ID in Header</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_3.png" width="800" /></p>
<ul>
<li>打开Credit Memo部分</li>
<li>选择Yes_Display Order ID in Header</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_4.png" width="800" /></p>
<ul>
<li>完成后，单击Save Config。</li>
<li>在管理面板上，单击Stores &gt; Settings &gt; Configuration。</li>
<li>在左侧面板中的销售下，选择销售。</li>
<li>打开常规部分</li>
</ul>
<h2><strong><span style="font-family: Outfit;">如何显示客户</span> IP 地址</strong><strong></strong></h2>
<p><strong><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_5.png" width="800" /></strong></p>
<ul>
<li>选择No_Hide Customer IP</li>
<li>完成后，单击Save Config。</li>
</ul>]]></description>
      <pubDate>Sat, 17 Sep 2022 08:33:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[设置商店信息：Magento 2 中的电话号码、地址、增值税号]]></title>
      <link>https://www.360magento.com/blog/Set-store-information-phone-number-address-VAT-number-in-Magento2/</link>
      <description><![CDATA[<p class="p"><span>设置商店信息</span><span>是在线商店所必需的，以提供将用于销售文件和其他通信的基本信息。您需要添加的商店信息包括电话号码、国家</span>/地区、地区/州、邮政编码、增值税号等。所有这些信息都可以在您需要时灵活编辑。</p>
<p>但是，由于Magento 2 支持自定义多个设置，因此有时商店管理员很难找到确切的编辑位置。以下指南希望对您有所帮助。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0916/_1.png" width="800" /></p>
<h2><strong><span style="font-family: Outfit;">在</span> Magento 2 中设置存储信息的 3 个步骤</strong><strong></strong></h2>
<ul>
<li><span style="font-family: Outfit;">第</span> 1 步：登录到您的 Magento 2 后端</li>
<li><span style="font-family: Outfit;">第</span> 2 步：设置您的商店信息</li>
<li><span style="font-family: Outfit;">第</span> 3 步：检查结果</li>
<li>在管理侧边栏上，单击Stores。然后在下Settings，选择Configuration。</li>
<li>在左侧下方的面板中General，选择General。</li>
<li>展开Store Information部分，然后执行以下操作：
<ul>
<li>输入Store Name要在所有通信中使用的。</li>
<li>输入Store Phone Number, 按照您希望的格式显示。</li>
<li>在该Store Hours of Operation<span style="font-family: Outfit;">字段中，输入您的商店的营业时间。例如：周一至周五，</span>9-5，周六 9-中午 PST</li>
<li>选择Country您的企业所在的位置。</li>
<li>选择Region/State国家。</li>
<li>输入Store Address.&nbsp;如果地址很长，请继续第Store Address2 行的地址。</li>
<li>如果适用，请输入您商店的<span style="font-family: Outfit;">增值税号</span>。要验证号码，请单击Validate VAT&nbsp;Number按钮。</li>
</ul>
</li>
<li>完成后，单击Save Config。</li>
</ul>
<h3><strong><span style="font-family: Outfit;">第</span> 1 步：登录到您的 Magento 2 后端</strong><strong></strong></h3>
<h3><strong><span style="font-family: Outfit;">第</span> 2 步：设置您的商店信息</strong><strong></strong></h3>
<h3><strong><span style="font-family: Outfit;">第</span> 3 步：检查结果</strong><strong></strong></h3>
<p class="p">您现在可以在任何订单测试中检查结果。</p>]]></description>
      <pubDate>Fri, 16 Sep 2022 08:29:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改商店电子邮件地址]]></title>
      <link>https://www.360magento.com/blog/change-store-email-addresses-magento/</link>
      <description><![CDATA[<p>当您开始在 Magento 2 上销售时，更改商店电子邮件地址是最重要的任务之一。您最多可以有五个不同的电子邮件地址来代表每个商店或视图的不同职能或部门。除了以下预定义的电子邮件身份之外，您还可以根据需要设置三个自定义身份。</p>
<p>一般联系人<br />销售代表<br />客户支持</p>
<p>每个身份及其关联的电子邮件地址都可以与特定的自动电子邮件相关联，并显示为从您的商店发送的电子邮件的发件人。联系我们表格将被发送到不同的电子邮件地址。多亏了这一点，您可以减少管理员的工作量，并通过将问题分配给合适的部门来确保更快的回复。</p>
<p>更改商店电子邮件地址的 3 个步骤<br />第 1 步：为您的域设置电子邮件地址<br />第 2 步：为您的商店配置电子邮件地址<br />第 3 步：更新销售电子邮件配置<br />第 1 步：为您的域设置电子邮件地址<br />在为商店配置电子邮件地址之前，必须将每个电子邮件地址设置为您的域的有效电子邮件地址。按照服务器管理员或电子邮件 托管服务提供商的说明创建所需的每个电子邮件地址。</p>
<p>第 2 步：为您的商店配置电子邮件地址<br />在此步骤中，您可以设置一般联系人、销售代表和客户支持的电子邮件地址。</p>
<p>在管理侧边栏上，单击Stores。然后在下Settings，选择Configuration。<br />在左侧下方的面板中General，选择Store Email Addresses。<br />展开该General Contact部分，然后执行以下操作：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/email-template.png" /></p>
<p>在发件人姓名字段中，键入要作为与常规联系人身份关联的任何电子邮件的发件人显示的人员姓名。<br />在发件人电子邮件字段中，键入关联的电子邮件地址。</p>
<p>对您计划使用的每个商店电子邮件地址重复此过程。</p>
<p>完成后，点击 Save Config</p>
<p>第 3 步：更新销售电子邮件配置<br />现在，您将更改将用于销售单据（例如订单、发票、装运和贷项通知单）的电子邮件。如果您使用自定义电子邮件地址，请确保更新任何相关电子邮件的配置，以便正确的身份显示为发件人。</p>
<p>在左侧面板的 下Sales，选择Sales Emails。该页面有一个单独的部分用于以下各项：<br />订单和订单评论<br />发票和发票注释<br />装运和装运评论<br />贷项通知单和贷项通知单注释<br />从Order开始，展开每条消息的部分，并确保选择了正确的发件人。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/store-email-address.png" /></p>
<p><br />完成后，单击 Save Config 。</p>]]></description>
      <pubDate>Thu, 15 Sep 2022 08:29:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改欢迎信息]]></title>
      <link>https://www.360magento.com/blog/change-welcome-message-in-magento/</link>
      <description><![CDATA[<p>欢迎消息显示在标题的右上角，其中包括客户登录时的姓名。但是，对于未登录您商店的访问者，默认 Magento 2 将自动显示消息&ldquo;默认欢迎消息&rdquo;。<br />因此，为了引起客户的注意，您应该确保此欢迎信息必须更具吸引力和醒目。本文将向您展示如何通过 3 个简单的步骤更改 Magento 2 中的欢迎信息。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/QQ20220914-140900_2x.png" /><br />在 Magento 2 中更改欢迎信息的 3 个步骤</p>
<p>第 1 步：登录到您的 Magento 2 后端。<br />第 2 步：更改特定商店的欢迎信息<br />第 3 步：检查结果</p>
<p>第 1 步：登录到您的 Magento 2 后端</p>
<p>Magento 2.0<br />在管理侧边栏上，转到Stores &gt; Settings &gt; Configuration。<br />Magento 2.1 或以上<br />在管理侧边栏上，转到Content &gt; Design &gt; Configuration &gt; Select your current theme &gt; 。</p>
<p>第 2 步：更改特定商店的欢迎信息<br />选择要更改欢迎消息的商店视图。<br />在操作列下，打开Edit模式。<br />向下滚动并展开该Header部分。然后，输入Welcome Text您要显示的。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/e-message.png" /></p>
<p>第 3 步：检查结果<br />一切完成后，点击Save Config。<br />当提示更新页面缓存时，单击Cache Management工作区顶部的链接。然后，按照说明刷新缓存。</p>]]></description>
      <pubDate>Wed, 14 Sep 2022 08:28:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中自定义电子邮件模板、事务性电子邮件]]></title>
      <link>https://www.360magento.com/blog/Customize-email-templates-and-transactional-emails-in-Magento2/</link>
      <description><![CDATA[<p><strong>事务性电子邮件</strong>是系统发送的短消息，作为对客户在您网站上的活动的响应，同时支持正文内容<span class="16"><span>的默认模板，并与已完成电子邮件的页眉和页脚模板相关联。</span></span><span>特别是，由于内容的格式是</span>&nbsp;HTML 和 CSS，可以灵活地<strong><span>为</span>&nbsp;Magento 2 商店定制电子邮件模板</strong>以适应每个网站或每个商店视图。通过插入变量并将其保存在后端很容易进行自定义，您的自定义电子邮件模板将可供使用。为了确保它被发送到客户的收件箱，您应该<span class="16"><span>启用</span>&nbsp;SMTP</span>。</p>
<p class="p"><span class="15"><span style="font-family: Outfit;">电子邮件模板包含您的徽标</span></span><span>和</span><span class="15"><span style="font-family: Outfit;">商店信息</span></span><span>，因此您无需再进行编辑或设计。按照本教程，您可以获得详细的指南来编辑电子邮件模板或创建新的交易电子邮件，</span><span class="15"><span style="font-family: Outfit;">跟进电子邮件</span></span><span>。此外，为确保您的定制符合您的预期，您应该在将链接发送给客户之前点击预览链接进行检查。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/1_1.png" width="800" /></span></p>
<p class="p"><span class="15"><span style="font-family: Outfit;">如上所述，电子邮件分为三个元素：</span>Header、Body 和 Footer。</span><span></span></p>
<p class="p"><strong>标头模板</strong><strong>Header Template</strong>：标头是发送给客户的电子邮件的顶部，同时它很好地吸引了查看者的视线，因此您的徽标被放置在那里并直接链接到您的商店。这是为您的网站带来更多流量的好主意。</p>
<p class="p"><strong>页脚模板</strong><strong>Footer Template</strong>：页脚模板包括结论和发件人的签名。随意编辑页脚的内容，并添加更多信息，如公司电子邮件、号码或地址。</p>
<p class="p"><strong>消息模板</strong><strong>Message Template</strong><span style="font-family: Outfit;">：消息模板被称为电子邮件的正文，当您使用页眉和页脚模板时，自定义是类似的。但是，使用消息模板时，应用不同的活动或事件时会有所不同。</span>Magento 为您提供了相应的模板来使用或修改如何适合您的品牌。例如，您可以从与收件人相关的主要信息开始。</p>
<h2><span style="font-family: Outfit;">在</span> Magento 2 中自定义电子邮件模板的 4 个步骤</h2>
<ul>
<li><span style="font-family: Outfit;">第</span> 1 步：加载默认模板</li>
<li><span style="font-family: Outfit;">第二步：填写模板信息</span></li>
<li><span style="font-family: Outfit;">第</span> 3 步：预览模板</li>
<li><span style="font-family: Outfit;">第</span> 4 步：应用新模板</li>
<li>在管理面板上，Marketing &gt; Communications &gt; Email Templates.</li>
<li>点击Add New Template,
<ul>
<li>选择<strong>模板</strong><strong>Template</strong>的类型：页眉Header、页脚Footer或消息模板&nbsp;Message Templates。</li>
<li>点击Load Template，会出现对应的格式。</li>
</ul>
</li>
</ul>
<h3><span style="font-family: Outfit;">第</span> 1 步：加载默认模板</h3>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/2.png" width="800" /></p>
<h3><strong>第二步：填写模板信息</strong><strong></strong></h3>
<p class="p">在此步骤中，您可以为模板添加信息，例如名称、主题、内容、变量和样式。</p>
<ul>
<li>字段中新模板的名称Template Name。</li>
<li>插入Template Subject模板的组织。模板列表可以按主题列进行排序和过滤。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/3_1.png" width="800" /></p>
<ul>
<li>Template Content在框中根据需要<span style="font-family: Outfit;">自定义</span> HTML 。</li>
<li>单击以在框中Insert Variable插入变量。Template Content</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/4.png" width="800" /></p>
<p class="p">使用插入的变量，您可以将其直接自定义到模板中。</p>
<ul>
<li><span style="font-family: Outfit;">如果要声明任何</span> CSS，请在Template Styles框中输入样式。</li>
</ul>
<h3><strong><span style="font-family: Outfit;">第</span> 3 步：预览模板</strong><strong></strong></h3>
<p class="p">修改完成后，让我们通过模板预览看看实际修改后的样子：</p>
<ul>
<li>为确保模板按照您的预期正确应用，Preview Template如果需要，请单击以进行调整。</li>
<li>Save Template去完成。</li>
</ul>
<p class="p">每个完成的新模板都会在可用电子邮件模板列表中自动更新。</p>
<h3><strong><span style="font-family: Outfit;">第</span> 4 步：应用新模板</strong><strong></strong></h3>
<p class="p">这是启动新电子邮件模板的最后一步。完成这些设置，您就可以开始了：</p>
<p class="p"><span style="font-family: Outfit;">页脚</span>/页眉模板</p>
<ul>
<li><span style="font-family: Outfit;">转到</span> Magento Admin，按照路径：Store &gt; Configurations &gt; General &gt; Design，打开Email部分。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/5.png" width="800" /></p>
<ul>
<li><span style="font-family: Outfit;">为新的页脚</span>/页眉模板设置名称</li>
<li>Save Config去完成。</li>
</ul>
<p class="p">消息模板</p>
<ul>
<li><span style="font-family: Outfit;">转到</span> Magento Admin，按照以下路径：Store &gt; Configuration &gt; Customers &gt; Customer Configuration</li>
</ul>
<p class="p">根据模板的放置位置打开相关选项，例如模板属于Create New Account Options：</p>
<ul>
<li><span style="font-family: Outfit;">为</span> <span style="font-family: Outfit;">设置新模板</span>Welcome Email。</li>
<li>Save Config去完成</li>
</ul>]]></description>
      <pubDate>Tue, 13 Sep 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 显示错误的客户IP]]></title>
      <link>https://www.360magento.com/blog/Magento2-displays-wrong-customer-IP/</link>
      <description><![CDATA[<p class="p"><span><span style="font-family: Arial;">有时，您可以在</span> Magento 2 管理面板中看到 127.0.0.1 或其他错误的客户 IP，而不是真实的客户 IP 地址。这可能是由于您的 Magento 2 商店启用了代理，例如Varnish、Cloudflare、Sucuri.net&nbsp; 。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">要解决错误的</span> IP 地址问题，您需要：</span><span></span></p>
<p class="p"><span>1.</span><span><span style="font-family: Arial;">在</span>M2目录下新建一个文件</span><span>app/etc/XIP/di.xml</span><span></span></p>
<p class="p"><span>2.</span><span>粘贴代码</span><span></span></p>
<p class="p"><span>&lt;?xml version="1.0"?&gt; </span><span></span></p>
<p class="p"><span>&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" </span><span></span></p>
<p class="p"><span>xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config. xsd"&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;type name="Magento\Framework\HTTP\PhpEnvironment\RemoteAddress"&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;arguments&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;argument name="alternativeHeaders" xsi:type="array"&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item name="x-client-ip" xsi: type="string"&gt;HTTP_X_REAL_IP&lt;/item&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;item name="x-cf-connecting-ip" xsi:type="string"&gt;HTTP_CF_CONNECTING_IP&lt;/item&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-- &lt;item name="x-cf- mfcustom-ip" xsi:type="string"&gt;SOME_CUSTOM_SERVER_KEY &lt;/item&gt; --&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/argument&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/arguments&gt; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/type&gt; </span><span></span></p>
<p class="p"><span>&lt;/config&gt;</span><span></span></p>
<p class="p"><span>&nbsp;</span></p>
<p class="p"><!--[if !supportLists]--><span>3.&nbsp;</span><!--[endif]--><span><span style="font-family: Arial;">保存文件，运行依赖注入编译，使用</span> CLI 命令：</span><span></span></p>
<p class="p"><span>php bin/magento setup:di:compile</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">4.</span></span><span>4. 如果这没有帮助，那么您需要使用其他值而不是&ldquo;</span><span>&nbsp;</span><strong><span class="15">SOME_CUSTOM_SERVER_KEY</span></strong><span>&nbsp;&rdquo;并取消注释行。要获得正确的值，您需要使用代码在 Magento 文件夹中创建 test.php 文件：</span><span></span></p>
<p class="p"><span>&lt;?php </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;echo '&lt;pre&gt;'; </span><span></span></p>
<p class="p"><span>&nbsp;&nbsp;&nbsp;&nbsp;var_dump($_SERVER);</span><span></span></p>]]></description>
      <pubDate>Mon, 12 Sep 2022 08:29:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[要启用 Magento 2 缺货通知：]]></title>
      <link>https://www.360magento.com/blog/To-enable-Magento2-out-of-stock-notification/</link>
      <description><![CDATA[<p class="p"><span>1. 在</span><strong><span class="15">Stores &gt; Configuration &gt; Catalog &gt; Inventory</span></strong><span>.</span><strong><span class="15">中启用显示缺货产品</span></strong><strong><span class="15">Display Out of Stock Products</span></strong><span>选项</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/_1.png" width="800" /></span></p>
<p class="p">2. 导航到<strong>Stores &gt; Configuration &gt; Catalog &gt; Catalog</strong>&nbsp;&gt;&nbsp;&nbsp;<strong>Product Alerts</strong>并启用<strong>Allow Alert When Product Comes Back in Stock</strong>选项。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/_2.png" width="800" /></p>
<p><span style="font-family: Arial;">只需启用此选项即可在店面上显示</span><span style="font-family: Arial;">&ldquo;有货时通知我&rdquo;通知。</span>但是，它不会发送通知</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/_3.png" width="800" /></p>
<p class="p">3.&nbsp;指定应在<strong>产品警报运行设置</strong><strong>Product Alert Run</strong>部分发送缺货通知的<strong>频率</strong><strong>Frequency</strong>和<strong>开始时间</strong><strong>Start Time</strong><strong>。</strong></p>
<p>填写<strong>错误电子邮件</strong>信息，以收到有关缺货通知和<strong>保存配置</strong>的任何问题的通知。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/_4.png" width="800" /></p>
<p>Magento 缺货通知可确保您不会错过任何转化，同时让客户满意。但是，如果您仍然不想在商店中展示缺货产品，则必须注意库存</p>]]></description>
      <pubDate>Sun, 11 Sep 2022 08:23:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 重新索引订单网格]]></title>
      <link>https://www.360magento.com/blog/Magento-2-Reindex-Order-Grid/</link>
      <description><![CDATA[<p class="p">无论商店中的订单流程如何，订单网格都是定义订单处理有效性的关键因素之一。</p>
<p class="p">您从订单网格中获得的信息越多，您<span class="15"><span>处理订单</span></span>的速度就越快，而无需分别处理每个订单。</p>
<p class="p"><span>然而，信息量并不是重点。它的有效性是最重要的。</span><span></span></p>
<p class="p"><span>有时，网格中显示的实际订单数据和订单数据不同。账单公司名称可能丢失，送货地址可能不完整，或者订单可能根本没有在网格中生成。</span><span></span></p>
<p class="p"><span>它使商店经理感到困惑并减慢了流程，因为他们在过滤时无法找到相关订单。</span><span></span></p>
<p class="p"><span>为避免这种情况</span><strong><span class="15"><span style="font-family: Arial;">，您需要重新索引</span> Magento 中的订单网格</span></strong><span>。</span><span></span></p>
<p class="p"><span>通常，要运行订单网格重新索引，您需要召集开发人员，除非您有一些技术知识可以自行创建自定义解决方案。</span><span></span></p>
<p class="p"><span>为了简化流程</span><strong><span class="15"><span style="font-family: Arial;">，我们引入了</span> Magento&nbsp;</span></strong><span class="16">2</span><span class="16"></span><span class="16"> Bett</span><span class="16">er</span><span class="16"> Adm</span><span class="16">in</span><span class="16"> Or</span><span class="16">der</span><span class="16"> Grid</span><span><span style="font-family: Arial;">的</span> Magento 2 重新索引订单网格功能。</span><span></span></p>
<p class="p"><span>它允许您直接从网格中重新索引订单网格，一键即可。</span><span></span></p>
<p class="p"><span>因此，您需要做的就是转到</span><strong><span class="15">Sales &gt; Orders</span></strong><span>&nbsp;</span><span>，然后按重新</span><strong><span class="15">Reindex Grid</span></strong><span>按钮。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/1.png" width="800" /></span></p>
<p class="p"></p>
<p class="p"><span><span style="font-family: Arial;">它将刷新</span> Magento 订单网格数据，因此有效的订单信息会显示在网格中。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0908/3.png" width="800" /></span></p>]]></description>
      <pubDate>Sat, 10 Sep 2022 08:26:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中启用管理员登录验证码]]></title>
      <link>https://www.360magento.com/blog/enable-admin-login-captcha-magento-2/</link>
      <description><![CDATA[<p>将验证码要求添加到管理员登录和忘记密码页面有助于将您的商店安全性提高到一个新的水平。当用户单击该Reload图标时，验证码将能够无限制地重新加载。</p>
<p><strong>在 Magento 2 中启用管理员验证码的步骤</strong></p>
<p>1、在管理面板上，单击Stores。在该Settings部分中，选择Configuration。<br />2、Admin在Advanced左侧面板中选择<br />3、打开该CAPTCHA部分，然后继续执行以下操作：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/Zir5S5l.png" /></p>
<p>在该Enable CAPTCHA on Frontend字段中，选择&ldquo;是&rdquo;以在前端启用 CAPTCHA<br />在该Font字段中，选择要用于 CAPTCHA 符号的字体名称。默认值为 LinLibertine。<br />在该Forms字段中，选择以下要使用 CAPTCHA 的表单之一<br />管理员登录<br />管理员忘记密码<br />在Displaying Mode，选择以下选项之一<br />总是<br />尝试登录次数后<br />在该Number of Unsuccessful Attempts to Login字段中，输入在出现验证码之前尝试登录失败的次数。如果您输入零，则验证码将始终可用<br />在该CAPTCHA Timeout (minutes)字段中，输入 CAPTCHA 过期前的分钟数。当 CAPTCHA 过期时，用户必须重新加载页面以生成新的 CAPTCHA。<br />在该Number of Symbols字段中，输入 CAPTCHA 将在其中更改的符号范围数，例如：3-7。最大符号数为八个。<br />在该Symbols Used in CAPTCHA字段中，指定可在 CAPTCHA 中使用的符号。仅设置字母（az 和 AZ）或数字（0-9）以输入框。不允许使用空格或其他字符，默认情况下不使用类似的符号。<br />在该Case Sensitive字段中，选择Yes是否要求用户完全按照所示输入大写和小写字符<br />完成后，点击Save Config</p>]]></description>
      <pubDate>Fri, 09 Sep 2022 08:29:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何配置 Magento 2 管理员操作日志？]]></title>
      <link>https://www.360magento.com/blog/configure-action-log-magento-2/</link>
      <description><![CDATA[<p>Magento 2 支持您配置管理员操作日志，帮助您管理和跟踪管理员的所有活动。您可以在网格上查看日志历史记录，并了解您的商店管理面板中已完成的操作，并了解执行操作的人员。此外，您可以在操作日志上查看 IP 和日期。该功能对于帮助您有效管理系统非常重要，尤其是在您的商店有多个管理员的情况下。</p>
<p>现在请按照下面给出的简单指南来配置操作日志：</p>
<p>1、在管理面板上，点击商店。在该Settings部分中，选择Configuration。<br />2、Admin在Advanced左侧面板中选择<br />3、打开该Admin Actions Logging部分，然后继续执行以下操作：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/8xmQ5tx.png" /></p>
<p></p>
<p><strong>要启用管理员日志记录，请选中该复选框。</strong><br /><strong>要禁用管理员日志记录，请清除该复选框。</strong></p>
<p><br />完成后，单击Save Config。<br />这就是可以配置 Magento 2 管理员操作日志以实现更好的系统管理的方式。如果您想通过查看 IP、名称、日期和操作等信息来监控多个管理员的活动，这将是一个很大的帮助。</p>
<p></p>]]></description>
      <pubDate>Thu, 08 Sep 2022 08:30:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中上传占位符]]></title>
      <link>https://www.360magento.com/blog/How-to-upload-Placeholders-in-Magento2/</link>
      <description><![CDATA[<p>如果您还没有完成主要的产品图片，那么预订即将推出的产品图片是一个好主意。替换的图像称为占位符。这意味着店主将在产品列表页面上使用临时图像，直到正式产品图像准备好出现。</p>
<p><span>在以下情况下，您可能需要 Magento 2 占位符：</span></p>
<ul>
<li><span>产品图片还没有准备好，但您仍然希望产品能够获得更好的 SEO 效果并引起客户的注意。</span></li>
<li><span>即使完整的内容还没有准备好，您也想检查前端的情况。</span></li>
<li><span>存在一些技术问题，在您找到解决这些问题的方法期间，您仍然希望客户体验不会因显示占位符而中断。</span></li>
</ul>
<p><span><span>默认情况下，上传的占位符图像通常是 Magento 徽标，但您也有权根据需要应用其他图像，例如您的品牌徽标。</span><span>占位符图像在目录页面上显示如下：</span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/1_3.png" width="800" /></span></p>
<p><span>那么通过 Magento Admin 上传占位符图像的快速方法是什么？</span></p>
<h2 id="3-steps-to-upload-placeholder-images-in-magento-2"><span>在 Magento 2 中上传占位符图像的 3 个步骤</span></h2>
<ul>
<li>第 1 步：登录到您的 Magento 2 后端</li>
<li>第 2 步：上传占位符图片</li>
<li>第三步：保存配置</li>
</ul>
<h3 id="login-magento-2-backend"><span>第 1 步：登录到您的 Magento 2 后端</span></h3>
<ul>
<li><span>在管理侧边栏上，</span><code class="language-plaintext highlighter-rouge">Stores &gt; Settings &gt; Configuration</code><span>.</span></li>
<li><span>在面板的 下</span><code class="language-plaintext highlighter-rouge">Catalog</code><span>，选择</span>Catalog<span>。</span></li>
</ul>
<h3 id="upload-placeholder"><span>第 2 步：上传占位符图片</span></h3>
<ul>
<li><span>展开该</span><code class="language-plaintext highlighter-rouge">Product Image Placeholders</code><span>部分。</span></li>
<li><span>单击</span><code class="language-plaintext highlighter-rouge">Choose File</code><span><span>以上传占位符图像。</span><span>您可以为每个角色使用相同或</span></span>不同的图像<span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/2_3.png" width="800" /></span></p>
<h3 id="save-configuration"><span>第三步：保存配置</span></h3>
<p><span>点击</span><code class="language-plaintext highlighter-rouge">Save</code><span>完成。</span></p>
<h2 id="final-words"><span>最后的话</span></h2>
<p><span><span>本教程向您展示了在 Magento 2 中上传占位符的快速步骤，这在各种情况下都非常有用，可确保为客户提供流畅的体验并支持品牌营销</span><span>。</span><span>如果您想了解更多信息，请不要忘记发表评论。</span></span></p>]]></description>
      <pubDate>Wed, 07 Sep 2022 08:28:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改 Favicon]]></title>
      <link>https://www.360magento.com/blog/How-to-Change-Favicon-in-Magento2/</link>
      <description><![CDATA[<p>更改 Favicon Magento 2&nbsp;-Favicon是&ldquo;favorite icon&rdquo;的缩写，指的是每个浏览器页面标签上的小图标。根据浏览器的不同，网站图标也会出现在地址栏中，就在 URL 之前。网站图标的大小通常为 16 x 16 像素或 32 x 32 像素。Magento 接受 ICO、PNG、JPG 和 SVG 文件类型，但并非所有浏览器都支持这些格式。&nbsp;用于网站图标的最广泛支持网上有许多免费工具可用于生成 ICO 图像或将现有图像转换为格式。</p>
<p><span>如果网站访问者打开许多选项卡并且无法再看到网站名称，他们将通过查看图标来识别您的商店。</span><span>图标可以代表您的品牌标识，因此使其在人群中脱颖而出将使您有机会在客户心目中变得更加独特。</span><span>这里有 3 个步骤供您更改 Magento 2 网站的 favicon。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/1_2.png" width="800" /></span></p>
<h2 id="3-steps-to-change-favicon-in-magento-2"><span>在 Magento 2 中更改 Favicon 的 3 个步骤</span></h2>
<p><em>您可以通过以下步骤更改 Magento 2 中的 Favicon：</em></p>
<ul>
<li>第 1 步：创建网站图标</li>
<li>第 2 步：将 Favicon 上传到您的商店</li>
<li>第三步：刷新缓存</li>
</ul>
<h3 id="create-favicon"><span>第 1 步：创建网站图标</span></h3>
<ul>
<li><span><span>使用您选择的图像编辑器</span><span>创建</span><span>徽标</span></span><code class="language-plaintext highlighter-rouge">16x16</code><span>的</span><code class="language-plaintext highlighter-rouge">32x32</code><span>图形图像。</span><a href="https://www.mageplaza.com/kb/how-upload-logo-magento-2.html"><span></span></a><span></span></li>
<li><span><span>（可选）使用可用的在线工具之一将文件转换为 .ico 格式。</span><span>然后，将文件保存到您的计算机。</span></span></li>
</ul>
<h3 id="upload-favicon"><span>第 2 步：将 Favicon 上传到您的商店</span></h3>
<h4 id="magento-20x"><span>Magento 2.0.x</span></h4>
<ul>
<li><span>在 上</span><code class="language-plaintext highlighter-rouge">Admin sidebar</code><span>，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>然后在下</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span>在左侧下方的面板中</span><code class="language-plaintext highlighter-rouge">General</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Design</code><span>。</span></li>
<li><span>展开该</span><code class="language-plaintext highlighter-rouge">HTML Head</code><span><span>部分。</span><span>然后，执行以下操作：</span></span></li>
</ul>
<h4 id="magento-21"><span>Magento 2.1+</span></h4>
<p><span><span>从 Magento 2.1 开始，这条路径发生了变化。</span><span>它位于</span></span><code class="language-plaintext highlighter-rouge">Content &gt; Configuration &gt; Select your current theme &gt; HTML Head</code></p>
<ul>
<li><span>在 上</span><code class="language-plaintext highlighter-rouge">Admin sidebar</code><span>，单击</span><code class="language-plaintext highlighter-rouge">Content</code><span><span>。</span><span>然后在下</span></span><code class="language-plaintext highlighter-rouge">Design</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li>
<p><span>在左侧下方的面板中</span><code class="language-plaintext highlighter-rouge">Design Configuration</code><span>，单击</span><code class="language-plaintext highlighter-rouge">Edit</code><span>您当前的网站 storeview。</span></p>
</li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/2_2.png" width="800" /></span></p>
<ul>
<li><span>展开该</span><code class="language-plaintext highlighter-rouge">HTML Head</code><span><span>部分。</span><span>然后，执行以下操作：</span></span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/3_2.png" width="800" /></span></p>
<ul>
<li><span><span>单击选择文件。</span><span>然后，找到您准备的网站图标文件。</span></span></li>
<li>
<p><span>如果要删除当前的网站图标，请标记删除图像复选框。</span></p>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。</span></li>
</ul>
<h3 id="refresh-cache"><span>第三步：刷新缓存</span></h3>
<ul>
<li><span>当提示</span>刷新缓存<span>时，单击</span><code class="language-plaintext highlighter-rouge">Cache Management</code><span>工作区顶部消息中的链接。</span></li>
<li><span>在列表中，标记已标记</span>的 Page Cache<span>复选框</span><code class="language-plaintext highlighter-rouge">Invalidated</code></li>
<li><span><span>将操作设置为&ldquo;刷新&rdquo;。</span><span>然后，单击</span></span><code class="language-plaintext highlighter-rouge">Submit</code><span>。</span></li>
<li><span>要查看新的网站图标，请返回您的店面并按 F5 刷新浏览器。</span></li>
</ul>
<p><span><span>立即开始更改您的网站图标，通过为其提供清晰的品牌标识来吸引更多流量并降低跳出率。</span><span>今天的帖子讨论了快速</span></span><span>更改 Magento 2 中的 favicon 的</span><span><span>步骤。</span><span>如果您有任何疑问，请随时在评论部分与我们分享。</span></span></p>]]></description>
      <pubDate>Tue, 06 Sep 2022 08:24:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改徽标]]></title>
      <link>https://www.360magento.com/blog/How-to-Change-Logo-in-Magento2/</link>
      <description><![CDATA[<p>为您的在线商店应用 Magento 2 平台后，您可能要做的第一件事就是更改标题中的 Magento 2 默认徽标，并为浏览器上传一个网站图标。上传您自己的标志将使商店在客户心目中更专业，更可靠。特别是，商业标志将帮助您显着提高品牌知名度。</p>
<h2 id="3-steps-to-change-logo-in-magento-2"><span>在 Magento 2 中更改徽标的 3 个步骤</span></h2>
<ul>
<li>第 1 步：上传您的徽标</li>
<li>第 2 步：在 Magento 2 中上传前端徽标</li>
<li>第 3 步：检查结果</li>
</ul>
<h3 id="uploading-logo"><span>第 1 步：上传您的徽标</span></h3>
<p><span><span>标头中徽标的大小和位置由商店的主题决定。</span><span>您的徽标可以保存为 GIF、PNG、JPG 或 SVG 文件类型，并从商店的管理员上传。</span><span>示例数据中的默认 Magento 徽标是一个 SVG 文件，它是一种基于 XML 的可扩展矢量图形格式。</span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/1_1.png" width="800" /></span></span></p>
<p><span><span>徽标图像位于服务器上的以下位置。</span><span>具有该名称并位于该位置的任何图像文件都用作主题徽标。</span></span></p>
<p><span>小路：</span><code class="language-plaintext highlighter-rouge">app/design/frontend/[vendor]/[theme]/web/images/logo.svg</code></p>
<p><span>如果您不知道徽标的大小或主题中使用的任何其他图像，请在浏览器中打开页面，右键单击图像，然后检查元素。</span></p>
<p><span>除了在标志上</span><code class="language-plaintext highlighter-rouge">the header</code><span>，你的标志还出现在</span><code class="language-plaintext highlighter-rouge">email templates</code><span>和</span><code class="language-plaintext highlighter-rouge">PDF invoices</code><span>上等</span><code class="language-plaintext highlighter-rouge">sales documents</code><span><span>。</span><span>用于电子邮件模板和发票的徽标有不同的尺寸</span></span>要求<span>，必须单独上传。</span></p>
<h3 id="upload-frontend-logo"><span>第 2 步：在 Magento 2 中上传前端徽标</span></h3>
<h4 id="magento-20"><span>Magento 2.0</span></h4>
<ul>
<li><span>在管理侧边栏上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>然后在下</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span>在左侧面板中</span><code class="language-plaintext highlighter-rouge">General</code><span>选择设计。</span></li>
<li><span>如果您有多个商店或视图，</span><code class="language-plaintext highlighter-rouge">Store View</code><span><span>请在左上角设置应用配置的视图。</span><span>然后，清除每个字段后的复选框，以便输入新值。</span></span></li>
<li><span>展开该</span><code class="language-plaintext highlighter-rouge">Header</code><span><span>部分。</span><span>然后，执行以下操作：</span></span></li>
</ul>
<h4 id="magento-21"><span>Magento 2.1</span></h4>
<p><span><span>从 Magento 2.1 开始，这条路径发生了变化。</span><span>它位于</span></span><code class="language-plaintext highlighter-rouge">Content &gt; Configuration &gt; Select your current theme &gt; Header</code></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/2_1.png" width="800" /></span></span></p>
<p><span><span><span>你可以看到像这样的 Header 部分。</span></span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/3_1.png" width="800" /></span></span></p>
<p></p>
<ul>
<li><span><span>要上传新徽标，请单击选择文件。</span><span>然后，从您的计算机中选择文件。</span></span></li>
<li><span>输入</span><code class="language-plaintext highlighter-rouge">Logo Image Width</code><span>和</span><code class="language-plaintext highlighter-rouge">Logo Image Height</code><span>。</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Logo Image Alt</code><span>字段中，输入您希望在有人将鼠标悬停在图像上时显示的文本。</span></li>
</ul>
<h3 id="check-result"><span>第 3 步：检查结果</span></h3>
<p><span>完成后，点击</span><code class="language-plaintext highlighter-rouge">Save Config</code></p>
<p><span>现在你的标志已经准备好了。</span></p>
<h2 class="active" id="where-should-you-use-your-brand-logo"><span>你应该在哪里使用你的品牌标志？</span></h2>
<p><span>除了您的网站标题之外，还有很多地方可以放置您的品牌徽标以获得更专业的形象、建立信任并将其用作营销工具：</span></p>
<ul>
<li>电子邮件</li>
<li>发票</li>
<li>表格/调查</li>
<li><span>横幅广告</span></li>
<li>社交媒体渠道</li>
<li><span>产品包装</span></li>
<li><span>名片和文具</span></li>
</ul>
<p><span>此外，您可能还想</span>更新页脚中的版权声明<span><span>。</span><span>这些是您可以立即处理的一些简单的设计任务。</span><span>当您的商店正在开发中时，您可以打开商店演示通知，然后在准备启动时将其删除。</span></span></p>
<h2 class="active" id="the-bottom-line"><span>最后的话</span></h2>
<p><span><span>如果您想专业化您的在线商店，请从更改徽标开始。</span><span>上述易于遵循的步骤将使您立即完成此操作。</span><span></span><span>如果您有任何问题，请在下方留言</span></span><span>与我们联系，我们将尽力提供帮助。</span></p>]]></description>
      <pubDate>Mon, 05 Sep 2022 08:28:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中上传产品视频 - Youtube API Key]]></title>
      <link>https://www.360magento.com/blog/How-to-upload-Product-Videos-in-Magento2-Youtube-API-Key/</link>
      <description><![CDATA[<p>您想知道如何更有效地吸引和说服客户吗？答案是，给他们看，不要告诉他们。为了帮助您的产品更具吸引力和活力，Magento 2 允许为您需要的任何产品上传单独的视频。视频包含从图像到音频的各种媒体，因此是传达任何信息的有力方法。这就是为什么观看 Magento 产品视频将在购买前向客户提供您产品的真实概览。产品越视觉化，客户创造的销售额就越多。</p>
<p><span><span>视频可以从您的浏览器上传，也可以将 Youtube 链接嵌入到产品设置中。</span><span>为此，您必须从您的 Google 帐户获取 API 密钥并将其插入到配置中。</span></span></p>
<p><span>本</span>教程<span>中清楚地列出了您应该遵循的必要步骤。</span></p>
<h2 id="3-steps-to-upload-product-videos-in-magento-2"><span>在 Magento 2 中上传产品视频的 3 个步骤</span></h2>
<ul>
<li>第 1 步：获取您的 YouTube API 密钥</li>
<li>第 2 步：配置 Magento</li>
<li>第 3 步：链接到视频</li>
</ul>
<h3 id="get-youtube-api-key"><span>第 1 步：获取您的 YouTube API 密钥</span></h3>
<p><span>首先，您必须通过访问您的 Google 帐户来获取您的 YouTube API 密钥：</span></p>
<ul>
<li><span>登录到您的 Google 帐户，然后访问</span>Google Developers Console<span><span>。</span><span>然后，按照这些：</span></span></li>
<ul>
<li><span>在</span>使用 Google API<span>下，单击</span><code class="language-plaintext highlighter-rouge">Youtube Data APIs</code><span>。</span></li>
</ul>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/1.png" width="800" /></p>
<ul>
<ul>
<li>点击<code class="language-plaintext highlighter-rouge">Manage</code></li>
</ul>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/2.png" width="800" /></p>
<ul>
<ul>
<li>在面板左侧选择<code class="language-plaintext highlighter-rouge">Credentials</code>，点击<code class="language-plaintext highlighter-rouge">Create Credentials</code>并选择<code class="language-plaintext highlighter-rouge">API key</code>。</li>
</ul>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/3.png" width="800" /></p>
<ul>
<ul>
<li>当提示创建新密钥时，选择<code class="language-plaintext highlighter-rouge">Server key</code>。输入密钥名称和IP 地址，然后单击<code class="language-plaintext highlighter-rouge">Create</code>。</li>
<li>获得密钥后，将密钥复制到剪贴板。</li>
</ul>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/4.png" width="800" /></p>
<h3 id="configure-magento"><span>第 2 步：在 Magento 中配置</span></h3>
<p><span>现在，回到 Magento 并完成设置：</span></p>
<ul>
<li><span>在管理侧边栏上，</span><code class="language-plaintext highlighter-rouge">Stores &gt; Settings &gt; Configuration</code><span>.</span></li>
<li><span>在面板中的</span>Catalog<span>下，选择</span><code class="language-plaintext highlighter-rouge">Catalog</code><span>。</span></li>
<li><span><span>展开该部分，将</span><span><span>Youtube API 密钥</span></span></span><code class="language-plaintext highlighter-rouge">Product Videos</code><span><span>粘贴</span><span>到必填字段中。</span></span></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/5.png" width="800" /></p>
<ul>
<li><span>单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。</span></li>
<li><span>转到</span>缓存管理<span>以刷新缓存。</span></li>
</ul>
<h3 id="link-to-video"><span>第 3 步：链接到视频</span></h3>
<p><span>在您的网站上添加视频，一切都会设置好！</span></p>
<ul>
<li><span><span>从 中</span><span>，</span></span><code class="language-plaintext highlighter-rouge">Product Detail</code><span>单击</span><code class="language-plaintext highlighter-rouge">Add Video</code><span>。</span><code class="language-plaintext highlighter-rouge">Images and Videos</code></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/6.png" width="800" /></p>
<ul>
<li><span>输入 YouTube 或 Vimeo 视频的</span><a href="https://www.mageplaza.com/kb/how-to-create-url-rewrites-magento-2.html">URL</a><span><span>。</span><span>在该</span></span><code class="language-plaintext highlighter-rouge">URL</code><span>字段中，如果您尚未输入 Youtube API 密钥，则会出现系统错误消息，点击</span><code class="language-plaintext highlighter-rouge">OK</code><span>继续。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/7.png" width="800" /></span></p>
<ul>
<li><span>输入视频的</span><code class="language-plaintext highlighter-rouge">Title</code><span>和</span><code class="language-plaintext highlighter-rouge">Description</code><span>。</span></li>
<li><span>要</span>上传预览图像<span>，请浏览到图像并选择文件。</span></li>
<li><span>如果您更喜欢使用视频元数据，请单击</span><code class="language-plaintext highlighter-rouge">Get Video Information</code><span>。</span></li>
<li><span>要将角色分配给视频，请标记每个角色的相应复选框：</span>
<ul>
<li><span>基本图像</span></li>
<li><span>小图像</span></li>
<li><span>色板图像</span></li>
<li><span>缩略图</span></li>
<li><span>从产品页面隐藏</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save</code><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0904/8.jpg" width="800" /></span></p>
<p></p>]]></description>
      <pubDate>Sun, 04 Sep 2022 08:29:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中上传图片产品]]></title>
      <link>https://www.360magento.com/blog/How-to-upload-Images-Product-in-Magento2/</link>
      <description><![CDATA[<p><span>高质量的图像是使您的网站更加美观并为您的购物者提供专业外观的力量。</span><span>多亏了这些图像，客户可以更快地做出购买决定，并减少与产品外观相关的问题，这可以显着减少支持团队的工作量。</span><span>但是，如果您的每个产品在目录中都有一组图像，那么管理数百或数千张图像是相当困难的。</span><span>因此，您现在应该为您的图像文件建立一个命名约定，这将有助于您更轻松地跟踪，即使您想找到原始文件。</span>在本主题中，我们将逐步向您展示如何在 Magento 2 中上传产品图片。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1_5.png" width="800" /></p>
<p><span>在产品详细信息中，您可以同时上传产品所需的任意数量的图像，链接到视频，重新排列它们的顺序，并确定每个图像的使用方式。</span><span>对于每个产品，您可以将三个角色分配给任何图像。</span><span>您可以设置必须足够大以产生缩放所需的放大倍率的主图像或基本图像。</span><span>除了基本图片之外，该图片的小图片将出现在产品列表中，缩略图将出现在购物车中。</span><span>分配对您来说很灵活；</span><span>但是，默认情况下，这些角色会自动分配给第一个上传的图像。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/2_2.png" width="800" /></span></p>
<p><span>如何在 Magento 2 中按以下选项上传图像产品</span></p>
<h2 class="active" id="2-steps-to-upload-images-product-in-magento-2"><span>在 Magento 2 中上传图片产品的 2 个步骤</span></h2>
<ul>
<li>第 1 步：如何进入 Magento 2 中的图像产品</li>
<li>第 2 步：如何在 Magento 2 中管理图像产品</li>
</ul>
<h3 id="get-into-images-product"><span>第 1 步：如何进入 Magento 2 中的图像产品</span></h3>
<ul>
<li><span>登录 Magento 2 后端后，转到</span><code class="language-plaintext highlighter-rouge">Catalog &gt; Manage Products</code></li>
<li><span>打开产品</span></li>
</ul>
<h3 id="manage-images-products"><span>第 2 步：如何在 Magento 2 中管理图像产品</span></h3>
<ul>
<li><span>单击</span><code class="language-plaintext highlighter-rouge">Edit</code><span>链接，然后执行以下操作：</span></li>
</ul>
<h4 id="21-upload-an-image"><span><span>2.1.&nbsp;</span><span>上传图片</span></span></h4>
<p><span>要上传新图像，您可以应用以下两种方式之一：</span></p>
<ul>
<li><span>从您的浏览器中拖动一个图像，并将其放入</span><span>图像和视频</span><span>框中。</span></li>
<li><span><span>单击</span><span><span>图像和视频</span></span></span><code class="language-plaintext highlighter-rouge">Camera</code><span><span>框中的标题</span><span>，浏览到图像文件并单击</span><span>以选择您需要的任何图像。</span></span><span><span></span></span><code class="language-plaintext highlighter-rouge"><br /></code></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/3_1.png" width="800" /></p>
<h4 id="22-assign-the-base-image"><span><span>2.2.&nbsp;</span><span>分配基础图像</span></span></h4>
<p><span><span>如果要分配给基本图像，只需单击图像下角的标签图标即可。</span><span>一旦您点击，就会出现一个橙色的小横幅，这意味着您的分配成功。</span></span></p>
<p><span><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/4_1.png" width="800" /></span></span></p>
<h4 id="23-reorder-images"><span><span>2.3.&nbsp;</span><span>重新排序图像</span></span></h4>
<p><span>要更改目录中图像的显示位置，请单击</span><code class="language-plaintext highlighter-rouge">Sort</code><span>图像右上角的图标，然后将其拖放到新位置。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/5_1.png" width="800" /></span></p>
<h4 id="24-delete-an-image"><span><span>2.4.&nbsp;</span><span>删除图像</span></span></h4>
<p><span>要删除任何图像，请单击</span><code class="language-plaintext highlighter-rouge">Delete</code><span>左下角的图标。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/6_1.png" width="800" /></span></p>
<p><span>单击</span><code class="language-plaintext highlighter-rouge">Save</code><span>以保存更改。</span></p>
<h4 id="25-view-image-detail"><span><span>2.5.&nbsp;</span><span>查看图像详细信息</span></span></h4>
<ul>
<li><span>要获取图像的详细信息，请单击</span><code class="language-plaintext highlighter-rouge">Images and Videos</code><span><span>图像标题下方或</span><span>面板中的</span></span><span>基本设置下。</span><span></span></li>
<li><span>在&ldquo;图像详细信息&rdquo;页面中，您可以执行以下任何操作：</span></li>
</ul>
<h4 id="26-enter-alt-text"><span><span>2.6.&nbsp;</span><span>输入替代文字</span></span></h4>
<p><span>在</span><code class="language-plaintext highlighter-rouge">Alt Text</code><span>框中，写下您的图像的一些描述。</span></p>
<p><span><span>屏幕阅读器引用图像替代文本以提高 Web 可访问性，并在索引站点时被搜索引擎引用。</span><span>某些浏览器会在鼠标悬停时显示 Alt 文本。</span><span>因此，您应该小心选择图像的关键词。</span></span></p>
<h4 id="27-assign-roles"><span><span>2.7.&nbsp;</span><span>分配角色</span></span></h4>
<p><span><span>默认情况下，三个角色（基本图像、小图像和缩略图）会自动分配给产品的第一个图像。</span><span>如果要重新分配，请执行以下操作：</span></span></p>
<ul>
<li><span>单击所需的图像以打开图像详细信息页面。</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Role</code><span>部分中，选择要分配给该图像的角色。</span></li>
</ul>
<p><span>分配的角色在选定模式下会显示一个复选标记，并且之前的图像不再分配给该角色。</span></p>
<h4 id="28-hide-images"><span><span>2.8.&nbsp;</span><span>隐藏图像</span></span></h4>
<p><span>要排除任何图像，请</span><code class="language-plaintext highlighter-rouge">Hide from Product Page</code><span>在&ldquo;图像详细信息&rdquo;页面中标记复选框，然后单击</span><code class="language-plaintext highlighter-rouge">Save</code><span>。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/7_1.png" width="800" /></span></p>
<ul>
<li><span>要退出详细视图，请单击右上角的</span><code class="language-plaintext highlighter-rouge">Close</code><span>框。</span></li>
<li><span>点击</span><code class="language-plaintext highlighter-rouge">Save</code><span>完成。</span></li>
</ul>
<h2 class="active" id="final-words"><span>最后的话</span></h2>
<p><span>这些是您可以在 Magento 2 中上传、编辑、删除和隐藏图像产品的可能操作。</span><span><span>如果您想获得更多指导，请随时</span><span>在下面发表评论或</span></span>联系我们。</p>]]></description>
      <pubDate>Sat, 03 Sep 2022 08:21:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加新的 CMS 块]]></title>
      <link>https://www.360magento.com/blog/How-to-Add-New-CMS-Blocks-in-Magento2/</link>
      <description><![CDATA[<p>从Magento 管理面板在 Magento 2 中添加新的 CMS 块很容易。您可以设置显示块的位置，可以是一个页面、一组页面或任何页面。创建块标题和标识符以确定块并易于管理。块的内容将使用编辑器方便地创建，该编辑器允许您格式化文本、创建链接和表格、图像、视频和音频。此外，如果您更喜欢使用 HTML 代码，只需单击&ldquo;显示/隐藏编辑器&rdquo;按钮。</p>
<p><span><span>CMS Blocks 将您的网站变成一个有吸引力且引人入胜的页面，以吸引更多流量。</span><span>要在 Magento 2 中添加新的 CMS 块，您可以按照下面给出的这些简单步骤进行操作。</span></span></p>
<h2 class="active" id="8-steps-to-add-new-cms-blocks-in-magento-2"><span>在 Magento 2 中添加新 CMS 块的 8 个步骤</span></h2>
<p><span><em>按照以下步骤在 Magento 2 中添加新的 CMS 块：</em></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1_4.png" width="800" /></span></span></p>
<p></p>
<ol>
<li><span><span>在管理面板上，单击内容。</span><span>在该</span></span><code class="language-plaintext highlighter-rouge">Elements</code><span>部分中，选择</span><code class="language-plaintext highlighter-rouge">Blocks</code><span>。</span></li>
<li><span>单击右上角的</span><code class="language-plaintext highlighter-rouge">Add New Block</code><span>按钮并继续。</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Block Title</code><span>字段中，输入新块的名称标题</span></li>
</ol>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/2_1.png" width="800" /></span></p>
<p></p>
<ol>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Identifier</code><span><span>字段中，为块选择一个唯一标识符。</span><span>请记住，使用所有小写字符并使用下划线而不是空格。</span></span></li>
<li><span>在</span>Store View<span><span>字段中，选择</span><span>块可用</span></span>的 Store View(s)<span></span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Status</code><span>字段中，设置为</span><code class="language-plaintext highlighter-rouge">Enable</code><span>使该块在</span>商店中可见</li>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Content</code><span>字段中，完成块的内容</span></li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Block</code><span>。</span></li>
</ol>
<h2 class="active" id="final-words"><span>最后的话</span></h2>
<p><span><span>CMS 块表示用于显示信息的内容块，例如文本、图像、视频，甚至是来自小部件和其他来源的信息。</span><span>按照上述步骤，您可以立即在 Magento 2 中创建一个新的 CMS Block，以更轻松地吸引您的访问者。</span><span></span><span>如果您需要任何帮助，请随时与我们联系以获得进一步的帮助。</span></span></p>]]></description>
      <pubDate>Fri, 02 Sep 2022 08:24:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中翻译 CMS 页面]]></title>
      <link>https://www.360magento.com/blog/How-to-Translate-CMS-Pages-in-Magento2/</link>
      <description><![CDATA[<p>翻译 CMS 页面是在全球范围内发展您的业务的受支持方式之一。这意味着您可以创建翻译后的网站，然后使其在特定商店视图中对您的客户可见。要设置翻译的内容页面，您必须创建一个具有相同 URL 的新页面以将其分配给商店。配置后，您将使用翻译后的文本更新特定视图的 CMS 页面。</p>
<h2 id="6-steps-to-translate-cms-page-in-magento-2"><span>在 Magento 2 中翻译 CMS 页面的 6 个步骤：</span></h2>
<ol>
<li><span>在管理面板上，</span><code class="language-plaintext highlighter-rouge">Content &gt; Elements &gt; Pages</code><span>.</span></li>
<li><span>找到需要翻译的页面，在编辑模式下打开。</span></li>
<li><span>复制</span><code class="language-plaintext highlighter-rouge">URL Key</code><span><span>到剪贴板。</span><span>然后，点击</span></span><code class="language-plaintext highlighter-rouge">Back</code><span>按钮返回页面网格。</span></li>
<li><span>点击</span><code class="language-plaintext highlighter-rouge">Add New Page</code><span>，您需要：</span>
<ul>
<li><span>翻译</span><code class="language-plaintext highlighter-rouge">Page Title</code><span>.</span></li>
<li><span>粘贴</span><code class="language-plaintext highlighter-rouge">URL Key</code><span>您之前复制的内容</span></li>
<li><span>在左上角，选择</span><code class="language-plaintext highlighter-rouge">Store View</code><span>翻译显示</span></li>
<li><span>在左侧面板的 下</span><code class="language-plaintext highlighter-rouge">Page Information</code><span>，选择</span><code class="language-plaintext highlighter-rouge">Content</code><span>，然后插入页面的翻译文本。</span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Layout</code><span><span>在选项卡中为页面</span><span>创建</span></span><code class="language-plaintext highlighter-rouge">Design</code><span>。</span></li>
<li><span><span>在</span><span>选项卡</span></span><code class="language-plaintext highlighter-rouge">Keywords</code><span><span>中</span><span>完成翻译</span></span><code class="language-plaintext highlighter-rouge">Description</code><span></span><code class="language-plaintext highlighter-rouge">Meta Data</code><span></span></li>
</ul>
</li>
<li><span>单击</span><code class="language-plaintext highlighter-rouge">Save Page</code><span><span>以完成，并在</span><span>出现提示时</span></span>刷新缓存。<span></span></li>
<li><span>前往店面并使用</span>语言<span>选择器检查</span>商店视图<span>上的翻译。</span>公司页脚链接块和欢迎信息<span><span>等一些元素</span><span>也需要翻译。</span></span></li>
</ol>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1_3.png" width="800" /></span></span></p>
<p></p>
<h2 class="active" id="final-words"><span>最后的话</span></h2>
<p><span><span>在线商家如果想在不同国家开展业务，需要在 Magento 2 中翻译 CMS 页面。</span><span>它有助于将 CMS 页面翻译成合适的语言，以增加流量。</span></span><span>如果您有任何问题，请随时在评论部分提出。</span></p>]]></description>
      <pubDate>Thu, 01 Sep 2022 08:31:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2：如何在主页上插入产品]]></title>
      <link>https://www.360magento.com/blog/Magento2-How-to-Insert-Products-on-Homepage/</link>
      <description><![CDATA[<p>主页可以被认为是每个网站最重要的部分，因为客户在决定是否留下之前会首先看到您的主页。设计不佳且信息不足的主页不会吸引或留住客户。因此，您的工作是让主页真正吸引人，并用它来说服他们采取行动。</p>
<p>增加转化率和降低跳出率的第一步可以是在您的主页上插入产品。想象一下，当他们访问您的网站并看到吸引他们的产品时，他们更有可能购买这些产品或留下来进一步探索。此外，您还可以按照本指南在主页中插入制造商/品牌。在本文中，我们将展示如何通过一些简单的步骤在主页上插入产品。</p>
<h2 id="5-steps-to-insert-products-on-the-homepage-in-magento-2"><span>在 Magento 2 的主页上插入产品的 5 个步骤：</span></h2>
<ul>
<li>第 1 步：导航到内容 &gt; 页面</li>
<li>第 2 步：在&ldquo;操作&rdquo;菜单下选择&ldquo;编辑&rdquo;</li>
<li>第 3 步：选择目录产品列表选项</li>
<li>第 4 步：选择类别并单击插入小部件按钮</li>
<li>第五步：点击保存页面完成</li>
</ul>
<h3 id="step-1-navigate-content"><span>第 1 步：导航到内容 &gt; 页面</span></h3>
<p><span>首先，您需要登录到您商店的</span>Magento 2 管理面板<span><span>。</span><span>导航至</span></span><code class="language-plaintext highlighter-rouge">Content</code><span>&gt;</span><code class="language-plaintext highlighter-rouge">Pages</code></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1_2.png" width="400" /></p>
<p><span>页面将在此处显示，您将看到商店的所有页面。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/2.png" width="800" /></span></p>
<h3 id="step-2-select-edit-under-actions-menu"><span>第 2 步：在&ldquo;操作&rdquo;菜单下选择&ldquo;编辑&rdquo;</span></h3>
<p><span>在</span><code class="language-plaintext highlighter-rouge">Homepage</code><span>标题上，从</span><code class="language-plaintext highlighter-rouge">Select</code><span>下拉菜单中选择</span><code class="language-plaintext highlighter-rouge">Edit</code><span>下拉</span><code class="language-plaintext highlighter-rouge">Actions</code><span>菜单。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/3.png" width="800" /></span></p>
<p><span><span>现在转到</span><code class="language-plaintext highlighter-rouge">Content</code><span>部分并单击</span><code class="language-plaintext highlighter-rouge">Insert widget</code></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/4.png" width="800" /></p>
<h3 id="step-3-choose-catalog-product-list-option"><span>第 3 步：选择目录产品列表选项</span></h3>
<p><code class="language-plaintext highlighter-rouge">Insert Widget</code><span>页面将出现，</span><code class="language-plaintext highlighter-rouge">Catalog Products List</code><span>选择</span><code class="language-plaintext highlighter-rouge">Widget type。</code><span><span><br /></span></span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/5.png" width="700" /></span></p>
<h3 id="step-4-select-category-and-click-on-insert-widget-button"><span>第 4 步：选择类别并单击插入小部件按钮</span></h3>
<p><span>在下一页上，有一个</span><code class="language-plaintext highlighter-rouge">Conditions</code><span>属性，</span><code class="language-plaintext highlighter-rouge">Category</code><span>从选项中选择，然后选择</span><code class="language-plaintext highlighter-rouge">category</code><span><span>要在商店主页上显示的属性。</span><span>然后，单击</span></span><code class="language-plaintext highlighter-rouge">Insert Widget</code><span>。</span></p>
<p><span>&nbsp;<img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/6.png" width="800" /></span></p>
<h3 id="step-5-click-save-page-to-finish"><span>第五步：点击保存页面完成</span></h3>
<p><span>返回</span><code class="language-plaintext highlighter-rouge">Content</code><span>选项卡，您将</span><code class="language-plaintext highlighter-rouge">Products</code><span><span>在文本框中看到一个图标。</span><span>点击</span></span><code class="language-plaintext highlighter-rouge">Save Page</code><span>按钮完成页面切换。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/7.png" width="800" /></span></p>
<h2 class="active" id="to-summarize"><span>总结</span></h2>
<p><span><span>我们相信完成所有这些步骤对您来说非常容易。</span><span>现在，是时候</span></span><span>在主页上插入新产品了，</span><span><span>这有助于吸引您的客户并增加流量并促进 Magento 2 商店的销售。</span><span></span></span><span><span>随时分享您的任何疑问，我们将尽力为您提供支持。</span></span></p>]]></description>
      <pubDate>Wed, 31 Aug 2022 08:26:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置默认​​页面]]></title>
      <link>https://www.360magento.com/blog/How-to-Configure-the-Default-Page-in-Magento2/</link>
      <description><![CDATA[<p><span>在本主题中，我将介绍</span><span>如何配置默认 CMS 页面</span><span><span>。</span><span>默认页面是当您单击基本 URL 时将出现的页面。</span><span>通常主页被配置为默认页面。</span><span>此外，当出现&ldquo;页面未找到&rdquo;错误时，将显示默认页面。</span></span></p>
<h2 id="configure-the-default-pages-in-magento-2"><span>在 Magento 2 中配置默认​​页面</span></h2>
<p><em>按照简单指南在 Magento 2 中配置默认​​页面：</em></p>
<ul>
<li><span>在管理面板上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>在该</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>部分中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Web</code><span>在</span><code class="language-plaintext highlighter-rouge">General</code><span><span>左侧面板中</span><span>选择</span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Default Pages</code><span>部分，然后继续执行以下操作：</span>
<ul>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Default Web URL</code><span>字段中，默认值</span><code class="language-plaintext highlighter-rouge">cms</code><span>或根据需要输入其他值</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">CMS Home Page</code><span>字段中，选择要成为主页的页面，您应该选择&ldquo;主页&rdquo;</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Default No-route URL</code><span><span>字段中，默认值为&ldquo;cms/noRoute/index&rdquo;。</span><span>或根据需要输入其他值</span></span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">CMS No Route Page</code><span><span>字段中，选择值以在出现</span><span>404 Not Found</span><span>错误</span></span><code class="language-plaintext highlighter-rouge">404 Page Not Found</code><span>时显示 CMS 页面</span><a href="https://www.mageplaza.com/kb/magento-2-404-page-not-found.html"><span></span></a><span></span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">CMS No Cookies Page</code><span>字段中，选择</span><code class="language-plaintext highlighter-rouge">Enable Cookies</code><span>值以在浏览器中禁用 cookie 时显示 CMS 页面</span></li>
<li><span>在该</span><code class="language-plaintext highlighter-rouge">Show Breadcrumbs for CMS Pages</code><span>字段中，设置</span><code class="language-plaintext highlighter-rouge">Yes</code><span>是否要在所有 CMS 页面的顶部显示面包屑路径</span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1_1.png" width="900" /></span></p>]]></description>
      <pubDate>Tue, 30 Aug 2022 08:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中配置 Robots.txt]]></title>
      <link>https://www.360magento.com/blog/How-to-Configure-Robots-txt-in-Magento2/</link>
      <description><![CDATA[<p>如您所知，配置robot.txt对于任何致力于网站搜索引擎优化的网站都很重要。特别是，当您将站点地图配置为允许搜索引擎为您的商店编制索引时，有必要向网络爬虫提供 robots.txt 文件中的说明，以避免索引不允许的站点。位于 Magento 安装根目录中的 robots.txt 文件指示 Google、Yahoo、Bing 等搜索引擎可以轻松识别和跟踪。在这篇文章中，我将介绍配置robot.txt 文件的指南，以便它与您的站点一起工作。</p>
<h2 id="what-is-robotstxt-in-magento-2"><span>Magento 2 中的 Robots.txt 是什么？</span></h2>
<p><span><span>robots.txt 文件指示网络爬虫知道在哪里索引您的网站以及在哪里跳过。</span><span>定义这个网站机器人 - 网站爬虫关系将帮助您优化您网站的排名。</span><span>有时您需要它来识别和避免索引特定部分，这可以通过配置来完成。</span><span>您可以决定使用默认设置或为每个搜索引擎设置自定义说明。</span></span></p>
<h2 class="active" id="steps-to-configure-magento-2-robotstxt-file"><span>配置 Magento 2 robots.txt 文件的步骤</span></h2>
<p><span>请按照此分步指南在 Magento 2 中配置您的 robots.txt 文件：</span></p>
<ul>
<li><span>在管理面板上，单击</span><code class="language-plaintext highlighter-rouge">Stores</code><span><span>。</span><span>在该</span></span><code class="language-plaintext highlighter-rouge">Settings</code><span>部分中，选择</span><code class="language-plaintext highlighter-rouge">Configuration</code><span>。</span></li>
<li><span></span><code class="language-plaintext highlighter-rouge">Design</code><span>在</span><code class="language-plaintext highlighter-rouge">General</code><span><span>左侧面板中</span><span>选择</span></span></li>
<li><span>打开该</span><code class="language-plaintext highlighter-rouge">Search Engine Robots</code><span>部分，然后继续执行以下操作：</span>
<ul>
<li><span>在</span><code class="language-plaintext highlighter-rouge">Default Robots</code><span>中，选择以下选项之一：</span>
<ul>
<li>INDEX, FOLLOW</li>
<li>NOINDEX, FOLLOW</li>
<li>INDEX, NOFOLLOW</li>
<li>INDEX, NOFOLLOW</li>
</ul>
</li>
<li><span>如果需要，在该</span><code class="language-plaintext highlighter-rouge">Edit Custom instruction of robots.txt File</code><span>字段中输入自定义说明。</span></li>
<li><span><span>如果您需要恢复默认说明，请</span><span>在该</span></span><code class="language-plaintext highlighter-rouge">Reset to Defaults</code><span>字段中单击按钮。</span><code class="language-plaintext highlighter-rouge">Reset to Default</code><span></span></li>
</ul>
</li>
<li><span>完成后，单击</span><code class="language-plaintext highlighter-rouge">Save Config</code><span>。</span></li>
</ul>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog0829/1.png" width="900" /></span></p>
<p></p>
<h2 id="magento-2-robotstxt-examples"><span>Magento 2 Robots.txt 示例</span></h2>
<p><span>您还可以通过设置自定义说明来隐藏您的网页，使其对网站爬虫隐藏，如下所示：</span></p>
<ul>
<li><span>允许完全访问</span></li>
</ul>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent:*
Disallow:
</code></pre>
</div>
</div>
<ul>
<li><span>禁止访问所有文件夹</span></li>
</ul>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent:*
Disallow: /<br /></code></pre>
<h2 id="more-robotstxt-examples"><span>更多 Robots.txt 示例</span></h2>
<h3 id="block-google-bot-from-a-folder"><span>从文件夹中阻止 Google bot</span></h3>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot 
Disallow: /subfolder/
</code></pre>
</div>
</div>
<h3 id="block-google-bot-from-a-page"><span>从页面中阻止 Google bot</span></h3>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot 
Disallow: /subfolder/page-url.html</code></pre>
</div>
</div>
<h2 id="common-web-crawlers-bots"><span>常见的网络爬虫（机器人）</span></h2>
<p><span>以下是互联网上的一些常见机器人。</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>User-agent: Googlebot
User-agent: Googlebot-Image/1.0
User-agent: Googlebot-Video/1.0
User-agent: Bingbot
User-agent: Slurp		# Yahoo
User-agent: DuckDuckBot
User-agent: Baiduspider
User-agent: YandexBot
User-agent: facebot		# Facebook
User-agent: ia_archiver		# Alexa</code></pre>
</div>
</div>
</div>
</div>]]></description>
      <pubDate>Mon, 29 Aug 2022 08:23:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2“拒绝访问”错误]]></title>
      <link>https://www.360magento.com/blog/Magento2-access-denied-error/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/1_1.png" width="800" /></p>
<p class="p"><span style="font-family: Arial;">虽然你们中的许多人都面临这个问题，但很少有人真正知道它与什么有关或如何解决这个问题。因此，在本指南中，我们将为</span><span style="font-family: Arial;">&ldquo;拒绝访问&rdquo;错误提供一个非常简单和快速的解决方案，以使任何有或没有技术技能的人都能处理它。</span></p>
<p class="p"><span style="font-family: Arial;">但是，让我们首先定义什么是</span> Magento&ldquo;拒绝访问&rdquo;错误。</p>
<h2><strong><span style="font-family: Arial;">什么是</span> Magento&ldquo;拒绝访问&rdquo;错误？</strong><strong></strong></h2>
<p class="p">Magento Access denied 错误是最常见的 Magento 错误，当您尝试访问网页而无权进入时出现。当您使用不正确的管理面板凭据、创建具有错误用户角色的新用户或安装Magento 2 扩展<span style="font-family: Arial;">时，它通常会出现在</span> Magento 管理员中。</p>
<h2><strong><span style="font-family: Arial;">如何修复</span> Magento 2 中的&ldquo;拒绝访问&rdquo;错误？</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">现在您知道</span><span style="font-family: Arial;">&ldquo;访问被拒绝&rdquo;错误可能出现的主要原因，让我们相应地解决它们。</span></p>
<h3><strong><span style="font-family: Arial;">解决方案</span> 1. 获取正确的凭据</strong><strong></strong></h3>
<p class="p"><span style="font-family: Arial;">如果您丢失了管理面板凭据，恢复它们的唯一方法是通过数据库表。转到您的数据库并运行以下</span> SQL 查询：</p>
<p>SET @salt = MD5(UNIX_TIMESTAMP());</p>
<p><br />UPDATE admin_user SET password = CONCAT(SHA2(CONCAT(@salt, 'YourNewPassword'), 256), ':', @salt, ':1') WHERE username = 'admin';</p>
<p>&nbsp;</p>
<p class="p">现在尝试使用新密码登录，如果无法登录，请检查<strong>admin_user</strong><span style="font-family: Arial;">表中的</span>2 列：&nbsp;<em>first_failure</em>和<em>lock_expires</em><span style="font-family: Arial;">并将这些列的值设置为</span> null。</p>
<h3><strong><span style="font-family: Arial;">解决方案</span> 2. 分配适当的用户角色</strong><strong></strong></h3>
<p class="p"><span style="font-family: Arial;">如果您在添加新用户后在</span> Magento 中遇到&ldquo;访问被拒绝&rdquo;问题，很可能您没有为他们分配用户角色。</p>
<p class="p">在这种情况下，使用其他用户登录或要求管理员转到<strong>System &gt; Permissions &gt; All Users</strong>并将您的用户分配给某个用户角色。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/2_1.png" width="800" /></p>
<h3><strong><span style="font-family: Arial;">解决方案</span> 3. 获取访问特定扩展程序的权限</strong><strong></strong></h3>
<p class="p"><span style="font-family: Arial;">由于</span> Magento 不会自动更新对新扩展的权限，因此您可能无权查看新的扩展设置。&nbsp;</p>
<p class="p"><span style="font-family: Arial;">它通常有助于重新登录管理面板。但是，如果</span> Magento &ldquo;拒绝访问&rdquo;错误仍然存​​在，请重置管理员权限。</p>
<p><span style="font-family: Arial;">1.</span>转到<strong>System &gt; Permissions &gt; User Roles</strong><strong>&nbsp;</strong>并找到新扩展被阻止的角色。</p>
<p><strong><span style="font-family: Arial;"></span></strong>2.在<strong>Resource Access</strong>更改为<em>全部</em>或某些特定扩展<strong>Role Resources</strong>。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/3_1.png" width="800" /></p>
<h3><strong><span><span style="font-family: Arial;">解决方案</span>4.修复system.xml和config.xml冲突</span></strong><strong><span></span></strong></h3>
<p class="p"><span><span style="font-family: Arial;">有时会发生在启用某些自定义模块后，</span>Magento 2 中的&ldquo;访问被拒绝&rdquo;问题出现并阻止您访问自定义模块。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">尝试禁用扩展并检查问题是否仍然存在。如果是，请检查</span> system.xml 和 config.xml 文件。</span><strong><span class="15">config.xml</span></strong><span>和</span><strong><span class="15">system.xml</span></strong><span><span style="font-family: Arial;">中的某些条目可能会丢失。</span>&nbsp;</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">现在您应该能够快速修复</span><span style="font-family: Arial;">&ldquo;访问被拒绝&rdquo;错误并立即跳回与 Magento 管理员一起工作。无论您是否是开发人员，您都应该知道如何对</span></span><span class="16">Magento</span><span class="16"> 进行故</span><span class="16">障排除</span>以消除所有可能的问题并更快地找到解决方案。<span></span></p>]]></description>
      <pubDate>Sun, 28 Aug 2022 08:30:15 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中添加相关产品]]></title>
      <link>https://www.360magento.com/blog/Add-related-products-in-Magento2/</link>
      <description><![CDATA[<p class="p"><span><span style="font-family: Arial;">在</span> Magento 2 中添加相关产品：</span><span></span></p>
<p class="p"><!--[if !supportLists]--><span>1.&nbsp;</span><!--[endif]--><span>转到</span><span class="15">Catalog &gt; Products</span><span>并选择您要添加产品推荐的产品。</span><span></span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/1.png" width="800" /></p>
<p class="p"><!--[if !supportLists]--><span>2.&nbsp;</span><!--[endif]--><span>向下滚动到</span><span class="15">相关产品</span><span class="15">Related Products</span><span class="15">、追加销售</span><span class="15">Up-sells</span><span class="15">和交叉销售</span><span class="15">Cross-sells</span>部分，然后按<span class="15">添加相关产品</span><span class="15">Add</span><span class="15"> Related Products</span><span>按钮。</span><span></span></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/2.png" width="800" /></p>
<p class="p"><!--[if !supportLists]--><span>3.&nbsp;</span><!--[endif]--><span>选择您要添加的与当前产品相关的产品，然后按</span><span class="15">添加所选产品</span>&nbsp;<span class="15">Add Selected Products</span><span>。</span><span></span></p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/3.png" width="800" /></p>
<p class="p"><!--[if !supportLists]--><span>4.&nbsp;</span><!--[endif]--><span>整理一下你添加的相关产品。</span><span><span style="font-family: Arial;">您可以通过</span> grad 和 drop 删除或更改它们的顺序。</span><span> </span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/blog822/4.png" width="800" /></span></p>
<p class="p">不要忘记<span class="15">保存</span>产品并在店面检查结果。产品将按照您安排的顺序排列。<span></span></p>]]></description>
      <pubDate>Sat, 27 Aug 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[配置 Magento 2 购物车]]></title>
      <link>https://www.360magento.com/blog/Configure-Magento-shopping-cart/</link>
      <description><![CDATA[<p>由于购物车与结账直接相关，因此配置选项位于Stores &gt; Configuration &gt; Sales &gt; Checkout<span style="font-family: Arial;">下。导航到那里以从</span> Magento 购物车选项开始。</p>
<p>&nbsp;</p>
<h2><strong>1.配置我的购物车链接</strong><strong></strong></h2>
<p class="p">购物车链接位于网站标题的右上角。它显示客户添加到购物车的产品数量。</p>
<p class="p"><span style="font-family: Arial;">相应地，您可以配置是否显示购物车中的商品总数或购物车中的商品数量（不考虑数量）。</span>&nbsp;</p>
<p class="p">因此，您所要做的就是找到My Cart Link&nbsp;部分并定义如何&nbsp;<span style="font-family: Arial;">显示</span> Cart Summary。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/1_3.png" width="800" /></p>
<p>Display item quantities<strong>&nbsp;</strong>显示购物车中的商品总数以及每个产品数量。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/2_2.png" width="800" /></p>
<p>Display number of items in cart显示购物车中的商品数量，不包括每个产品数量。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/3_2.png" width="800" /></p>
<h2><strong><span>2. 设置迷你购物车</span></strong><strong><span></span></strong></h2>
<p class="p"><span><span style="font-family: Arial;">单击</span> Magento 购物车链接后，您将触发一个迷你购物车。与购物车链接相同，它在目录的每一页上都可用。因此，客户可以快速查看他们已经添加到购物车的内容，而不管他们在哪个页面上。</span><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/4_2.png" width="800" /></p>
<p class="p"><span style="font-family: Arial;">要在</span> Magento 中设置迷你购物车，您只需在<strong>&nbsp;</strong>Mini Cart&nbsp;部分配置三个选项：</p>
<ul>
<li><span style="font-family: Arial;">设备是否在</span>&nbsp;&nbsp;Display Mini Cart&nbsp;&nbsp;字段中启用或禁用迷你车。</li>
<li><span style="font-family: Arial;">输入</span>&nbsp;Number of Items to Display Scrollbar<span style="font-family: Arial;">，</span><strong>&nbsp;</strong>该滚动条定义了客户在启用滚动之前必须添加的项目数。</li>
<li><span style="font-family: Arial;">设置</span>&nbsp;要&nbsp;在迷你购物车中显示&nbsp;的最近添加&nbsp;项目的最大数量&nbsp;Maximum Number&nbsp;of recently added&nbsp;Items to Display<strong>。</strong></li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/5.png" width="800" /></p>
<h2><strong><span>3.设置重定向到购物车</span></strong><strong><span></span></strong></h2>
<p class="p"><span>有关添加到购物车的产品的所有信息都已在迷你购物车中。相应地，在客户将任何产品添加到购物车后，不需要将他们重定向到购物车页面。默认情况下，重定向是禁用的。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">您可以让您的客户选择随时访问购物车摘要页面。这样结帐看起来并不强制。</span>&nbsp;</span><span></span></p>
<p class="p">但是，您可以选择您喜欢的任何选项。转到<span class="15">购物车</span>部分并启用或禁用<span class="15">将产品重定向到购物车后</span><span>&nbsp;选项</span><span class="15">After Adding a Product Redirect to Shopping Cart</span><span>&nbsp;。</span><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/6.png" width="800" /></p>
<h2><strong><span>4. 定义报价生命周期</span></strong><strong><span></span></strong></h2>
<p class="p"><span>有时，顾客离开购物车的时间过长，以后仍然会回来购买。然而，在此期间产品的价格可能会发生变化。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">相应地，</span></span><span class="15">报价有效期（天）</span><span class="15">Quote Lifetime (days)</span><span>&nbsp;选项定义了报价有效的天数。</span><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/7.png" width="800" /></p>
<h2><strong><span>5.配置购物车缩略图</span></strong><strong><span></span></strong></h2>
<p class="p"><span><span style="font-family: Arial;">缩略图可帮助您的客户了解他们已经添加到购物车的产品。通常，它们与客户添加的产品相匹配。但是，当产品有变体时，购物车中的缩略图可能与添加到购物车的产品不匹配。</span>&nbsp;</span><span></span></p>
<p class="p"><span>对于可配置和分组的产品，图像与产品变体或父产品图像相匹配。</span><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/8.png" width="800" /></p>
<p class="p"><span style="font-family: Arial;">因此，您可以设置</span>&nbsp;Grouped&nbsp;&nbsp;and&nbsp;&nbsp;Configurable Product Images<span style="font-family: Arial;">。</span>&nbsp;</p>
<ul>
<li>产品缩略图本身&nbsp;Product Thumbnail Itself&mdash; 使用客户添加到购物车的产品缩略图。</li>
<li>父产品缩略图&nbsp;Parent Product Thumbnail&mdash; 使用父产品的缩略图。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/9.png" width="800" /></p>
<h2><strong><span>6. 指定最小订购数量</span></strong><strong><span></span></strong></h2>
<p class="p">如果您想鼓励更多购买或仅向某些客户群体出售特定数量，您可以配置<span class="15">购物车中允许的最小数量</span><span class="15">Minimum</span><span class="15"> Qty Allowed in Shopping Cart</span><span>.。&nbsp;</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">转到</span>&nbsp;</span><span class="15">Stores &gt; Configuration &gt; Catalog &gt; Inventory &gt; Product Stock Options</span><span>&nbsp;进行设置。</span><span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/10.png" width="800" /></p>
<p class="p">然后，根据您的配置，不同组的客户将看到他们需要选择的数量以将商品添加到购物车。</p>
<h2><strong>7.配置最低订单金额</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">与</span> Magento 中的购物车相关的另一个鼓励购买的选项是最低订购量。根据它，客户必须满足一定的小计才能结帐。否则，结帐按钮根本不可用。&nbsp;</p>
<p class="p">此外，您还可以要求将订单运送到多个地址，以满足每个地址的最低订单金额。</p>
<p class="p"><span style="font-family: Arial;">要配置最小订单量，请转到</span>&nbsp;Stores &gt; Configuration &gt; Sales &gt; Sales &gt; Minimum Order Amount<strong>&nbsp;</strong>并设置以下选项：</p>
<ul>
<li>启用&nbsp;最低订单金额。</li>
<li><span style="font-family: Arial;">应用折扣后输入小计的</span>&nbsp;Minimum&nbsp;Amount。</li>
<li><span style="font-family: Arial;">决定是否将</span>&nbsp;折扣金额&nbsp;Include Discount Amount&nbsp;计入最低金额。</li>
</ul>
<p class="p"><span style="font-family: Arial;">如果您选择</span>是<span style="font-family: Arial;">Yes</span><span style="font-family: Arial;">，则订单将满足应用折扣的最低要求。即使应用了折扣，也没有客户必须达到最低订单金额</span>&nbsp;<strong>。</strong><strong></strong></p>
<ul>
<li><span style="font-family: Arial;">选择最低订单金额是否应</span>&nbsp;包括税额Include Tax to Amount。</li>
<li><span style="font-family: Arial;">配置</span>&nbsp;客户在购物车中看到的不符合要求的最小订单数量&nbsp;的描述消息Description Message，以及在购物车中显示的错误Error to Show in Shopping Cart，以防有任何错误。</li>
<li>如果您想要求每个地址的最低订单量，请启用&nbsp;Validate Each Address Separately in Multi-address Checkout在多地址结帐中分别验证每个地址<strong>。</strong></li>
<li><span style="font-family: Arial;">设置</span>&nbsp;多地址描述消息Multi-address Description Message&nbsp;和&nbsp;多地址错误以显示在购物车Multi-address Error to Show in Shopping Cart中。</li>
</ul>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/11.png" width="800" /></p>
<h2><strong><span>8. 设置礼物选项</span></strong><strong><span></span></strong></h2>
<p class="p"><span><span style="font-family: Arial;">由于</span> Magento 购物车是结账前的最后一步，因此客户可以在此阶段留下礼物信息是有道理的。无论客户在什么场合下订单，礼品信息都能提供个性化的体验并给人留下深刻印象。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/12.png" width="800" /></span></p>
<h2><strong><span>9.检查购物车规则</span></strong><strong><span></span></strong></h2>
<p class="p">最后但并非最不重要的是您配置的<span class="15">Magento</span><span class="15"> 购物车价</span><span class="15">格规则</span>以提供折扣。购物车价格规则允许您设置某些条件并提供客户可以在购物车或结账时应用的优惠券。<span></span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/13.png" width="800" /></p>]]></description>
      <pubDate>Fri, 26 Aug 2022 08:24:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中启用模板路径提示]]></title>
      <link>https://www.360magento.com/blog/Enable-template-path-prompt-in-Magento-2/</link>
      <description><![CDATA[<p class="p"><span>Magento 2 中的模板路径提示是帮助您定义 .&nbsp;</span><span class="15">ph</span><span class="15">p</span><span class="15"> 块类</span>或<span class="15">.phtml</span><span class="15"> 模板</span><span><span style="font-family: Arial;">，对应于</span> Magento 2 商店的特定页面区域。换句话说，模板路径提示为每个模板的路径添加了一个符号，以帮助您更轻松地找到 .phtml 文件并相应地更快地编辑它们。您可以在前端和管理员的 Magento 文件结构中找到代码。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">因此，让我们找出可以启用</span> Magento 2 模板路径提示的方法。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/1_2.png" width="800" /></span></p>
<h2>从管理面板启用模板路径提示<strong></strong></h2>
<p class="p"><span style="font-family: Arial;">为了在</span> Magento 2 中启用模板路径提示，请按照下列步骤操作：</p>
<ol>
<li><span style="font-family: Arial;">确保您的</span> Magento 2 处于<span style="font-family: Arial;">默认模式或开发者模式</span><span style="font-family: Arial;"></span><span style="font-family: Arial;"></span>。</li>
<li>转到Admin Panel &gt; Stores &gt; Settings &gt; Configuration &gt;&nbsp;Advanced &gt; Developer &gt; Debug</li>
</ol>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/2_1.png" width="800" /></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 3. 检查并配置开发者客户端限制Developer Client Restrictions。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/3_1.png" width="800" /></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 4.&nbsp;启用<span class="15">模板路径提示</span>。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 选择是否要为<span class="15">StoreFront</span>或<span class="15">Admin</span><span style="font-family: Arial;">启用它。如果您希望模板路径提示在</span> PHTML 模板文件路径之外显示块 PHP 类名&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 称，请在<span class="15">Add</span><span class="15"> Blo</span><span class="15">ck</span><span class="15"> Names to Hints</span><span style="font-family: Arial;">选择框中选择</span> Yes 。</p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/4_1.png" width="800" /></span></p>
<p class="p"></p>
<p class="p">&nbsp; &nbsp; &nbsp; &nbsp; 5.&nbsp;<span style="font-family: Arial;">完成后不要忘记按</span>保存配置按钮。</p>
<h2><strong><span>使用命令行界面启用模板路径提示</span></strong><strong><span></span></strong></h2>
<p class="p"><span class="15">注意：</span><span><span style="font-family: Arial;">与以前的方法不同，使用</span> CLI 您只能为 Magento 2 店面启用或禁用模板路径提示。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">要在</span> Magento 2 中启用模板路径提示，请运行以下命令：</span><span></span></p>
<p class="p"><span>php bin/magento dev:template-hints:enable</span><span></span></p>
<p class="p"><span>要禁用模板路径提示，请使用以下命令：</span><span></span></p>
<p class="p"><span>php bin/magento dev:template-hints:disable</span><span></span></p>
<p class="p"></p>]]></description>
      <pubDate>Thu, 25 Aug 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[配置 Magento 2 结帐选项]]></title>
      <link>https://www.360magento.com/blog/Configure-Magento2-checkout-options/</link>
      <description><![CDATA[<p class="p"><span style="font-family: Arial;">客户登陆</span> Magento 结账页面，他们希望能够快速轻松地完成下单流程。因此，您的工作是处理定义结帐页面和布局属性的 Magento 结帐选项。&nbsp;</p>
<p class="p"><span style="font-family: Arial;">如您所见，</span>Magento 结帐页面配置相对简单。</p>
<p class="p"><span style="font-family: Arial;">要配置</span> Magento 结帐选项：</p>
<p class="p">1. 导航到Stores &gt; Configuration &gt; Sales &gt; Checkout &gt; Checkout Options</p>
<p>2.<span style="font-family: Arial;">启用</span> Onepage Checkout作为默认格式。</p>
<p class="p">3.允许或禁止<span style="font-family: Arial;">访客结帐</span>以定义客户是否能够在未注册的情况下进行结帐。</p>
<p class="p">注意：如果您愿意，您仍然可以在结帐后将<span style="font-family: Arial;">客人订单转换为客户<a href="https://magefan.com/blog/magento2-convert-guest-to-customer" title="在 Magento 2 中将访客结账客户转换为注册客户"></a></span>以进行营销。</p>
<p class="p">4. Enable Terms and Conditions.启用条款和条件。</p>
<p class="p">5. Display Billing Addresses.决定在哪里显示帐单地址<span style="font-family: Arial;">。</span>&nbsp;</p>
<p class="p">6. Maximum Number of Items to Display in Order Summary.设置在订单汇总中显示的最大项目数。</p>
<p class="p"><img src="https://www.360magento.com/media/wysiwyg/blog_84/1_1.png" width="800" /></p>
<p>不要忘记保存配置并转到结帐页面以检查您刚刚配置的选项。</p>
<p><textarea id="BFI_DATA" style="width: 1px; height: 1px; display: none;"></textarea></p>
<div class="LTRStyle" id="WidgetFloaterPanels" style="display: none; text-align: left; direction: ltr; visibility: hidden;">
<div id="WidgetFloater" onmouseout="Microsoft.Translator.OnMouseOutFloater()" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;">
<div id="WidgetLogoPanel"><span id="WidgetTranslateWithSpan"><span>TRANSLATE with </span><img id="FloaterLogo" /></span> <span id="WidgetCloseButton" onclick="Microsoft.Translator.FloaterOnClose()" title="Exit Translation">x</span></div>
<div id="LanguageMenuPanel">
<div class="DDStyle_outer"><input id="LanguageMenu_svid" name="LanguageMenu_svid" onclick="this.select()" style="display: none;" type="text" value="en" /> <input id="LanguageMenu_textid" name="LanguageMenu_textid" onclick="this.select()" style="display: none;" type="text" /> <span class="DDStyle" id="__LanguageMenu_header" onclick="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);" onkeydown="return LanguageMenu &amp;&amp; !LanguageMenu.Show('__LanguageMenu_popup', event);">English</span>
<div style="position: relative; text-align: left; left: 0;">
<div style="position: absolute; ;left: 0px;">
<div class="DDStyle" id="__LanguageMenu_popup" style="display: none;">
<table border="0" id="LanguageMenu">
<tbody>
<tr>
<td><a href="#ar" onclick="return LanguageMenu.onclick('ar');" tabindex="-1">Arabic</a></td>
<td><a href="#he" onclick="return LanguageMenu.onclick('he');" tabindex="-1">Hebrew</a></td>
<td><a href="#pl" onclick="return LanguageMenu.onclick('pl');" tabindex="-1">Polish</a></td>
</tr>
<tr>
<td><a href="#bg" onclick="return LanguageMenu.onclick('bg');" tabindex="-1">Bulgarian</a></td>
<td><a href="#hi" onclick="return LanguageMenu.onclick('hi');" tabindex="-1">Hindi</a></td>
<td><a href="#pt" onclick="return LanguageMenu.onclick('pt');" tabindex="-1">Portuguese</a></td>
</tr>
<tr>
<td><a href="#ca" onclick="return LanguageMenu.onclick('ca');" tabindex="-1">Catalan</a></td>
<td><a href="#mww" onclick="return LanguageMenu.onclick('mww');" tabindex="-1">Hmong Daw</a></td>
<td><a href="#ro" onclick="return LanguageMenu.onclick('ro');" tabindex="-1">Romanian</a></td>
</tr>
<tr>
<td><a href="#zh-CHS" onclick="return LanguageMenu.onclick('zh-CHS');" tabindex="-1">Chinese Simplified</a></td>
<td><a href="#hu" onclick="return LanguageMenu.onclick('hu');" tabindex="-1">Hungarian</a></td>
<td><a href="#ru" onclick="return LanguageMenu.onclick('ru');" tabindex="-1">Russian</a></td>
</tr>
<tr>
<td><a href="#zh-CHT" onclick="return LanguageMenu.onclick('zh-CHT');" tabindex="-1">Chinese Traditional</a></td>
<td><a href="#id" onclick="return LanguageMenu.onclick('id');" tabindex="-1">Indonesian</a></td>
<td><a href="#sk" onclick="return LanguageMenu.onclick('sk');" tabindex="-1">Slovak</a></td>
</tr>
<tr>
<td><a href="#cs" onclick="return LanguageMenu.onclick('cs');" tabindex="-1">Czech</a></td>
<td><a href="#it" onclick="return LanguageMenu.onclick('it');" tabindex="-1">Italian</a></td>
<td><a href="#sl" onclick="return LanguageMenu.onclick('sl');" tabindex="-1">Slovenian</a></td>
</tr>
<tr>
<td><a href="#da" onclick="return LanguageMenu.onclick('da');" tabindex="-1">Danish</a></td>
<td><a href="#ja" onclick="return LanguageMenu.onclick('ja');" tabindex="-1">Japanese</a></td>
<td><a href="#es" onclick="return LanguageMenu.onclick('es');" tabindex="-1">Spanish</a></td>
</tr>
<tr>
<td><a href="#nl" onclick="return LanguageMenu.onclick('nl');" tabindex="-1">Dutch</a></td>
<td><a href="#tlh" onclick="return LanguageMenu.onclick('tlh');" tabindex="-1">Klingon</a></td>
<td><a href="#sv" onclick="return LanguageMenu.onclick('sv');" tabindex="-1">Swedish</a></td>
</tr>
<tr>
<td><a href="#en" onclick="return LanguageMenu.onclick('en');" tabindex="-1">English</a></td>
<td><a href="#ko" onclick="return LanguageMenu.onclick('ko');" tabindex="-1">Korean</a></td>
<td><a href="#th" onclick="return LanguageMenu.onclick('th');" tabindex="-1">Thai</a></td>
</tr>
<tr>
<td><a href="#et" onclick="return LanguageMenu.onclick('et');" tabindex="-1">Estonian</a></td>
<td><a href="#lv" onclick="return LanguageMenu.onclick('lv');" tabindex="-1">Latvian</a></td>
<td><a href="#tr" onclick="return LanguageMenu.onclick('tr');" tabindex="-1">Turkish</a></td>
</tr>
<tr>
<td><a href="#fi" onclick="return LanguageMenu.onclick('fi');" tabindex="-1">Finnish</a></td>
<td><a href="#lt" onclick="return LanguageMenu.onclick('lt');" tabindex="-1">Lithuanian</a></td>
<td><a href="#uk" onclick="return LanguageMenu.onclick('uk');" tabindex="-1">Ukrainian</a></td>
</tr>
<tr>
<td><a href="#fr" onclick="return LanguageMenu.onclick('fr');" tabindex="-1">French</a></td>
<td><a href="#ms" onclick="return LanguageMenu.onclick('ms');" tabindex="-1">Malay</a></td>
<td><a href="#ur" onclick="return LanguageMenu.onclick('ur');" tabindex="-1">Urdu</a></td>
</tr>
<tr>
<td><a href="#de" onclick="return LanguageMenu.onclick('de');" tabindex="-1">German</a></td>
<td><a href="#mt" onclick="return LanguageMenu.onclick('mt');" tabindex="-1">Maltese</a></td>
<td><a href="#vi" onclick="return LanguageMenu.onclick('vi');" tabindex="-1">Vietnamese</a></td>
</tr>
<tr>
<td><a href="#el" onclick="return LanguageMenu.onclick('el');" tabindex="-1">Greek</a></td>
<td><a href="#no" onclick="return LanguageMenu.onclick('no');" tabindex="-1">Norwegian</a></td>
<td><a href="#cy" onclick="return LanguageMenu.onclick('cy');" tabindex="-1">Welsh</a></td>
</tr>
<tr>
<td><a href="#ht" onclick="return LanguageMenu.onclick('ht');" tabindex="-1">Haitian Creole</a></td>
<td><a href="#fa" onclick="return LanguageMenu.onclick('fa');" tabindex="-1">Persian</a></td>
<td></td>
</tr>
</tbody>
</table>
<img alt="" style="height: 7px; width: 17px; border-width: 0px; left: 20px;" /></div>
</div>
</div>
</div>
<script type="text/javascript">// <![CDATA[
 var LanguageMenu; var LanguageMenu_keys=["ar","bg","ca","zh-CHS","zh-CHT","cs","da","nl","en","et","fi","fr","de","el","ht","he","hi","mww","hu","id","it","ja","tlh","ko","lv","lt","ms","mt","no","fa","pl","pt","ro","ru","sk","sl","es","sv","th","tr","uk","ur","vi","cy"]; var LanguageMenu_values=["Arabic","Bulgarian","Catalan","Chinese Simplified","Chinese Traditional","Czech","Danish","Dutch","English","Estonian","Finnish","French","German","Greek","Haitian Creole","Hebrew","Hindi","Hmong Daw","Hungarian","Indonesian","Italian","Japanese","Klingon","Korean","Latvian","Lithuanian","Malay","Maltese","Norwegian","Persian","Polish","Portuguese","Romanian","Russian","Slovak","Slovenian","Spanish","Swedish","Thai","Turkish","Ukrainian","Urdu","Vietnamese","Welsh"]; var LanguageMenu_callback=function(){ }; var LanguageMenu_popupid='__LanguageMenu_popup'; 
// ]]]]><![CDATA[></script>
</div>
<div id="CTFLinksPanel"><span id="ExternalLinksPanel"><a href="https://go.microsoft.com/?linkid=9722454" id="HelpLink" title="Help" target="_blank"> <img id="HelpImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowEmbed()" id="EmbedLink" title="Get this widget for your own site"> <img id="EmbedImg" /></a> <a href="javascript:Microsoft.Translator.FloaterShowSharePanel()" id="ShareLink" title="Share translated page with friends"> <img id="ShareImg" /></a> </span></div>
<div id="FloaterProgressBar"><span id="ProgressFill"></span></div>
</div>
<div id="WidgetFloaterCollapsed" onmouseover="Microsoft.Translator.OnMouseOverFloater()" style="display: none;"><span>TRANSLATE with </span><img id="CollapsedLogoImg" /></div>
<div id="FloaterSharePanel" style="display: none;">
<div id="ShareTextDiv"><span id="ShareTextSpan"> COPY THE URL BELOW </span></div>
<div id="ShareTextboxDiv"><input id="ShareTextbox" name="ShareTextbox" onclick="this.select()" readonly="readonly" type="text" /> <!--a id="TwitterLink" title="Share on Twitter"> <img id="TwitterImg" /></a> <a-- id="FacebookLink" title="Share on Facebook"> <img id="FacebookImg" /></a--> <a id="EmailLink" title="Email this translation"></a> <img id="EmailImg" /></div>
<div id="ShareFooter"><span id="ShareHelpSpan"><a id="ShareHelpLink"></a> <img id="ShareHelpImg" /></span> <span id="ShareBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnShareBackClick()" id="ShareBack" title="Back To Translation"> Back</a></span></div>
<input id="EmailSubject" name="EmailSubject" type="hidden" value="Check out this page in {0} translated from {1}" /> <input id="EmailBody" name="EmailBody" type="hidden" value="Translated: {0}%0d%0aOriginal: {1}%0d%0a%0d%0aAutomatic translation powered by Microsoft&reg; Translator%0d%0ahttp://www.bing.com/translator?ref=MSTWidget" /> <input id="ShareHelpText" type="hidden" value="This link allows visitors to launch this page and automatically translate it to {0}." /></div>
<div id="FloaterEmbed" style="display: none;">
<div id="EmbedTextDiv"><span id="EmbedTextSpan">EMBED THE SNIPPET BELOW IN YOUR SITE</span> <a id="EmbedHelpLink" title="Copy this code and place it into your HTML."></a> <img id="EmbedHelpImg" /></div>
<div id="EmbedTextboxDiv"><input id="EmbedSnippetTextBox" name="EmbedSnippetTextBox" onclick="this.select()" readonly="readonly" type="text" value="&lt;div id='MicrosoftTranslatorWidget' class='Dark' style='color:white;background-color:#555555'&gt;&lt;/div&gt;&lt;script type='text/javascript'&gt;setTimeout(function(){var s=document.createElement('script');s.type='text/javascript';s.charset='UTF-8';s.src=((location &amp;&amp; location.href &amp;&amp; location.href.indexOf('https') == 0)?'https://ssl.microsofttranslator.com':'http://www.microsofttranslator.com')+'/ajax/v3/WidgetV3.ashx?siteData=ueOIGRSKkd965FeEGM5JtQ**&amp;ctf=true&amp;ui=true&amp;settings=manual&amp;from=en';var p=document.getElementsByTagName('head')[0]||document.documentElement;p.insertBefore(s,p.firstChild); },0);&lt;/script&gt;" /></div>
<div id="EmbedNoticeDiv"><span id="EmbedNoticeSpan">Enable collaborative features and customize widget: <a href="http://www.bing.com/widget/translator" target="_blank">Bing Webmaster Portal</a></span></div>
<div id="EmbedFooterDiv"><span id="EmbedBackSpan"><a href="javascript:Microsoft.Translator.FloaterOnEmbedBackClick()" title="Back To Translation">Back</a></span></div>
</div>
<script type="text/javascript">// <![CDATA[
 var intervalId = setInterval(function () { if (MtPopUpList) { LanguageMenu = new MtPopUpList(); var langMenu = document.getElementById(LanguageMenu_popupid); var origLangDiv = document.createElement("div"); origLangDiv.id = "OriginalLanguageDiv"; origLangDiv.innerHTML = "<span id='OriginalTextSpan'>ORIGINAL: </span><span id='OriginalLanguageSpan'></span>"; langMenu.appendChild(origLangDiv); LanguageMenu.Init('LanguageMenu', LanguageMenu_keys, LanguageMenu_values, LanguageMenu_callback, LanguageMenu_popupid); window["LanguageMenu"] = LanguageMenu; clearInterval(intervalId); } }, 1); 
// ]]]]><![CDATA[></script>
</div>]]></description>
      <pubDate>Wed, 24 Aug 2022 08:25:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 图像优化的 3 个技巧]]></title>
      <link>https://www.360magento.com/blog/Magento2-3-tips-for-image-optimization/</link>
      <description><![CDATA[<h2><strong><span><span style="font-family: Arial;">技巧</span> 1 - WebP 图片</span></strong><strong><span></span></strong></h2>
<p class="p"><span>PNG 和 JPG 图像格式已过时且尺寸较大。它使它们加载时间更长，并相应地降低您的网站性能。幸运的是，谷歌开发了 WebP&mdash;&mdash;大多数浏览器普遍接受的下一代文件格式。</span><span></span></p>
<p class="p"><span>查看完整指南以了解有关</span><span class="15">Magento 2 中 WebP 图像的</span><span><span style="font-family: Arial;">更多信息、它们与</span> PNG 和 JPG 格式的区别、在您的商店中使用它们的好处和原因。</span><span></span></p>
<p class="p">对于您的网站图像优化，您可以选择<span class="15">Ma</span><span class="15">gento</span><span class="15"> 2</span><span class="15"> We</span><span class="15">bP</span><span class="15"> 图像</span><span><span style="font-family: Arial;">扩展，它可以帮助您将网站上所有当前和未来的图像自动转换为</span> WebP 格式。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">这个</span> Magento 图像优化扩展允许您将图像的大小减少多达 50% 并同时保存它们的质量。真的很难看出区别。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/1.png" width="800" /></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/2.png" width="800" /></span></p>
<p class="p"><span><span style="font-family: Arial;">如果您仔细阅读本文，您可能想知道如果有人从不支持新</span> WebP 格式的旧浏览器进入您的 Magento 2 网站会发生什么。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">由于此</span> Magento 2 图像优化扩展不会将您的 PNG 和 JPG 图像替换为 WEBP 图像，因此它已得到处理。它只是制作他们的副本。因此，那些来自尚未与 WebP 集成的浏览器的人将看到您的原始图像为 PNG 和 JPG 格式。</span><span></span></p>
<p class="p"><strong><em><span class="15"><span style="font-family: Arial;">专业提示：如果您可以使用一些在线转换器将您的图像转换为</span> WebP 并将它们上传到您的网站，为什么还需要 Magento 2 WebP 图像扩展？</span></em></strong><span></span></p>
<p class="p"><span><span style="font-family: Arial;">并不是所有的浏览器都支持</span> WebP（你现在可能已经理解了）。如果您上传已转换的图像，来自&ldquo;非 webp&rdquo;浏览器的人会看到损坏的图像。这个图像优化工具不仅可以帮助您通过快速执行的网站满足所有客户的需求，而且无论使用何种浏览器，都可以向他们展示所有高质量的图片。</span><span></span></p>
<h2><strong><span><span style="font-family: Arial;">提示</span> 2 - 手动图像优化</span></strong><strong><span></span></strong></h2>
<p class="p"><span>这可能是优化您网站上的图像的最简单和最常用的方法。</span><a href="https://imagecompressor.com/" title="在线图像优化器"><span style="text-decoration: underline;"><span class="15">Optimizilla</span></span></a><span>&nbsp;- 是一个完全免费的在线图像优化器，可帮助您将图像的大小减小到可能的最小尺寸。&nbsp;</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">您需要做的就是上传最多</span> 20 张图像，然后等待几秒钟让图像优化器压缩它们。然后，您将能够单独下载每个图像或整个图像包。</span><span></span></p>
<p class="p"><span>Optimizilla 还允许您做的是调节颜色并比较原始图像和压缩图像的质量。</span><span></span></p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/3.png" width="800" /></span></p>
<p><span style="font-family: Arial;">我们强烈建议您在将图像上传到所见即所得编辑器之前使用</span> Optimizilla 压缩图像，以尽可能减少页面大小和加载时间</p>
<h2><strong><span style="font-family: Arial;">技巧</span> 3 - 图片延迟加载</strong><strong></strong></h2>
<p class="p"><span style="font-family: Arial;">一旦您尝试了上面提到的</span> Magento 2 图像优化工具，您的网站性能应该会显着提高。但是，还有另一种方法可以确保快速网页加载 -<span style="font-family: Arial;">延迟加载</span><span style="font-family: Arial;">。</span>&nbsp;</p>
<p class="p">当有人进入一个包含大量图片的页面时，他们通常会立即开始加载。这就是加载速度变慢的原因。您可以使用Magento 2 Image Lazy Load扩展，在向下滚动时将加载哪些图像。</p>
<p class="p">Image Lazy Load 模块与 Magento 2 WebP 图片扩展完全兼容。因此，除了减小图像大小外，您还可以逐步提高网站加载图像的性能。</p>
<p class="p"><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/4.png" width="800" /></span></p>
<p><span style="font-family: Arial;">总而言之，</span>Magento 2 图像优化实际上是您开始优化网站速度所需的第一件事。无论您的产品多么棒，或者您创造了多么令人惊叹的内容。如果您的网站需要大量时间来加载，人们就不会发现它。</p>]]></description>
      <pubDate>Tue, 23 Aug 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在产品页面 Magento 2 中添加自定义选项卡]]></title>
      <link>https://www.360magento.com/blog/How-to-Add-Custom-Tab-in-Product-Page-Magento2/</link>
      <description><![CDATA[<p><span>在 Magento 2 的产品页面中添加自定义选项卡的 5 个步骤：</span></p>
<ul>
<li>第 1 步：定义模板和布局文件</li>
<li>第 2 步：重命名产品选项卡</li>
<li>第 3 步：删除产​​品标签</li>
<li>第 4 步：添加自定义选项卡</li>
<li>第 5 步：在标签式导航中添加相关产品</li>
</ul>
<h2 id="step-1"><span>第 1 步：定义模板和布局文件</span></h2>
<p><span><span>首先，您需要定义要自定义的模板和布局文件。</span><span>一种可以帮助您做到这一点的有效方法是通过 Magento 管理员启用</span><span>和</span><span>添加</span></span><code class="language-plaintext highlighter-rouge">Template Path Hints</code><span><span>。</span><span></span><span>现在，您将看到负责产品信息选项卡的 Magento 模块，</span><span>&nbsp;</span><span>您现在可以开始自定义。</span></span><code class="language-plaintext highlighter-rouge">Block Names</code><span></span><code class="language-plaintext highlighter-rouge">Hints</code><span></span><code class="language-plaintext highlighter-rouge">Stores &gt; Configuration &gt; Advanced &gt; Developer &gt; Debug</code><span></span><code class="language-plaintext highlighter-rouge">module-catalog</code><span></span></p>
<h2 class="active" id="step-2"><span>第 2 步：重命名产品选项卡</span></h2>
<p><span>在为产品选项卡设置另一个标题之前，您需要覆盖</span><code class="language-plaintext highlighter-rouge">catalog_product_view.xml</code><span>可以在</span><code class="language-plaintext highlighter-rouge">vendor/module_catalog</code><span><span>文件夹中找到的基本布局文件。</span><span>覆盖这个文件的标准方法是在你的主题范围内创建一个新的布局文件，然后像基本文件一样命名它。</span><span>以下是您的文件路径的样子：&nbsp;</span></span><code class="language-plaintext highlighter-rouge">app/design/frontend/&lt;Mageplaza&gt;/&lt;Theme&gt;/Magento_Catalog/layout/catalog_product_view.xml</code></p>
<p><span>这是文件内的代码：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?xml version="1.0"?&gt;
&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";; xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;body&gt;
    &lt;referenceBlock name="product.info.details"&gt;                
      &lt;referenceBlock name="product.info.description"&gt;
        &lt;arguments&gt;
          &lt;argument name="title" translate="true" xsi:type="string"&gt;Description&lt;/argument&gt;
        &lt;/arguments&gt;
      &lt;/referenceBlock&gt;
    &lt;/referenceBlock&gt;
  &lt;/body&gt;
&lt;/page&gt;
</code></pre>
</div>
</div>
<p><span>在上面的代码中，第一个布局处理程序</span><code class="language-plaintext highlighter-rouge">&lt;referenceBlock name="product.info.details"&gt;</code><span><span>用于整体引用您的产品选项卡式导航。</span><span>同时，子处理程序</span></span><code class="language-plaintext highlighter-rouge">&lt;referenceBlock name="product.info.description"&gt;</code><span>引用单个选项卡，在此示例中是您的案例详细信息选项卡。</span></p>
<p><span>通过使用</span><code class="language-plaintext highlighter-rouge">&lt;argument name="title" translate="true" xsi:type="string"&gt;</code><span><span>，您可以为标签设置新标题。</span><span>请注意，处理程序</span></span><code class="language-plaintext highlighter-rouge">&lt;arguments&gt;</code><span>只是一个容器</span><code class="language-plaintext highlighter-rouge">&lt;argument&gt;</code><span>，它没有自己的属性。</span></p>
<h2 class="active" id="step-3"><span>第 3 步：删除产​​品标签</span></h2>
<p><span><span>删除产品标签是一项非常简单的任务。</span><span>您只需要引用您的目标块并将 remove 属性设置为 true。</span></span></p>
<p><span>波纹管是</span><code class="language-plaintext highlighter-rouge">the catalog_product_view.xml</code><span>：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?xml version="1.0"?&gt;
&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";; xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;body&gt;
    &lt;referenceBlock name="product.info.review" remove="true" /&gt;
  &lt;/body&gt;
&lt;/page&gt;
</code></pre>
</div>
</div>
<h2 class="active" id="step-4"><span>第 4 步：添加自定义选项卡</span></h2>
<p><span><span>波纹管是您可以向产品页面添加自定义选项卡的方式：首先，转到 Magento 管理员并创建一个新属性。</span><span>然后，为其命名并将其</span></span><code class="language-plaintext highlighter-rouge">Packaging</code><span>添加到</span><code class="language-plaintext highlighter-rouge">default</code><span>属性集。</span></p>
<p><span><span>完成上述步骤后，您需要创建一个新的模板文件。</span><span>该文件可以命名为</span></span><code class="language-plaintext highlighter-rouge">packaging-content.phtml</code><span>并保存在</span><code class="language-plaintext highlighter-rouge">app/design/frontend/&lt;Magplaza&gt;/&lt;Theme&gt;/Magento_Catalog/templates/product/view/</code><span>.</span></p>
<p><span>接下来，将此代码粘贴到文件中：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?php
$_helper = $this-&gt;helper('Magento\Catalog\Helper\Output');
$_product = $block-&gt;getProduct();
$_code = $block-&gt;getAtCode();
$_className = $block-&gt;getCssClass();
$_attributeLabel = $block-&gt;getAtLabel();
$_attributeType = $block-&gt;getAtType();
$_attributeAddAttribute = $block-&gt;getAddAttribute();
if ($_attributeLabel &amp;&amp; $_attributeLabel == 'default') {
    $_attributeLabel = $_product-&gt;getResource()-&gt;getAttribute($_code)-&gt;getFrontendLabel();
}
  $_attributeValue = $_product-&gt;getResource()-&gt;getAttribute($_code)-&gt;getFrontend()-&gt;getValue($_product);
?&gt;
 
&lt;?php if ($_attributeValue): ?&gt;
    &lt;div class="packaging-content" &lt;?php  echo $_attributeAddAttribute;?&gt;&gt;
        &lt;?php echo $_attributeValue; ?&gt;
    &lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
</div>
</div>
<p><span>确保 NB 属性集与 if 语句中第 9 行的字符串值匹配。</span></p>
<p><span>最后，将以下代码放入您的布局文件中</span><code class="language-plaintext highlighter-rouge">catalog_product_view.xml</code><span>：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?xml version="1.0"?&gt;
&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";; xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;body&gt;
    &lt;referenceBlock name="product.info.details"&gt;                
      &lt;block class="Magento\Catalog\Block\Product\View\Description" name="packaging-content" template="Magento_Catalog::product/view/packaging-content.phtml" group="detailed_info"&gt;
        &lt;arguments&gt;
          &lt;argument name="at_call" xsi:type="string"&gt;getPackaging&lt;/argument&gt;
          &lt;argument name="at_code" xsi:type="string"&gt;packaging&lt;/argument&gt;
          &lt;argument name="css_class" xsi:type="string"&gt;packaging&lt;/argument&gt;
          &lt;argument name="at_label" xsi:type="string&rdquo;&gt;packaging&lt;/argument&gt;
          &lt;argument name="add_attribute" xsi:type="string"&gt;itemprop="packaging"&lt;/argument&gt;
          &lt;argument name="title" translate="true" xsi:type="string"&gt;Packaging content&lt;/argument&gt;
        &lt;/arguments&gt;
      &lt;/block&gt;
    &lt;/referenceBlock&gt;
  &lt;/body&gt;
&lt;/page&gt;
</code></pre>
</div>
</div>
<h2 class="active" id="step-5"><span>第 5 步：在标签式导航中添加相关产品</span></h2>
<p><span>为了在选项卡式导航中添加相关产品，您需要编辑两个文件，即模板和布局。</span></p>
<p><span>使用模板文件，将其命名为</span><code class="language-plaintext highlighter-rouge">related-products.phtml</code><span>并保存为</span><code class="language-plaintext highlighter-rouge">app/design/frontend/&lt;Mageplaza&gt;/&lt;Theme&gt;/Magento_Catalog/templates/product/</code><span><span>.&nbsp;</span><span>该文件将只有一个代码行：</span></span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?php echo $this-&gt;getBlockHtml('catalog.product.related'); ?&gt;
</code></pre>
</div>
</div>
<p><span>命名的布局文件</span><code class="language-plaintext highlighter-rouge">catalog_product_view.xml</code><span>如下所示：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?xml version="1.0"?&gt;
&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";; xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
  &lt;body&gt;
    &lt;!&mdash; 1st Code Block: Get Related Products as new tab --&gt;
    &lt;referenceBlock name="product.info.details"&gt;
      &lt;block class="Magento\Catalog\Block\Product\View" name="deliveryinfo.tab" as="deliveryinfo" template="Magento_Catalog::product/related-products.phtml" group="detailed_info" &gt;
        &lt;arguments&gt;
          &lt;argument translate="true" name="title" xsi:type="string"&gt;Related Products&lt;/argument&gt;
        &lt;/arguments&gt;
      &lt;/block&gt;
    &lt;/referenceBlock&gt;
 
    &lt;!&mdash; 2nd Code Block: Move original block to product info tabs --&gt;
    &lt;move element="catalog.product.related" destination="product.info.details" /&gt;
  &lt;/body&gt;
&lt;/page&gt;
</code></pre>
</div>
</div>
<p><span><span>第一个代码用于设置包含相关产品的新选项卡。</span><span>第二个代码用于将您的</span></span><code class="language-plaintext highlighter-rouge">upsell-products.phtml</code><span>模板文件更改为：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?php echo $this-&gt;getBlockHtml('product.info.upsell'); ?&gt;</code></pre>
<p><span>以下是您需要在布局文件中进行的一些自定义：</span></p>
<ul>
<li><span>第 6 行：将模板文件的名称更改为</span><code class="language-plaintext highlighter-rouge">upsell-products.phtml</code><span>.</span></li>
<li><span>第 8 行：将标签命名为</span><code class="language-plaintext highlighter-rouge">You might be interested</code><span>.</span></li>
<li><span>第 14 行：将属性添加到</span><code class="language-plaintext highlighter-rouge">product.info.upsell</code><span>.</span></li>
</ul>
<h2 class="active" id="conclusion"><span>结论</span></h2>
<p><span><span>总之，在产品页面的选项卡式导航中自定义和添加自定义选项卡并不难。</span><span>我希望在阅读这篇文章后，您将能够通过添加一些 CSS 样式轻松地拥有包含新自定义内容的新标签。</span></span></p>
</div>
</div>]]></description>
      <pubDate>Mon, 22 Aug 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento2中使用弹出窗口小部件jQuery]]></title>
      <link>https://www.360magento.com/blog/Using-Popup-Widget-jQuery-in-Magento2/</link>
      <description><![CDATA[<p><span>在本文中，我们将看一个在Magento 2中使用jQuery弹出窗口小部件的示例。为了清晰起见，我们将使用这个小部件创建一个模态窗口，在其中放置搜索表单，搜索表单默认位于header中。首先，让我们看看现有的小部件选项。以下选项是默认可用的:</span></p>
<ul>
<li>autoOpen</li>
<li>buttons</li>
<li>clickableOverlay</li>
<li>focus</li>
<li>innerScroll</li>
<li>modalClass</li>
<li>modalLeftMargin</li>
<li>responsive</li>
<li>title</li>
<li>type</li>
</ul>
<p><span>但是，这个列表不是最终的列表，您可以自由地添加所需的选项，从而扩展这个小部件的原始功能。</span></p>
<p><span>让我们仔细看看每个选项。</span></p>
<p><strong>autoOpen</strong></p>
<p><span>此属性的默认值为&ldquo;false&rdquo;。属性确定小部件初始化后是否立即显示模态窗口。</span></p>
<p><strong>buttons</strong></p>
<p><span>该属性的值是一个数组，其中包含一个对象，您可以在该对象中传递按钮、CSS类和处理程序函数的文本，单击按钮时将触发处理程序函数。</span></p>
<p><strong>clickableOverlay</strong></p>
<p><span>此属性确定在单击叠加时是否可以关闭模态窗口。默认值为true。</span></p>
<p><strong>focus</strong></p>
<p><span>此属性确定在窗口打开后立即处于焦点位置的元素。具有CSS类名称的字符串被接受为值。在我们的例子中，在打开一个弹出窗口之后，重点应该放在搜索输入字段上。</span></p>
<p><strong>innerScroll</strong></p>
<p><span>如果模态窗口超过了屏幕的大小，这个属性将确定滚动位置，并且在打开弹出窗口时，我们需要滚动位于特定位置。</span></p>
<p><strong>modalClass</strong></p>
<p><span>有了这个属性，我们可以定义样式化所需的任何CSS属性</span></p>
<p><strong>modalLeftMargin</strong></p>
<p><span>此属性设置模态窗口之间的缩进。</span></p>
<p><strong>responsive</strong></p>
<p><span>定义模态窗口的自适应行为。默认情况下，该值设置为false。</span></p>
<p><strong>title</strong></p>
<p><span>定义模态窗口的标题。</span></p>
<p><strong>type</strong></p>
<p><span>此属性接受两个值作为字符串弹出或模态。根据所选的值，将定义一个用于呈现弹出窗口的模板。这些模板默认位于下列文件夹中:</span></p>
<ul>
<li>&lt;Magento_Ui_module_dir&gt;/view/base/web/templates/modal/modal-popup.html popup template.</li>
<li>&lt;Magento_Ui_module_dir&gt;/view/base/web/templates/modal/modal-slide.html slide template.</li>
</ul>
<p><span>如果需要，可以在theme文件夹中覆盖它们。</span></p>
<p><span>由于我们将为标题搜索表单创建一个弹出窗口，因此需要覆盖form.mini并稍微修改它。phtml模板。</span></p>
<p><span>该模板位于vendor/magento/module-search中。让我们覆盖它，把它放在下面的文件夹:</span></p>
<p><em>Vendor_Name/Vendor_Theme/Magento_Search/templates/form.mini.phtml.</em></p>
<p><span>在搜索块前面添加一个标记，它将显示搜索按钮，单击该按钮后，我们的模态窗口将弹出。</span></p>
<div class="crayon-syntax crayon-theme-sublime-text crayon-font-consolas crayon-os-pc print-yes notranslate" id="crayon-63023b6531f49022424965" data-settings=" no-popup minimize scroll-always">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-1">1</div>
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-2">2</div>
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-3">3</div>
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-4">4</div>
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-5">5</div>
<div class="crayon-num" data-line="crayon-63023b6531f49022424965-6">6</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div class="crayon-line" id="crayon-63023b6531f49022424965-1"><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle"</span><span class="crayon-h"> </span><span class="crayon-i">id</span>=<span class="crayon-s">"search-popup-toggle"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f49022424965-2"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle-icon"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f49022424965-3"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">img </span><span class="crayon-i">src</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?php</span><span class="crayon-h"> </span><span class="crayon-k ">echo</span><span class="crayon-h"> </span><span class="crayon-v">$block</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getViewFileUrl</span><span class="crayon-sy">(</span><span class="crayon-s">'images/search-icon.svg'</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span><span class="crayon-h"> </span><span class="crayon-i">alt</span>=<span class="crayon-s">"search-icon"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f49022424965-4"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-i">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f49022424965-5"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle-text"</span><span class="crayon-h">&gt;</span><span class="crayon-i">Search</span><span class="crayon-h">&lt;</span>/<span class="crayon-i">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f49022424965-6"><span class="crayon-h">&lt;</span>/<span class="crayon-i">div</span><span class="crayon-h">&gt;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>从技术上讲，这并不一定是一个按钮元素。这可以是任何DOM元素，稍后我们将向其附加事件处理程序。</span></p>
<p><span>下一步是连接RequireJS模块，在这个模块中我们定义了弹出窗口的设置。为了连接模块，我们使用了一个声明性的符号，通过</span><em>&lt;script type=&rdquo;text/x-magento-init&rdquo; /&gt;</em><span>&nbsp;</span><span>标签</span></p>
<p><span>在模板的末尾添加以下代码:</span></p>
<div class="crayon-syntax crayon-theme-sublime-text crayon-font-consolas crayon-os-pc print-yes notranslate" id="crayon-63023b6531f51439594018" data-settings=" no-popup minimize scroll-always">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-1">1</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-2">2</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-3">3</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-4">4</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-5">5</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-6">6</div>
<div class="crayon-num" data-line="crayon-63023b6531f51439594018-7">7</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div class="crayon-line" id="crayon-63023b6531f51439594018-1"><span class="crayon-ta">&lt;script </span><span class="crayon-e ">type</span>=<span class="crayon-s">"text/x-magento-init"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-2"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-3"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-s">"#search-popup-toggle"</span><span class="crayon-sy">:</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-4"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-s">"Magento_Search/js/search-popup"</span><span class="crayon-sy">:</span><span class="crayon-h"> </span><span class="crayon-sy">{</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-5"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-6"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f51439594018-7"><span class="crayon-ta">&lt;/script&gt;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p><span>在这个JSON对象中，我们传递#search-popup-toggle元素和search-popup.js脚本，我们将在下一步创建。请注意，在上面的代码中，我们指定了没有扩展名的js文件的名称。</span></p>
<p><span>Vendor_Name/Vendor_Theme/Magento_Search/we/js文件夹中，我们创建了一个新文件<strong>search-popup.js</strong></span></p>
<p><span>在文件中放入以下代码:</span></p>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-code">
<div class="crayon-pre">
<div class="crayon-line" id="crayon-63023b6531f54568905780-1"><span class="crayon-ta">&lt;?php</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-2"><span class="crayon-c">/**</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-3"><span class="crayon-c">* Copyright &copy; Magento, Inc. All rights reserved.</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-4"><span class="crayon-c">* See COPYING.txt for license details.</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-5"><span class="crayon-c">*/</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-6"><span class="crayon-c">// @codingStandardsIgnoreFile</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-7"><span class="crayon-ta">?&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-8"><span class="crayon-ta">&lt;?php</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-9"><span class="crayon-c">/** @var $block \Magento\Framework\View\Element\Template */</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-10"><span class="crayon-c">/** @var $helper \Magento\Search\Helper\Data */</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-11"><span class="crayon-v">$helper</span><span class="crayon-h"> </span>=<span class="crayon-h"> </span><span class="crayon-v">$this</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">helper</span><span class="crayon-sy">(</span><span class="crayon-sy">\</span><span class="crayon-i">Magento</span><span class="crayon-sy">\</span><span class="crayon-i">Search</span><span class="crayon-sy">\</span><span class="crayon-i">Helper</span><span class="crayon-sy">\</span><span class="crayon-e">Data::</span><span class="crayon-t">class</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-12"><span class="crayon-ta">?&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-13"><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle"</span><span class="crayon-h"> </span><span class="crayon-i">id</span>=<span class="crayon-s">"search-popup-toggle"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-14"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle-icon"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-15"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">img </span><span class="crayon-i">src</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?php</span><span class="crayon-h"> </span><span class="crayon-k ">echo</span><span class="crayon-h"> </span><span class="crayon-v">$block</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getViewFileUrl</span><span class="crayon-sy">(</span><span class="crayon-s">'images/search-icon.svg'</span><span class="crayon-sy">)</span><span class="crayon-sy">;</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span><span class="crayon-h"> </span><span class="crayon-i">alt</span>=<span class="crayon-s">"search-icon"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-16"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-i">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-17"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span </span><span class="crayon-t">class</span>=<span class="crayon-s">"block-search-toggle-text"</span><span class="crayon-h">&gt;</span><span class="crayon-i">Search</span><span class="crayon-h">&lt;</span>/<span class="crayon-i">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-18"><span class="crayon-h">&lt;</span>/<span class="crayon-i">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-19"><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"block block-search"</span><span class="crayon-h"> </span><span class="crayon-i">id</span>=<span class="crayon-s">"search-block"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-20"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"block block-title"</span><span class="crayon-h">&gt;</span><span class="crayon-h">&lt;</span><span class="crayon-e">strong</span><span class="crayon-h">&gt;</span><span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Search'</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span><span class="crayon-h">&lt;</span>/<span class="crayon-i">strong</span><span class="crayon-h">&gt;</span><span class="crayon-h">&lt;</span>/<span class="crayon-i">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-21"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"block block-content"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-22"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">form </span><span class="crayon-t">class</span>=<span class="crayon-s">"form minisearch"</span><span class="crayon-h"> </span><span class="crayon-i">id</span>=<span class="crayon-s">"search_mini_form"</span><span class="crayon-h"> </span><span class="crayon-i">action</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-v">$helper</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getResultUrl</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span><span class="crayon-h"> </span><span class="crayon-i">method</span>=<span class="crayon-s">"get"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-23"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"field search"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-24"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">label </span><span class="crayon-t">class</span>=<span class="crayon-s">"label"</span><span class="crayon-h"> </span><span class="crayon-st">for</span>=<span class="crayon-s">"search"</span><span class="crayon-h"> </span><span class="crayon-i">data</span>-<span class="crayon-i">role</span>=<span class="crayon-s">"minisearch-label"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-25"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span</span><span class="crayon-h">&gt;</span><span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Search'</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span><span class="crayon-h">&lt;</span>/<span class="crayon-i">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-26"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-i">label</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-27"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"control"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-28"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">input </span><span class="crayon-i">id</span>=<span class="crayon-s">"search"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-29"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">data</span>-<span class="crayon-i">mage</span>-<span class="crayon-i">init</span>=<span class="crayon-s">'{"quickSearch":{</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-30"><span class="crayon-s">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "formSelector":"#search_mini_form",</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-31"><span class="crayon-s">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "url":"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-v">$helper</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getSuggestUrl</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-ta">?&gt;</span>",</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-32"><span class="crayon-s">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "destinationSelector":"#search_autocomplete"}</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-33"><span class="crayon-s">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}'</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-34"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">type</span>=<span class="crayon-s">"text"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-35"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">name</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-v">$helper</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getQueryParamName</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-36"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">value</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-v">$helper</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getEscapedQueryText</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-37"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">placeholder</span>=<span class="crayon-s">"Search By Typing"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-38"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-t">class</span>=<span class="crayon-s">"input-text"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-39"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">maxlength</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-v">$helper</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getMaxQueryLength</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-40"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">role</span>=<span class="crayon-s">"combobox"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-41"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">aria</span>-<span class="crayon-i">haspopup</span>=<span class="crayon-s">"false"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-42"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">aria</span>-<span class="crayon-i">autocomplete</span>=<span class="crayon-s">"both"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-43"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="crayon-i">autocomplete</span>=<span class="crayon-s">"off"</span>/<span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-44"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-i">id</span>=<span class="crayon-s">"search_autocomplete"</span><span class="crayon-h"> </span><span class="crayon-t">class</span>=<span class="crayon-s">"search-autocomplete"</span><span class="crayon-h">&gt;</span><span class="crayon-h">&lt;</span>/<span class="crayon-e">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-45"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-v">$block</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">getChildHtml</span><span class="crayon-sy">(</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-46"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-i">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-47"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-i">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-48"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">div </span><span class="crayon-t">class</span>=<span class="crayon-s">"actions"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-49"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">button </span><span class="crayon-i">type</span>=<span class="crayon-s">"submit"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-50"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-i">title</span>=<span class="crayon-s">"<span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-v">$block</span>-<span class="crayon-h">&gt;</span><span class="crayon-e">escapeHtml</span><span class="crayon-sy">(</span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Search'</span><span class="crayon-sy">)</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span>"</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-51"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-t">class</span>=<span class="crayon-s">"action search"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-52"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span><span class="crayon-e">span</span><span class="crayon-h">&gt;</span><span class="crayon-ta">&lt;?=</span><span class="crayon-h"> </span><span class="crayon-c">/* @escapeNotVerified */</span><span class="crayon-h"> </span><span class="crayon-e">__</span><span class="crayon-sy">(</span><span class="crayon-s">'Search'</span><span class="crayon-sy">)</span><span class="crayon-h"> </span><span class="crayon-ta">?&gt;</span><span class="crayon-h">&lt;</span>/<span class="crayon-e">span</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-53"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-e">button</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-54"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-e">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-55"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-e">form</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-56"><span class="crayon-h">&nbsp;&nbsp; </span><span class="crayon-h">&lt;</span>/<span class="crayon-e">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-57"><span class="crayon-h">&lt;</span>/<span class="crayon-e">div</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-58"><span class="crayon-ta">&lt;script </span><span class="crayon-e ">type</span>=<span class="crayon-s">"text/x-magento-init"</span><span class="crayon-h">&gt;</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-59"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-60"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-s">"#search-popup-toggle"</span><span class="crayon-sy">:</span><span class="crayon-h"> </span><span class="crayon-sy">{</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-61"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-s">"Magento_Search/js/search-popup"</span><span class="crayon-sy">:</span><span class="crayon-h"> </span><span class="crayon-sy">{</span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-62"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-63"><span class="crayon-h">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span class="crayon-sy">}</span></div>
<div class="crayon-line" id="crayon-63023b6531f54568905780-64"><span class="crayon-ta">&lt;/script&gt;</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<p><span>这就是jQuery弹出窗口小部件在Magento 2中的样子，感谢您的阅读!在下面的部分留下你的评论和问题，我很乐意回答。</span></p>]]></description>
      <pubDate>Sun, 21 Aug 2022 08:30:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[xampp怎么修改php版本]]></title>
      <link>https://www.360magento.com/blog/How-does-xampp-modify-the-PHP-version/</link>
      <description><![CDATA[<h2>1、下载安装包与压缩包</h2>
<p><span>打开&nbsp;</span><code>XAMPP</code><span>&nbsp;官网，下载你所需要的版本，这里以 7.3.30 与 7.4.29 为例，那么你可以选择下载两个压缩包，或者一个压缩包一个安装包，但不能都是安装包，至于为什么，后面你应该会明白，所以这里我们选择了&nbsp;</span><code>7.4.29</code><span>&nbsp;安装包，</span><code>7.3.30</code><span>&nbsp;压缩包。</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/1.PNG" width="819" /></span></p>
<p></p>
<h2>2、目录配置</h2>
<p><span>1、确保XAMPP已退出，<span>并重命名 XAMPP 安装目录中的 php 目录为 php7.4，如D:\xampp\php 改变为 D:\xampp\php7.4。</span></span></p>
<p><span><span><span>2、将下载的另一个版本压缩包解压，并将其中的 php 目录移动到 XAMPP 安装目录。</span></span></span></p>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/1_1.PNG" width="819" /></span></span></p>
<h2>3、文件配置</h2>
<p><span>1、在 D:\xampp\apache\conf 目录下的 httpd.conf 文件中，找到 PHP 的 XAMPP 设置，配置如下所示：</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # XAMPP settings<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #Include "conf/extra/httpd-xampp-7.4.conf"<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Include "conf/extra/httpd-xampp-7.3.conf"</p>
<p><span>注：当你真正使用时，该配置只能启用一个。</span></p>
<p>2、将 ‪D:\xampp\apache\conf\extra 目录中的 httpd-xampp.conf 文件重命名为 httpd-xampp-7.4.conf。</p>
<p>3、将另一个版本压缩包中同目录下的 httpd-xampp.conf，重命名为 httpd-xampp-7.3.conf，复制它并粘贴到D:\xampp\apache\conf\extra。</p>
<p><span>现在打开你的 XAMPP 控制面板启动 Apache。</span></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_84/1_2.PNG" width="819" /></p>
<p><span>注：如果你想要从一个版本切换到另一个版本，只需要在 D:\xampp\apache\conf\httpd.conf 注释与打开对应配置，修改xampp安装目录下的php文件夹名称，如D:\xampp\php 改变为 D:\xampp\php7.3，将你需要的php版本文件夹重命名为php，如D:\xampp\php7.4 改变为 D:\xampp\php，最后重新启动 Apache即可。</span></p>]]></description>
      <pubDate>Sat, 20 Aug 2022 08:28:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[可以在 Magento 2 中禁用 Elasticsearch 吗？]]></title>
      <link>https://www.360magento.com/blog/Can-Elasticsearch-be-disabled-in-Magento-2/</link>
      <description><![CDATA[<h2><span>配置 Magento 2 ElasticSearch 扩展</span></h2>
<p><span></span><span><span>步骤 1. 首先，您需要设置连接。</span><span>为此，导航到&nbsp;</span></span><span>管理面板 &gt; 商店 &gt; 配置 &gt; 弹性搜索 &gt; 连接：</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/connection2.jpg" width="819" /></span></p>
<p><span>步骤 2.</span><span><span>&nbsp;在&nbsp;</span><span><span>搜索引擎</span></span><span>&nbsp;下拉列表中</span><span>&nbsp;选择&nbsp;</span></span><span>Amasty ElasticSearch 。</span><span></span><span><span></span></span><span></span></p>
<p><span>步骤 3.</span><span>&nbsp;然后，输入 ElasticSearch 运行机器 IP 地址，指明</span><span>&nbsp;Elasticsearch Server Hostname&nbsp;</span><span>。</span></p>
<p><span>步骤 4.</span><span>&nbsp;定义</span><span>&nbsp;Elasticsearch 服务器端口。</span></p>
<p><span>步骤 5.</span><span><span>&nbsp;为您实施弹性搜索的每个商店</span><span>&nbsp;配置特定的&nbsp;</span></span><span>Elasticsearch 索引前缀。</span><span></span></p>
<p><span>步骤 6.</span><span><span>&nbsp;如果您的 Elasticsearch 服务器的验证已启用，请</span><span>在&nbsp;</span><span><span>Elasticsearch HTTP Auth</span></span><span>下拉列表中&nbsp;设置&nbsp;</span></span><span>是&nbsp;，并通过您的身份验证数据满足显示的行。</span><span></span><span><span></span></span><span></span></p>
<p><span>步骤 7.&nbsp;</span><span>如果需要，设置&nbsp;</span><span>Elasticsearch Server Timeout</span><span>的时间。</span></p>
<p><span>步骤 8.&nbsp;</span><span><span>测试连接。</span><span>如果它成功了，那么你做的一切都是正确的。</span></span></p>
<p>&nbsp;</p>
<p><span>之后，您需要设置&nbsp;</span><span>自动完成建议和拼写更正。</span></p>
<p><span>步骤 1.&nbsp;</span><span>导航到&nbsp;</span><span>管理面板 &gt; 商店 &gt; 配置 &gt; 弹性搜索 &gt; 目录：</span></p>
<p><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/catalog2.jpg" width="819" /></span></p>
<p><span>步骤 2.&nbsp;</span><span>在&nbsp;</span><span>通配符类型</span><span>&nbsp;字段中，从 3 个选项中选择将自动填写的单词部分。</span></p>
<p><span>步骤 3.&nbsp;</span><span>然后将字符数写入&nbsp;</span><span>Enable Wildcard After</span><span>。</span></p>
<p><span>步骤 4.&nbsp;</span><span><span>然后</span><span>通过输入字符数定义何时启用</span></span><span>&nbsp;拼写校正&nbsp;。</span><span></span></p>
<p><span>第 5 步。&nbsp;</span><span>在&ldquo;&nbsp;</span><span>搜索结果的最大数量&rdquo;</span><span>&nbsp;字段中，您可以在搜索结果中编写自己的最大元素数，或者将其保留为 0 以使用预设的 Magento 值。</span></p>
<p><span>第 6 步。</span><span>&nbsp;在下一个下拉列表中，您可以将&nbsp;</span><span>&ldquo;是&rdquo;&nbsp;</span><span>设置为&nbsp;</span><span>允许特殊字符</span><span>&nbsp;，这在客户使用高度特定的搜索短语和包含斜杠、连字符、破折号或任何其他非字母符号的单词时很有用。</span></p>
<p><span>第 7 步。&nbsp;</span><span>这里的最后一件事是配置&nbsp;</span><span>高级查询设置。&nbsp;</span><span>只需为每个属性选择您的偏好。&nbsp;</span></p>
<p><span>请记住，如果您需要将产品属性添加到搜索查询配置中，您需要执行以下操作：</span></p>
<p><span>导航到管理面板 &gt; 商店 &gt; 属性 &gt; 产品 &gt;&nbsp;</span><span>选择所需的&nbsp;</span><em>产品属性</em><span></span><span>&gt;&nbsp;</span><span><span>单击&nbsp;</span><span><span>店面属性 &gt; 启用在搜索中使用</span></span><span>&nbsp;。&nbsp;</span></span><span><span></span></span></p>
<p><span>之后，您必须&nbsp;根据需要填写</span><span>Indexation Settings</span><span>&nbsp;字段并选择是否要启用&nbsp;</span><span>Debug</span><span>。</span></p>
<h2><span>有什么方法可以在 Magento 2 中禁用 Elasticsearch？</span></h2>
<p><span>如果您已升级到 Magento 2.4，则Magento 2 禁用</span>Elasticsearch 功能<span><span>不可用，因为必须安装 Elasticsearch，并且无法绕过此限制。</span><span>由于 Magento 2.4 禁用 Elasticsearch 功能自 2.4 版本平台以来不可用，因此在最新版本的 Magento 2 中使用 Elasticsearch 进行更改的唯一方法是安装第三方扩展。</span></span></p>
<p><span>&nbsp;</span></p>
<p></p>
<p></p>]]></description>
      <pubDate>Fri, 19 Aug 2022 08:26:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何使用内联翻译翻译 Magento 2 扩展]]></title>
      <link>https://www.360magento.com/blog/How-to-Translate-Magento2-Extension-Using-Inline-Translation/</link>
      <description><![CDATA[<p><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">在本文中，您将学习如何执行 Magento 2 内联翻译。</span></span></span></p>
<p><span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">首先，确保您对不同语言有不同的商店视图。</span></span></span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">然后，您需要在 Magento 2 后端启用内联翻译并在前端翻译元素。</span></span></span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">请按照下面的快速指南正确执行 Magento 2 内联翻译。</span></span></span></span></p>
<p class="pr-notice-title"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">分步操作：</span></span></p>
<ol>
<li><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">转到Magento 2 管理面板中的商店。</span></span></li>
<li><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">在设置选项卡中选择配置部分。</span></span></li>
</ol>
<p><span><span><img height="471" src="https://www.360magento.com/media/wysiwyg/blog_84/Magento_2_inline_translation_1.jpg" width="819" /></span></span></p>
<p class="pr-notice-title"><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">分步操作：</span></span></span></p>
<ol>
<li><span>转到</span><span>高级</span><span>选项卡。</span></li>
<li><span>选择</span><span>开发人员</span><span>部分。</span></li>
<li><span>选择您需要执行翻译的商店视图。</span></li>
<li><span>启用内联翻译。</span></li>
<li><span>应为 Storefront 和 Admin 内联翻译禁用翻译、块和其他输出缓存。</span></li>
<li><span>按</span><span>保存配置</span><span>按钮以保存您的更改。</span></li>
</ol>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/Magento_2_inline_translation_2vz.jpg" width="819" /></span></span></p>
<p><span>在 Magento 2 后端设置配置后，您可以在前端开始翻译。</span></p>
<div class="wp-block-group pr-notice pr-notice-info">
<div class="wp-block-group__inner-container">
<p class="pr-notice-title"><span>分步操作：</span></p>
<ol>
<li><span>从下拉菜单中选择所需的语言（例如德语）。</span></li>
<li><span>在您需要翻译的页面上选择一个元素，然后翻译表单将打开。</span></li>
<li><span>将翻译后的文本输入</span><span>自定义</span><span>字段。</span></li>
<li><span>按</span><span>提交</span><span>保存翻译。</span></li>
</ol></div>
</div>
<p><span><span><img src="https://www.360magento.com/media/wysiwyg/blog_84/Magento_2_inline_translation_3_v1.jpg" width="819" /></span></span></p>
<p><span><span><span>请确保在提交翻译后刷新页面。</span></span></span></p>]]></description>
      <pubDate>Thu, 18 Aug 2022 08:22:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 部署静态内容]]></title>
      <link>https://www.360magento.com/blog/magento-2-static-content-deploy/</link>
      <description><![CDATA[<h2 class="active" id="overview-of-static-view-files-deployment"><span>静态视图文件部署概述</span></h2>
<p><span>首先，让我们了解更多关于静态视图的知识。</span></p>
<p><span><span>这里的静态是指可以缓存非动态生成的文件。</span><span>&ldquo;视图&rdquo;一词是指模型-视图-控制器 (MVC) 中的表示层。</span></span></p>
<p><span><span>静态视图文件的部署受三种 Magento 模式的影响，包括生产模式、默认模式和开发者模式。</span><span>静态视图文件部署命令使您能够在 Magento 2 商店处于生产模式时编写静态内容文件。</span></span></p>
<h2 class="active" id="deploy-static-content-via-command-line"><span>通过命令行部署静态内容</span></h2>
<p><span>转到 Magento 管理根文件夹并显示用法：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento setup:static-content:deploy -h</code><br /><br /><a href="https://www.mageplaza.com/install-magento-2-extension/">安装/更新扩展</a>时，只需运行以下命令行即可部署您的商店的静态内容</pre>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento setup:static-content:deploy -f</code></pre>
</div>
</div>
</div>
</div>]]></description>
      <pubDate>Wed, 17 Aug 2022 08:45:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 如何通过命令行解锁管理员用户]]></title>
      <link>https://www.360magento.com/blog/magento-2-unlock-admin-user/</link>
      <description><![CDATA[<h2 class="active" id="how-to-unlock-admin-user-via-command-line"><span>如何通过命令行解锁管理员用户</span></h2>
<h2 class="active" id="syntax-to-unlock-admin-user"><span>解锁管理员用户的语法</span></h2>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento admin:user:unlock username
</code></pre>
</div>
</div>
<p><span>让我们解锁一个管理员帐户：</span><code>360Magento</code>并提供以下信息</p>
<p><span>在命令行中输入：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento admin:user:unlock 360Magento
</code></pre>
</div>
</div>
<p><span>输出：</span></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>The user account "</code><code>360Magento</code><code>" has been unlocked<br /><br /><span>如果管理员用户未锁定，您可能会收到以下消息：</span><br /></code></pre>
<pre class="highlight"><code>The user account "</code><code>360Magento</code><code>" was not locked or could not be unlocked</code></pre>
<p></p>
</div>
</div>]]></description>
      <pubDate>Tue, 16 Aug 2022 08:25:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在 Magento 2 中配置 Cron（定时任务）]]></title>
      <link>https://www.360magento.com/blog/configure-cron-scheduled-task-in-magento-2/</link>
      <description><![CDATA[<p class="p"><span>1. 导航到&nbsp;</span><strong><span class="15">Stores &gt; Configuration &gt; Advanced &gt; System &gt; Cron (Scheduled Tasks)</span></strong><span>。</span><span></span></p>
<p class="p"><span>您将在</span><strong><span class="15">Cron（计划任务）</span></strong><span><span style="font-family: Arial;">选项卡下看到所有默认的</span> cron 作业，以及与您使用的各种 Magento 2 模块一起使用的 cron 作业。每个 cron 的选项都是相同的，因此您只需使用首选值填写它们。</span><span></span></p>
<p class="p"><span><img height="374" src="https://www.360magento.com/media/wysiwyg/blog_84/_1.png" width="616" /></span></p>
<p class="p"></p>
<p class="p">2.&nbsp;<span style="font-family: Arial;">配置</span> cron 计划选项。</p>
<p class="p"><strong>3. 在Generate Schedules Every</strong><span style="font-family: Arial;">中定义您希望</span> cron 多久&nbsp;生成一次计划。</p>
<p class="p">4. 在&nbsp;<strong>Schedule Ahead for</strong><span style="font-family: Arial;">字段中指定提前多长时间来安排</span> cron 作业的时间（以分钟为单位）。</p>
<p class="p"><em><span style="font-family: Arial;">例如，如果您在此处设置</span> </em><em><span style="font-family: Arial;">2</span></em><em>0，则 cron 作业将在 cron 运行后的下一个 </em><em><span style="font-family: Arial;">2</span></em><em>0 分钟内安排。</em></p>
<p class="p"><strong>5. 在Missed if not Run Within&nbsp;</strong><span style="font-family: Arial;">字段中设置时间（以分钟为单位），如果</span> cron 作业在预定时间后未运行，则将&nbsp;其分配为<em>Missed状态。</em></p>
<p class="p">6. 在&nbsp;<strong>History Cleanup Every</strong>字段中，您设置时间（以分钟为单位），在该时间之后应清除已完成任务的历史记录。</p>
<p class="p">7. 定义&nbsp;<strong>Success History Lifetime&nbsp; ，它指定具有</strong><em>成功</em><span style="font-family: Arial;">状态的</span> cron 作业应保留在数据库中的时间（以分钟为单位） 。</p>
<p class="p"><strong>8. 在Failure History Lifetime</strong>&nbsp;字段中设置状态为Error 的cron 作业应在数据库中保留多长时间</p>
<p><strong>9. 在Use Separate Process</strong><span style="font-family: Arial;">中选择是否要单独运行组中的所有</span> cron 作业&nbsp;。</p>
<p><img height="495" src="https://www.360magento.com/media/wysiwyg/blog_84/_2.png" width="819" /></p>
<h2><strong><span><span style="font-family: Arial;">在</span> Magento 中处理 Cron 作业的有用命令</span></strong><strong><span></span></strong></h2>
<p class="p"><span><span style="font-family: Arial;">尽管</span> Magento 中的 crons 按计划运行，您可以将它们配置为，但有时您可能需要手动按需执行它们。&nbsp;</span><span></span></p>
<p class="p"><strong><span class="15">注意：</span></strong><span><span style="font-family: Arial;">您需要在作为</span> Magento 所有者的用户下运行命令。</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">对于这些情况，您需要最常见的命令来与</span> Magento crons 一起使用</span><span></span></p>
<p class="p"><span><span style="font-family: Arial;">1.</span><span style="font-family: 宋体;">需要</span></span><strong><span class="15"><span style="font-family: Arial;">要创建</span> crontab</span></strong><span></span></p>
<p class="p"><span><span style="font-family: Arial;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">bin/magento cron：安装</span></span></span></span><span></span></p>
<p class="p"><strong><span class="15"><span style="font-family: Arial;">2.</span></span></strong><strong><span class="15"><span style="font-family: Arial;">要检查</span> crontab</span></strong><strong><span class="15"></span></strong></p>
<p class="p"><strong><span class="15"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">crontab -1</span></span></span></strong><strong><span class="15"></span></strong></p>
<p class="p"><strong><span class="15"><span style="font-family: Arial;">3.</span></span></strong><strong><span class="15"><span style="font-family: Arial;">要删除该用户的所有</span> Magento crons</span></strong><strong><span class="15"></span></strong></p>
<p class="p"><strong><span class="15">&nbsp;</span></strong><strong><span class="15"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">crontab </span></span></span></strong><strong><span class="15"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">-r</span></span></span></strong><strong><span class="15"></span></strong></p>
<p class="p"><strong><span class="15">4.</span></strong><strong><span class="15"><span style="font-family: Arial;">要运行</span> cron</span></strong><strong><span class="15">&nbsp;</span></strong><strong><span class="15">任务</span></strong><strong><span class="15"></span></strong></p>
<p class="p"><span><span style="font-family: Arial;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">bin/magento cron：运行</span></span></span></span><span></span></p>
<p class="p"><strong><span class="15">5</span></strong><span><span style="font-family: Arial;">.</span></span><strong><span class="15"><span style="font-family: Arial;">要运行</span> cron 组</span></strong><span></span></p>
<p class="p"><span><span style="font-family: Arial;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">bin/magento cron:run --group [cron 组名]</span></span></span></span><span></span></p>
<p class="p"><strong><span class="15">6</span></strong><span><span style="font-family: Arial;">.</span></span><strong><span class="15"><span style="font-family: Arial;">要删除</span> Magento crontab</span></strong><span></span></p>
<p class="p"><span><span style="font-family: Arial;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">bin/magento cron：删除</span></span></span></span><strong><span class="15"></span></strong></p>]]></description>
      <pubDate>Mon, 15 Aug 2022 08:27:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 通过命令行创建管理员用户]]></title>
      <link>https://www.360magento.com/blog/magento-2-add-admin-user-command-line/</link>
      <description><![CDATA[<p><span><span>从后端手动创建管理员用户是最基本的方法。</span><span>如果您处于以下情况，通过命令行创建管理员用户帐户具有一些优势：</span></span></p>
<ul>
<li><span>您希望通过使用命令行而不是在商店后端的帐户信息中填写多个字段来节省创建管理员帐户的时间</span></li>
<li><span>您是开发人员，您的客户需要您在不知道任何管理员帐户的情况下登录后端</span></li>
<li><span>您需要在短时间内创建多个管理员帐户<br /><br /></span></li>
</ul>
<p>如何在 Magento 2 中通过命令行创建管理员用户？ 获得服务器访问权限后，转到 Magento 管理根文件夹：</p>
<p><span>例如，现在我们将使用以下信息创建一个管理员帐户：</span></p>
<ul>
<li>User: 360magento</li>
<li>Password:&nbsp;<span>WeLoveMagento123</span></li>
<li>Email:&nbsp;hi@360magento.com</li>
<li>First Name:&nbsp;360magento</li>
<li>Last Name: Family</li>
</ul>
<p>所以这里是命令行：</p>
<pre class="highlight"><code>php bin/magento admin:user:create --admin-user=360magento --admin-password=<span>WeLoveMagento123</span> --admin-email=hi@360magento.com --admin-firstname=360magento --admin-lastname=Family<br /><br /><span>现在，我们成功创建了一个新的管理员帐户。</span><span>系统返回此消息：</span><br /></code></pre>
<pre class="highlight"><code>Created Magento administrator user named 360magento</code></pre>
<pre class="highlight"><code><br /><br /></code></pre>]]></description>
      <pubDate>Tue, 09 Aug 2022 01:59:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中添加/删除静态文件 JS、CSS、字体]]></title>
      <link>https://www.360magento.com/blog/add-remove-static-files-js-css-fonts-magento-2/</link>
      <description><![CDATA[<p>在今天的文章中，我将指导您如何在 Magento 2 中添加和删除静态文件，包括 JS、CSS 和字体。通过这个易于理解的教程，可以轻松添加或删除静态文件 JS、CSS、字体。</p>
<p><strong>添加静态文件</strong></p>
<p>通常，如果您想在 Magento 2 中使用外部库来自定义页面，您需要添加 JavaScript 和 CSS 文件。JavaScript、CSS 和其他静态文件将添加到页面配置文件的 &lt;head&gt; 部分。<br />在页面配置文件中，该&lt;head&gt;部分包括各种静态资源，例如 JavaScript、CSS。该文件定义了 Magento 商店页面</p>
<p>app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml中该部分的原始外观。&lt;head&gt;</p>
<p>要添加 CSS 和 JavaScript，建议您在自定义主题中扩展文件，然后在其中添加文件。<br />以下是必须添加的文件示例：</p>
<p><br />&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;<br /> &lt;head&gt;<br /> &lt;!-- Add local resources --&gt;<br /> &lt;css src="css/my-styles.css"/&gt;<br /> &lt;!-- The following two ways to add local JavaScript files are equal --&gt;<br /> &lt;script src="Magento_Catalog::js/sample1.js"/&gt;<br /> &lt;link src="js/sample.js"/&gt;<br /> &lt;!-- Add external resources --&gt;<br /> &lt;css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" src_type="url" /&gt;<br /> &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" src_type="url" /&gt;<br /> &lt;link rel="stylesheet" type="text/css" src="http://fonts.googleapis.com/css?family=Montserrat" src_type="url" /&gt;<br /> &lt;/head&gt;<br />&lt;/page&gt;</p>
<p>添加外部资源时，您必须指定src_type="url"参数值。<br />指令&lt;link src="js/sample.js"/&gt;可&lt;script src="js/sample.js"/&gt;用于将本地存储的 JavaScript 文件添加到您的主题中。</p>
<p><strong>删除静态文件</strong></p>
<p>对于要删除的页面中链接的静态资产&lt;head&gt;，您可以在扩展主题中进行更改，app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml如下所示：</p>
<p>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;<br /> &lt;head&gt;<br /> &lt;!-- Remove local resources --&gt;<br /> &lt;remove src="css/styles-m.css" /&gt;<br /> &lt;remove src="my-js.js"/&gt;<br /> &lt;remove src="Magento_Catalog::js/compare.js" /&gt;<br /> &lt;!-- Remove external resources --&gt;<br /> &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"/&gt;<br /> &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"/&gt;<br /> &lt;remove src="http://fonts.googleapis.com/css?family=Montserrat" /&gt;<br /> &lt;/head&gt;<br />&lt;/page&gt;</p>
<p>需要记住，如果您在初始布局中添加或删除具有模块路径的静态资产，则需要指定模块路径，例如Magento_Catalog::js/sample.js</p>
<div id="gtx-trans" style="position: absolute; left: -24px; top: 461px;">
<div class="gtx-trans-icon"></div>
</div>]]></description>
      <pubDate>Mon, 08 Aug 2022 06:19:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2 以编程方式添加 URL 重写]]></title>
      <link>https://www.360magento.com/blog/magento-2-url-rewrite-programmatically/</link>
      <description><![CDATA[<p>Magento 2 URL 以编程方式重写是在线零售商想要创建大量网站流量的绝佳解决方案之一。重写 url 的目的是允许您通过编程方式生成 301 重定向到Magento 2 。</p>
<h2 class="active" id="what-is-url-redirect"><span>什么是 URL 重定向？</span></h2>
<p><a href="https://en.wikipedia.org/wiki/URL_redirection" rel="nofollow" target="_blank">URL 重定向</a><span>是</span><a href="https://www.mageplaza.com/kb/how-to-configure-seo-in-magento-2.html">SEO</a><span><span>中的一个流行术语，它用于将访问者导航到商店所有者期望的任何链接。</span><span>重定向主要有两种类型：</span></span><a href="https://www.mageplaza.com/blog/magento-2-redirect-301-302.html">301 重定向和 302 重定向</a><span><span>。</span><span>因此，如果您想知道如何继续与当前站点的现有访问者合作，同时您计划构建一个更高效的新站点，最好的答案是通过重定向 301 创建搜索重定向。</span></span></p>
<p>在 Magento 中以编程方式添加 URL 的 2 个步骤<br />第 1 步：生成构造函数文件</p>
<pre class="highlight"><code>/**<span></span>
* @var \Magento\UrlRewrite\Model\UrlRewriteFactory<span></span>
*/<span></span>
protected $_urlRewriteFactory;<span></span>
<span></span>
/**<span></span>
* @param Context $context<span></span>
* @param \Magento\UrlRewrite\Model\UrlRewriteFactory $urlRewriteFactory<span></span>
*/<span></span>
public function __construct(<span></span>
    Context $context,<span></span>
    \Magento\UrlRewrite\Model\UrlRewriteFactory $urlRewriteFactory<span></span>
) {<span></span>
    $this-&gt;_urlRewriteFactory = $urlRewriteFactory;<span></span>
    parent::__construct(<span></span>
        $context<span></span>
    );<span></span>
}</code></pre>
<p><br />第 2 步：在执行方法中插入自定义 URL 重写</p>
<p>仅当您的原始网站是example.com/customModule/customController/customAction时，您才希望将URL重写为，www.example.com/xyz而不是。然后您可以运行以下方法：</p>
<p></p>
<pre class="highlight"><code>$urlRewriteModel = $this-&gt;_urlRewriteFactory-&gt;create()<span></span>
/* set current store id */<span></span>
$urlRewriteModel-&gt;setStoreId(1);<span></span>
/* this url is not created by system so set as 0 */<span></span>
$urlRewriteModel-&gt;setIsSystem(0);<span></span>
/* unique identifier - set random unique value to id path */<span></span>
$urlRewriteModel-&gt;setIdPath(rand(1, 100000));<span></span>
/* set actual url path to target path field */<span></span>
$urlRewriteModel-&gt;setTargetPath("www.example.com/customModule/customController/customAction");<span></span>
/* set requested path which you want to create */<span></span>
$urlRewriteModel-&gt;setRequestPath("www.example.com/xyz");<span></span>
/* set current store id */<span></span>
$urlRewriteModel-&gt;save();</code></pre>]]></description>
      <pubDate>Fri, 05 Aug 2022 07:16:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中更改样本图像大小]]></title>
      <link>https://www.360magento.com/blog/magento-2-change-swatch-image-size/</link>
      <description><![CDATA[<p><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><img alt="如何在 Magento-2 中更改色板图像大小" height="374" src="https://www.360magento.com/media/wysiwyg/blog_84/How-to-Change-Swatch-Image-Size-in-Magento-2-1.png" title="如何在 Magento-2 中更改色板图像大小" width="950" /></span></span></span></span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Magento 2 中的样本是向客户提供产品变化的功能。</span></span></span></span></span></span></p>
<p><span></span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Magento 2 可配置产品</span></span></span></span></span></span></span><span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">显示</span></span></span></span></span></span></span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp;在前端并带有样本，使客户可以轻松地从可用选项中进行选择。</span></span></span></span></span></span></span></span></p>
<p><span><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">默认的 Magento 2 色板类型是文本、颜色和图像色板，使产品描述更具洞察力并促进转换过程。</span></span></span></span></span></span></span></span></span><span><br /></span></span></p>
<p><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">现在，如果您想根据主题</span></span></span><em><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">更改 Magento 2 商店中的样本图像大小</span></span></span></em><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">，您可以使用以下代码进行操作。</span></span></span></p>
<p><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">调整图像样本大小，让访问者更好地了解产品变化并鼓励销售！</span></span></span></p>
<p><span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">以下是默认样本图像的外观</span></span></span></p>
<p><span><img alt="默认样本图像大小在 Magento-2" height="361" src="https://www.360magento.com/media/wysiwyg/blog_84/default-swatch-image-size-in-Magento-2.jpg" title="默认样本图像大小在 Magento-2" width="819" /></span></p>
<p></p>
<h2><span>在 Magento 2 中更改样本图像大小的方法：</span></h2>
<p><span>如果您在本地安装了带有 Luma 主题的 Magento 2 并希望更改样本图像的大小：</span></p>
<p><span>打开</span><em><span>vendor\magento\module-swatches\etc\view.xml</span></em></p>
<p><span>替换以下代码：</span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;image id="swatch_image" type="swatch_image"&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;width&gt;30&lt;/width&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;height&gt;20&lt;/height&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;/image&gt;</span></span></span></span></span></span></p>
<p><span>和</span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;image id="swatch_image" type="swatch_image"&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;width&gt;210&lt;/width&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;height&gt;210&lt;/height&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;/image&gt;</span></span></span></span></span></span></p>
<p><span>如果您安装了主题，请打开</span><em><span>app/design/frontend/[theme]/etc/view.xml</span></em><span>文件并搜索&ldquo;swatch_image&rdquo;</span></p>
<p><span>如果可用，则更改代码：</span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;image id="swatch_image" type="swatch_image"&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;width&gt;210&lt;/width&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;height&gt;210&lt;/height&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;/image&gt;</span></span></span></span></span></span></p>
<p><span>如果没有找到，请</span>将以下行放入媒体标签</p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;images module="Magento_Catalog"&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;image id="swatch_image" type="swatch_image"&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &nbsp; &nbsp; &lt;width&gt;210&lt;/width&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &nbsp; &nbsp; &lt;height&gt;210&lt;/height&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp; &nbsp; &lt;/image&gt; </span></span></span></span></span></span><br /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&lt;/images&gt;</span></span></span></span></span></span></p>
<p><span>完成后，您可以检查更新的图像样本，如下所示：</span></p>
<p><span><img alt="更改图像样本大小在 Magento-2" height="361" src="https://www.360magento.com/media/wysiwyg/blog_84/changed-image-swatch-size-in-Magento-2.jpg" title="更改图像样本大小在 Magento-2" width="819" /></span></p>
<p><span><span>如果对解决方案有任何疑问，请联系我们，我们很乐意提供帮助。</span></span></p>
<p><span>谢谢。</span></p>]]></description>
      <pubDate>Thu, 04 Aug 2022 07:28:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在 Magento 2 中备份数据库/回滚、媒体、代码]]></title>
      <link>https://www.360magento.com/blog/magento-2-backup-database-media-code/</link>
      <description><![CDATA[<p><span><span>运行在线商店时最重要的事情之一就是正确备份所有内容，以便如果出现问题，您可以回滚或恢复它。</span><span>因此，备份商店中最重要的数据非常重要。</span><span>备份文件后，您可以恢复或回滚它。</span><span>在这个过程中很容易出错，因为系统会在恢复之前删除特定的文件和数据库。</span></span></p>
<p><span><span>我们将讨论如何</span><span>在</span><a href="https://www.mageplaza.com/devdocs/magento-2-command-line-interface-cli.html"><span>命令行系列</span></a></span><span>中备份/回滚数据库、媒体、代码</span><span><span>。</span><span>如您所知，从 Magento 2 开始，他们在</span><span>.&nbsp;</span><span>这可能很难解决，让我解释一下有关</span><span><span>如何备份/回滚数据库、媒体、代码的</span></span><span>更多细节。</span></span><a href="https://www.mageplaza.com/devdocs/magento-2-command-line-interface-cli.html"><span></span></a><span></span><code class="language-plaintext highlighter-rouge">bin/magento</code><span></span><span><span></span></span><span></span></p>
<p><span>&nbsp;</span></p>
<h2 class="active" id="how-to-backup--rollback-db-media-code-command-line"><span>如何备份/回滚数据库、媒体、代码命令行</span></h2>
<p><span><span>转到 Magento 程序根文件夹执行命令：</span></span></p>
<h2 class="active" id="list-all-existed-backup-files"><span>查看所有已存在的备份文件</span></h2>
<pre class="highlight"><code>php bin/magento info:backups:list<br /></code><br /><span></span></pre>
<h2 class="active" id="backup-database"><span>备份数据库</span></h2>
<p><span><span>在过程开始时，它将进入</span><a href="https://www.mageplaza.com/devdocs/magento-2-maintaince-mode.html">维护模式</a><span>，并开始备份然后存储到</span><code class="language-plaintext highlighter-rouge">./var/backups/</code><span><span>文件夹。</span><span>之后，它将再次禁用维护模式。</span></span></span></p>
<pre class="highlight"><code>php bin/magento setup:backup --db</code><br /><br /><br /></pre>
<h2 class="active" id="backup-media"><span>备份媒体</span></h2>
<pre class="highlight"><code>php bin/magento setup:backup --media</code><br /><br /><br /></pre>
<h2 class="active" id="backup-code"><span>备用代码</span></h2>
<pre class="highlight"><code>php bin/magento setup:backup --code</code><br /><br /><br /></pre>
<h2 class="active" id="how-to-rollback-database-media-code"><span>如何回滚数据库、媒体、代码</span></h2>
<p><span>回滚数据库：</span></p>
<pre class="highlight"><code>php bin/magento setup:rollback --db-file=1534245793_db.sql<br /><br /></code></pre>
<p>备注：<span>所有备份文件都必须放在</span><code class="language-plaintext highlighter-rouge">./var/backups/</code><span>文件夹中</span></p>
<pre class="highlight"><br /><br /></pre>]]></description>
      <pubDate>Tue, 02 Aug 2022 09:14:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2常用全部命令]]></title>
      <link>https://www.360magento.com/blog/magento-2-cli-ssh-commands/</link>
      <description><![CDATA[<p>
如果您刚刚开始使用 Magento 2  或已经使用它很久了，您必须了解这些有用的SSH 命令，它们将帮助您轻松完成某些任务。 
</p>
<p>
当您必须清理缓存、启用 – 禁用缓存、运行 cron、数据索引和各种其他任务时，Magento SSH 命令会非常方便。要运行这些 SSH 命令，您需要具有对服务器的 SSH 访问权限，或者您可以使用命令行进行本地访问。 
</p>
<p>
因此，为了节省您最宝贵的时间 – 我们建议所有开发人员和感兴趣的人将此帖子加入书签收藏。这是 Magento2 的所有有用 SSH 命令的汇总。 
</p>

<table><tbody><tr><td><b>命令说明 &nbsp;</b></td><td><b>命令</b></td><td><b>短命令</b></td></tr><tr><td><span style="font-weight: 400;">显示命令帮助</span></td><td><b>php bin/magento help (command)</b></td><td><b>php bin/magento h</b></td></tr><tr><td><span style="font-weight: 400;">检查所有命令的列表 –</span><p></p><p><span style="font-weight: 400;">这将有助于列出 Magento2 的所有命令</span></p></td><td><b>php bin/magento list</b></td><td><b>php bin/magento</b></td></tr><tr><td><span style="font-weight: 400;">清理缓存</span></td><td><b>php bin/magento cache:clean</b></td><td><b>php bin/magento c:c</b></td></tr><tr><td><span style="font-weight: 400;">禁用缓存</span></td><td><b>php bin/magento cache:disable</b></td><td><b>php bin/magento c:d</b></td></tr><tr><td><span style="font-weight: 400;">启用缓存&nbsp;</span></td><td><b>php bin/magento cache:enable</b></td><td><b>php bin/magento c:e</b></td></tr><tr><td><span style="font-weight: 400;">刷新缓存</span></td><td><b>php bin/magento cache:flush</b></td><td><b>php bin/magento c:f</b></td></tr><tr><td><span style="font-weight: 400;">检查缓存的状态</span></td><td><b>php bin/magento cache:status</b></td><td><b>php bin/magento c:s</b></td></tr><tr><td><span style="font-weight: 400;">创建管理员账户&nbsp;</span></td><td><b>php bin/magento admin:user:create</b></td><td><b>php bin/magento a:u:c</b></td></tr><tr><td><span style="font-weight: 400;">解锁管理员帐户</span></td><td><b>php bin/magento admin:user:unlock</b></td><td><b>php bin/magento a:u:u</b></td></tr><tr><td><span style="font-weight: 400;">创建应用程序的转储&nbsp;</span></td><td><b>php bin/magento app:config:dump</b></td><td></td></tr><tr><td><span style="font-weight: 400;">将数据从共享文件导入到适当的数据存储e</span></td><td><b>php bin/magento app:config:import</b></td><td></td></tr><tr><td><span style="font-weight: 400;">调整图像大小&nbsp;</span></td><td><b>php bin/magento catalog:images:resize</b></td><td><b>php bin/magento c:i:r</b></td></tr><tr><td><span style="font-weight: 400;">删除未使用的产品属性&nbsp;</span></td><td><b>php bin/magento catalog:product:attribute:cleanup&nbsp;</b></td><td><b>php bin/magento c:p:a:c</b></td></tr><tr><td><span style="font-weight: 400;">设置sensitive配置值</span></td><td><b>php bin/magento config:sensitive:set</b></td><td></td></tr><tr><td><span style="font-weight: 400;">更改系统配置</span></td><td><b>php bin/magento config:set</b></td><td></td></tr><tr><td><span style="font-weight: 400;">显示给定路径的配置值。如果未指定路径，则将显示所有值</span></td><td><b>php bin/magento config:show</b></td><td></td></tr><tr><td><span style="font-weight: 400;">为当前用户生成并安装 crontab</span></td><td><b>php bin/magento cron:install</b></td><td></td></tr><tr><td><span style="font-weight: 400;">从 crontab 中删除任务&nbsp;</span></td><td><b>php bin/magento cron:remove</b></td><td></td></tr><tr><td><span style="font-weight: 400;">按计划运行cron jobs</span></td><td><b>php bin/magento cron:run</b></td><td><b>php bin/magento c:r</b></td></tr><tr><td><span style="font-weight: 400;">根据最新算法升级客户的哈希值</span></td><td><b>php bin/magento customer:hash:upgrade</b></td><td><b>php bin/magento c:h:u</b></td></tr><tr><td><span style="font-weight: 400;">设置应用模式</span></td><td><b>php bin/magento deploy:mode:set</b></td><td><b>php bin/magento d:m:set</b></td></tr><tr><td><span style="font-weight: 400;">显示当前应用模式</span></td><td><b>php bin/magento deploy:mode:show</b></td><td><b>php bin/magento d:m:sho</b></td></tr><tr><td><span style="font-weight: 400;">获取命令的依赖注入配置信息</span></td><td><b>php bin/magento dev:di:info</b></td><td></td></tr><tr><td><span style="font-weight: 400;">禁用数据库查询日志记录g</span></td><td><b>php bin/magento dev:query-log:disable</b></td><td></td></tr><tr><td><span style="font-weight: 400;">启用数据库查询日志记录</span></td><td><b>php bin/magento dev:query-log:enable</b></td><td></td></tr><tr><td><span style="font-weight: 400;">收集和发布主题的源文件。</span></td><td><b>php bin/magento dev:source-theme:deploy</b></td><td><b>php bin/magento d:s:d</b></td></tr><tr><td><span style="font-weight: 400;">禁用前端模板提示。需要缓存刷新。</span></td><td><b>php bin/magento dev:template-hints:disable</b></td><td></td></tr><tr><td><span style="font-weight: 400;">启用前端模板提示。需要缓存刷新。</span></td><td><b>php bin/magento dev:template-hints:enable</b></td><td></td></tr><tr><td><span style="font-weight: 400;">运行测试</span></td><td><b>php bin/magento dev:tests:run</b></td><td><b>php bin/magento d:t:r</b></td></tr><tr><td><span style="font-weight: 400;">生成 URN 到 *.xsd 映射的目录，以便 IDE 突出显示 xml。</span></td><td><b>php bin/magento dev:urn-catalog:generate</b></td><td><b>php bin/magento d:u:g</b></td></tr><tr><td><span style="font-weight: 400;">使用 XSL 样式表转换 XML 文件</span></td><td><b>php bin/magento dev:xml:convert</b></td><td><b>php bin/magento d:x:c</b></td></tr><tr><td><span style="font-weight: 400;">显示允许的索引器</span></td><td><b>php bin/magento indexer:info</b></td><td><b>php bin/magento i:i</b></td></tr><tr><td><span style="font-weight: 400;">重新索引数据</span></td><td><b>php bin/magento indexer:reindex</b></td><td><b>php bin/magento i:rei</b></td></tr><tr><td><span style="font-weight: 400;">将索引器状态重置为无效</span></td><td><b>php bin/magento indexer:reset</b></td><td><b>php bin/magento i:res</b></td></tr><tr><td><span style="font-weight: 400;">设置索引模式类型</span></td><td><b>php bin/magento indexer:set-mode</b></td><td><b>php bin/magento i:set</b></td></tr><tr><td><span style="font-weight: 400;">显示索引模式</span></td><td><b>php bin/magento indexer:show-mode</b></td><td><b>php bin/magento i:sho</b></td></tr><tr><td><span style="font-weight: 400;">显示索引器的状态</span></td><td><b>php bin/magento indexer:status</b></td><td><b>php bin/magento i:sta</b></td></tr><tr><td><span style="font-weight: 400;">发现代码库中的短语</span></td><td><b>php bin/magento i18n:collect-phrases</b></td><td><b>php bin/magento i1:c</b></td></tr><tr><td><span style="font-weight: 400;">保存语言包</span></td><td><b>php bin/magento i18n:pack</b></td><td><b>php bin/magento i1:p</b></td></tr><tr><td><span style="font-weight: 400;">卸载语言包</span></td><td><b>php bin/magento i18n:uninstall</b></td><td><b>php bin/magento i1:u</b></td></tr><tr><td><span style="font-weight: 400;">显示 Magento 管理 URI</span></td><td><b>php bin/magento info:adminuri</b></td><td><b>php bin/magento i:a</b></td></tr><tr><td><span style="font-weight: 400;">打印可用备份文件列表</span></td><td><b>php bin/magento info:backups:list</b></td><td><b>php bin/magento i:b:l</b></td></tr><tr><td><span style="font-weight: 400;">显示可用货币列表</span></td><td><b>php bin/magento info:currency:list</b></td><td><b>php bin/magento i:c:l</b></td></tr><tr><td><span style="font-weight: 400;">显示对 Magento 框架的依赖数量</span></td><td><b>php bin/magento info:dependencies:show-framework</b></td><td><b>php bin/magento i:d:show-f</b></td></tr><tr><td><span style="font-weight: 400;">显示模块之间的依赖关系数</span></td><td><b>php bin/magento info:dependencies:show-modules</b></td><td></td></tr><tr><td><span style="font-weight: 400;">显示模块之间循环依赖的数量</span></td><td><b>php bin/magento info:dependencies:show-modules-circular</b></td><td></td></tr><tr><td><span style="font-weight: 400;">显示可用语言区域列表</span></td><td><b>php bin/magento info:language:list</b></td><td><b>php bin/magento i:l:l</b></td></tr><tr><td><span style="font-weight: 400;">显示可用时区列表</span></td><td><b>php bin/magento info:timezone:list</b></td><td><b>php bin/magento i:t:l</b></td></tr><tr><td><span style="font-weight: 400;">设置维护模式允许IP</span></td><td><b>php bin/magento maintenance:allow-ips</b></td><td><b>php bin/magento m:a</b></td></tr><tr><td><span style="font-weight: 400;">禁用维护模式</span></td><td><b>php bin/magento maintenance:disable</b></td><td><b>php bin/magento ma:d</b></td></tr><tr><td><span style="font-weight: 400;">启用维护模式</span></td><td><b>php bin/magento maintenance:enable</b></td><td><b>php bin/magento ma:e</b></td></tr><tr><td><span style="font-weight: 400;">显示维护模式状态</span></td><td><b>php bin/magento maintenance:status</b></td><td><b>php bin/magento ma:s</b></td></tr><tr><td><span style="font-weight: 400;">禁用指定模块</span></td><td><b>php bin/magento module:disable</b></td><td><b>php bin/magento mo:d</b></td></tr><tr><td><span style="font-weight: 400;">启用指定模块</span></td><td><b>php bin/magento module:enable</b></td><td><b>php bin/magento mo:e</b></td></tr><tr><td><span style="font-weight: 400;">显示模块状态</span></td><td><b>php bin/magento module:status</b></td><td><b>php bin/magento mo:s</b></td></tr><tr><td><span style="font-weight: 400;">卸载由 composer 安装的模块</span></td><td><b>php bin/magento module:uninstall</b></td><td><b>php bin/magento m:u</b></td></tr><tr><td><span style="font-weight: 400;">部署示例数据模块</span></td><td><b>php bin/magento sampledata:deploy</b></td><td><b>php bin/magento sa:d</b></td></tr><tr><td><span style="font-weight: 400;">从 composer.json 中删除所有示例数据包</span></td><td><b>php bin/magento sampledata:remove</b></td><td><b>php bin/magento sa:rem</b></td></tr><tr><td><span style="font-weight: 400;">重置所有示例数据模块以重新安装</span></td><td><b>php bin/magento sampledata:reset</b></td><td><b>php bin/magento sa:res</b></td></tr><tr><td><span style="font-weight: 400;">备份 Magento 应用程序代码库、媒体和数据库</span></td><td><b>php bin/magento setup:backup</b></td><td><b>php bin/magento s:b</b></td></tr><tr><td><span style="font-weight: 400;">创建或修改部署配置	</span></td><td><b>php bin/magento setup:config:set</b></td><td><b>php bin/magento s:c:s</b></td></tr><tr><td><span style="font-weight: 400;">运行为安装应用程序安排的 cron job</span></td><td><b>php bin/magento setup:cron:run</b></td><td><b>php bin/magento s:c:r</b></td></tr><tr><td><span style="font-weight: 400;">安装和升级数据库中的数据</span></td><td><b>php bin/magento setup:db-data:upgrade</b></td><td><b>php bin/magento s:db-d:u</b></td></tr><tr><td><span style="font-weight: 400;">安装和升级数据库架构</span></td><td><b>php bin/magento setup:db-schema:upgrade</b></td><td><b>php bin/magento s:db-s:u</b></td></tr><tr><td><span style="font-weight: 400;">检查数据库架构或数据是否需要升级</span></td><td><b>php bin/magento setup:db:status</b></td><td><b>php bin/magento s:d:s</b></td></tr><tr><td><span style="font-weight: 400;">生成可自动生成的 DI 配置和所有缺失的类</span></td><td><b>php bin/magento setup:di:compile</b></td><td><b>php bin/magento s:d:c</b></td></tr><tr><td><span style="font-weight: 400;">安装 Magento 应用程序</span></td><td><b>php bin/magento setup:install</b></td><td><b>php bin/magento s:i</b></td></tr><tr><td><span style="font-weight: 400;">生成夹具</span></td><td><b>php bin/magento setup:performance:generate-fixtures</b></td><td><b>php bin/magento s:p:g</b></td></tr><tr><td><span style="font-weight: 400;">回滚 Magento 应用程序代码库、媒体和数据库</span></td><td><b>php bin/magento setup:rollback</b></td><td><b>php bin/magento se:r</b></td></tr><tr><td><span style="font-weight: 400;">部署静态视图文件</span></td><td><b>php bin/magento setup:static-content:deploy</b></td><td><b>php bin/magento s:s:d</b></td></tr><tr><td><span style="font-weight: 400;">安装商店配置。自 2.2.0 起已弃用。使用 config:set 代替</span></td><td><b>php bin/magento setup:store-config:set</b></td><td><b>php bin/magento s:s:s</b></td></tr><tr><td><span style="font-weight: 400;">卸载 Magento 应用程序</span></td><td><b>php bin/magento setup:uninstall</b></td><td><b>php bin/magento s:un</b></td></tr><tr><td><span style="font-weight: 400;">升级 Magento 应用程序、数据库数据和架构</span></td><td><b>php bin/magento setup:upgrade</b></td><td><b>php bin/magento s:up</b></td></tr><tr><td><span style="font-weight: 400;">显示商店列表</span></td><td><b>php bin/magento store:list</b></td><td></td></tr><tr><td><span style="font-weight: 400;">显示网站列表</span></td><td><b>php bin/magento store:website:list</b></td><td></td></tr><tr><td><span style="font-weight: 400;">卸载主题</span></td><td><b>php bin/magento theme:uninstall</b></td><td><b>php bin/magento t:u</b></td></tr><tr><td><span style="font-weight: 400;">生成Varnish VCL 并将其回显到命令行</span></td><td><b>php bin/magento varnish:vcl:generate</b></td><td></td></tr></tbody></table>
<p>要了解有关命令的更多信息，您可以查看<a href="https://devdocs.magento.com/guides/v2.4/config-guide/cli/config-cli-subcommands.html" rel="noopener noreferrer nofollow">Magento的官方指南</a>。我们希望这将帮助您节省更多时间，以便您可以更加专注于您的工作。</p>
<style>
table, table td, table th {
    border: 1px solid #ddd;
    padding: 8px;
    text-align: center;
    vertical-align: middle;
}
blockquote, hr, pre, table {
    margin-top: 8px;
    margin-bottom: 24px;
}
</style>]]></description>
      <pubDate>Mon, 19 Jul 2021 07:32:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2下载-开源版本]]></title>
      <link>https://www.360magento.com/blog/magento-2-download-all/</link>
      <description><![CDATA[<p><span style="font-weight: 400;">要使用Magento 2，用户必须在官方网站资源上下载Magento 2。但是需要登录或注册新帐户，Magento 2下载变得麻烦或花费大量时间。&nbsp;</span></p>
<p><span style="font-weight: 400;">因此，我们想向您介绍一种更简单，更快速的下载Magento 2的方法。</span></p>
<p><span style="font-weight: 400;">您可以直接在本文中下载Magento 2，而无需经历冗长而复杂的步骤。更重要的是，当Magento正式投放市场时，360Magento将尽我们最大的努力不断更新并为您提供最新版本。</span></p>
<p>让我们立即开始Magento免费下载！</p>
<h3><strong>带有示例数据和没有示例数据的Magento 2下载</strong></h3>
<p><span style="font-weight: 400;">下载Magento 2 zip包，您可以选择2个选项：带有示例数据下载和不带示例数据下载。那么您应该下载哪一个呢？我们将详细解释如下：</span></p>
<p><span style="font-weight: 400;">对于带有示例数据的Magento zip下载，您将拥有一个完整的店铺以及产品，类别和其他数据。该店铺提供Luma主题以及默认的Magento 2网站的所有完整功能。</span></p>
<p><span style="font-weight: 400;">因此，将Magento 2与示例数据一起使用将帮助您体验默认网站，并详细了解Magento管理员以及前端中的配置如何执行。 </span></p>
<p><span style="font-weight: 400;">如果是不带示例数据的Magento zip下载，那么的店铺就没有任何体验数据，只是一个网站框架。 </span></p>
<p><span style="font-weight: 400;"><strong>*注意</strong>：我们将以.zip格式提供文件，该文件易于处理Magento下载文件。</span></p>
<blockquote>
<p><strong></strong> 在免费下载Magento之前，请先<strong>检查</strong><a href="https://latest-m2.360magento.com/" rel="noopener noreferrer" target="_blank">Magento 2演示</a>以进行检查。</p>
</blockquote>
<h3><span style="font-weight: 400;"><strong>Magento 2</strong></span><span style="font-weight: 400;"><strong>下载</strong></span><span style="font-weight: 400;"><strong>最新版本&ndash; v2.4.x</strong></span></h3>
<p><span style="font-weight: 400;">Magento开源2.4.2包含280多个核心代码修复，35个安全增强功能以​​及社区成员解决的约290个GitHub问题。安全性增强包括扩展了对所有cookie的`SameSite`属性的支持。现在支持Elasticsearch 7.9.x和Redis6.x。</span></p>
<table><colgroup> <col width="15%" /> <col width="15%" /> <col width="15%" /> <col width="55%" /> </colgroup>
<tbody>
<tr>
<td><strong>Magento 2.4.x</strong></td>
<td><strong>无样本数据</strong></td>
<td><strong>带有样本数据</strong></td>
<td><strong>Magento 2版本的主要特点</strong></td>
</tr>
<tr>
<td><strong>Magento 2.4.2-p1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.2-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.2-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>补丁 2.4.2-p1 是一个仅限安全的补丁，它为我们之前的季度版本 Magento 2.4.2 中发现的漏洞提供修复，以及应用于该版本的热修复。商家可以安装这些对时间敏感的安全修复程序，使他们的站点与最新的安全修复程序保持同步，而无需应用完整的季度版本提供的数百个功能修复程序和增强功能。在应用此补丁之前，您必须部署 Magento 2.4.2。</td>
</tr>
<tr>
<td><strong>Magento 2.4.2</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento开源2.4.2包含280多个核心代码修复，35个安全增强功能以​​及社区成员解决的约290个GitHub问题。安全性增强包括扩展了对所有cookie的`SameSite`属性的支持。现在支持Elasticsearch 7.9.x和Redis6.x。</td>
</tr>
<tr>
<td><strong>Magento 2.4.1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento开源2.4.1包含130多个核心代码修复，15个安全增强功能以​​及我们社区成员解决的大约300个GitHub问题。它引入了对性能和安全性的增强。安全性增强包括对Cookie的SameSite属性的支持以及对与付款相关和与订单相关的API端点的CAPTCHA保护。</td>
</tr>
<tr>
<td><strong>Magento 2.4.0-p1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.0-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>补丁2.4.0-p1是仅用于安全性的补丁，它提供了针对我们先前的季度版本Magento 2.4.0中已发现的漏洞的修复程序，以及应用于该版本的热修复程序。商家可以安装这些对时间敏感的安全修补程序，以使其站点与最新的安全修补程序保持最新，而无需应用整个季度版本（Magento 2.4.1）提供的数百个功能修补程序和增强功能。</td>
</tr>
<tr>
<td><strong>Magento 2.4.0</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.4.0包含100多个核心代码修复，30个安全增强功能以​​及我们社区成员解决的226个GitHub问题。它引入了对PHP 7.4，Elasticsearch 7.6.x和MySQL 8.0的支持。Authorize.Net和Braintree付款方式集成已从核心代码中删除。重大的安全更改包括默认情况下在Admin中启用两因素身份验证。</td>
</tr>
<tr>
<td><strong>Magento 2.4.0</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.4.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.4.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.4.0包含100多个核心代码修复，30个安全增强功能以​​及我们社区成员解决的226个GitHub问题。它引入了对PHP 7.4，Elasticsearch 7.6.x和MySQL 8.0的支持。Authorize.Net和Braintree付款方式集成已从核心代码中删除。重大的安全更改包括默认情况下在Admin中启用两因素身份验证。</td>
</tr>
<tr></tr>
</tbody>
</table>
<h3><strong>Magento 2下载：2.2.x和2.3.x版本 </strong></h3>
<p><span style="font-weight: 400;">Magento 2.3.x是Magento提供的用户的最新Magento 2版本。因此，我们将为您提供有关每个版本的更多详细信息，以便您获得更多的了解并下载Magento2。</span></p>
<table><colgroup> <col width="15%" /> <col width="15%" /> <col width="15%" /> <col width="55%" /> </colgroup>
<tbody>
<tr>
<td><strong>Magento 2.2.x和2.3.x</strong></td>
<td><strong>没有样本数据</strong></td>
<td><strong>带有样本数据</strong></td>
<td><strong>每个Magento 2版本的主要特点</strong></td>
</tr>
<tr>
<td><strong>Magento 2.3.7</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.3.7 包括针对核心产品的重大平台升级、40 项安全增强和 15 项功能修复。它引入了对 PHP 7.4 的支持以及对PHP 7.1和7.2 的弃用。它现在与 Composer 2.x 兼容。现在支持 Elasticsearch 7.9.x 和 Redis 6.x。</td>
</tr>
<tr>
<td><strong>Magento 2.3.6-p1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.6-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.6-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>补丁 2.3.6-p1 是一个仅限安全的补丁，它为我们在上一季度发布的 Magento 2.3.6 中发现的漏洞提供修复，以及应用于该版本的热修复。商家可以安装这些对时间敏感的安全修复程序，使他们的站点与最新的安全修复程序保持同步，而无需应用完整的季度版本提供的数百个功能修复程序和增强功能。
在应用此补丁之前，您必须部署 Magento 2.3.6 并更新到 PHP 7.3。</td>
</tr>
<tr>
<td><strong>Magento 2.3.6</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.3.6包括将近200个对核心代码的修复和15个安全性增强。安全性增强包括对Cookie的SameSite属性的支持以及对与付款相关和与订单相关的API端点的CAPTCHA保护。这是包含功能修复程序的2.3.x产品系列中的最新版本。</td>
</tr>
<tr>
<td><strong>Magento 2.3.5-p2</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.5-p2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>修补程序2.3.5-p2是仅用于安全性的修补程序，它提供了针对我们上一季度版本Magento 2.3.5中已发现的漏洞的修复程序，以及应用于该版本的热修复程序。商家可以安装这些对时间敏感的安全修补程序，以使其站点与最新的安全修补程序保持最新，而无需应用整个季度版本（Magento 2.3.5）提供的数百个功能修补程序和增强功能。</td>
</tr>
<tr>
<td><strong>Magento 2.3.5-p1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.5-p1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento开源2.3.5-p1包含对核心产品的180多个功能修复，25个安全增强功能以​​及社区成员解决的46多个问题。此版本包括对Elasticsearch 7.x的支持，对核心Framework组件的升级以及从Zend框架到Laminas的迁移。</td>
</tr>
<tr>
<td><strong>Magento 2.3.4</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.3.4包括对核心产品的150多个功能修复，32个安全增强功能以​​及社区成员解决的275多个问题。此版本包括框架增强和性能改进。自定义布局更新已被删除，布局更新已被弃用。</td>
</tr>
<tr>
<td><strong>Magento 2.3.3</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.3.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.3.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento2.3.3包含针对核心产品的170多个功能修复和75个安全增强功能。除了PHP 7.2.x，此版本还提供对PHP 7.3.x的支持。它还为核心支付方法引入了PSD2遵从性，以及不遵循PSD2的Cyber​​source和eWay支付模块的弃用。添加了对varnish v6.2.0的支持。</td>
</tr>
<tr>
<td><strong>Magento 2.3.2</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento Open Source 2.3.2包括对核心产品的200多个功能修复，350多个社区提交的拉取请求以及75个关键的安全性增强。商家将赞赏店面页面响应时间的改善。此版本还包括实质性的基础结构改进。</td>
</tr>
<tr>
<td><strong>Magento 2.3.1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td>Magento2.3.1为商户和开发人员提供了重要的新工具，并进行了30多项核心安全改进。商家将赞赏改进的Admin订单创建工作流程。此版本还提供对Elasticsearch 6.0的支持，它是一个新的Authorize.Net扩展，以取代Authorize.Net Direct Post模块，并增强了Progressive Web Apps（PWA）Studio和GraphQL</td>
</tr>
<tr>
<td><strong>Magento 2.3.0</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.3.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.3.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括一些有趣的功能：</span><span style="font-weight: 400;">新的API；&nbsp;</span><span style="font-weight: 400;">渐进式Web应用程序（PWA）；&nbsp;</span><span style="font-weight: 400;">声明式数据库架构；&nbsp;</span><span style="font-weight: 400;">缓存管理访问控制级别（ACL）；&nbsp;</span><span style="font-weight: 400;">多源清单（MSI），&nbsp;</span><span style="font-weight: 400;">页面生成器；&nbsp;</span><span style="font-weight: 400;">Elasticsearch v.5;&nbsp;</span><span style="font-weight: 400;">所见即所得的变化；和&nbsp;</span><span style="font-weight: 400;">Google reCAPTCHA和两因素身份验证</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.7</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.2.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.2.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括</span><span style="font-weight: 400;">对产品安全性的30个关键增强；&nbsp;</span><span style="font-weight: 400;">超过150个核心代码修复和增强功能；以及&nbsp;</span><span style="font-weight: 400;">超过350个社区提交的请求。</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.6</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.2.6.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.2.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括</span><span style="font-weight: 400;">针对目录索引的性能调整增强功能；</span><span style="font-weight: 400;">提高了结帐流程的可靠性和易用性；&nbsp;</span><span style="font-weight: 400;">现在，可配置产品按可见价格按预期排序，&nbsp; </span><span style="font-weight: 400;">Magento不再发送重复的删除请求</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.5</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.2.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.2.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括</span><span style="font-weight: 400;">有关存储XSS，SQL注入和跨站点请求伪造（CSRF）漏洞的增强功能；&nbsp;</span><span style="font-weight: 400;">解决多个网站升级到Magento 2.2.4时的问题；&nbsp;</span><span style="font-weight: 400;">大幅改善索引性能；&nbsp;</span><span style="font-weight: 400;">对我们核心捆绑扩展程序的改进。</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.4</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.2.4.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.2.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括以下许多重要更改：</span><span style="font-weight: 400;">支持新的付款捆绑扩展：Amazon Pay，Vertex，Klarna；&nbsp;</span><span style="font-weight: 400;">增强Magento的运输和dotmailer；&nbsp;</span><span style="font-weight: 400;">改善网站性能，例如通过加载图片来加快购物速度，并</span><span style="font-weight: 400;">优化搜索性能</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.3</strong></td>
<td><a href="https://github.com/magento2-download/magento-2.x/releases/download/2.2.3/Magento-CE-2.2.3.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.2.3/Magento-CE-2.2.3_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括产品安全性增强，支持即将进行的USPS发货更改，版权更新，对Elasticsearch 5.0.x的支持以及对通过Magento Admin进行缓存管理的ACL控制的增强。</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.2</strong></td>
<td><a href="https://github.com/magento2-download/magento-CE-2.2.2/releases/download/2.2.2/Magento-CE-2.2.2.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.2.2-sample/releases/download/2.2.2-sample/Magento-CE-2.2.2_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">带来了一个新的即时购买选项，集成的dotmailer营销自动化软件，Magento Shipping，以及社区中的其他功能修复和增强功能。</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.1</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-CE-2.2.1/releases/download/2.2.1/Magento-CE-2.2.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.2.1-sample/releases/download/2.2.1-sample/Magento-CE-2.2.1_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">增强您的Magento软件的安全性和多项功能修复，并包括集成的Signifyd欺诈保护。</span></td>
</tr>
<tr>
<td><strong>Magento 2.2.0</strong></td>
<td><a href="https://github.com/magento2-download/2.2.0/releases/download/magento2.2.0/Magento-CE-2.2.0.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.2.0/Magento-CE-2.2.0_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="font-weight: 400;">包括许多修补程序和新功能，例如捆绑的扩展，通过改进索引编制和缓存操作以及安全性增强而带来的更好的性能。</span></td>
</tr>
</tbody>
</table>
<h3><span class="ez-toc-section" id="Magento_2_Download_2_1_x_versions"></span><strong style="font-family: Oswald; font-size: 33px;">Magento 2下载：2.1.x版本</strong><span class="ez-toc-section-end"></span></h3>
<table><colgroup> <col width="200px" /> <col width="200px" /> <col width="200px" /> </colgroup>
<tbody>
<tr>
<td><strong>Magento 2.1.x版本</strong></td>
<td><strong>没有样本数据</strong></td>
<td><strong>带有样本数据</strong></td>
</tr>
<tr>
<td><strong>Magento 2.1.14</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.1.14.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.14.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.13</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.13.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.13.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.12</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.12.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.12.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.11</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.11.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.11.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.10</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.10.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.1.10/Magento-CE-2.1.10_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.9</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-CE-2.1.9/releases/download/magento-2.1.9/Magento-CE-2.1.9.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.1.9/Magento-CE-2.1.9_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.8</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-CE-2.1.8/releases/download/2.1.8/Magento-CE-2.1.8.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.1.8/Magento-CE-2.1.8_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.7</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-CE-2.1.7/releases/download/2.1.7/Magento-CE-2.1.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-2.x-sample/releases/download/2.1.7/Magento-CE-2.1.7_sample_data.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.6</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento2-download/magento-CE-2.1.6/releases/download/2.1.6/Magento-CE-2.1.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.5</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.4</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.3</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.3.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.3.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.2</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.1</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><span style="color: #000000;"><strong>Magento 2.1.0</strong></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.1.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.1.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
</tbody>
</table>
<h3><span class="ez-toc-section" id="Magento_2_Download_2_0_x_versions"></span><strong style="font-family: Oswald; font-size: 33px;">Magento 2下载：2.0.x版本</strong><span class="ez-toc-section-end"></span></h3>
<table><colgroup> <col width="200px" /> <col width="200px" /> <col width="200px" /> </colgroup>
<tbody>
<tr>
<td><strong>Magento 2.0.x版本</strong></td>
<td><strong>没有样本数据</strong></td>
<td><strong>带有样本数据</strong></td>
</tr>
<tr>
<td><strong>Magento 2.0.18</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.0.18.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.18.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.17</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.17.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.17.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.16</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.16.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.16.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.15</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.15.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.15.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.14</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.14.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.14.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.13</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.13.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.13.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.12</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.0.12.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.12.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.11</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.0.11.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.11.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.10</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.10.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.10.zip" rel="nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.9</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.9.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.9.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.8</strong></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2/archive/2.0.8.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.8.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.7</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.7.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.7.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.6</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.6.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.6.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.5</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.5.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.5.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.4</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.4.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.4.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.3</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.3.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.3.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.2</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.2.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.2.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.1</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.1.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.1.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
<tr>
<td><strong>Magento 2.0.0</strong></td>
<td><a href="https://github.com/magento/magento2/archive/2.0.0.zip" rel="noopener noreferrer nofollow" target="_blank"><span style="font-weight: 400;"><span style="color: #ff6600;">下载</span></span></a></td>
<td><span style="color: #ff6600;"><a href="https://github.com/magento/magento2-sample-data/archive/2.0.0.zip" rel="noopener noreferrer nofollow" style="color: #ff6600;" target="_blank"><span style="font-weight: 400;">下载</span></a></span></td>
</tr>
</tbody>
</table>
<p>此外，这里有一些非常有用的文章，可帮助您获得有关Magento方面和相关问题的更多知识和理解：下载Magento之后，您必须了解安装Magento 2的要求。</p>
<blockquote>
<p><strong>请查看</strong> <span style="color: #ff6600;"><a href="https://devdocs.magento.com/guides/v2.4/install-gde/system-requirements.html" rel="noopener nofollow noreferrer" style="color: #ff6600;" target="_blank">Magento 2系统要求</a></span>以了解您应该遵循的要求。</p>
</blockquote>
<p>我们希望您喜欢这些Magento免费下载并及时更新您的网站以获得新的和高级的功能。</p>
<p>360Magento是中国领先的Magento定制开发服务商之一。我们拥有经验丰富且经过认证的Magento开发人员，致力于提供高质量的产品和服务，以有效地优化我们的业务。</p>
<p>现在就<span style="color: #ff6600;"><a href="https://www.360magento.com/contacts" rel="noopener noreferrer" style="color: #ff6600;" target="_blank">联系</a></span>，让我们知道您的问题。我们愿意随时为您提供支持。</p>
<style><!--
tbody tr:nth-child(2n+1) td {
    background: rgba(0, 0, 0, 0.03);
}
--></style>]]></description>
      <pubDate>Sun, 20 Dec 2020 02:11:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Paypal在Magento 1下线前的公告]]></title>
      <link>https://www.360magento.com/blog/paypal-magento-1-eol-announcement/</link>
      <description><![CDATA[<p><a href="#paypal-magento-1-eol-announcement"><strong>该公告中提到了什么？</strong></a></p>
<p><a href="#magento-1-eol-consequences"><strong>我们为什么要关心？</strong></a></p>
<p><a href="#Non-PCI-DSS-compliant">1.不符合PCI DSS规定的Magento商家可能被罚款100,000美元</a></p>
<p><a href="#paypal-end-support-magento-1">2. PayPal可能随时终止对Magento 1系统的支持</a></p>
<p><a href="#visa-magento-announcement">3.不仅PayPal向Magento系统发出警告</a></p>
<p><a href="#magento-1-data-breaches">4.数据泄露将损害Magento商家的声誉</a></p>
<p><a href="#magento-1-end-of-life-risks">5.即将来临的更多风险&hellip;&hellip;</a></p>
<p><a href="#magento-2-migration"><strong>不要惊慌。有解决办法！</strong></a></p>
<p><a href="#conclusion"><strong>结尾</strong></a></p>
<h2 id="paypal-magento-1-eol-announcement">该公告中提到了什么？</h2>
<p>最近，许多Magento 1网站的所有者都收到了一封电子邮件，通知他们Magento 1.x平台寿命终止。令人惊讶的是，该电子邮件不是来自Magento，而是来自PayPal。它提醒商家有关Magento 1停止日期，提及其相关风险并建议及时进行Magento 2迁移：</p>
<p><img alt="贝宝将停止支持magento 1" src="https://www.360magento.com/media/wysiwyg/blog_280/will-paypal-stop-supporting-magento-1-667x899.png" /></p>
<p>同时，贝宝（PayPal）指出未迁移到其网站上的Magento 2的后果，并敦促商家采取适当的措施：</p>
<p><img alt="" src="https://www.360magento.com/media/wysiwyg/blog_280/paypal-ends-support-for-magento-1.png" /></p>
<h2 id="magento-1-eol-consequences">我们为什么要关心？</h2>
<p>尽管PayPal没有透露他们是否会停止为Magento商店提供支持，但它的公告强调了Magento 1 终结的威胁，以帮助商家了解他们将要面对的问题以及如何应对。</p>
<h3 class="has-vivid-cyan-blue-color has-text-color" id="Non-PCI-DSS-compliant">1.不符合PCI DSS规定的Magento商家每月可能被罚款100,000美元</h3>
<p>由于Magento 1 的终结，2020年6月之后可能不会再出现针对Magento 1漏洞的安全补丁。因此，商家很可能会脱离PCI DSS合规性。</p>
<p><strong> <em>什么是PCI DSS？</em> </strong></p>
<p>不仅Magento网站，世界上所有允许信用卡付款的电子商务网站都必须符合<a href="https://www.pcisecuritystandards.org/" rel="nofollow">Payment Card Industry Data Security Standards </a>（PCI DSS）的要求。</p>
<p>尽管PCI DSS仅由大型信用卡公司（VISA，Mastercard，Discover和American Express）管理，但无论选择哪种支付服务，都必须遵循其要求，以确保安全地传输，存储和处理持卡人信息。</p>
<p>这些要求一般管理的做法，例如限制对持卡人数据的访问和生成非默认密码，以及诸如防火墙和加密应用之类的。</p>
<p><em><strong>Magento 1系统违反了PCI DSS的哪些要求？</strong></em></p>
<p>按照<a href="https://www.pcisecuritystandards.org/documents/PCI_DSS-QRG-v3_2_1.pdf?agreement=true&amp;time=1587662200387" rel="nofollow"> PCI DSS要求 6</a>，电子商务商店需要&ldquo;通过安装供应商提供的安全补丁来开发和维护安全的系统和应用程序&hellip;&hellip;&rdquo;：</p>
<p><img alt="PCI DSS要求" src="https://www.360magento.com/media/wysiwyg/blog_280/pci-dss-requirements.png" /></p>
<p>从2020年7月起，如果没有重要的安全补丁，Magento 1商家就不可能满足上述要求！</p>
<p><em><strong>如果Magento系统不兼容PCI DSS，会发生什么？</strong></em></p>
<p>忽视PCI DSS合规性并不会带来任何好处。</p>
<p>首先，如果在网站上购物后泄露了客户信息（持卡人数据），Magento商家可能会面临5,000美元至100,000美元的巨额罚款，具体取决于情况的严重性，卡交易的数量以及商店的违规时间。</p>
<p>其次，那些Magento 1网站甚至会失去接受支付卡的能力。</p>
<h3 class="has-vivid-cyan-blue-color has-text-color" id="paypal-end-support-magento-1">2. PayPal可能随时终止对Magento 1网站的支持</h3>
<p>众所周知，贝宝（PayPal）在为客户提供快速安全的方式进行全球在线支付方面处于领先地位。该支付网关默认情况下与Magento平台集成在一起，以允许客户使用其借记卡或信用卡在线支付。因此，现在超过50％的Magento商店都使用PayPal作为其主要的支付网关。</p>
<p><em><strong>如果PayPal终止其对Magento 1商店的服务将有多糟糕？</strong></em></p>
<p>值得注意的是，不仅Magento商家，而且所有支付程序都必须符合PCI DSS。因此，如果在Magento 1终结后PayPal继续对Magento 1网站做出让步，可能会对其声誉造成负面影响。</p>
<p>此外，由于PayPal与Magento紧密合作，它将帮助Magento鼓励平台用户从Magento 1迁移到Magento 2。。</p>
<p><em><strong>由于上述原因，PayPal迟早可能会停止支持Magento 1网站，这可能会带来很多危害：</strong></em></p>
<p>在第一种情况下，假设Magento商店未及时更新PayPal的政策，并且仍在其网站上通过PayPal提供付款方式。由此，购物者无法处理付款并放弃了购物车。</p>
<p>在第二种情况下，假设Magento商家通过另一个支付网关快速替换PayPal；但是，买家没有找到熟悉且可靠的付款方式，于是他们离开了商店。</p>
<h3 class="has-vivid-cyan-blue-color has-text-color" id="visa-magento-announcement">3.不仅贝宝向Magento商店发出警告</h3>
<p>其他信用卡公司也很有可能会撤销Magento 1商店的处理信用卡交易的权利。</p>
<p>最近，<a href="http://usa.visa.com/content/dam/VCOM/global/support-legal/documents/acquirer-advisory-magento-migration.pdf" rel="nofollow">VISA</a>呼吁Magento商家从1迁移到2，或者从Magento迁移到另一个电子商务平台，以保持PCI兼容性。此外，他们指出了剩余的Magento 1平台带来的5种后果：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_280/visa-encourages-magento-migration-1024x432.png" /></p>
<p>当所有支付网关提供商拒绝时，Magento商店如何生存？</p>
<h3 class="has-vivid-cyan-blue-color has-text-color" id="magento-1-data-breaches">4.数据泄露将损害Magento商家的声誉</h3>
<p>除了罚款之外，Magento商店可能还会面临客户数量急剧减少和收入下降的问题。</p>
<p>一些报告显示，近70%的在线购买者将远离与不符合安全标准和数据泄露有关的电子商务。</p>
<p>此外，Magento 1商家在被信息被盗的买家起诉时，应做好更糟糕的准备。另外，他们可能必须通过信用监控或身份盗窃保险来补偿持卡人，这绝对不便宜。</p>
<h3 class="has-vivid-cyan-blue-color has-text-color" id="magento-1-end-of-life-risks">5.即将来临的更多风险&hellip;&hellip;</h3>
<p>Magento 1终结可能导致比想象的还要糟糕的情况。</p>
<p>例如，它为黑客追踪Magento网站中的不安全漏洞创造了有利条件。现在，他们可以窃取客户的信用卡和订单详细信息以及其他机密商业信息。此外，如果黑客成功删除了网站数据，则Magento商店可能会经历漫长的网站停机时间。</p>
<p><img alt="magento 1寿命终止的后果" src="https://www.360magento.com/media/wysiwyg/blog_280/consequences-of-magento-1-end-of-life-1024x614.jpg" /></p>
<p>此外，大多数Magento开发公司现在已将注意力转移到Magento 2开发上。如果网站被黑客入侵，对于Magento商店所有者来说，向这些公司寻求帮助将具有挑战性。换句话说，他们将不得不弄清楚如何自己解决问题。</p>
<h2 id="magento-2-migration">不要惊慌。有解决办法！</h2>
<p>根据PayPal和VISA的建议，Magento商店应尽快开始Magento 2迁移或更改为另一个电子商务平台。</p>
<p>与将网站更改为完全不同的平台相比，更推荐使用Magento的最新版本。本质上，Magento 1和Magento 2的工作方式相似，只是界面和功能得到了改善。</p>
<p>如果您想将Magento 1迁移到2，选择我们的<a href="https://www.360magento.com/magento-migration">Magento 2迁移服务</a>将帮助您以最实惠的价格进行magento迁移。在2020年6月，我们提供了诱人的折扣&ndash;所有Magento 2迁移项目的将优惠10%。立即与我们联系（sales@360magento.com），以获得完善的计划和免费的迁移报价！</p>
<p><img alt="magento 1 下线解决方案" src="https://www.360magento.com/media/wysiwyg/blog_280/magento-1-eol-solution.png" /></p>
<h2 id="conclusion">结尾</h2>
<p>Magento 1 下线是不可避免的。到目前为止，只有PayPal和VISA警告Magento商店注意Magento 1终止支持。但是，可能有许多支付业务公司将关闭这些商店的大门。因此，所有Magento商家都应立即采取行动，从各种危险中解救其商店。</p>
<p><strong>相关文章：</strong></p>
<p><a href="https://www.360magento.com/blog/magento-1-end-of-life/">解答有关Magento 1生命终结（EOL）的所有问题</a></p>
<p><a href="https://www.360magento.com/blog/migrate-magento-1-9-x-to-2-3-x/">如何将Magento 1.9.x迁移到2.3.x</a></p>
<p><a href="https://www.360magento.com/blog/magento-migration-from-1-to-2/">Magento 1迁移到Magento2有什么好处？</a></p>]]></description>
      <pubDate>Thu, 04 Jun 2020 12:55:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[关于Magento1生命终结的话题]]></title>
      <link>https://www.360magento.com/blog/magento-1-end-of-life/</link>
      <description><![CDATA[<p>距Magento 1生命终结之日&ndash;2020年6月30日仅剩1个月的时间。因此，所有现有的Magento 1商店都必须尽快迁移到Magento 2。</p>
<p>在本文中，我们将回答有关Magento 1生命终止的所有问题，并提出如何处理它的建议。</p>
<ol>
<li><a href="#Why-Is-Magento-1-End-Of-Life">是什么导致Magento 1生命终结？</a></li>
<li><a href="#What-Are-Impacts-Of-Magento-1-End-Of-Life-To-Your-Website">Magento 1生命终止对您的网站有什么影响？</a></li>
<li><a href="#solution-for-magento-1-end-of-support">现有的Magento 1商店有什么解决方案？</a></li>
<li><a href="#How-Does-The-Magento-2-Migration-Process-Work">Magento 2迁移过程如何工作？</a></li>
<li><a href="#What-To-Expect-From-Magento-2-Website">从Magento 2网站可以期待什么？</a></li>
<li><a href="#When-Should-You-Migrate-Your-Website">您应何时迁移到Magento 2？</a></li>
</ol>
<p></p>
<h2>1.是什么导致Magento 1生命终止？</h2>
<p>自2014年中以来，Magento 1在新功能开发方面未进行任何更新，仅发布了一些可解决安全问题的补丁。原因很简单，Magento将所有精力都投入了Magento 2框架。</p>
<p>Magento为什么放弃&ldquo;第一个孩子&rdquo;？为什么它不同时培育Magento 1和2？</p>
<p><img alt="magento 1 eol公告" src="https://www.360magento.com/media/wysiwyg/blog_279/01.jpg" /></p>
<p>这样做的主要原因有3个。</p>
<p><em>首先，</em>关于Magento 1的投诉很多，例如性能差，页面加载速度慢，管理面板不友好（技术含量过高），前端不吸引人（即使应用现成的主题）等等。为了改善所有这些弱点，Magento几乎需要从头开始构建所有内容。实际上，他们是通过引入Magento 2做到这一点的。</p>
<p><em>其次，</em>假设Magento 1是免费的，而Magento 2是高级版本，那么Magento可以使它们两者都满足不同的需求。但事实不是这样的。Magento 1和2都有免费和付费版本（开源和商业版）。当以相同的比例放置时，绝对没有人会以相同的价格购买更好的版本（Magento 2），而选择Magento 1。因此，当继续提供旧版本时，Magento没有经济利益。</p>
<p><em>第三，</em> Magento 1逐渐弱化了Magento。将Magento与其他电子商务平台进行比较时，许多人会利用它来批评Magento。因此，Magento继续提供Magento 1平台弊大于利。</p>
<p>到目前为止，Magento维持对Magento 1的支持的唯一原因是仍然有大量的Magento 1商店。在Magento 1使用寿命终止日期之前这些商店所有者需要一些时间才能将其网站迁移。</p>
<p></p>
<h2>2. Magento 1生命终止对您的网站有什么影响？</h2>
<p>Magento 1寿命终止会带来一系列后果。</p>
<p>从2020年7月开始，Magento不再提供任何官方安全补丁。这意味着什么你？</p>
<p><img alt="magento 1支持何时结束" src="https://www.360magento.com/media/wysiwyg/blog_279/02.jpg" /></p>
<p>您的Magento商店安全性可能无法保证。一些黑客可能会抓住Magento 1的安全漏洞，以窃取您网站上的关键数据，甚至使您的网站崩溃。数据丢失，尤其是客户的个人信息丢失，将严重损害您的业务。&nbsp;</p>
<p>如果Magento 1终止其生命，那么您的扩展程序也可能会遇到许多麻烦。目前，从Magento官方，Magento开发人员，Magento服务商到Magento扩展提供商的几乎所有都将注意力转移到了Magento2。因此，如果您的Magento 1模块遇到任何问题，将很难找到人帮助。如果您没有内部开发人员，也找不到外部支持，您应该怎么做？</p>
<p></p>
<h2 class="has-luminous-vivid-orange-color has-text-color" id="solution-for-magento-1-end-of-support">3.现有的Magento 1商店有什么解决方案？</h2>
<p>Magento 1商家可以考虑迁移到另一个电子商务平台，例如Shopify，WooCommerce，BigCommerce，以应对Magento 1平台的结束。但是，最好的解决方案无疑是从Magento 1迁移到Magento 2。</p>
<p><img alt="magento 2迁移" src="https://www.360magento.com/media/wysiwyg/blog_279/03.jpg" /></p>
<p>如您所知，由于架构不同，在不同平台之间传输数据（产品，客户，订单等）的风险很大。另一方面，Magento提供了数据迁移工具来帮助商店所有者轻松地将数据库资产从Magento 1迁移到2。</p>
<p>此外，由于您已经熟悉了Magento平台，因此只需很少的时间即可熟悉Magento 2管理面板并有效地管理新站点。相比之下，如果决定使用全新的电子平台，则需要从头开始学习所有内容。</p>
<p></p>
<h2>4. Magento 2迁移过程如何工作？</h2>
<p>要将网站从Magento 1迁移到Magento 2，您的网站将执行以下一些基本步骤：</p>
<p><img alt="将magento 1迁移到2" src="https://www.360magento.com/media/wysiwyg/blog_279/04.png" /></p>
<h3><strong><em>迁移主题</em></strong></h3>
<p>由于Magento 2在编码方面与Magento 1完全不同，因此您的Magento 2网站必须具有新的主题。您可以在主题市场上轻松获得精美的现成的Magento 2网页设计模板。</p>
<p>但是，如果您对可用主题的质量/设计不满意，则应寻求定制Web设计服务。在360Magento，我们提供了许多选择，从克隆您当前的Magento 1设计到根据您的要求创建全新的设计不等。</p>
<h3><strong><em>迁移扩展</em></strong></h3>
<p>由于Magento 1的所有插件都与Magento 2不兼容，因此必须具有新的扩展。</p>
<p>好消息是，大多数Magento 1扩展都具有与Magento 2相似的版本。您需要做的是找到最佳替代品并将其安装在新站点上。</p>
<p>通常，当客户向我们发送迁移Magento 2的请求时，我们会要求他们提供其Magento 1模块的列表。然后，凭借我们的丰富经验，我们可以立即为M2提供最佳选择。有时，无需购买新插件，但我们将直接在新商店中开发自定义功能。</p>
<h3><strong><em>迁移资料</em></strong></h3>
<p>从Magento 1到2的数据传输无疑是最关键的一步。尽管我们可以使用Magento的官方数据迁移工具，但仍有很多事情要做。因此，该过程必须由专业/经验丰富的开发人员来实施，以避免数据丢失。</p>
<p>如果您需要360Magento来进行Magento 2迁移服务，尤其是数据迁移，我们将分两步执行数据迁移。首先，我们将创建一个备份并将数据从您当前的站点迁移到开发站点（在我们的服务器上）。其次，我们将再次将数据从开发站点传输到您的在线站点（在您选择的服务器上）。因此，在迁移过程中不会丢失任何东西。</p>
<h3><strong><em>迁移设置/配置 </em></strong></h3>
<p>语言，货币，付款，运输，电子邮件模板，商店信息&hellip;&hellip;在您当前的商店中，都需要重新设置以完成Magento 2迁移过程。</p>
<p></p>
<h2>5.您对Magento 2网站有什么期望？</h2>
<h3><em>网站速度快，<strong>性能</strong>稳定<strong></strong></em></h3>
<p>Magento 2上的默认Ajax购物车支持切换会话而无需重新加载整个页面，这将为您站点上的所有客户带来更好的体验。</p>
<p>另外，与旧版PHP版本相比，Magento 2的编程语言PHP 7提供了更高的负载。&nbsp;</p>
<p>缓存还可以提高站点性能。Magento 2使用Varnish缓存和HTTP加速器，可以轻松地缓存请求。</p>
<h3><strong><em>快速结帐</em></strong></h3>
<p>复杂的结帐增加了购物车的丢失率。为了解决这个问题，Magento 2提供了一页结帐，这比Magento 1快得多。</p>
<p><img alt="magento 2默认结帐" src="https://www.360magento.com/media/wysiwyg/blog_279/05.jpg" /></p>
<h3><strong><em>易于现代技术整合</em></strong></h3>
<p>有许多解决方案可将Magento 2网站与加速移动页面（AMP），渐进式Web应用程序（PWA）或其他先进技术集成在一起。但是，这些不适用于Magento 1平台。</p>
<p>完成Magento 2迁移后，使用AMP或PWA将您的网站提升到一个新水平将不再困难。</p>
<p></p>
<h2>6.您何时应该迁移到Magento 2？</h2>
<p>自Magento 2问世以来（距2015年7月）已有5年了。还可以理解，Magento已给企业所有者5年的时间为迁移做准备。如果您仍在使用Magento 1平台，那么您将错过多年提升店铺实力的绝佳机会。</p>
<p>再次提醒您，Magento将在2020年6月结束时停止支持Magento 1。如果您的网站尚未重新平台化，则应立即进行。</p>
<p><img alt="magento 1支持终止" src="https://www.360magento.com/media/wysiwyg/blog_279/06.jpg" /></p>
<p>尽快迁移到Magento 2的另一个原因是，360Magento为Magento迁移服务提供了最大促销：项目总成本的<strong>15％</strong>折扣。</p>
<p></p>
<h2>总结</h2>
<p>Magento 1生命终止对每个Magento电子商务业务都是不便之处。为了解决这个问题，没有比从1到2进行Magento迁移更好的选择了。</p>
<p>自2012年以来，凭借在Magento开发方面的综合经验，360Magento是许多商店店主想要升级其站点时的首选。我们希望很快收到您的来信！</p>]]></description>
      <pubDate>Thu, 21 May 2020 08:12:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中创建运输方式]]></title>
      <link>https://www.360magento.com/blog/magento-2-create-shipping-method/</link>
      <description><![CDATA[<p>电子商务就是为了客户便利。提供便利的运输方式是在线商店中客户体验的必然部分。默认情况下，有7种<a href="https://docs.magento.com/m2/ee/user_guide/configuration/sales/shipping-methods.html" target="_blank" rel="noopener noreferrer">Magento 2运送方式</a>：</p><ol><li>Free Shipping</li><li>Flat Rates</li><li>Table Rates</li><li>UPS</li><li>USPS</li><li>edEx</li><li>DHL</li></ol><p>您还可以学习如何轻松<a href="https://docs.magento.com/m2/ee/user_guide/shipping/magento-shipping-setup.html" target="_blank" rel="noopener noreferrer">配置Magento 2运送方式</a>。</p><p>然而，随着电子商务普及程度的提高，越来越多的类型的企业选择了在线购物平台，特别是Magento，因为它的功能和性能。但是，这些默认的运输方式还不足以满足目前所有类型的企业。</p><p>因此，我想出了一种编程方法来<i><strong>在Magento 2</strong></i>商店中<i><strong>创建运输方式</strong></i>。</p><p>考虑到业务需求而实施的定制运输方式是可行的选择。运输策略必须确保其在订单履行成本中所获得的收益不超过该订单所获利润。</p><p>理想的运输方式必须易于管理，快速且价格合理。并不是每个店主都能从默认的Magento 2送货方式中找到这样的送货方式。</p><p>在Magento 2商店中以编程方式创建适合您的业务需求并且可行的自定义运输方法，是拥有正确运输系统的最优化解决方案。</p><p>为什么我要强调优化运输策略呢？</p><p>以下统计信息解释了原因：</p><ol><li>61％的购物者表示由于额外的费用（例如运费）而退出交易– <a href="https://99firms.com/blog/ecommerce-statistics/#gref" target="_blank" rel="noopener noreferrer">99firms</a></li><li>79％的美国消费者表示免费送货将使他们更有可能在网上购物。– <a href="https://www.walkersands.com/wp-content/uploads/2018/07/Walker-Sands_2018-Future-of-Retail-Report.pdf" target="_blank" rel="noopener noreferrer">Walkersands</a></li><li>46.5％的中小型企业表示，提供免费送货可增加利润。– <a href="https://multichannelmerchant.com/blog/shopping-cart-abandonment-is-your-shipping-approach-hurting-your-conversions/" target="_blank" rel="noopener noreferrer">MCM</a></li></ol><h2>在Magento 2中创建运输方式的步骤：</h2><ol><li>在<strong>app/code/Alwayly/CustomShipping/registration.php</strong>中创建<strong>registration.php</strong>文件，&nbsp;并将以下代码添加到该文件中：<br>
<pre>
;&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
&nbsp; &nbsp; \Magento\Framework\Component\ComponentRegistrar::MODULE,
&nbsp; &nbsp; 'Alwayly_CustomShipping',
&nbsp; &nbsp; __DIR__
);
</pre>
</li><li>在<strong>app/code/Alwayly/CustomShipping/etc/module.xml</strong>中创建<strong>module.xml</strong>文件，并将以下代码添加到该文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
&nbsp; &nbsp; &lt;module name="Alwayly_CustomShipping" setup_version="1.0.0"&gt;
&nbsp; &nbsp; &lt;/module&gt;
&lt;/config&gt;
</pre>
</li>
<li>在<strong>app/code/Alwayly/CustomShipping/etc/adminhtml/system.xml</strong>中创建<strong>system.xml</strong>文件，&nbsp;并将以下代码添加到该文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"&gt;
&nbsp; &nbsp; &lt;system&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;group id="custom" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Custom Shipping&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Enabled&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Method Name&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="price" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Price&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;validate&gt;validate-number validate-zero-or-greater&lt;/validate&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="handling_type" translate="label" type="select" sortOrder="7" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Calculate Handling Fee&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Shipping\Model\Source\HandlingType&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="handling_fee" translate="label" type="text" sortOrder="8" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Handling Fee&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;validate&gt;validate-number validate-zero-or-greater&lt;/validate&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Sort Order&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Title&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Ship to Applicable Countries&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;frontend_class&gt;shipping-applicable-country&lt;/frontend_class&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Shipping\Model\Config\Source\Allspecificcountries&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Ship to Specific Countries&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Directory\Model\Config\Source\Country&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;can_be_empty&gt;1&lt;/can_be_empty&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Show Method if Not Applicable&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Displayed Error Message&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/group&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/section&gt;
&nbsp; &nbsp; &lt;/system&gt;
&lt;/config&gt;
</pre>
</li><li>在<strong>app/code/Alwayly/CustomShipping/etc/config.xml</strong>中创建<strong>config.xml</strong>文件，并将以下代码添加到该文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"&gt;
&nbsp; &nbsp; &lt;default&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;carriers&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;custom&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;active&gt;1&lt;/active&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;sallowspecific&gt;0&lt;/sallowspecific&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;model&gt;Alwayly\CustomShipping\Model\Carrier\Custom&lt;/model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;name&gt;Custom Shipping&lt;/name&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;price&gt;15.00&lt;/price&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;title&gt;Custom Method&lt;/title&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;type&gt;I&lt;/type&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;specificerrmsg&gt;This shipping method is not available right now.&lt;/specificerrmsg&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/custom&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/carriers&gt;
&nbsp; &nbsp; &lt;/default&gt;
&lt;/config&gt;
</pre>
</li><li>在<strong>app/code/Alwayly/CustomShipping/Model/Carrier/Custom.php</strong>中创建<strong>Custom.php</strong>文件，并将以下代码添加到此文件中：<br>
<pre>
&lt;?php

namespace Alwayly\CustomShipping\Model\Carrier;

use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Rate\Result;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
use Psr\Log\LoggerInterface;
use Magento\Shipping\Model\Rate\ResultFactory;
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;

class Custom extends AbstractCarrier implements CarrierInterface
{
&nbsp; &nbsp; protected $_code = 'custom';
&nbsp; &nbsp; protected $rateResultFactory;
&nbsp; &nbsp; protected $rateMethodFactory;

&nbsp; &nbsp; public function __construct(
&nbsp; &nbsp; &nbsp; &nbsp; ScopeConfigInterface $scopeConfig,
&nbsp; &nbsp; &nbsp; &nbsp; ErrorFactory $rateErrorFactory,
&nbsp; &nbsp; &nbsp; &nbsp; LoggerInterface $logger,
&nbsp; &nbsp; &nbsp; &nbsp; ResultFactory $rateResultFactory,
&nbsp; &nbsp; &nbsp; &nbsp; MethodFactory $rateMethodFactory,
&nbsp; &nbsp; &nbsp; &nbsp; array $data = []
&nbsp; &nbsp; ) {
&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;rateResultFactory = $rateResultFactory;
&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;rateMethodFactory = $rateMethodFactory;
&nbsp; &nbsp; &nbsp; &nbsp; parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
&nbsp; &nbsp; }

&nbsp; &nbsp; public function getAllowedMethods()
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; return ['custom' =&gt; $this-&gt;getConfigData('name')];
&nbsp; &nbsp; }

&nbsp; &nbsp; public function collectRates(RateRequest $request)
&nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; if (!$this-&gt;getConfigFlag('active')) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;
&nbsp; &nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; &nbsp; /** @var \Magento\Shipping\Model\Rate\Result $result */
&nbsp; &nbsp; &nbsp; &nbsp; $result = $this-&gt;rateResultFactory-&gt;create();

&nbsp; &nbsp; &nbsp; &nbsp; /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
&nbsp; &nbsp; &nbsp; &nbsp; $method = $this-&gt;rateMethodFactory-&gt;create();

&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setCarrier('custom');
&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setCarrierTitle($this-&gt;getConfigData('title'));

&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setMethod('custom');
&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setMethodTitle($this-&gt;getConfigData('name'));

&nbsp; &nbsp; &nbsp; &nbsp; /*you can fetch shipping price from different sources over some APIs, we used price from config.xml - xml node price*/
&nbsp; &nbsp; &nbsp; &nbsp; $amount = $this-&gt;getConfigData('price');

&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setPrice($amount);
&nbsp; &nbsp; &nbsp; &nbsp; $method-&gt;setCost($amount);

&nbsp; &nbsp; &nbsp; &nbsp; $result-&gt;append($method);

&nbsp; &nbsp; &nbsp; &nbsp; return $result;
&nbsp; &nbsp; }
}
</pre>
</li></ol><p>这就是在Magento 2中创建自定义送货方式的全部操作。创建Magento 2自定义送货方式后，其配置将在后端显示：</p><p>
<img src="https://www.360magento.com/media/wysiwyg/blog_278/shipping-method-configuration.png" alt="定制运输方式配置" />
</p><p>一旦配置并启用了自定义送货方式，它就会显示在前端：</p><p>
<img src="https://www.360magento.com/media/wysiwyg/blog_278/shipping-method-in-frontend.png" alt="前端中的自定义送货方式" /></p>]]></description>
      <pubDate>Wed, 25 Dec 2019 13:39:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中创建支付方式]]></title>
      <link>https://www.360magento.com/blog/m2-create-payment-method/</link>
      <description><![CDATA[<p>支付网关是确保电子商务业务安全的关键。选择适合您的业务类型的付款方式应引起适当注意。错误的选择将对您的支付系统造成灾难。客户的信任和忠诚度取决于您提供的付款处理系统。</p><h2>付款网关应该如何？</h2><ul><li>100％安全</li><li>与您的商店平台兼容</li><li>提供快速的付款流程</li><li>欺诈识别</li><li>开票功能</li><li>令人印象深刻的用户界面</li><li>可行的费用</li><li>支持国际支付</li><li>支援政策</li><li>支持的卡类型</li><li>支持定期付款</li><li>托管/非托管付款</li></ul><p>如果您是Magento商店的老板，则需要筛选出用于满足业务需求的支付网关。</p><p>但是，满足您所有要求的理想支付网关仅存在于并行世界中。但是，等等，您可以自行<i><strong>在Magento 2中创建付款方式</strong></i>！这篇文章向您展示了如何做到这一点。</p><h2>在Magento 2中创建付款方式的步骤：</h2><ol><li>在<strong>app/code/Alwayly/CustomPayment/registration.php</strong>中创建<strong>registration.php</strong>文件，并将以下代码添加到其中：<br>
<pre>&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
&nbsp; &nbsp; \Magento\Framework\Component\ComponentRegistrar::MODULE,
&nbsp; &nbsp; 'Alwayly_CustomPayment',
&nbsp; &nbsp; __DIR__
);</pre>
</li>
<li>在<strong>app/code/Alwayly/CustomPayment/etc/module.xml</strong>中创建<strong>module.xml</strong>文件，并将以下代码添加到此文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
&nbsp; &nbsp; &lt;module name="Alwayly_CustomPayment" setup_version="1.0.0"&gt;
&nbsp; &nbsp; &lt;/module&gt;
&lt;/config&gt;
</pre>
</li>
<li>在<strong>app/code/Alwayly/CustomPayment/etc/config.xml</strong>中创建<strong>config.xml</strong>文件，并将以下代码添加到该文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd"&gt;
&nbsp; &nbsp; &lt;default&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;payment&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;custompayment&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;payment_action&gt;authorize&lt;/payment_action&gt; &lt;!-- You can use another method --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;model&gt;Alwayly\CustomPayment\Model\PaymentMethod&lt;/model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;active&gt;1&lt;/active&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;title&gt;Custom Payment&lt;/title&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;order_status&gt;pending_payment&lt;/order_status&gt;&lt;!-- set default order status--&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/custompayment&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/payment&gt;
&nbsp; &nbsp; &lt;/default&gt;
&lt;/config&gt;
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/etc/adminhtml/system.xml</strong>中创建<strong>system.xml</strong>文件，并将以下代码添加到此文件中：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"&gt;
&nbsp; &nbsp; &lt;system&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;section id="payment"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;group id="custompayment" translate="label" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Custom Payment Method&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="active" translate="label comment" sortOrder="10" type="select" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Enable&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;field id="title" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;label&gt;Custom Payment&lt;/label&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/field&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/group&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/section&gt;
&nbsp; &nbsp; &lt;/system&gt;
&lt;/config&gt;
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/Model/PaymentMethod.php</strong>中创建<strong>PaymentMethod.php</strong>文件，&nbsp;将以下代码添加到此文件中：<br>
<pre>
&lt;?php
&nbsp;
namespace Alwayly\CustomPayment\Model;
&nbsp;
/**
&nbsp;* Pay In Store payment method model
&nbsp;*/
class PaymentMethod extends \Magento\Payment\Model\Method\AbstractMethod
{
&nbsp; &nbsp; /**
&nbsp; &nbsp; &nbsp;* Payment code
&nbsp; &nbsp; &nbsp;*
&nbsp; &nbsp; &nbsp;* @var string
&nbsp; &nbsp; &nbsp;*/
&nbsp; &nbsp; protected $_code = 'custompayment';
}
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/view/frontend/layout/checkout_index_index.xml</strong>中创建<strong>checkout_index_index.xml</strong>文件，并将以下代码添加到该文件：<br>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
&nbsp; &nbsp; &lt;body&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;referenceBlock name="checkout.root"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;arguments&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;argument name="jsLayout" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="components" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="checkout" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="children" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="steps" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="children" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="billing-step" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="component" xsi:type="string"&gt;uiComponent&lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="children" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="payment" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="children" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="renders" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- merge payment method renders here --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="children" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="custompayment" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="component" xsi:type="string"&gt;Emipro_Custompayment/js/view/payment/method-renderer&lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="methods" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="custompayment" xsi:type="array"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;item name="isBillingAddressRequired" xsi:type="boolean"&gt;true&lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/item&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/argument&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/arguments&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/referenceBlock&gt;
&nbsp; &nbsp; &lt;/body&gt;
&lt;/page&gt;
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/view/frontend/web/js/view/payment/method-renderer.js</strong>上创建<strong>method-renderer.js</strong>文件，并将以下代码添加到该文件中：<br>
<pre>
define(
&nbsp; &nbsp; [
&nbsp; &nbsp; &nbsp; &nbsp; 'uiComponent',
&nbsp; &nbsp; &nbsp; &nbsp; 'Magento_Checkout/js/model/payment/renderer-list'
&nbsp; &nbsp; ],
&nbsp; &nbsp; function (
&nbsp; &nbsp; &nbsp; &nbsp; Component,
&nbsp; &nbsp; &nbsp; &nbsp; rendererList
&nbsp; &nbsp; ) {
&nbsp; &nbsp; &nbsp; &nbsp; 'use strict';
&nbsp; &nbsp; &nbsp; &nbsp; rendererList.push(
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type: 'custompayment',
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component: 'Alwayly_CustomPayment/js/view/payment/method-renderer/custompayment'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; );
&nbsp; &nbsp; &nbsp; &nbsp; return Component.extend({});
&nbsp; &nbsp; }
);
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/view/frontend/web/js/view/payment/method-renderer/custompayment.js</strong>上创建<strong>custompayment.js</strong>文件，在&nbsp;此文件中添加以下代码：<br>
<pre>
define(
&nbsp; &nbsp; [
&nbsp; &nbsp; &nbsp; &nbsp; 'Magento_Checkout/js/view/payment/default'
&nbsp; &nbsp; ],
&nbsp; &nbsp; function (Component) {
&nbsp; &nbsp; &nbsp; &nbsp; 'use strict';
&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; return Component.extend({
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; defaults: {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; template: 'Alwayly_CustomPayment/payment/customtemplate'
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; });
&nbsp; &nbsp; }
);
</pre>
</li><li>在<strong>app/code/Alwayly/CustomPayment/view/frontend/web/template/payment/customtemplate.html</strong>上创建<strong>customtemplate.html</strong>文件，并将以下代码添加到此文件中：<br>
<pre>
&lt;div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"&gt;
&nbsp; &nbsp; &lt;div class="payment-method-title field choice"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;input type="radio"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;name="payment[method]"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;class="radio"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;label data-bind="attr: {'for': getCode()}" class="label"&gt;&lt;span data-bind="text: getTitle()"&gt;&lt;/span&gt;&lt;/label&gt;
&nbsp; &nbsp; &lt;/div&gt;
&nbsp; &nbsp; &lt;div class="payment-method-content"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko foreach: getRegion('messages') --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko template: getTemplate() --&gt;&lt;!-- /ko --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;!--/ko--&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;div class="payment-method-billing-address"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko template: getTemplate() --&gt;&lt;!-- /ko --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!--/ko--&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/div&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;div class="checkout-agreements-block"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko foreach: $parent.getRegion('before-place-order') --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!-- ko template: getTemplate() --&gt;&lt;!-- /ko --&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;!--/ko--&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/div&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;div class="actions-toolbar"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;div class="primary"&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;button class="action primary checkout"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type="submit"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data-bind="
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; click: placeOrder,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attr: {title: $t('Place Order')},
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; css: {disabled: !isPlaceOrderActionAllowed()},
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; enable: (getCode() == isChecked())
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; disabled&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;span data-bind="i18n: 'Place Order'"&gt;&lt;/span&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/button&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/div&gt;
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/div&gt;
&nbsp; &nbsp; &lt;/div&gt;
&lt;/div&gt;
</pre>
</li></ol><p>这就是在Magento 2商店中创建自定义付款方式的过程。该扩展程序将创建后端设置以启用付款方式并为其设置标题。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_277/custom-payment-method-configuration.png" alt="自定义付款方式创建"/>
</p>
<p>启用付款方式后，可以在检出产品时将其显示在前端：</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_277/custom-payment-method-in-frontend.png" alt="前端结帐页面上的自定义付款方式" />
</p>
]]></description>
      <pubDate>Mon, 23 Dec 2019 07:13:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中获取订单的付款方式名称]]></title>
      <link>https://www.360magento.com/blog/m2-get-payment-method-title-of-order/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_276/How-To-Get-Payment-Method-Title-Of-Order-In-Magento-2.png" alt=" How To Get Payment Method Title Of Order In Magento 2 如何在Magento 2中获取订单的付款方式名称" /></p>
<p>电子商务网站有时需要注意一些小细节，例如按钮的颜色，订单完成页面中的细节或显示什么订购信息！</p><p>这是因为每一步都在推动用户转化或改善客户体验方面发挥作用。</p><p>有这样的一个细节是<i><strong>在Magento 2中获得订单的付款方式名称</strong></i>。</p><p>作为后期购物体验的一部分，您将在Magento 2的“My Orders”部分中显示哪些订单信息。当客户检查“My Orders”部分以查找有关该订单的任何信息时，它应该存在。</p><p>但是，默认的Magento 2并未在Magento 2中包含所有订单付款信息。</p><p>因此，以下解决方案允许管理员在Magento 2中获得订单的付款方式名称。请记住您的业务性质和客户洞察力，以决定是否需要在Magento 2商店中添加订单付款信息。</p><h2>Magento 2中获取付款方式名称的方法：</h2><p>从订单中获取支付模型，然后从支付中获取方法实例：</p>
<pre>
$orderIncrementId=10000003;
$objectManager&nbsp;=&nbsp;\Magento\Framework\App\ObjectManager::getInstance();
$order&nbsp;=&nbsp;$objectManager-&gt;create('Magento\Sales\Model\Order')-&gt;loadByIncrementId($orderIncrementId)
​​​​​​​$payment = $order-&gt;getPayment();
$method = $payment-&gt;getMethodInstance();
$methodTitle = $method-&gt;getTitle();
</pre>
<p>其中<code>$order</code>&nbsp;是<code>Magento\Sales\Model\Order</code>的实例</p>]]></description>
      <pubDate>Fri, 20 Dec 2019 06:26:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中以编程方式创建客户组]]></title>
      <link>https://www.360magento.com/blog/m2-create-customer-group/</link>
      <description><![CDATA[<p>在Magento 2中以编程方式创建客户之后，您可能需要根据类似的购买行为对他们进行分组，比如说，要轻松地组织他们，给他们打折并限制对特定产品或类别的访问。Magento 2提供了一种将客户分为<a href="https://docs.magento.com/m2/ce/user_guide/customers/customer-groups.html" target="_blank" rel="noopener noreferrer">Magento 2客户组</a>的解决方案。</p><p>这种安排可以帮助商店所有者进行有针对性的客户管理和营销。根据客户组有效地管理用户体验，规则，税种等。</p><p>Magento 2的默认客户组是：</p><ul><li>General</li><li>Not Logged In</li><li>Wholesale</li></ul><p>但是，对于我们的开发人员而言，默认功能是远远不够的（或者可以说，对于客户的要）</p><p>使用自定义客户组可以更轻松地管理用户体验和商店自定义！这就是为什么我编写<i><strong>在Magento 2中</strong></i>以<i><strong>编程</strong></i>方式<i><strong>创建客户组</strong></i>的方法。</p><h3>在Magento 2商店里，你能把顾客分成几个小组吗？</h3><ul><li>管理显示给用户的内容</li><li>配置税收规则</li><li>设计折扣和销售策略</li><li>限制产品或类别</li><li>提供特定的运输或付款方式</li></ul><p>列表是无止境的。提供您能想到的与客户类型有关的任何信息。客户将为这种双赢的情况而感恩，在这种双赢的情况下，您可以使他们的购物体验更加顺畅！</p><h2>在Magento 2中以编程方式创建客户组的步骤：</h2><p>&nbsp;在<strong>app/code/Vendor/Extension/Setup</strong>目录中创建<i><strong>InstallData.php</strong></i>文件：</p>
<pre>
&lt;?php
namespace Vendor\Extension\Setup;

use Magento\Framework\Module\Setup\Migration;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Customer\Model\GroupFactory;

class InstallData implements InstallDataInterface
{
&nbsp; &nbsp; protected $groupFactory;

&nbsp; &nbsp; public function __construct(GroupFactory $groupFactory) {
&nbsp; &nbsp; &nbsp; &nbsp; $this-&gt;groupFactory = $groupFactory;
&nbsp; &nbsp; }

&nbsp; &nbsp; public function install(
&nbsp; &nbsp; &nbsp; &nbsp; ModuleDataSetupInterface $setup,
&nbsp; &nbsp; &nbsp; &nbsp; ModuleContextInterface $context
&nbsp; &nbsp; ) {
&nbsp; &nbsp; &nbsp; &nbsp; $setup-&gt;startSetup();

&nbsp; &nbsp; &nbsp; &nbsp; $group = $this-&gt;groupFactory-&gt;create();
&nbsp; &nbsp; &nbsp; &nbsp; $group
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt;setCode('New Group')
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt;setTaxClassId(3)&nbsp;
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt;save();

&nbsp; &nbsp; &nbsp; &nbsp; $setup-&gt;endSetup();
&nbsp; &nbsp; }
}
</pre>
<p>好了，这就是代码</p>]]></description>
      <pubDate>Thu, 19 Dec 2019 10:09:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何禁用在Magento 2的产品页面上的Ajax“添加到购物车”]]></title>
      <link>https://www.360magento.com/blog/disable-ajax-add-to-cart-on-product-page-m2/</link>
      <description><![CDATA[<p>您的大量客户是否由于冗长的结帐流程而放弃了购物车？您是否要优化结帐流程，使您不会失去可能成为潜在客户的用户？</p>
<p>Magento 2“Add to Cart”按钮的默认行为是单击，它使用ajax将产品添加到购物车并使用户停留在产品页面上。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_274/ajax-add-to-cat.gif" alt="Magento 2的产品页面购物车按钮" />
</p>
<p>现在，为了加快购买过程，您需要<strong>在Magento 2的产品页面上禁用ajax添加到购物车</strong>，并将客户直接重定向到结帐页面。这可以推动您的客户进行购买，也可以节省客户完成订单的时间。</p>
<h2>在Magento 2的产品页面上禁用Ajax添加到购物车的步骤：</h2><ol><li>从<strong>vendor\magento\module-catalog\view\frontend\templates\product\view\addtocart.phtml</strong>文件中找到以下代码<br>
<pre>
&lt;script type="text/x-magento-init"&gt;
&nbsp;&nbsp; &nbsp;{
&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;"#product_addtocart_form": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "Magento_Catalog/product/view/validation": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "radioCheckboxClosest": ".nested"
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;}
&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;}
&lt;/script&gt;
</pre>
&nbsp;</li><li>转到&nbsp; <strong>app/design/frontend/[Vendor]/[Theme]/Magento_Catalog/templates/product/view/addtocart.phtml</strong>并替换以下代码以添加<strong>bindsubmit</strong>事件：<br>
<pre>
&lt;script type="text/x-magento-init"&gt;
&nbsp; &nbsp;{
&nbsp;&nbsp; &nbsp;"#product_addtocart_form": {
&nbsp; &nbsp; &nbsp; &nbsp; "Magento_Catalog/product/view/validation": {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;"bindSubmit": true,
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp;"radioCheckboxClosest": ".nested"
&nbsp; &nbsp; &nbsp;&nbsp; &nbsp;}
&nbsp;&nbsp; &nbsp;}
&nbsp; &nbsp;}
&lt;/script&gt;
</pre>
&nbsp;</li><li>要想单击添加到购物车按钮从购物车页面重定向到结帐页面，请转到<strong>Stores > Configuration > Sales > Checkout > Shopping Cart</strong>，并将“ <strong>After Adding a Product Redirect to Shopping Cart</strong> ”设置为<strong>Yes</strong>。
<img src="https://www.360magento.com/media/wysiwyg/blog_274/Redirect-directly-to-checkout.png" />
</li></ol><p>在Magento 2产品页面上禁用ajax添加到购物车并将客户直接重定向到结帐页面。</p>]]></description>
      <pubDate>Mon, 16 Dec 2019 07:38:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2路由的完整教程]]></title>
      <link>https://www.360magento.com/blog/magento-2-routing/</link>
      <description><![CDATA[<p><i><strong>Magento 2路由</strong></i>就是定义模块的URL。</p><p>整个Magento 2应用程序流基于处理URL请求和路由器类，它们负责匹配和处理请求。</p><p>Magento 2中的请求URL是http://example.com/index.php/router_name/controller/action</p><p>在这里，<strong>router_name</strong>用于查找模块。</p><p>当在Magento 2中发出请求时，&nbsp; <strong>controller/action:index.php → HTTP app → FrontController → Routing → Controller processing → etc</strong>流程。</p><p>在Http类中调用FrontController来路由请求，该请求将找到controller/action匹配项。</p><p><strong>vendor/magento/framework/App/FrontController.php</strong></p>
<pre>
public function dispatch(RequestInterface $request)
{
   \Magento\Framework\Profiler::start('routers_match');
   $routingCycleCounter = 0;
   $result = null;
   while (!$request-&gt;isDispatched() &amp;&amp; $routingCycleCounter++ &lt; 100) {
	   /** @var \Magento\Framework\App\RouterInterface $router */
	   foreach ($this-&gt;_routerList as $router) {
		   try {
			   $actionInstance = $router-&gt;match($request);
			   if ($actionInstance) {
				   $request-&gt;setDispatched(true);
				   $this-&gt;response-&gt;setNoCacheHeaders();
				   if ($actionInstance instanceof \Magento\Framework\App\Action\AbstractAction) {
					   $result = $actionInstance-&gt;dispatch($request);
				   } else {
					   $result = $actionInstance-&gt;execute();
				   }
				   break;
			   }
		   } catch (\Magento\Framework\Exception\NotFoundException $e) {
			   $request-&gt;initForward();
			   $request-&gt;setActionName('noroute');
			   $request-&gt;setDispatched(false);
			   break;
		   }
	   }
   }
   \Magento\Framework\Profiler::stop('routers_match');
	if ($routingCycleCounter &gt; 100) {
	   throw new \LogicException('Front controller reached 100 router match iterations');
	}
	return $result;
}
</pre>
<h2 id="create-custom-route-on-frontendadmin">在前端和后台管理上创建自定义路由的步骤：</h2><p>在实施以下方法之前，您可以参考有关<a href="https://www.360magento.com/blog/create-moudle-m2" target="_blank">Magento 2模块开发</a>的教程。</p><h3>创建前端路由：</h3><p>在<strong> app/code/[Vendor]/[Module]/etc/frontend </strong>文件夹中创建<strong>routes.xml</strong>，添加以下代码：</p>
<pre>
&lt;?xml version="1.0" ?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
	&lt;router id="standard"&gt;
		&lt;route frontName="helloworld" id="helloworld"&gt;
			&lt;module name="[Vendor]_[Module]"/&gt;
		&lt;/route&gt;
	&lt;/router&gt;
&lt;/config&gt;
</pre>
<h3>创建管理路由：</h3><p>在app/code/[Vendor]/[Module]/etc/adminhtml文件夹中创建<strong>routes.xml</strong>，并添加以下代码：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
	&lt;router id="admin"&gt;
		&lt;route id="helloworld" frontName="helloworld"&gt;
			&lt;module name="[Vendor]_[Module]"/&gt;
		&lt;/route&gt;
	&lt;/router&gt;
&lt;/config&gt;
</pre>
<h3>使用路由重写控制器：</h3><p>在<strong> app/code/[Vendor]/[Module]/etc/frontend</strong>文件夹中创建<strong>routes.xml</strong>，并添加以下代码：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
   &lt;router id="standard"&gt;
		&lt;route frontName="helloworld" id="helloworld"&gt;
			&lt;module name="[Vendor]_[Module]"/&gt;
		&lt;/route&gt;
	   &lt;route id="account"&gt;
		   &lt;module name="[Vendor]_[Module]" before="Magento_Customer" /&gt;
	   &lt;/route&gt;
   &lt;/router&gt;
&lt;/config&gt;
</pre>
这就是Magento 2路由的全部内容！</p>]]></description>
      <pubDate>Fri, 13 Dec 2019 10:27:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中重新排序产品页标签选项卡]]></title>
      <link>https://www.360magento.com/blog/m2-reorder-product-tabs/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_272/How-To-Reorder-Product-Tabs-In-Magento-2-880x346.png" alt="如何在Magento 2中重新排序产品页标签选项卡" /></p>
<p>电商网站的产品页面设计非常重要，因为在大多数情况下，潜在客户将搜索产品而不是品牌。此外，产品页面是将在社交媒体上共享最多的页面。</p>
<p>电商网站网页设计对于创造正确的视觉效果、产生引导和转化具有重要的作用。</p>
<p>此外，一个易于遵循逻辑的设计可以提高用户的购物体验！</p><p>关于Magento 2，在开发网站时，您可能需要调整默认页面的设计。这是为了优化页面以获得更好的购物体验，并吸引访问者停留在页面上。</p><p><i><strong>重新排列Magento 2中的产品标签选项卡，</strong></i>如下所示：</p><p><strong>整整之前：</strong></p><p>
<img src="https://www.360magento.com/media/wysiwyg/blog_272/Product-tabs-in-Magento-2-Meetanshi-880x324.png" alt="之前-Magento 2中的产品选项卡" />
<br> <strong>调整之后：</strong><br> 
<img src="https://www.360magento.com/media/wysiwyg/blog_272/Reordered-product-tabs-in-Magento-2-Meetanshi-880x325.png" alt="之后Magento 2中的产品选项卡" />
</p><h2>在Magento 2中重新排序产品标签选项卡的方法：</h2><ol><li>在<strong>app/design/frontend/Vendor/Theme/Magento_Catalog/layout/catalog_product_view.xml中</strong>创建/更改文件&nbsp;<br>
<pre>
&lt;referenceBlock name="product.info.details"&gt;
        &lt;referenceBlock name="product.info.description"&gt;
            &lt;arguments&gt;
                &lt;argument name="priority" xsi:type="string"&gt;1&lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
        &lt;referenceBlock name="product.attributes"&gt;
            &lt;arguments&gt;
                &lt;argument name="priority" xsi:type="string"&gt;3&lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
        &lt;referenceBlock name="reviews.tab"&gt;
            &lt;arguments&gt;
                &lt;argument name="priority" xsi:type="string"&gt;4&lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
        &lt;!-- Your Custom Tab --&gt;
        &lt;block class="Magento\Catalog\Block\Product\View\Description" name="product.features" as="features" template="product/view/features.phtml" group="detailed_info"&gt;
            &lt;arguments&gt;
                &lt;argument translate="true" name="title" xsi:type="string"&gt;Custom Tab&lt;/argument&gt;
                &lt;argument name="priority" xsi:type="string"&gt;2&lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/block&gt;
    &lt;/referenceBlock&gt;
</pre>
</li><li>如果&nbsp; 主题目录中不存在<em><strong>details.phtml</strong></em>文件，<br>则从<strong>vendor/magento-catalog-view/frontend/templates/product/view/details.phtml</strong>复制到<br> <strong>app/design/frontend/Vendor/Theme/Magento_Catalog/templates/product/view/details.phtml<br></strong><br>
<pre>
&lt;?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

// @codingStandardsIgnoreFile

?&gt;
&lt;?php if ($detailedInfoGroup = $block-&gt;getGroupChildNames('detailed_info', 'getChildHtml')):?&gt;
    &lt;div class="product info detailed"&gt;
        &lt;?php $layout = $block-&gt;getLayout(); ?&gt;
        &lt;?php
            # We create a new array;
            $newPriority = array();
            # forEach the original $detailedInfoGroup Array;
            foreach ($detailedInfoGroup as $name){
                $alias = $layout-&gt;getElementAlias($name);
                # Get the priority which we applied via xml file
                # If no priority is applied via xml file then just set it to 10
                $priority = $block-&gt;getChildData($alias,'priority') ? $block-&gt;getChildData($alias,'priority') : '10';
                # variables pushed into new two-dimensional array
                array_push($newPriority, array($name, $priority));
            }
            # Sort array by priority
            usort($newPriority, function($a, $b) {
                return $a['1'] &lt;=&gt; $b['1'];
            });
        ?&gt;
        &lt;div class="product data items" data-mage-init='{"tabs":{"openedState":"active"}}'&gt;
            &lt;?php
            # Delete the original forEach statement
            #foreach ($detailedInfoGroup as $name)
            foreach ($newPriority as $name):?&gt;
                &lt;?php
                    # rename $name[0] to $name because it's a two-dimensional array
                    # No further changes to this file, it works as explained
                    $name = $name[0];
                    $html = $layout-&gt;renderElement($name);
                    if (!trim($html)) {
                        continue;
                    }
                    $alias = $layout-&gt;getElementAlias($name);
                    $label = $block-&gt;getChildData($alias, 'title');
                ?&gt;
                &lt;div class="data item title"
                     aria-labeledby="tab-label-&lt;?php /* @escapeNotVerified */ echo $alias;?&gt;-title"
                     data-role="collapsible" id="tab-label-&lt;?php /* @escapeNotVerified */ echo $alias;?&gt;"&gt;
                    &lt;a class="data switch"
                       tabindex="-1"
                       data-toggle="switch"
                       href="#&lt;?php /* @escapeNotVerified */ echo $alias; ?&gt;"
                       id="tab-label-&lt;?php /* @escapeNotVerified */ echo $alias;?&gt;-title"&gt;
                        &lt;?php /* @escapeNotVerified */ echo $label; ?&gt;
                    &lt;/a&gt;
                &lt;/div&gt;
                &lt;div class="data item content" id="&lt;?php /* @escapeNotVerified */ echo $alias; ?&gt;" data-role="content"&gt;
                    &lt;?php /* @escapeNotVerified */ echo $html; ?&gt;
                &lt;/div&gt;
            &lt;?php endforeach;?&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;?php endif; ?&gt;
</pre>
</li></ol>
<p>就这样而已。</p>
<p>更改Magento 2商店中产品页面上选项卡的顺序。根据买方角色和内容相关性来调整产品页面的设计。</p><p>如果你被困在这两个步骤之间，请联系我们，我们很乐意提供帮助。</p><p>谢谢。</p>]]></description>
      <pubDate>Wed, 11 Dec 2019 09:50:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中如何从URL导入产品图像]]></title>
      <link>https://www.360magento.com/blog/m2-import-product-images-from-url/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_271/How-To-Import-Product-Images-From-URL-In-Magento-2-880x346.png" alt="" /></p>
<p>Magento 2是目前最受欢迎的电子商务平台，通常会有很多从其他平台转移到M2的平台上来，这样在Magento 2中就需要<i><strong>从URL导入产品图像</strong></i>。默认情况下，Magento 2可以很好地处理图像导入，但是图片路径仅位于服务器中。然而，从外部URL导入产品图片时，可以使用以下解决方案。</p>
<p>以下内容可以包含在任何需要的地方，它的execute方法将使用以下参数调用：：</p>
<ul><li><em>$product</em> &nbsp;–加载的产品实例，图像将添加到其中</li><li><em>$imageUrl</em> &nbsp;–外部图片网址</li><li><em>$visible</em> &nbsp;–默认情况下将隐藏图像。您可以通过传递布尔值“true”使其可见。</li><li><em>$imageType</em> &nbsp;–数组，可选参数，您可以在其中指定将图像设置为主图像，小图像还是缩略图或它们的任意组合。</li></ul>
<p>该帖子提供了从Magento 2商店中的外部URL轻松导入产品图像的解决方案。</p>
<h2>在Magento 2中从URL导入产品图像的方法：</h2>
<p>在<strong>app/code/[Vendor]/[Module]/Service</strong>文件夹中创建<em><strong>ImportImageService.php</strong></em>类，并添加以下代码：</p>
<pre>
&lt;?php
	namespace [Vendor]\[Module]\Service;
	
	use Magento\Catalog\Model\Product;
	use Magento\Framework\App\Filesystem\DirectoryList;
	use Magento\Framework\Filesystem\Io\File;
	
	class ImportImageService
	{
		protected $directoryList;
		protected $file;
		public function __construct(
			DirectoryList $directoryList,
			File $file
		) {
			$this-&gt;directoryList = $directoryList;
			$this-&gt;file = $file;
		}
		public function execute($product, $imageUrl, $visible = false, $imageType = [])
		{
			$tmpDir = $this-&gt;getMediaDirTmpDir();
			$this-&gt;file-&gt;checkAndCreateFolder($tmpDir);
			$newFileName = $tmpDir . baseName($imageUrl);
			$result = $this-&gt;file-&gt;read($imageUrl, $newFileName);
			if ($result) {
				$product-&gt;addImageToMediaGallery($newFileName, $imageType, true, $visible);
			}
			return $result;
		}
		protected function getMediaDirTmpDir()
		{
			return $this-&gt;directoryList-&gt;getPath(DirectoryList::MEDIA) . DIRECTORY_SEPARATOR . 'tmp';
		}
	}
</pre>
<p>在将数据<a href="https://www.360magento.com/magento-migration" target="_blank">迁移到Magento 2</a>时，上述解决方案证明是节省时间的。</p>]]></description>
      <pubDate>Mon, 09 Dec 2019 07:37:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[已解决–未定义索引：在Magento 2.XX中运行Cron时出错]]></title>
      <link>https://www.360magento.com/blog/undefined-index-jobs-error/</link>
      <description><![CDATA[<p><img alt="Magento2 Cron job error" src="https://www.360magento.com/index.php/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yNzAvU29sdmVkLVVuZGVmaW5lZC1pbmRleC1qb2JzLUVycm9yLU9uLVJ1bm5pbmctQ3Jvbi1Jbi1NYWdlbnRvLTJfWF9YLTg4MHgzNDYucG5nIn19/key/1a3c3a1fca1f24547416cddd016979ba/" /></p>
<p>Magento 2中的Cron Job是自动化重复任务的绝佳工具！</p>
<p>但是，有时开发人员<em><strong>在Magento 2.xx中运行cron时</strong></em>会遇到<em><strong>未定义的索引：作业错误</strong></em>。（包括我）</p>
<p>在运行以下命令时，</p>
<pre>/usr/bin/php [magento root directory]/bin/magento cron:run | grep -v "Ran jobs by schedule" &gt;&gt; [magento root directory]/var/log/magento.cron.log
</pre>
<p>Magento将抛出以下异常：</p>
<blockquote>
<p><em><code>[Exception] Notice: Undefined index: jobs in /home/ubuntu/repo/project/vendor/magento/<br /> module-cron/Model/Config/Converter/Db.php on line 39</code></em></p>
</blockquote>
<h2>未定义索引的解决方案：在Magento 2.xx中运行cron时出现作业错误：</h2>
<p>从Magento 1迁移到Magento 2时，您可能会获得<strong>crontab/{groupname}/jobs/{code}</strong>条目，其中缺少组名，即<strong>core_config_data</strong>表中的默认名称。您需要删除错误的表条目，然后运行upgrade 和 deploy命令来解决此问题。</p>
<p>这样错误就解决了。</p>
<p>如果仍然存​​在任何问题，联系我们。</p>
<p>我们很乐意为您服务。</p>
<p>并与其他开发人员共享解决方案。</p>
<p>谢谢。</p>]]></description>
      <pubDate>Thu, 05 Dec 2019 09:42:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何将带有过滤器的列添加到Magento 2订单网格？]]></title>
      <link>https://www.360magento.com/blog/add-column-to-magento-2-orders-grid/</link>
      <description><![CDATA[<p>通常，Magento 2商店的管理员在使用和自定义订单网格时都需要其他选项-基于特定的即用型参数进行过滤可能会成为真正的挑战。<br></p>
<p>最近，Magento开发人员向我提出了一个问题。他试图扩展Magento 2.3.2上的订单网格。网络上的旧帖子并没有起到任何作用，自最近两年以来，Magento发生了很多变化。</p>
<p>于他的问题，我建议你看一看具体案例的解决方案：<br></p>
<p>我们需要在订单网格中添加一列（包含完成购买的客户的区域代码）。此外，商店管理员必须可以通过此新添加的列来过滤订单。<br></p>
<p>这似乎很容易，但是有几件事需要注意。例如，在虚拟订单的情况下，购买商品的购物者可能没有任何送货地址。或者，我们该如何列出地区？开始开发时，应考虑所有这些因素。根据前面提到的问题，我们假设：<br></p>
<ul><li>虚拟产品没有运送地区（“null”）。这将帮助您根据此参数选择它们，</li><li> 就像默认的Magento 2一样，将列出地区并显示代码，而无需将其转换为标签。 </li></ul>
<p>因此，要将新列添加到订单网格，您需要：</p>
<div id="toc_container" class="no_bullets">
<ul class="toc_list"><li><a href="#1_Create_a_new_module">1.创建一个新模块</a></li><li><a href="#2_Add_a_column_to_the_grid">2.在网格中添加一列</a><ul><li><a href="#Explanations"><span class="toc_number toc_depth_2">2.1</span>解释</a></li></ul></li><li><a href="#3_Add_data_to_the_column">3.将数据添加到列</a></li></ul></div>
<h2><span id="1_Create_a_new_module">1.创建一个新模块<br></span></h2>
<p>首先，让我们确定模块和供应商名称。好吧，我不需要选择供应商名称-它是Alwayly（好像我可以选择一样）。我仍然可以选择模块名称。把它命名为<em>ExtendedOrdersGrid</em></p>
<p>让我们创建以下目录：<code>app/code/Alwayly/ExtendedOrdersGrid</code>。要注册一个模块，我们将需要一些标准文件：<br></p>
<pre>
&gt; registration.php

php
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Alwayly_ExtendedOrdersGrid',
    __DIR__
);


&gt; composer.json

json
{
    "name": "alwayly/module-extended-orders-grid",
    "description": "Extended Orders Grid Extension",
    "require": {
        "magento/module-ui" : "&gt;=100.1.0 &lt; 102",
        "magento/module-sales" : "&gt;=100.0.0 &lt;103"
    },
    "type": "magento2-module",
    "version": "1.0.0",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [ "registration.php" ],
        "psr-4": {
            "Alwayly\\ExtendedOrdersGrid\\": ""
        }
    }
}


&gt; etc/module.xml

xml
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_ExtendedOrdersGrid" setup_version="1.0.0"&gt;
        &lt;sequence&gt;
            &lt;module name="Magento_Sales"/&gt;
            &lt;module name="Magento_Ui"/&gt;
        &lt;/sequence&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>

<p>重要的是要注意，我已经削减了自动添加到我的IDE中的版权。因此，您可以毫无困难地使用此代码。<img draggable="false" class="emoji" alt="]]></description>
      <pubDate>Fri, 29 Nov 2019 03:31:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[利用Magento Facebook Shop集成工具提升销售]]></title>
      <link>https://www.360magento.com/blog/magento-facebook-shop-integration-tools/</link>
      <description><![CDATA[<p>社交媒体不再仅仅是在线社交网络的场所。用户一直在探索Facebook和Instagram之类的平台，几乎涵盖所有内容&mdash;&mdash;新闻、视频、内容分享以及吸引他们的一切。。&nbsp;</p>
<p>Facebook在全球拥有近24.1亿月活跃用户，同时也为企业提供了无限的平台。卖家只需点击几下即可免费找到潜在的买家，而无需花一分钱进行营销。</p>
<p>以下是<a href="https://blog.hootsuite.com/facebook-statistics/" rel="noopener nofollow" target="_blank">Hootsuite</a>在Facebook营销上的一些统计数据：</p>
<p><strong>&rarr;15％的美国社交媒体用户在Facebook上购物</strong></p>
<p><strong>&rarr;惊人的9000万家小型企业正在使用Facebook，其中大多数都坚持使用免费工具（例如&ldquo;Groups&rdquo;和&ldquo;pages&rdquo;）。&nbsp;</strong></p>
<p><strong>&rarr;2020年有87.1％的美国营销人员将使用Facebook营销</strong></p>
<p>对于全球的卖家来说，这些数字实在太惊人了，以至于在他们的营销策略中不得不考虑Facebook shopping。</p>
<p>Facebook提供了各种可能的方式来吸引用户，包括卖家和潜在买家。如果您看到这里，则可能您已经拥有一家在线商店或正准备<a href="https://www.360magento.com/magento-custom">搭建一个在线商店</a>，并期待利用社交媒体的影响力来增强产品的知名度，从而提高商店的销售额。</p>
<p>该博客讨论了社交媒体购物的见解以及将Facebook与Magento 1和Magento 2平台上的商店集成的最佳工具。</p>
<h2><strong>Magento Facebook页面集成提供什么？</strong></h2>
<p>这是英国一家受欢迎的在线商店<strong><a href="https://www.coxandcox.co.uk/" rel="noopener nofollow" target="_blank">Cox and Cox</a></strong>的示例。该商店基于Magento 2电子商务平台建立的，是各类家居装饰用品之家。<strong>Cox and Cox</strong>通过其<a href="https://www.facebook.com/coxandcoxmailorderltd/" rel="noopener nofollow" target="_blank"><strong>Facebook page store</strong></a>来挖掘其客户范围。</p>
<p><strong><img alt="Cox和Cox Facebook页面应用商店" class="alignnone wp-image-10455 size-full" height="524" src="https://www.360magento.com/media/wysiwyg/blog_264/Coxandcox-Facebook-page-app-store.gif" title="Cox and Cox Facebook页面应用商店" width="1015" /></strong></p>
<p>Facebook page store与常规的Magento商店看起来是否有所不同？</p>
<p>它几乎囊括了理想的在线商店所拥有的一切：</p>
<ul>
<li><strong>产品清单</strong></li>
<li><strong>价格&nbsp;</strong></li>
<li><strong>商品详情</strong></li>
<li><strong>完美的产品目录</strong></li>
<li><strong>结帐页面，该页面重定向到在线商店的结帐页面&nbsp;</strong></li>
</ul>
<p>这家社交媒体巨头使您能够创建一个以客户为中心的商店，在那里您的潜在买家可以很轻松找到您的Magento商店产品。这几乎就像你原来商店的复制品，只是在一个更大的平台&nbsp;</p>
<p>此外，当客户订阅您的Facebook商店时，他将<strong>根据其购物历史</strong>收到<strong>个性化建议</strong>，从而提供再次购买的机会。</p>
<p>好吧，这并不是Facebook页面商店集成可以提供给你的Magento商店的全部功能。根据<a href="https://wearesocial.com/blog/2019/01/digital-2019-global-internet-use-accelerates" rel="noopener nofollow" target="_blank">Wearesocial的数据</a>，<strong>在每月24.1亿活跃FB用户中</strong>，有<strong>22亿使用移动设备，这表明您有90％的潜在受众在移动端上找到您。</strong></p>
<p>如果您仅是Magento商店，则您可能需要雇用移动应用程序开发人员来让移动用户知道您的存在。在面向移动设备的Facebook页面上设有商店，您可以节省开发时间和设计专用移动应用程序的成本。</p>
<p>使用Magento商店的Facebook产品目录，您的大部分任务已经完成了。您的客户在他们的移动设备上（通过Facebook）找到您，并且很有可能为现成的用户体验付费。</p>
<p>接下来出现的问题是：<em><strong>卖家是否有任何DIY解决方案，可直接从其Magento商店建立Facebook页面商店？</strong></em>Magento Marketplace中提供了一些现成的解决方案：</p>
<p><strong><span style="color: #065aa0;"><a href="https://cedcommerce.com/magento-2-extensions/facebook-shop-magento-2-integration" rel="nofollow noopener" target="_blank">Cedcommerce Facebook商店整合</a></span></strong></p>
<p><img alt="Magento2 Commerce" class="alignnone wp-image-10512 size-full" height="250" src="https://www.360magento.com/media/wysiwyg/blog_264/Ced-Commerce-2.png" title="Magento2 Commerce" width="980" /></p>
<p>该品牌为Magento推出了两个Facebook商店整合工具</p>
<p>&rarr; <strong>Magento1的</strong> Facebook商店集成<strong></strong></p>
<p>&rarr; <strong>Magento2的</strong> Facebook商店集成<strong></strong></p>
<p>这是Cedcommerce Magento Facebook商店集成提供的配置，管理员可以在其中启用Facebook设置以及Shop标语。</p>
<p><img alt="magento 2后端" class="aligncenter wp-image-10457 size-full" height="400" src="https://www.360magento.com/media/wysiwyg/blog_264/Cedcommerce-magento-2-backend.png" title="magento 2后端" width="900" /></p>
<p>以下是此扩展程序提供的一些主要功能。</p>
<p><strong>控制产品：</strong></p>
<p>管理员可以完全控制他要在Facebook Page商店上显示的产品。他可以选择添加新产品，也可以单击简单的按钮撤回现有产品。</p>
<p><strong>批量产品列表：</strong></p>
<p>卖家可以在Facebook页面商店中批量添加产品。他们可以选择多个产品，然后将其导出到FB。</p>
<p><strong>产品信息变更：</strong></p>
<p>Facebook商店集成使您可以从单个面板管理产品详细信息。管理员可以通过Magento Admin修改详细信息，最终通过集成工具将其反映在Facebook页面商店中。</p>
<p>管理员因此可以节省在多个平台上更新信息的时间。</p>
<p><strong>同步库存</strong></p>
<p>Magento 1和Magento 2 Facebook商店集成可以很好地管理集中式库存。该工具使用Facebook API和Magento商店来连续检查产品的可用性。</p>
<p><strong>重定向到结帐页面</strong></p>
<p>Facebook页面商店将用户重定向到Magento结帐页面。这样，卖方就可以轻松地管理订单。该功能适用​​于Magento 1商店和Magento 2商店。&nbsp;</p>
<p>这是用于管理Facebook商店产品的Magento管理面板的屏幕截图：</p>
<p><img alt="facebook magento面板" class="aligncenter wp-image-10458 size-full" height="480" src="https://www.360magento.com/media/wysiwyg/blog_264/Cedcommerce-magento-panel.png" title="facebook magento面板" width="980" /></p>
<p><strong>价格：$ 199.00</strong></p>
<p>Magento 1商店也提供类似的扩展。</p>
<p><strong>注意：</strong>无论如何，我还是得告诉您，Magento将在2020年6月终止对Magento1平台的官方支持。如果您仍然对迁移过程一无所知，请阅读我们的博客：<a href="https://www.360magento.com/blog/migrate-magento-1-9-x-to-2-3-x/" title="如何将Magento1迁移到Magento2">将Magento1迁移到Magento2</a>。您也可以向我们咨询<a href="https://www.360magento.com/magento-migration" title="Magento迁移">Magento迁移服务</a>。我们的Magento专家小组可以为您提供帮助。</p>
<p><strong><span style="color: #065aa0;"><a href="https://marketplace.magento.com/zestardtech-zestard-facebookstore.html" rel="nofollow noopener" target="_blank">Zestard Facebook Store</a></span></strong></p>
<p><img alt="Facebook Magento集成" class="alignnone wp-image-10514 size-full" height="250" src="https://www.360magento.com/media/wysiwyg/blog_264/Zestard.png" title="Facebook Magento集成" width="980" /></p>
<p>Zestard提供了出色的Magento Facebook商店集成工具。该品牌声称可以在社交媒体上轻松设置商店。正如我们在CedCommerce Facebook商店集成中所讨论的，它具有以下共同特征：</p>
<p>&rarr;大宗商品清单</p>
<p>&rarr;从Magento管理面板更新产品信息</p>
<p>此外，该工具还具有一些其他功能：</p>
<p><strong>商店特定的设计：</strong></p>
<p>该工具使用Magento配置中的内部CSS设计FB商店页面。该功能使其成为在Facebook页面商店上创建Magento产品目录的更灵活的选择。你现在可以有一个Facebook商店提供几乎与你原来的Magento商店相同的用户体验。</p>
<p><strong>针对速度和性能进行了优化：</strong></p>
<p>该工具优化了最终商店的速度和性能，使产品加载速度更快。</p>
<p>这是管理面板中用于管理Magento Facebook商店集成的屏幕截图。</p>
<p><img alt="Facebook连接设置" class="aligncenter wp-image-10462 size-full" height="349" src="https://www.360magento.com/media/wysiwyg/blog_264/Zestard-Facebook-Connection-Setting.png" title="Facebook连接设置" width="837" /></p>
<p><strong>价钱：$ 99</strong></p>
<p><strong><span style="color: #065aa0;"><a href="https://marketplace.magento.com/meetanshi-magento2-facebook-store-integration.html" target="_blank">Meetanshi Facebook商店整合</a></span></strong></p>
<p><img alt="Facebook商店整合" class="alignnone wp-image-10565 size-full" height="250" src="https://www.360magento.com/media/wysiwyg/blog_264/Zestard-1.png" title="Facebook商店整合" width="980" /></p>
<p>Meetanshi使用新的工具为Magento商店分配Facebook页面而声名远播。有足够的理由这样说。</p>
<p><strong>计划产品生成：&nbsp;</strong></p>
<p>用户可以安排具有开始时间的产品，以将产品生成为CSV文件。</p>
<p>该面板还允许管理员像其他工具一样手动导出该内容。自动化平台使管理员不必频繁访问Magento面板。</p>
<p><strong>为产品添加属性：</strong>&nbsp;</p>
<p>管理员可以为商品添加标签，例如New/Used/Refurbished，就像亚马逊在其商店中所做的那样。</p>
<p><strong>添加类别：</strong></p>
<p>借助此Magento Facebook商店集成应用程序，管理员可以提及其他详细信息，例如产品类别和产品状况。</p>
<p>此Magento Facebook商店集成工具的常见功能与其他功能共有：</p>
<p>&rarr;在Facebook商店中显示产品和产品信息</p>
<p>&rarr;产品完全在管理员的控制之下，可以添加或删除&nbsp;</p>
<p>Magento管理面板中的配置页面说明了一切。</p>
<p><img alt="Facebook商店整合" class="alignnone wp-image-10531 size-full" height="420" src="https://www.360magento.com/media/wysiwyg/blog_264/Facebook-Store-Integration.png" title="Facebook商店整合" width="980" /></p>
<p><strong>价格：$ 189</strong></p>
<p>有很多解决方案可以帮助您直接从Magento商店展示Facebook页面产品目录。该列表中的所有解决方案在一定程度上都具有一些共同的特征。</p>
<p>开发人员之所以能够想出数不清的解决方案，仅仅是因为Facebook API允许他们这样做。此集成的基本工作流程如下：：</p>
<p>1.管理员必须从管理面板以CSV格式导出产品。</p>
<p>2. Facebook商店仅通过手动上传接受CSV格式的文件。</p>
<p>3. Magento Store产品的产品ID与Facebook API提供的ID相匹配。</p>
<p>4.库存处于连续同步状态</p>
<p>功能的交叉显然可以说明一件事-Magento后端可以为创建商店的Facebook API提供更多功能。您的业​​务需求将决定哪种工具最适合您。</p>
<p>但是，值得注意的是，这些工具倾向于避免一些被其他人用作USP的功能。主要原因之一可能是无数企业及其需求的实现。&nbsp;</p>
<p>虽然像上面提到的那样现成的解决方案可以证明是一种方便的解决方案，但是您可以要求我们进行定制设计的Magento Facebook商店集成。</p>
<p><strong>定制设计的Magento Facebook商店集成扩展的优势：</strong></p>
<p>1.您的自定义扩展程序具有您选择的功能</p>
<p>2.扩展没有过载影响性能的函数</p>
<p>3.您可以要求一个易于管理的自定义管理面板</p>
<p>4.您已经知道管理面板的全部潜能</p>
<p>&nbsp;360Magento的<a href="https://www.360magento.com/contacts/" target="_blank">Magento开发专家</a>一直根据客户的特定业务需求为他们提供即用型解决方案.</p>
<h2><strong>关于设置Magento Facebook商店集成的总结</strong></h2>
<p>显而易见，Facebook专页商店可以为您提供期望的Magento商店曝光率，以及您一直渴望的访问量和转化率。有了这些随时可以帮助你的工具，你可以为涌入量客户的客户而做准备。</p>
<p>对于您的Magento商店的个性化解决方案，您可以聘请我们经验丰富的<a href="https://www.360magento.com/" target="_blank">Magento开发团队</a> &nbsp;，他们可以根据您的自定义要求进行设计。在此处<a href="https://www.360magento.com/contacts/">联系我们</a>以定制Magento扩展或进行其他定制开发</p>]]></description>
      <pubDate>Wed, 20 Nov 2019 09:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2主题中如何包含使用javascript脚本？]]></title>
      <link>https://www.360magento.com/blog/how-to-include-custom-javascript-magento2/</link>
      <description><![CDATA[<p>Magento 2允许在整个站点，某个页面甚至页面的指定块和部分链接自定义javascript脚本。</p>
<p><a href="#step_1">在页面上包含自定义JavaScript有哪些选择<br></a><a href="#step_2">内联JavaScript的优缺点是什么？<br></a><a href="#step_3">如何在页面上异步加载JavaScript？<br></a><a href="#step_4">如何使用布局XML中的块参数配置页面上的JavaScript？<br></a><a href="#step_5">如何直接在.phtml模板中完成？</a></p>
<h2><strong><a id="step_1"></a>在页面上包含自定义JavaScript有哪些选择？</strong></h2>
<p>您可以通过以下三种方式进行操作：通过一个特殊的引擎框架将脚本连接到页面的头部，或者借助RequireJS（最佳的选项）。让我们考虑<strong>第一种方法</strong> –将脚本连接到页面头部。请记住，如果使用他的方法，将不可能覆盖脚本中的类，并且将最大程度地减少用户交互。当您通过已知库的cdn连接，或者您的脚本使用第三方聚合器时，此方法可能是最合适的。</p>
<p><span style="font-weight: 400;"><a id="step_5"></a>连接过程如下所示：</span><br></p>
<pre>
&lt;script src=”absolute or relative path to the script” &gt;&lt;/script&gt;
</pre>
<p><br><span style="font-weight: 400;">如果路径是绝对的，请&nbsp;</span>使用<br></p>
<pre>
src_type="url"
</pre>
<p><br>
或者<br></p>
<pre>
&lt;script type="text/javascript"&gt;script content&lt;/script&gt;
</pre>
<p><br>
内联在phtml中。</p>
<p>要改进此方法，请尝试在可以的地方使用deferred =”true”属性或至少async =”true”（但是，该属性仅适用于通过引用的脚本，不适用于嵌入式脚本）。更重要的是，<span style="font-weight: 400;">替换掉&nbsp;</span><br></p>
<pre>
&lt;script src="js/script.js"/&gt;
</pre>
<p>您可以使用</p>
<pre>
&lt;link src="js/script.js"/&gt;
</pre>
<p>现在，让我们继续<strong>第二种方法</strong> -通过Magento框架。您可以通过两种方式包含脚本：</p>
<ul><li>使用以下属性<br>
<pre>
data-mage-init='{ "VendorName_Module/js/script": {"configuration-value":true} }'
</pre>
<br>
它将请求一个脚本，其中包含要使用的元素及其参数（动画速度，元素数量等）。</li>
</ul><p>脚本的最终形式如下：<br></p>
<pre>
app/code/VendorName/Module/view/frontend/web/js/script.js
define([], function() {
return function(element, config) {
/* config: {
configuration-value: true
} */
};
});
</pre>
<ul><li>使用标签脚本<br>
<pre>
&lt;script type="script/x-magento-init"&gt;
{".element-selector": 
{"VendorName_Module/js/script": 
{"configuration-value": true}
}
}
&lt;/script&gt;
</pre>
<br>
&nbsp;</li>
</ul><p><span style="font-weight: 400;">其中.element-selector是将为其应用模块的选择器。如果选择器匹配的不是一个元素，而是几个元素，它将应用于每个元素。</span></p>
<p><span style="font-weight: 400;">连接依赖于第三方库的脚本不是最好的方法，但无疑是简单的方法：</span><br></p>
<pre>
&lt;script type="text/javascript"&gt;
require([
"VendorName_Module/js/script" 	//&lt;span style="font-weight: 400;"&gt;indicate library dependence&lt;/span&gt;
], function(loader) {
/* your script */
});
&lt;/script&gt;
</pre>
<p><br>
<strong>第三种方法</strong>是通过RequireJS。</p>
<p>这种方法允许将脚本连接到任何页面，并且比前两个页面工作更快，因为初始化所需的代码更少。<br></p>
<pre>
var config = {
deps: ['VendorName_Module/js/script']
};
</pre>
<h2><span style="color: #000000;"><a id="step_2"></a>内联JavaScript的优缺点是什么？</span></h2>
<p>内联JS的优点包括：</p>
<ul><li>易于连接</li>
<li>页面上没有其他请求</li>
</ul><p>但是此方法有一些缺点，因为代码：</p>
<ul><li>没有延迟并立即执行，因此不建议放置较大的内联代码；</li>
<li>很难再次使用；您必须再次将其插入其他页面；</li>
<li>在模板中很难找到，这就是为什么难以维护的原因；</li>
<li>没有被浏览器缓存，因为它是页面的一部分；</li>
<li>违反了Content-Security-Policy，这在跨站点脚本编制方面非常危险。</li>
</ul><h2><span style="color: #000000;"><a id="step_3"></a>如何在页面上异步加载JavaScript？</span></h2>
<p>这可以通过<strong>define</strong>方法来完成。</p>
<p>Require立即执行，而define将等待其他模块的调用。例如：<br></p>
<pre>
require([
'VendorName_Module/js/script'
], function(nameFunction) {
/* … */
});
</pre>
<h2><span style="color: #000000;"><strong><a id="step_4"></a>如何使用布局XML中的块参数配置页面上的JavaScript？</strong></span></h2>
<p>在AbstractBlock中，有一个getJsLayout方法，该方法返回带有jsLayout –参数的数组。在前端<br></p>
<pre>
&lt;?= $block-&gt;getJsLayout();?&gt;
</pre>
<p><br><span style="font-weight: 400;"> 会以jsLayout格式返回以json格式显示的一行。</span></p>
<p><span style="font-weight: 400;">因此，使用&lt;arguments /&gt;，您可以构建自己的json对象：</span><br></p>
<pre>
&lt;referenceBlock name="nameBlock"&gt;
	&lt;arguments&gt;
		&lt;argument name="jsLayout" xsi:type="array"&gt;
			&lt;item name="components" xsi:type="array"&gt;
			&lt;item name="script" xsi:type="array"&gt;
			&lt;item name="component" xsi:type="string"&gt;VendorName_Module/js/script&lt;/item&gt;
			&lt;/item&gt;&lt;/item&gt;
		&lt;/argument&gt;
	&lt;/arguments&gt;
&lt;/referenceBlock&gt;
</pre>
<p><br>
这就是本主题的全部内容。我希望我的文章对你有用。</p>
<p>寻找专业的<a href="https://www.360magento.com/" target="_blank" rel="noopener">Magento 2开发团队</a>联系我们</p>]]></description>
      <pubDate>Fri, 15 Nov 2019 07:02:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何生成sitemap文件]]></title>
      <link>https://www.360magento.com/blog/how-to-create-sitemap-in-magento/</link>
      <description><![CDATA[<p>站点地图是网站上所有URL的结构化列表，并带有其参数列表。站点地图的主要功能是使搜索引擎更容易理解和索引您的网站内容。网站站点地图也是一种有用的工具，以确保确保Googlebot能够看到您网站上的所有内容。幸运的是，大多数CMS系统都会生成一个。</p>
<p>最多有六种不同类型的站点地图，但是在本文中，我们将重点介绍两种最常见且被认为是最常用的站点地图格式：HTML和XML。</p>
<p><strong>目录：</strong></p>
<p><a href="#step_1">什么是HTML网站地图？<br></a><a href="#step_2">什么是XML网站地图？<br></a><a href="#step_3">HTML和XML网站地图有什么区别？<br></a><a href="#step_4">如何在Magento中创建站点地图XML？<br></a><a href="#step_5">如何向Google提交站点地图？<br></a><a href="#step_6">如何为自定义模型生成站点地图？</a></p>
<h2 id="step_1">什么是HTML网站地图？</h2>
<p>简单来说，HTML网站地图是一页上网站导航的轮廓文本版本。这种类型的站点地图对于任何类型的网站都是必不可少的，无论是电子商务网站，非营利性网站，博客网站还是娱乐网站。HTML网站地图的重要功能是使某些用户可以更轻松地浏览网站，因为他们可能需要的所有资源都可以快速访问。这就是为什么创建并保持用户友好的站点地图很重要的原因。如果它易于导航，快速加载并且结构整洁，那么您的网站的访问者可以轻松使用它。</p>
<p>根据HTML网站地图的最佳做法，它应具有链接到您网站上每个页面的锚链接。它将帮助用户浏览网站，并最终使其搜索引擎可爬行。读取站点地图后，搜索引擎将了解站点上的每个页面，包括大多数搜索引擎不断运行的，无法通过正常爬网过程轻易发现的所有URL。</p>
<h2>HTML网站地图的重要性</h2>
<p>HTML网站地图的最大好处是，它是清晰了解网站及其所有页面的好方法。这使站点地图成为可靠的导航工具，可随时在网站页脚使用。在大多数情况下，提供适当的HTML网站地图将改善用户体验，从而对您网站的排名产生影响。</p>
<p>此外，为了提升您的在线形象，这种类型的站点地图非常有价值，因为它是搜索引擎将阅读的页面，以了解您的网站并在其中建立索引。当网站上的信息是新的并且没有太多链接时，或者某些文章包含很多内容而链接不正确时，搜索引擎优化对具有动态内容的网站特别有用。</p>
<h2 id="step_2">什么是XML网站地图？</h2>
<p>XML网站地图是一个文本文件，用于详细说明网站上的所有URL。它可以在每个URL上包含额外的数据，包括解决其最新更新，其优先级，发生平均频率变化的信息，与站点其余部分的URL关系其余部分的关系以及是否有其他语言版本的相同URL。根据Google文档，XML站点地图对于具有大量存档或大量媒体内容的网站很有用，尽管我们认为，即使您的网络商店不符合这些特征，拥有站点地图仍将在很大程度上受益。</p>
<p>站点地图协议格式包含XML标签，并且应：</p>
<ul><li>以&lt;urlset&gt;开头标记开始，以&lt;/ urlset&gt;结束标记结束。</li>
<li>包括URL的&lt;url&gt;项作为父XML标记。</li>
<li>在&lt;urlset&gt;标记内指定名称空间（协议标准）。</li>
<li>包括&lt;url&gt;父标记的&lt;loc&gt;子条目。</li> 
</ul><p>其他标签是可选的，它们的支持可能因搜索引擎而异。因此，在包含任何这些可选标记之前，请查阅每个搜索引擎的文档。</p>
<h2>为什么XML网站地图对SEO很重要？</h2>
<p>创建站点地图对于SEO尤其有用。XML站点地图是为搜索漫游器设计的，更新的XML文件可用于对搜索引擎执行ping操作，并向它们发出更改和更新警报。XML文档使搜索引擎知道有新鲜的新内容。拥有完善的XML网站地图，可以极大地增加您的网页被搜索引擎抓取和编制索引的机会，尤其是在网站的导航系统无法正常工作或常规内部链接策略无法提供与所有您的页面。</p>
<p>如果您的网站是国际网站或将同一页面翻译成不同语言的网站，则可以使用XML网站地图来对搜索引擎的内容进行排序。该站点地图将能够告知抓取工具该页面具有多个版本，并且他们将使用此信息来确保根据用户的语言或位置向他们提供正确的网站版本。</p>
<h2 id="step_3">HTML和XML网站地图有什么区别？</h2>
<p>由于本文针对两个站点地图，因此必须清楚地了解它们之间的区别，这一点很重要。因此，本段专门讨论HTML网站地图与XML网站地图的比较。</p>
<p>HTML和XML网站地图在搜索引擎优化方面有不同的用途和价值。HTML和XML站点地图之间的主要区别在于，HTML站点地图主要是为用户编写的，是帮助他们全面了解网站的最主要工具，而XML站点地图则首先是为搜索引擎编写的。</p>
<p>HTML站点地图是网站，页面和信息的一般概述，可能对用户有用。虽然主要由网站的访问者使用，但它也可以帮助搜索引擎排名。</p>
<p>简而言之，主要创建XML来促进搜索引擎的功能，为搜索引擎提供有关网站结构的所有必要信息。</p>
<h2 id="step_4">如何在Magento中创建站点地图XML？</h2>
<p>您将在下面找到有关如何在Magento后台建立站点地图的清晰的分步说明。</p>
<p>第1步：导航至Stores-&gt;Settings-&gt;Configuration。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_262/settings-configuration.png" alt="settings configuration" /></p>
<p>步骤2：在“Catalog”选项中，选择“XML Sitemap”。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/catalog-xml-sitemap.png" alt="catalog xml sitemap" />
</p>
<p>请记住，根据任务，可以针对默认配置以及网站或商店视图执行这些设置。</p>
<p>步骤＃3：在“Categories Options”，“ Products Options”和“CMS Pages Options”部分中配置类别，产品和CMS页面的更新频率和优先级。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/categories-option.png" alt="categories option"
</p>
<p>在大多数情况下，这些部分中的默认值是首选值，但如果您需要引入一些自定义更改，以下是必须修改的字段。</p>
<p>以下值可用于频率设置：</p>
<ul><li>Always</li>
<li>Hourly</li>
<li>Daily</li>
<li>Weekly</li>
<li>Monthly</li>
<li>Yearly</li>
<li>Never</li>
</ul><p>频率值针对搜索引擎爬虫程序，并设置爬虫程序访问该页面的频率。建议将每次访问时更改的页面设置为Always。Never值应应用于已存档的页面；这样，搜索引擎爬虫将很少访问它们，以跟踪无法预料的变化（如果有的话）。但是，爬虫程序可能会忽略您设置的值，并更频繁地访问具有“Weekly”值的页面，而不是具有“Hourly”值的页面。</p>
<p>优先级值设置为0到1，其中1是最高优先级。</p>
<p>使用优先级设置，您可以指定哪些页面最重要，哪些页面不那么重要。因此，为所有页面设置1优先级是没有用的，因为所有页面都同样重要。对于“Priority”，默认值为0.5，这是大多数情况下的建议值。</p>
<p>另外，在“Add Images to Sitemap”字段中设置所需的站点地图图像–无，仅基础或全部。</p>
<p>完成后，按Save Config。</p>
<p>步骤＃4：设置站点地图生成设置。</p>
<p>展开“ Generation Settings”部分并配置以下内容：</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/generation-settings.png" alt="generation settings" />
</p>
<ul><li>Enabled-启用站点地图生成，因此设置为“Yes”。</li>
<li>Start Time–启动站点地图生成的服务器时间。最好的时间是晚上，当负载最小时，</li>
<li>Frequency-网站地图更新的频率。最好的方法是将值设置为等于商店中产品添加或更改的频率。</li>
<li>Error Email Recipient-有关生成站点地图错误的消息将被发送到的电子邮件地址。</li>
<li>Error Email Sender–发送有关站点地图生成错误的消息的电子邮件地址。可用选项包括General Contact, Sales representative, Customer support, Custom email。</li>
</ul><p>要为这些字段设置电子邮件地址，请导航至Stores-&gt;Configuration-&gt; General-&gt;Store Email Addresses。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/store-emain-addresses.png" alt="store emain addresses"
</p>
<p>Magento设置允许为整个网站或单独的商店定义它们。</p>
<p>Error Email Template–将用于生成站点地图通知的消息模板。</p>
<p>步骤＃5：定义站点地图文件限制</p>
<p>展开Sitemap File Limits部分，并填写以下字段：</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/sitemap-file-limits.png" alt="sitemap file limits" />
</p>
<ul><li>Maximum No of URLs Per File-限制添加到网站的URL数。</li>
<li>Maximum File Size–限制文件大小。</li>
</ul><p>步骤＃6：定义将站点地图添加到robots.txt中的规则</p>
<p>展开“Search Engine Submission Settings”部分，然后将“Enable Submission”字段设置为“Yes”。此配置将站点地图链接添加到robots.txt文件中，爬虫程序使用该文件来获取网站索引规则。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/search-engine-submission-settings.png" alt="search engine submission settings" />
</p>
<p>步骤＃7：按“Save Config”并刷新配置缓存以启用您所做的更改。</p>
<p>步骤＃8：要设置站点地图生成，请导航至Marketing-&gt;SEO & Search-&gt;Sitemap。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/marketing-sitemap.png" alt="marketing sitemap" />
</p>
<p>步骤＃9：按右上角的Add Sitemap按钮。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/add-sitemap-button.png" alt="add sitemap button" />
</p>
<p>步骤＃10：输入Filename和Path值。</p>
<p>
<img class="aligncenter size-full wp-image-23495" src="https://www.360magento.com/media/wysiwyg/blog_262/new-site-map.png" alt="new site map" />
</p>
<p>通常，sitemap.xml用作文件名，而路径设置为正斜杠。请记住，创建站点地图文件的目录必须是可写的。</p>
<p>步骤＃11：按“Save”或“Save & Generate”按钮。</p>
<p>如果按Save，则地图将在设置日期和时间自动生成。否则，如果按“Save & Generate”，则将立即生成站点地图。</p>
<p>如果您的Magento商店中有大量产品，则第一种选择更可取，您可以将生成时间安排在商店负荷最小的时候。</p>
<h2 id="step_5">如何向Google提交站点地图？</h2>
<p>可以通过Google Search Console来将XML网站地图提交给Google，不需要特别的知识。以下是一个简单的分步指南，将指导您完成此过程。</p>
<p><strong>注意！</strong>在向Google添加站点地图之前，必须先在Google Search Console中确认其对网站的权利。</p>
<p>步骤1：转到Google Search Console工具，然后输入网站的地址。</p>
<p>步骤2：在左侧栏中选择Sitemap。</p>
<p>步骤＃3：在相应的输入行中输入不带域名地址的XML网站地图URL（在屏幕截图中标记为2）。通常，地址是站点URL + sitemap.xml，但是可以肯定的是，您可以签入Magento站点地图生成设置。</p>
<p>步骤4：按Submit（提交）按钮。</p>
<p>站点地图将添加到web爬虫程序队列中。您可以在下面提交的站点地图部分中跟踪其站点地图提交的进度。</p>
<p>如果出现以下警告–“Your sitemap appears to be an HTML page. Please use a supported sitemap format instead” –在Google提交站点地图时出现，然后您需要检查在第3步中提交的站点地图URL是否正确。</p>
<p>
<img src="https://www.360magento.com/media/wysiwyg/blog_262/google-search-console.png" alt="google search console" />
</p>
<!-- Shortcoder conditions not met -->
<h2 id="step_6">如何为自定义模型生成站点地图？</h2>
<p>通过将新的ItemProvider添加到\Magento\Sitemap\Model\ItemProvider\Composite中，可以从自定义模型添加URL。</p>
<p>以下是将CMS页面添加到站点地图中的示例。尽管CMS页面默认包含在XML网站地图中，但是我们的示例演示了如何添加任何模型：</p>
<p><strong>app/code/VendorName/Sitemap/etc/module.xml</strong><br></p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
	&lt;module name="VendorName_Sitemap" &gt;
    	&lt;sequence&gt;
        	&lt;module name="Magento_Sitemap"/&gt;
    	&lt;/sequence&gt;
	&lt;/module&gt;
&lt;/config&gt;
</pre>
<p><br><strong>app/code/VendorName/Sitemap/etc/di.xml</strong><br></p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"&gt;

	&lt;!-- Types --&gt;

	&lt;type name="Magento\Sitemap\Model\ItemProvider\Composite"&gt;
    	&lt;arguments&gt;
        	&lt;argument name="itemProviders" xsi:type="array"&gt;
            	&lt;item name="examplePagesProvider" xsi:type="object"&gt;
                	VendorName\Sitemap\Model\ItemProvider\ExamplePages
            	&lt;/item&gt;
        	&lt;/argument&gt;
    	&lt;/arguments&gt;
	&lt;/type&gt;
	&lt;type name="VendorName\Sitemap\Model\ItemProvider\ExamplePages"&gt;
    	&lt;arguments&gt;
        	&lt;argument name="configReader" xsi:type="object"&gt;
            	VendorName\Sitemap\Model\ItemProvider\ExamplePagesConfigReader
        	&lt;/argument&gt;
    	&lt;/arguments&gt;
	&lt;/type&gt;

&lt;/config&gt;
</pre>
<p><br><strong>app/code/VendorName/Sitemap/etc/adminhtml/system.xml</strong><br></p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;

&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"&gt;
	&lt;system&gt;
    	&lt;section id="sitemap"&gt;
        	&lt;group id="example_pages" translate="label" type="text" sortOrder="0" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
            	&lt;label&gt;
                	&lt;![CDATA[Example Pages Options]]&gt;
            	&lt;/label&gt;
            	&lt;field id="changefreq" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"&gt;
                	&lt;label&gt;
                    	&lt;![CDATA[Frequency]]&gt;
                	&lt;/label&gt;
                	&lt;source_model&gt;Magento\Sitemap\Model\Config\Source\Frequency&lt;/source_model&gt;
            	&lt;/field&gt;
            	&lt;field id="priority" translate="label comment" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"&gt;
                	&lt;label&gt;
                    	&lt;![CDATA[Priority]]&gt;
                	&lt;/label&gt;
                	&lt;comment&gt;
                    	&lt;![CDATA[Valid values range from 0.0 to 1.0.]]&gt;
                	&lt;/comment&gt;
                	&lt;backend_model&gt;Magento\Sitemap\Model\Config\Backend\Priority&lt;/backend_model&gt;
            	&lt;/field&gt;
        	&lt;/group&gt;
    	&lt;/section&gt;
	&lt;/system&gt;
&lt;/config&gt;
</pre>

<p><b>app/code/VendorName/Sitemap/Model/ItemProvider/ExamplePages.php</b><br></p>
<pre>
&lt;?php

namespace VendorName\Sitemap\Model\ItemProvider;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Sitemap\Model\ItemProvider\ItemProviderInterface;
use Magento\Sitemap\Model\SitemapItemFactory;


/**
 * Class ExamplePages
 * @package VendorName\Sitemap\Model\ItemProvider
 */
class ExamplePages implements ItemProviderInterface
{
	/**
 	* @var ExamplePagesConfigReader
 	*/
	private $configReader;

	/**
 	* @var SitemapItemFactory
 	*/
	private $itemFactory;

	/**
 	* @var \Magento\Cms\Api\PageRepositoryInterface
 	*/
	private $pageRepositoryInterface;

	/**
 	* @var \Magento\Framework\Api\SearchCriteriaBuilder
 	*/
	private $searchCriteriaBuilder;

	/**
 	* @var array
 	*/
	protected $sitemapItems = [];

	/**
 	* ExamplePages constructor.
 	* @param ExamplePagesConfigReader $configReader
 	* @param SitemapItemFactory $itemFactory
 	* @param \Magento\Cms\Api\PageRepositoryInterface $pageRepositoryInterface
 	* @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
 	*/
	public function __construct(
    	ExamplePagesConfigReader $configReader,
    	SitemapItemFactory $itemFactory,

//    	CMS pages will be used as an example

    	\Magento\Cms\Api\PageRepositoryInterface $pageRepositoryInterface,
    	\Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
	) {
    	$this-&gt;configReader = $configReader;
    	$this-&gt;itemFactory = $itemFactory;

    	$this-&gt;pageRepositoryInterface = $pageRepositoryInterface;
    	$this-&gt;searchCriteriaBuilder = $searchCriteriaBuilder;
	}

	/**
 	* @param int $storeId
 	* @return array
 	* @throws NoSuchEntityException
 	*/
	public function getItems($storeId): array
	{

//  	CMS pages will be used as an example

    	$searchCriteria = $searchCriteria = $this-&gt;searchCriteriaBuilder-&gt;create();
    	$pages = $this-&gt;pageRepositoryInterface-&gt;getList($searchCriteria)-&gt;getItems();

    	foreach ($pages as $page) {
        	$this-&gt;sitemapItems[] = $this-&gt;itemFactory-&gt;create(
            	[
                	'url' =&gt; $page-&gt;getIdentifier(),
                	'updatedAt' =&gt; $page-&gt;getUpdateTime(),
                	'priority' =&gt; $this-&gt;getPriority($storeId),
                	'changeFrequency' =&gt; $this-&gt;getChangeFrequency($storeId)
            	]
        	);
    	}

    	return $this-&gt;sitemapItems;
	}

	/**
 	* @param int $storeId
 	*
 	* @return string
 	*
 	*/
	private function getChangeFrequency(int $storeId): string
	{
    	return $this-&gt;configReader-&gt;getChangeFrequency($storeId);
	}

	/**
 	* @param int $storeId
 	*
 	* @return string
 	*
 	*/
	private function getPriority(int $storeId): string
	{
    	return $this-&gt;configReader-&gt;getPriority($storeId);
	}

}
</pre>
<p><br><b>app/code/VendorName/Sitemap/Model/ItemProvider/ExamplePagesConfigReader.php</b><br></p>
<pre>
&lt;?php

namespace VendorName\Sitemap\Model\ItemProvider;

use Magento\Sitemap\Model\ItemProvider\ConfigReaderInterface;;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

/**
 * Class ExamplePagesConfigReader
 * @package VendorName\Sitemap\Model\ItemProvider
 */
class ExamplePagesConfigReader implements ConfigReaderInterface
{
	const XML_PATH_CHANGE_FREQUENCY = 'sitemap/example_pages/changefreq';
	const XML_PATH_PRIORITY = 'sitemap/example_pages/priority';

	/**
 	* @var ScopeConfigInterface
 	*/
	private $scopeConfig;

	/**
 	* @param ScopeConfigInterface $scopeConfig
 	*
 	*/
	public function __construct(ScopeConfigInterface $scopeConfig)
	{
    	$this-&gt;scopeConfig = $scopeConfig;
	}

	/**
 	* @param int $storeId
 	* @return string
 	*/
	public function getPriority($storeId): string
	{
    	$storeId = (int)$storeId;
    	return $this-&gt;getConfigValue(self::XML_PATH_PRIORITY, $storeId);
	}

	/**
 	* @param int $storeId
 	* @return string
 	*/
	public function getChangeFrequency($storeId): string
	{
    	$storeId = (int)$storeId;
    	return $this-&gt;getConfigValue(self::XML_PATH_CHANGE_FREQUENCY, $storeId);
	}

	/**
 	* @param string $configPath
 	* @param int $storeId
 	*
 	* @return string
 	*
 	*/
	private function getConfigValue(string $configPath, int $storeId): string
	{
    	$configValue = $this-&gt;scopeConfig-&gt;getValue(
        	$configPath,
        	ScopeInterface::SCOPE_STORE,
        	$storeId
    	);
    	return (string)$configValue;
	}
}
</pre>
<h2>总结</h2>
<p>如您所见，有两种主要的站点地图类型-XML和HTML。它们提供不同的功能-一种用于搜索引擎，另一种用于用户体验和搜索优化。按照上面提供的详细分步说明，您可以自行创建必要的站点地图，但是如果您需要支持，可以转到<a href="https://www.360magento.com/magento-maintenance" target="_blank" rel="noopener">“技术支持”</a>，我们将解决您可能遇到的任何问题，并为您提供优质的Magento开发解决方案。</p>]]></description>
      <pubDate>Tue, 05 Nov 2019 02:20:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2中如何添加js(javascript)脚本]]></title>
      <link>https://www.360magento.com/blog/add-javascript-to-magento-2/</link>
      <description><![CDATA[<p>在本文中，我们将研究Magento 2中的如何连接JavaScript。这里有四种连接方法：</p>
<p><a href="#step_1">通过&lt;script type =&rdquo;text/javascript&gt; &lt;/script&gt; <br /></a><a href="#step_2">以Magento风格<br /></a><a href="#step_3">命令式方法<br /></a><a href="#step_4">通过require-config.js文件</a></p>
<div class="h2text">
<h2><a id="step_1"></a>通过&lt;script type =&rdquo;text/javascript&gt; &lt;/script&gt;</h2>
</div>
<p><span style="font-weight: 400;">这是最简单但不推荐的方法，唯一的一个优点就是简单。如果要连接第三方库，可以保留此方法。在其他情况下，这种方法有几个明显的缺点：代码将很难再次使用，并且可能阻止页面加载（当然，这取决于脚本包含的内容）。显然，随着项目复杂性的增加，控制此类代码变得非常困难。在讨论此方法时，我们还应提及CSP（内容安全策略）。以这种方式连接的代码非常容易受到CSS攻击（跨站点脚本）的攻击。如果仍要使用此方法，则在连接时添加以下属性：deferred =&ldquo;true&rdquo;，async =&ldquo;true&rdquo;。</span></p>
<div class="h2text">
<h2><a id="step_2"></a>Magento风格</h2>
</div>
<p><span style="font-weight: 400;">现在，让我们考虑以Magento风格连接JS脚本的方法。首先，值得一提的是Magento 2使用RequireJS脚本来连接JS。这种方法允许模块化使用JS，以及后台和异步加载。要了解更多信息，请访问</span><a href="https://requirejs.org/" rel="noopener" target="_blank"><span style="font-weight: 400;">requirejs.org</span></a><span style="font-weight: 400;">的链接</span><span style="font-weight: 400;">。<br /></span></p>
<p><span style="font-weight: 400;">因此，第一种方法是使用特殊的</span><strong>data-mage-init </strong><span style="font-weight: 400;">属性。该属性必须包含JS模块的路径作为值、要应用JS代码的元素和配置参数。</span></p>
<p><span style="font-weight: 400;">例如，假设我们有一个requireJS模块调用一个弹出窗口。让我们在以下目录中创建一个JS文件：</span></p>
<p><strong>app/code/Example/JavascriptInitExample/view/frontend/web/example.js</strong></p>
<p><span style="font-weight: 400;">接下来，我们将在文件内编写以下代码：</span></p>
<pre>define([], function(){
    alert("A simple Example module");  
});
</pre>
<p><br /><span style="font-weight: 400;">现在假设有一个特定的模板，我们想在其中连接我们的JS模块。首先，让我们按照以下方式连接它：</span></p>
<pre>&lt;div class="example-element"  data-mage-init='{"Example_JavascriptInitExample/example": {}}'&gt;A single div&lt;/div&gt;
</pre>
<p><br /><span style="font-weight: 400;">加载页面时，浏览器将仅显示带有指定文本的弹出窗口。没什么特别的，但是如果我们将一些配置值传递给data-mage-init呢？例如，让我们这样写：</span></p>
<pre>&lt;div class="example-element"  data-mage-init='{"Example_JavascriptInitExample/example": {"config": "value"}}'&gt;A single div&lt;/div&gt;
</pre>
<p><span style="font-weight: 400;">并通过以下方式更改JS模块：</span></p>
<pre>define([], function(config){
    alert("A simple Example module");
    console.log(config);   
});
</pre>
<p><br /> 重新加载页面时，我们将获得相同的弹出窗口，但是如果我们看一下控制台，我们将看到config参数的值等于该值。同样，我们可以在JS模块中传递任何参数。除此之外，我们可以传递一个DOM元素作为参数，然后调用脚本。为此，我们通过以下方式重写模块：</p>
<pre>define([], function(config, element){
    alert("A simple Example module");
    console.log(config);
    console.log(element);   
});
</pre>
<p><br /> 重新加载页面后，该元素的输出将添加到控制台。在我们的例子中，将是</p>
<pre>&lt;div class="example-element"&gt;&lt;/div&gt;
</pre>
<p><br /> 当我们使用布局中的<strong>&lt;arguments&gt; &lt;/ arguments&gt;</strong>标记将一系列参数传递给块时，我们也可能遇到一种情况。如果我们想将这些参数作为JS模块的参数，则需要通过以下方式传递它们：</p>
<p>\</p>
<pre>&lt;div class="example-element"  data-mage-init='{"Example_JavascriptInitExample/example": 
&lt;?= /* @escapeNotVerified */ $block-&gt;getJsLayout() ?&gt;'&gt;A single div&lt;/div&gt;
</pre>
<p><br /><span style="font-weight: 400;">我们将JSON作为输入参数，可以根据需要进一步使用JSON。</span></p>
<p><span style="font-weight: 400;">通常，我们必须向模块传递多个参数。上面描述的语法可能很难理解，因此可以使用</span><strong>type =&ldquo;text/x-magento-init&rdquo; </strong><span style="font-weight: 400;">作为替代。看起来像这样：</span></p>
<pre>&lt;script type="text/x-magento-init"&gt;
    {
        ".example-element": {
            "Example_JavascriptInitExample/example":{
"config":"value",
"config2":"value2",
"config3": "optionConfig": &lt;?php /* @noEscape */ echo $block-&gt;getJsonConfig()?&gt;

   }          
        }
    }        
&lt;/script&gt;
</pre>
<p><br /> 如您所见，此代码更容易阅读。</p>
<div class="h2text">
<h2><a id="step_3"></a>命令式方法</h2>
</div>
<p>还值得一提的是，在连接JS模块时所谓的命令式方法通常可以在Magento 2代码中找到。但是，在M2文档中建议不要使用它。连接如下所示：</p>
<pre>&lt;script type="text/javascript"&gt;
require( [
       'jquery'
   ],
   function($) {
       	alert('Example');
       });
   }
);
&lt;/script&gt;
</pre>
<div class="h2text">
<h2><a id="step_4"></a>通过require-config.js文件</h2>
</div>
<p><span style="font-weight: 400;">最后，让我们考虑以下情况：当我们需要将脚本连接到多个页面而不是在同一个页面和特定元素中时。在这种情况下，您可以使用</span><strong>require-config.js </strong><span style="font-weight: 400;">文件，该文件需要在</span><strong>view/base/ require-config.js </strong><span style="font-weight: 400;">子目录下</span><span style="font-weight: 400;">的模块文件夹中创建</span><span style="font-weight: 400;">。内容应如下所示：</span></p>
<pre>var config = {
deps: [
'Example_JavascriptInitExample/js/example',
'AnotherExample_JavascriptInitExample/js/example',
]
};
</pre>
<p><br /> 在这种情况下，我们连接的脚本将在模块的所有页面上运行。通常，某些第三方库以这种方式连接。您还可以设置map属性并为各种模块定义前缀。将来，我们可以使用这些前缀在其他模块中连接所需的JS模块。例如<span style="font-weight: 400;">：</span></p>
<pre>var config = {
map: {
	" * " : {
		"example_alias": "example.js"
}
}
}
</pre>
<p><br /> 现在我们可以使用创建的别名连接相应的JS模块：</p>
<pre>define([
	"jquery",
	"example_alias"
], function($, config){
	/* code goes here */    
});
</pre>
<p><br /> 如果需要确定JS文件的加载顺序，则可以使用shim选项。</p>
<p>好了，这些都是Magento 2中连接JS文件的所有现有方法，希望一切都清楚了。感谢您的阅读。</p>]]></description>
      <pubDate>Fri, 01 Nov 2019 06:49:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中使用JavaScript组件]]></title>
      <link>https://www.360magento.com/blog/utilizing-javascript-component-m2/</link>
      <description><![CDATA[<p>Magento 2使用RequireJS库来使用JavaScript。该库使用异步依赖项加载模型-AMD。这使您可以优化加载包含JavaScript文件的页面所需的时间。另外，通过管理JavaScript资源依赖性，我们摆脱了已加载库的重复。</p>
<p><a href="#step_1">JavaScript资源的存储位置<br></a><a href="#step_2">JavaScript组件<br></a><a href="#step_3">Define vs require<br></a><a href="#step_4">在PHTML模板中插入JS组件<br></a><a href="#step_5">选择器上初始化组件<br></a><a href="#step_6">在带参数的选择器上初始化组件<br></a><a href="#step_7">在JavaScript中选择器上初始化组件</a></p>
<h2><a id="step_1"></a><strong><span style="color: #000000;">JavaScript资源的存储位置</span></strong></h2>
<ul><li><strong>lib/web/</strong> -此文件夹包含Magento中使用的库。这些可以是第三方库，例如jquery，underscore.js，knockout.js，也可以是基于<em>/mage/</em>文件夹中的Magento库。</li>
<li><strong>app/code/[Vendor]/[Module]/view/[areaName]/web/ </strong> —模块中使用的javascript文件的路径；</li>
<li><strong>app/design/[areaName]/[VendorTheme]/[themeName]/web/</strong> -主题中使用的javascript文件的路径；</li>
<li><strong>app/design/[areaName]/[VendorTheme]/[themeName]/[Vendor]_[Module]/web/</strong> -模块的继承javascript文件的路径。</li>
</ul><h2><strong><a id="step_2"></a><span style="color: #000000;">JavaScript组件</span></strong></h2>
<p>JS组件是作为AMD模块的RequireJS模块。这种方法使我们可以将逻辑封装在模块中，而不会阻塞全局名称空间。模块也可以使用其他模块。</p>
<p>这是一个简单的RequireJS模块的示例：<br></p>
<pre>
requirejs([], function() {
   alert("Hello World!");
});
</pre>
<p><br>
现在，在加载页面时，您将看到弹出“ Hello world”！</p>
<p>让我们连接jQuery和mage/cookies：<br></p>
<pre>
define([
  "jquery",
  "mage/cookies"
], function($){
  ...
});
</pre>
<p><br>
如您所见，您需要以数组的形式指定必要的模块以连接这些模块。然后RequireJs将按照声明模块的顺序将模块传递给函数。</p>
<h2><a id="step_3"></a><strong><span style="color: #000000;">Define vs require</span></strong></h2>
<p>如果要创建模块，应用程序的其他部分将依赖该模块，则需要使用define()。如果我们的模块仅使用其他模块，则使用require（）。</p>
<h2><strong><a id="step_4"></a><span style="color: #000000;">在PHTML模板中插入JS组件</span></strong></h2>
<p>根据任务，您可以使用两个选项之一来表示：</p>
<ul><li>使用data-mage-init属性</li>
<li>使用<em>&lt;script type =“text/x-magento-init”/&gt;</em>标记</li>
</ul><p>让我们弄清楚哪些选项可用以及何时可以使用它们。假设您只需要一个简单的JS文件连接，而无需指定参数或组件。</p>
<p>PHTML中JS的简单连接：<br></p>
<pre>

&lt;script type="text/x-magento-init"&gt;
{
   "*": {
       "Vendor_Module/js/myfile": {}
   }
}
&lt;/script&gt;
</pre>
<p><br>
在这个案例中，文件的路径为：</p>
<p><em>Vendor/Module/view/frontend/web/js/myfile.js</em></p>
<p>其中您的代码：<br></p>
<pre>
require([],
function(){
   "use strict";
   //your js goes here
});
</pre>
<h2><a id="step_5"></a><strong><span style="color: #000000;">在选择器上初始化组件</span></strong></h2>
<p>有两种方法可以做到这一点：</p>
<p>1)在data-mage-init属性中初始化组件。例如：<br></p>
<pre>
&lt;div id="element-id" data-mage-init='{"Vendor_Module/js/myfile":{}}'&gt;&lt;/div&gt;
</pre>
<p><br>
2)使用具有<em>&lt;script type =”text/x-magento-init”</em>属性的标签。例如：<br></p>
<pre>
&lt;script type="text/x-magento-init"&gt;
{
&nbsp;&nbsp;&nbsp;"#element-id": { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Vendor_Module/js/myfile": {} 
&nbsp;&nbsp;&nbsp;} 
} 
&lt;/script&gt;
</pre>
<p><br>
在这个案例中，文件的路径为：</p>
<p><em>Vendor/Module/view/frontend/web/js/jsfilename.js</em></p>
<p>其中您的代码：<br></p>
<pre>
define(['uiComponent'],
function (Component) {
&nbsp;&nbsp;&nbsp;'use strict';
&nbsp;&nbsp;&nbsp;return Component.extend({
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;initialize: function (config, node) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// some code
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;});
});
</pre>
<p></p>
<h2><a id="step_6"></a><strong><span style="color: #000000;">在带参数的选择器上初始化组件</span></strong></h2>
<p>初始化组件时，向其发送参数（由php动态确定）也很重要。</p>
<p>1)data-mage-init<br></p>
<pre>
&lt;div id="element-id" data-mage-init='{"Vendor_Module/js/myfile":{"parameter":"value","status":&lt;?php echo $block-&gt;getStatus(); ?&gt;
}}'&gt;&lt;/div&gt;
</pre>
<p><br>
2)使用具有<em>&lt;script type =”text/x-magento-init”</em>属性的标签。例如：<br></p>
<pre>
&lt;script type="text/x-magento-init"&gt;
{
&nbsp;&nbsp;&nbsp;"#element-id": { 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Vendor_Module/js/myfile1": {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"parameter":"value",
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"status":&lt;?php echo $block-&gt;getStatus(); ?&gt;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} 
&nbsp;&nbsp;&nbsp;}
} 
&lt;/script&gt;
</pre>
<h2><a id="step_7"></a><strong><span style="color: #000000;">在JavaScript中的选择器上初始化组件</span></strong></h2>
<p>如果我们没有使用php获取动态参数，则可以在javascript文件中的选择器上初始化组件。</p>
<p>例如：</p>
<p><em>vendor/magento/module-swatches/view/adminhtml/web/js/visual.js</em><br></p>
<pre>
…
$('[data-role=swatch-visual-options-container]').sortable({
&nbsp;&nbsp;distance: 8,
&nbsp;&nbsp;tolerance: 'pointer',
&nbsp;&nbsp;cancel: 'input, button',
&nbsp;&nbsp;axis: 'y',
&nbsp;&nbsp;....
&nbsp;&nbsp;}
});
...
</pre>]]></description>
      <pubDate>Fri, 18 Oct 2019 09:28:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2创建多站点多商店]]></title>
      <link>https://www.360magento.com/blog/magento2-create-multiwebsite/</link>
      <description><![CDATA[<h2><b>步骤1：在Magento后台创建websites, stores, 和 store views</b></h2>
<ol>
<li>登录到Magento后台创建websites, stores, 和 store views。</li>
<li>单击<b>Stores</b>&gt;Settings&gt;<b>All Stores</b>。</li>
<li>在Stores页面上，点击<b>Create Website</b>。
<ul>
<li><b>Name</b>字段：输入名称以标识网站。</li>
<li><b>Code</b>字段：输入唯一的代码；例如，如果您有法国商店或德国商店，则可以输入french, german</li>
<li><b>Sort Order</b>字段：输入数字用来识别排序顺序。</li>
</ul>
</li>
<li>单击<b>Save Web Site</b>。</li>
</ol>
<h2><b>步骤2：创建Apache虚拟主机</b></h2>
<ol>
<li>以具有root 用户特权的用户身份，在文本编辑器中打开虚拟主机配置文件。</li>
<li>例如，打开/etc/httpd/conf/httpd.conf</li>
<li>找到以&lt;VirtualHost *：80&gt; 开头的部分。</li>
<li>在任何现有虚拟主机之后创建以下虚拟主机：</li>
<li>
<pre>
<VirtualHost *:80>
   ServerName          mylocalsite.com
   DocumentRoot        /var/www/html/magento2/pub/
</VirtualHost>

<VirtualHost *:80>
   ServerName          french.mylocalsite.com
   DocumentRoot        /var/www/html/magento2/pub/
   SetEnv MAGE_RUN_CODE "french"
   SetEnv MAGE_RUN_TYPE "website"
</VirtualHost>

<VirtualHost *:80>
   ServerName          german.mylocalsite.com
   DocumentRoot        /var/www/html/magento2/pub/
   SetEnv MAGE_RUN_CODE "german"
   SetEnv MAGE_RUN_TYPE "website"
</VirtualHost>
</pre>
</li>
<li>将更改保存到httpd.conf 并退出文本编辑器。</li>
<li>重新启动Apache：
<ul>
<li>CentOS：service httpd restart</li>
<li>Ubuntu：service apache2 restart</li>
</ul>
</li>
</ol>
<h2><b>步骤3：验证您的网站</b></h2>
<ol>
<li>打开操作系统的hosts文件。</li>
<li>以以下格式添加静态路由：</li>
<li>&lt;ip地址&gt; french.mylocalsite.com &lt;ip地址&gt; german.mylocalsite.com<br>
</li>
<li>在浏览器中打开以下URL之一：</li>
<li>http://mylocalsite.com/admin http://french.mylocalsite.com/frenchstoreview http://german.mylocalsite.com/germanstoreview<br>
<br>
</li>
</ol>]]></description>
      <pubDate>Mon, 14 Oct 2019 05:00:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2中的国家地区代码]]></title>
      <link>https://www.360magento.com/blog/magento-country-code/</link>
      <description><![CDATA[<p>估计很多朋友跟我一样，不知道从哪儿获取<strong>Magentro国家/地区代码</strong>。</p>
<p>当您要上传<strong>运输价格表</strong>（csv文件）时，需要在文件中输入这些代码。</p>
<p>下面我已经全部列出来了</p>
<table style="width: 75%;" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td valign="bottom" nowrap="nowrap" width="281"><b>Country</b></td>
<td valign="bottom" nowrap="nowrap" width="97"><b>2 Digit Code</b></td>
<td valign="bottom" nowrap="nowrap" width="95"><b>3 Digit Code</b></td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Afghanistan</td>
<td valign="bottom" nowrap="nowrap" width="97">AF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AFG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Albania</td>
<td valign="bottom" nowrap="nowrap" width="97">AL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ALB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Algeria</td>
<td valign="bottom" nowrap="nowrap" width="97">DZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DZA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;American Samoa</td>
<td valign="bottom" nowrap="nowrap" width="97">AS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ASM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Andorra</td>
<td valign="bottom" nowrap="nowrap" width="97">AD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AND</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Angola</td>
<td valign="bottom" nowrap="nowrap" width="97">AO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AGO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Anguilla</td>
<td valign="bottom" nowrap="nowrap" width="97">AI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AIA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Antarctica</td>
<td valign="bottom" nowrap="nowrap" width="97">AQ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ATA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Antigua and Barbuda</td>
<td valign="bottom" nowrap="nowrap" width="97">AG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ATG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Argentina</td>
<td valign="bottom" nowrap="nowrap" width="97">AR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ARG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Armenia</td>
<td valign="bottom" nowrap="nowrap" width="97">AM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ARM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Aruba</td>
<td valign="bottom" nowrap="nowrap" width="97">AW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ABW</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Australia</td>
<td valign="bottom" nowrap="nowrap" width="97">AU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AUS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Austria</td>
<td valign="bottom" nowrap="nowrap" width="97">AT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AUT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Azerbaijan</td>
<td valign="bottom" nowrap="nowrap" width="97">AZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;AZE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bahamas</td>
<td valign="bottom" nowrap="nowrap" width="97">BS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BHS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bahrain</td>
<td valign="bottom" nowrap="nowrap" width="97">BH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BHR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bangladesh</td>
<td valign="bottom" nowrap="nowrap" width="97">BD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BGD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Barbados</td>
<td valign="bottom" nowrap="nowrap" width="97">BB</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BRB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Belarus</td>
<td valign="bottom" nowrap="nowrap" width="97">BY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BLR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Belgium</td>
<td valign="bottom" nowrap="nowrap" width="97">BE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BEL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Belize</td>
<td valign="bottom" nowrap="nowrap" width="97">BZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BLZ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Benin</td>
<td valign="bottom" nowrap="nowrap" width="97">BJ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BEN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bermuda</td>
<td valign="bottom" nowrap="nowrap" width="97">BM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BMU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bhutan</td>
<td valign="bottom" nowrap="nowrap" width="97">BT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BTN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bolivia</td>
<td valign="bottom" nowrap="nowrap" width="97">BO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BOL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bosnia and Herzegovina</td>
<td valign="bottom" nowrap="nowrap" width="97">BA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BIH</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Botswana</td>
<td valign="bottom" nowrap="nowrap" width="97">BW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BWA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bouvet Island</td>
<td valign="bottom" nowrap="nowrap" width="97">BV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BVT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Brazil</td>
<td valign="bottom" nowrap="nowrap" width="97">BR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BRA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;British Indian Ocean Territory</td>
<td valign="bottom" nowrap="nowrap" width="97">IO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IOT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;British Virgin Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">VG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VGB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Brunei</td>
<td valign="bottom" nowrap="nowrap" width="97">BN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BRN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Bulgaria</td>
<td valign="bottom" nowrap="nowrap" width="97">BG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BGR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Burkina Faso</td>
<td valign="bottom" nowrap="nowrap" width="97">BF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BFA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Burundi</td>
<td valign="bottom" nowrap="nowrap" width="97">BI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BDI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cambodia</td>
<td valign="bottom" nowrap="nowrap" width="97">KH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KHM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cameroon</td>
<td valign="bottom" nowrap="nowrap" width="97">CM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CMR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Canada</td>
<td valign="bottom" nowrap="nowrap" width="97">CA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CAN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cape Verde</td>
<td valign="bottom" nowrap="nowrap" width="97">CV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CPV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cayman Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">KY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CYM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Central African Republic</td>
<td valign="bottom" nowrap="nowrap" width="97">CF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CAF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Chad</td>
<td valign="bottom" nowrap="nowrap" width="97">TD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TCD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Chile</td>
<td valign="bottom" nowrap="nowrap" width="97">CL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CHL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;China</td>
<td valign="bottom" nowrap="nowrap" width="97">CN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CHN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Christmas Island</td>
<td valign="bottom" nowrap="nowrap" width="97">CX</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CXR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cocos [Keeling] Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">CC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CCK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Colombia</td>
<td valign="bottom" nowrap="nowrap" width="97">CO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;COL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Comoros</td>
<td valign="bottom" nowrap="nowrap" width="97">KM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;COM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Congo</td>
<td valign="bottom" nowrap="nowrap" width="97">CG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;COG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Congo</td>
<td valign="bottom" nowrap="nowrap" width="97">CD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;COD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cook Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">CK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;COK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Costa Rica</td>
<td valign="bottom" nowrap="nowrap" width="97">CR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CRI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Croatia</td>
<td valign="bottom" nowrap="nowrap" width="97">HR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HRV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cuba</td>
<td valign="bottom" nowrap="nowrap" width="97">CU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CUB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Cyprus</td>
<td valign="bottom" nowrap="nowrap" width="97">CY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CYP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Czech Republic</td>
<td valign="bottom" nowrap="nowrap" width="97">CZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CZE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Côte d’Ivoire</td>
<td valign="bottom" nowrap="nowrap" width="97">CI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CIV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Denmark</td>
<td valign="bottom" nowrap="nowrap" width="97">DK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DNK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Djibouti</td>
<td valign="bottom" nowrap="nowrap" width="97">DJ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DJI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Dominica</td>
<td valign="bottom" nowrap="nowrap" width="97">DM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DMA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Dominican Republic</td>
<td valign="bottom" nowrap="nowrap" width="97">DO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DOM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Ecuador</td>
<td valign="bottom" nowrap="nowrap" width="97">EC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ECU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Egypt</td>
<td valign="bottom" nowrap="nowrap" width="97">EG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;EGY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;El Salvador</td>
<td valign="bottom" nowrap="nowrap" width="97">SV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SLV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Equatorial Guinea</td>
<td valign="bottom" nowrap="nowrap" width="97">GQ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GNQ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Eritrea</td>
<td valign="bottom" nowrap="nowrap" width="97">ER</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ERI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Estonia</td>
<td valign="bottom" nowrap="nowrap" width="97">EE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;EST</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Ethiopia</td>
<td valign="bottom" nowrap="nowrap" width="97">ET</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ETH</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Falkland Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">FK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FLK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Faroe Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">FO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FRO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Fiji</td>
<td valign="bottom" nowrap="nowrap" width="97">FJ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FJI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Finland</td>
<td valign="bottom" nowrap="nowrap" width="97">FI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FIN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;France</td>
<td valign="bottom" nowrap="nowrap" width="97">FR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FRA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;French Guiana</td>
<td valign="bottom" nowrap="nowrap" width="97">GF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GUF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;French Polynesia</td>
<td valign="bottom" nowrap="nowrap" width="97">PF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PYF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;French Southern Territories</td>
<td valign="bottom" nowrap="nowrap" width="97">TF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ATF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Gabon</td>
<td valign="bottom" nowrap="nowrap" width="97">GA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GAB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Gambia</td>
<td valign="bottom" nowrap="nowrap" width="97">GM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GMB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Georgia</td>
<td valign="bottom" nowrap="nowrap" width="97">GE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GEO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Germany</td>
<td valign="bottom" nowrap="nowrap" width="97">DE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;DEU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Ghana</td>
<td valign="bottom" nowrap="nowrap" width="97">GH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GHA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Gibraltar</td>
<td valign="bottom" nowrap="nowrap" width="97">GI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GIB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Greece</td>
<td valign="bottom" nowrap="nowrap" width="97">GR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GRC</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Greenland</td>
<td valign="bottom" nowrap="nowrap" width="97">GL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GRL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Grenada</td>
<td valign="bottom" nowrap="nowrap" width="97">GD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GRD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guadeloupe</td>
<td valign="bottom" nowrap="nowrap" width="97">GP</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GLP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guam</td>
<td valign="bottom" nowrap="nowrap" width="97">GU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GUM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guatemala</td>
<td valign="bottom" nowrap="nowrap" width="97">GT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GTM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guernsey</td>
<td valign="bottom" nowrap="nowrap" width="97">GG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GGY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guinea</td>
<td valign="bottom" nowrap="nowrap" width="97">GN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GIN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guinea</td>
<td valign="bottom" nowrap="nowrap" width="97">GW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GNB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Guyana</td>
<td valign="bottom" nowrap="nowrap" width="97">GY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GUY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Haiti</td>
<td valign="bottom" nowrap="nowrap" width="97">HT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HTI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Heard Island and McDonald Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">HM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HMD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Honduras</td>
<td valign="bottom" nowrap="nowrap" width="97">HN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HND</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Hong Kong SAR China</td>
<td valign="bottom" nowrap="nowrap" width="97">HK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HKG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Hungary</td>
<td valign="bottom" nowrap="nowrap" width="97">HU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;HUN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Iceland</td>
<td valign="bottom" nowrap="nowrap" width="97">IS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ISL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;India</td>
<td valign="bottom" nowrap="nowrap" width="97">IN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IND</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Indonesia</td>
<td valign="bottom" nowrap="nowrap" width="97">ID</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IDN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Iran</td>
<td valign="bottom" nowrap="nowrap" width="97">IR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IRN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Iraq</td>
<td valign="bottom" nowrap="nowrap" width="97">IQ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IRQ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Ireland</td>
<td valign="bottom" nowrap="nowrap" width="97">IE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IRL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Isle of Man</td>
<td valign="bottom" nowrap="nowrap" width="97">IM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;IMN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Israel</td>
<td valign="bottom" nowrap="nowrap" width="97">IL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ISR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Italy</td>
<td valign="bottom" nowrap="nowrap" width="97">IT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ITA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Jamaica</td>
<td valign="bottom" nowrap="nowrap" width="97">JM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;JAM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Japan</td>
<td valign="bottom" nowrap="nowrap" width="97">JP</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;JPN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Jersey</td>
<td valign="bottom" nowrap="nowrap" width="97">JE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;JEY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Jordan</td>
<td valign="bottom" nowrap="nowrap" width="97">JO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;JOR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Kazakhstan</td>
<td valign="bottom" nowrap="nowrap" width="97">KZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KAZ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Kenya</td>
<td valign="bottom" nowrap="nowrap" width="97">KE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KEN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Kiribati</td>
<td valign="bottom" nowrap="nowrap" width="97">KI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KIR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Kuwait</td>
<td valign="bottom" nowrap="nowrap" width="97">KW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KWT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Kyrgyzstan</td>
<td valign="bottom" nowrap="nowrap" width="97">KG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KGZ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Laos</td>
<td valign="bottom" nowrap="nowrap" width="97">LA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LAO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Latvia</td>
<td valign="bottom" nowrap="nowrap" width="97">LV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LVA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Lebanon</td>
<td valign="bottom" nowrap="nowrap" width="97">LB</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LBN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Lesotho</td>
<td valign="bottom" nowrap="nowrap" width="97">LS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LSO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Liberia</td>
<td valign="bottom" nowrap="nowrap" width="97">LR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LBR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Libya</td>
<td valign="bottom" nowrap="nowrap" width="97">LY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LBY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Liechtenstein</td>
<td valign="bottom" nowrap="nowrap" width="97">LI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LIE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Lithuania</td>
<td valign="bottom" nowrap="nowrap" width="97">LT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LTU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Luxembourg</td>
<td valign="bottom" nowrap="nowrap" width="97">LU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LUX</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Macau SAR China</td>
<td valign="bottom" nowrap="nowrap" width="97">MO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MAC</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Macedonia</td>
<td valign="bottom" nowrap="nowrap" width="97">MK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MKD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Madagascar</td>
<td valign="bottom" nowrap="nowrap" width="97">MG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MDG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Malawi</td>
<td valign="bottom" nowrap="nowrap" width="97">MW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MWI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Malaysia</td>
<td valign="bottom" nowrap="nowrap" width="97">MY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MYS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Maldives</td>
<td valign="bottom" nowrap="nowrap" width="97">MV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MDV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mali</td>
<td valign="bottom" nowrap="nowrap" width="97">ML</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MLI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Malta</td>
<td valign="bottom" nowrap="nowrap" width="97">MT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MLT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Marshall Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">MH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MHL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Martinique</td>
<td valign="bottom" nowrap="nowrap" width="97">MQ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MTQ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mauritania</td>
<td valign="bottom" nowrap="nowrap" width="97">MR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MRT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mauritius</td>
<td valign="bottom" nowrap="nowrap" width="97">MU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MUS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mayotte</td>
<td valign="bottom" nowrap="nowrap" width="97">YT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MYT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mexico</td>
<td valign="bottom" nowrap="nowrap" width="97">MX</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MEX</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Micronesia</td>
<td valign="bottom" nowrap="nowrap" width="97">FM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;FSM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Moldova</td>
<td valign="bottom" nowrap="nowrap" width="97">MD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MDA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Monaco</td>
<td valign="bottom" nowrap="nowrap" width="97">MC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MCO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mongolia</td>
<td valign="bottom" nowrap="nowrap" width="97">MN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MNG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Montenegro</td>
<td valign="bottom" nowrap="nowrap" width="97">ME</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MNE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Montserrat</td>
<td valign="bottom" nowrap="nowrap" width="97">MS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MSR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Morocco</td>
<td valign="bottom" nowrap="nowrap" width="97">MA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MAR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Mozambique</td>
<td valign="bottom" nowrap="nowrap" width="97">MZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MOZ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Myanmar [Burma]</td>
<td valign="bottom" nowrap="nowrap" width="97">MM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MMR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Namibia</td>
<td valign="bottom" nowrap="nowrap" width="97">NA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NAM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Nauru</td>
<td valign="bottom" nowrap="nowrap" width="97">NR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NRU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Nepal</td>
<td valign="bottom" nowrap="nowrap" width="97">NP</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NPL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Netherlands</td>
<td valign="bottom" nowrap="nowrap" width="97">NL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NLD</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Netherlands Antilles</td>
<td valign="bottom" nowrap="nowrap" width="97">AN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ANT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;New Caledonia</td>
<td valign="bottom" nowrap="nowrap" width="97">NC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NCL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;New Zealand</td>
<td valign="bottom" nowrap="nowrap" width="97">NZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NZL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Nicaragua</td>
<td valign="bottom" nowrap="nowrap" width="97">NI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NIC</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Niger</td>
<td valign="bottom" nowrap="nowrap" width="97">NE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NER</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Nigeria</td>
<td valign="bottom" nowrap="nowrap" width="97">NG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NGA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Niue</td>
<td valign="bottom" nowrap="nowrap" width="97">NU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NIU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Norfolk Island</td>
<td valign="bottom" nowrap="nowrap" width="97">NF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NFK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;North Korea</td>
<td valign="bottom" nowrap="nowrap" width="97">KP</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PRK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Northern Mariana Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">MP</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MNP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Norway</td>
<td valign="bottom" nowrap="nowrap" width="97">NO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;NOR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Oman</td>
<td valign="bottom" nowrap="nowrap" width="97">OM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;OMN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Pakistan</td>
<td valign="bottom" nowrap="nowrap" width="97">PK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PAK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Palau</td>
<td valign="bottom" nowrap="nowrap" width="97">PW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PLW</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Palestinian Territories</td>
<td valign="bottom" nowrap="nowrap" width="97">PS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PSE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Panama</td>
<td valign="bottom" nowrap="nowrap" width="97">PA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PAN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Papua New Guinea</td>
<td valign="bottom" nowrap="nowrap" width="97">PG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PNG</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Paraguay</td>
<td valign="bottom" nowrap="nowrap" width="97">PY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PRY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Peru</td>
<td valign="bottom" nowrap="nowrap" width="97">PE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PER</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Philippines</td>
<td valign="bottom" nowrap="nowrap" width="97">PH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PHL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Pitcairn Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">PN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PCN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Poland</td>
<td valign="bottom" nowrap="nowrap" width="97">PL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;POL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Portugal</td>
<td valign="bottom" nowrap="nowrap" width="97">PT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PRT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Puerto Rico</td>
<td valign="bottom" nowrap="nowrap" width="97">PR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;PRI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Qatar</td>
<td valign="bottom" nowrap="nowrap" width="97">QA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;QAT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Romania</td>
<td valign="bottom" nowrap="nowrap" width="97">RO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ROU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Russia</td>
<td valign="bottom" nowrap="nowrap" width="97">RU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;RUS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Rwanda</td>
<td valign="bottom" nowrap="nowrap" width="97">RW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;RWA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Réunion</td>
<td valign="bottom" nowrap="nowrap" width="97">RE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;REU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Barthélemy</td>
<td valign="bottom" nowrap="nowrap" width="97">BL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;BLM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Helena</td>
<td valign="bottom" nowrap="nowrap" width="97">SH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SHN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Kitts and Nevis</td>
<td valign="bottom" nowrap="nowrap" width="97">KN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KNA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Lucia</td>
<td valign="bottom" nowrap="nowrap" width="97">LC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LCA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Martin</td>
<td valign="bottom" nowrap="nowrap" width="97">MF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;MAF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Pierre and Miquelon</td>
<td valign="bottom" nowrap="nowrap" width="97">PM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SPM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saint Vincent and the Grenadines</td>
<td valign="bottom" nowrap="nowrap" width="97">VC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VCT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Samoa</td>
<td valign="bottom" nowrap="nowrap" width="97">WS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;WSM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;San Marino</td>
<td valign="bottom" nowrap="nowrap" width="97">SM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SMR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Saudi Arabia</td>
<td valign="bottom" nowrap="nowrap" width="97">SA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SAU</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Senegal</td>
<td valign="bottom" nowrap="nowrap" width="97">SN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SEN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Serbia</td>
<td valign="bottom" nowrap="nowrap" width="97">RS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SRB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Seychelles</td>
<td valign="bottom" nowrap="nowrap" width="97">SC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SYC</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Sierra Leone</td>
<td valign="bottom" nowrap="nowrap" width="97">SL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SLE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Singapore</td>
<td valign="bottom" nowrap="nowrap" width="97">SG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SGP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Slovakia</td>
<td valign="bottom" nowrap="nowrap" width="97">SK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SVK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Slovenia</td>
<td valign="bottom" nowrap="nowrap" width="97">SI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SVN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Solomon Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">SB</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SLB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Somalia</td>
<td valign="bottom" nowrap="nowrap" width="97">SO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SOM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;South Africa</td>
<td valign="bottom" nowrap="nowrap" width="97">ZA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ZAF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;South Georgia and the South Sandwich Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">GS</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SGS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;South Korea</td>
<td valign="bottom" nowrap="nowrap" width="97">KR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;KOR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Spain</td>
<td valign="bottom" nowrap="nowrap" width="97">ES</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ESP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Sri Lanka</td>
<td valign="bottom" nowrap="nowrap" width="97">LK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;LKA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Sudan</td>
<td valign="bottom" nowrap="nowrap" width="97">SD</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SDN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Suriname</td>
<td valign="bottom" nowrap="nowrap" width="97">SR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SUR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Svalbard and Jan Mayen</td>
<td valign="bottom" nowrap="nowrap" width="97">SJ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SJM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Swaziland</td>
<td valign="bottom" nowrap="nowrap" width="97">SZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SWZ</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Sweden</td>
<td valign="bottom" nowrap="nowrap" width="97">SE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SWE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Switzerland</td>
<td valign="bottom" nowrap="nowrap" width="97">CH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;CHE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Syria</td>
<td valign="bottom" nowrap="nowrap" width="97">SY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;SYR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;São Tomé and Príncipe</td>
<td valign="bottom" nowrap="nowrap" width="97">ST</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;STP</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Taiwan</td>
<td valign="bottom" nowrap="nowrap" width="97">TW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TWN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tajikistan</td>
<td valign="bottom" nowrap="nowrap" width="97">TJ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TJK</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tanzania</td>
<td valign="bottom" nowrap="nowrap" width="97">TZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TZA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Thailand</td>
<td valign="bottom" nowrap="nowrap" width="97">TH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;THA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Timor</td>
<td valign="bottom" nowrap="nowrap" width="97">TL</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TLS</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Togo</td>
<td valign="bottom" nowrap="nowrap" width="97">TG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TGO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tokelau</td>
<td valign="bottom" nowrap="nowrap" width="97">TK</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TKL</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tonga</td>
<td valign="bottom" nowrap="nowrap" width="97">TO</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TON</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Trinidad and Tobago</td>
<td valign="bottom" nowrap="nowrap" width="97">TT</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TTO</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tunisia</td>
<td valign="bottom" nowrap="nowrap" width="97">TN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TUN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Turkey</td>
<td valign="bottom" nowrap="nowrap" width="97">TR</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TUR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Turkmenistan</td>
<td valign="bottom" nowrap="nowrap" width="97">TM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TKM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Turks and Caicos Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">TC</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TCA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Tuvalu</td>
<td valign="bottom" nowrap="nowrap" width="97">TV</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;TUV</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;U.S. Minor Outlying Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">UM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;UMI</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;U.S. Virgin Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">VI</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VIR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Uganda</td>
<td valign="bottom" nowrap="nowrap" width="97">UG</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;UGA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Ukraine</td>
<td valign="bottom" nowrap="nowrap" width="97">UA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;UKR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;United Arab Emirates</td>
<td valign="bottom" nowrap="nowrap" width="97">AE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ARE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;United Kingdom</td>
<td valign="bottom" nowrap="nowrap" width="97">GB</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;GBR</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;United States</td>
<td valign="bottom" nowrap="nowrap" width="97">US</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;USA</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Uruguay</td>
<td valign="bottom" nowrap="nowrap" width="97">UY</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;URY</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Uzbekistan</td>
<td valign="bottom" nowrap="nowrap" width="97">UZ</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;UZB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Vanuatu</td>
<td valign="bottom" nowrap="nowrap" width="97">VU</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VUT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Vatican City</td>
<td valign="bottom" nowrap="nowrap" width="97">VA</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VAT</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Venezuela</td>
<td valign="bottom" nowrap="nowrap" width="97">VE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VEN</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Vietnam</td>
<td valign="bottom" nowrap="nowrap" width="97">VN</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;VNM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Wallis and Futuna</td>
<td valign="bottom" nowrap="nowrap" width="97">WF</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;WLF</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Western Sahara</td>
<td valign="bottom" nowrap="nowrap" width="97">EH</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ESH</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Yemen</td>
<td valign="bottom" nowrap="nowrap" width="97">YE</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;YEM</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Zambia</td>
<td valign="bottom" nowrap="nowrap" width="97">ZM</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ZMB</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Zimbabwe</td>
<td valign="bottom" nowrap="nowrap" width="97">ZW</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ZWE</td>
</tr>
<tr>
<td valign="bottom" nowrap="nowrap" width="281">&nbsp;Åland Islands</td>
<td valign="bottom" nowrap="nowrap" width="97">AX</td>
<td valign="bottom" nowrap="nowrap" width="95">&nbsp;ALA</td>
</tr>
</tbody>
</table>]]></description>
      <pubDate>Tue, 08 Oct 2019 03:57:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[7个Magento安全提示，可确保您的电子商务商店安全无虞]]></title>
      <link>https://www.360magento.com/blog/magento-security-tips/</link>
      <description><![CDATA[<p>使用Magento系统建立网站时，真正困扰您的主要问题是<strong>如何保护Magento网站</strong>。Magento带有一些强大的内置安全功能，但是您必须采取一些措施来增强您的站点并保持其免受潜在攻击或数据丢失的影响。</p>
<p>尽管它是支持25万个活跃站点的最强大的电子商务平台之一，但它也存在一定的安全风险。根据TechRadar最近发布的Magento安全报告，在Magento上运行的<a href="https://www.techradar.com/news/magento-ecommerce-sites-at-high-risk-of-cyberattack" rel="nofollow" target="_blank">超过87％的电子商务网站</a>面临网络攻击的较高风险。</p>
<p>您的网站可能是其中之一。</p>
<p><strong>目录</strong></p>
<ul>
<li><a href="#1-install-an-ssl-certificate-on-your-store-website">1.在您的网站上安装SSL证书</a></li>
<li><a href="#2-insist-on-the-latest-version-of-magento">2.坚持最新版本的Magento</a></li>
<li><a href="#3-use-strong-passwords">3.使用较强密码</a></li>
<li><a href="#4-use-magento-scan-tool-to-scan-your-ecommerce-store">4.使用Magento扫描工具扫描您的电子商务网站</a></li>
<li><a href="5-use-magento-recaptcha">5.使用Magento reCAPTCHA</a></li>
<li><a href="#6-backup-your-site-regularly">6.定期备份您的网站</a></li>
<li><a href="#7-use-a-unique-url-for-admin-dashboard">7.对管理仪表板使用唯一的URL</a></li>
</ul>
<h2 id="magento-security-best-practices">Magento安全最佳做法</h2>
<p>如果您的站点仍然可以运行，您应该感到高兴，因为在本文中，我们将向您展示重要的Magento安全技巧，这些技巧将确保您的网站日后获得最强的安全性。继续阅读。</p>
<h3 id="1-install-an-ssl-certificate-on-your-store-website">1.在您的网站上安装SSL证书</h3>
<p><img src="https://i.imgur.com/NeS7bM8.png" alt="安装SSL证书"></p>
<p>您需要在网站上使用<a href="https://www.ssl2buy.com/" rel="nofollow" target="_blank">SSL证书</a>有很多理由。从帮助您提高Google排名到增强在网站上购物时的客户信心，这几乎是所有电子商务网站所有者的必备条件。</p>
<p>在安全方面，安全套接字层（SSL）证书旨在加密网站上共享的所有数据。这样，如果您将其安装在您的Magento电子商务网站中，它将对网站上共享的所有机密数据（例如信用卡详细信息和登录信息）进行加密。这对于防止网络攻击者获取此类信息至关重要，因为他们可能会试图窃取这些信息以实施身份盗窃和伪造等犯罪行为。</p>
<p>这样的骗局不仅可能损害您的声誉，而且还会因泄漏而导致巨额赔偿。</p>
<h3 id="2-insist-on-the-latest-version-of-magento">2.坚持最新版本的Magento</h3>
<p><img src="https://i.imgur.com/Zklz8O1.jpg" alt="坚持使用最新版本的Magento"></p>
<p>值得指出的是，Magento本身就是开源软件。因此，任何人都可以为它的发展做出贡献，这对于了解它是如何针对使用它的企业主的黑客来说是一个可行的选择。</p>
<p>不过，请不要担心，因为Magento开发人员已经有了解决此问题的方法。他们始终监视该软件，并且每次发现风险概况时，都会立即对其进行修补并发布该软件的最新版本，而该版本没有任何风险可以锁定这些欺骗手段。</p>
<p>问题是网络犯罪分子总是在寻找那些不<a href="https://www.360magento.com/blog/upgrade-magento-2">安装这些升级程序的</a>企业主。他们使用功能强大的自动化工具来帮助他们定位和定位易受攻击的站点。</p>
<p>随时注意最新的升级，避免成为受害者。</p>
<h3 id="3-use-strong-passwords">3.使用强密码</h3>
<p><img src="https://i.imgur.com/BTXPrq1.jpg" alt="使用强密码"></p>
<p>密码是访问您的网站的密钥。如果在线攻击者得到了它，他/她将不会浪费时间使用它来恶意访问您的网站。</p>
<p>您不希望您的用户数据被盗；您也不想被锁定在您的商业网站之外。避免这种情况的最佳方法是使用难以猜测但容易为您记住的强密码。</p>
<p>如果您不容易记住密码，专家建议使用免费的密码管理器之类的工具来存储密码。除此之外，请勿将密码保存在使用的系统中。</p>
<p>如果系统被感染，某些计算机病毒可以找到并窃取它们。最后，偶尔<a href="https://www.360magento.com/blog/how-reset-admin-password-magento-2">更改密码</a>是确保安全的一个好主意。</p>
<h3 id="4-use-magento-scan-tool-to-scan-your-ecommerce-store">4.使用Magento扫描工具扫描您的电子商务网站</h3>
<p><img src="https://i.imgur.com/6V1bK1Q.png" alt="使用Magento扫描工具"></p>
<p>只看一下就很难在您的电子商务网站中发现安全风险。Magento开发人员了解这一点，因此他们为您介绍了Magento免费扫描工具。</p>
<p>这个工具附带了许多安全工具，这些工具是专门设计的，可以方便地进行自动的网站安全扫描。在例行扫描期间，它可以帮助您检查存储的安全一致性，并在检测到站点上的任何可疑活动时转发实时警报。</p>
<p>此工具的一些核心功能包括将安全扫描会话保存在Magento商家帐户中，安排安全扫描，对可能使您的站点处于风险中的配置问题提供实时警报。</p>
<p>它还为您提供了一个免费指南，告诉您解决这些风险的最佳方法。</p>
<h3 id="5-use-magento-recaptcha">5.使用Magento reCAPTCHA</h3>
<p>使用Magento reCAPTCHA是阻止垃圾邮件并保护您免受攻击者攻击的一种简单方法。它的工作原理是确定在您的站点上启动的访问会话是由机器人还是人来完成，以确保站点登录的真实性和安全性。</p>
<p>大多数网站所有者使用它来抵御字典攻击等攻击，并确保搜索引擎蜘蛛仅对网站上的重要页面进行爬网，以避免垃圾邮件内容可能会使敏感数据或数据库面临被恶意攻击者利用的风险。</p>
<h3 id="6-backup-your-site-regularly">6.定期备份您的网站</h3>
<p><img src="https://i.imgur.com/fDWmgRd.jpg" alt="定期备份您的网站"></p>
<p>尽管互联网使您可以存储并连接到客户端，但它永远都不安全。经验法则是始终准备好备份，以防万一您的站点出现问题。</p>
<p>如果发生任何事情，<a href="https://www.360magento.com/blog/how-to-create-backups-magento-2">备份您的网站</a>将使恢复Magento电子商务网站变得非常容易，如果发生什么事情，导致数据丢失超级容易。您可以通过FTP客户端下载站点数据，然后将其备份到您的帐户中。</p>
<p>无论哪种方式，您都可以使用phpMyAdmin导出存储的数据库。导出后，您可以从Pixie控制面板下的数据库区域访问此数据。之后，选择数据库名称以查看其内容。</p>
<h3 id="7-use-a-unique-url-for-admin-dashboard">7.对管理仪表板使用唯一的URL</h3>
<p><img src="https://i.imgur.com/92pZnKf.jpg" alt="使用唯一网址"></p>
<p>所有Magento网站均设计为在管理控制面板上具有默认的my-site.com/admin URL。大多数网站所有者都不会为密码和用户名更改并保存。</p>
<p>这是一个重大风险，因为它为在线攻击者打开了更多途径，可在您的Web网站上发起危险攻击。最好的例子是蛮力攻击，他们尝试使用多种密码组合来获取您的准确登录详细信息并恶意访问管理面板。</p>
<p>为避免这种情况，在创建管理面板的URL时应使用其他名称。为此，您只需要修改网站的admin路径的URL，并为其命名即可轻松记住和难以猜测的名称。</p>
<p>查看此<a href="http://docs.magento.com/m1/ce/user_guide/configuration/url-admin-custom.html" rel="nofollow" target="_blank">免费的Magento指南，</a>以了解有关如何自行配置的更多信息。</p>
<h3 id="bonus-point">其他</h3>
<p>修改站点管理面板的安全设置。您是否想知道是否可以保护电子商务网站的后端区域免受恶意访问？</p>
<p>好吧，Magento可以让您轻松地从管理面板修改安全设置，从而做到这一点。使用此配置选项，您可以始终为您的网站网址创建一个密钥。</p>
<p>您还可以为管理会话设置上限，在这种情况下，这是用于访问该站点的密码有效的期限。此外，您还可以配置阻止尝试访问仪表板的人之前允许的确切登录尝试次数。</p>
<p>最后，请确保还使用此选项配置允许重置密码的请求数。</p>
<h2 id="final-thoughts">最后的想法</h2>
<p>这些技巧可以确保您的网站安全。现在必须实施它们，并且在您开始在网站上接受付款之前，请确保在Magento网站中拥有有效的SSL证书。使用这些证书保护您的网站之前，请勿冒险在网站中付款。</p>]]></description>
      <pubDate>Fri, 27 Sep 2019 19:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级Magento 2的终极指南]]></title>
      <link>https://www.360magento.com/blog/upgrade-magento-2/</link>
      <description><![CDATA[<p>该帖子由360Magento的技术人员进行了验证，以指导用户<strong>如何使用命令行和composer升级Magento 2版本</strong>。让我们逐步遵循本指南。</p>
<h2 id="to-updating-magento-2">更新Magento 2</h2>
<ul>
<li><a href="#step-1-backup-your-store">步骤1：备份网站</a></li>
<li><a href="#step-2-turn-on-maintenance-mode">步骤2：开启维护模式</a></li>
<li><a href="#step-3-upgrade-to-magento-2">步骤3：升级至Magento 2</a></li>
<li><a href="#step-4-check-the-current-magento-2s-version">步骤4：检查当前的Magento 2版本</a></li>
</ul>
<h3 id="step-1-backup-your-store">步骤1：备份网站</h3>
<p>为您的Magento 2站点创建备份非常紧急且必要，如果站点上有任何更改或中断，您可以通过备份管理保护所有数据免遭丢失。请按照本指南<a href="https://www.360Magento.com/blog/how-to-create-backups-magento-2">备份您的Magento 2网站</a>。</p>
<h3 id="step-2-turn-on-maintenance-mode">步骤2：开启维护模式</h3>
<p>升级时，应将网站置于维护模式。要启用维护模式：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento maintenance:enable
</code></pre></div></div>
<p>它将创建一个新文件<code class="language-plaintext highlighter-rouge">var/.maintenance.flag</code>。如果无法禁用维护模式，则可以删除此文件[记住！]</p>
<h3 id="step-3-upgrade-to-magento-2">步骤3：升级至Magento 2</h3>
<p>在这种情况下，我将升级到Magento版本<code class="language-plaintext highlighter-rouge">2.2.1</code>。在<a href="https://github.com/magento/magento2/releases">Github版本中</a>查看最新<a href="https://github.com/magento/magento2/releases">版本</a></p>
<h4 id="step-31-pull-package">步骤3.1拉包</h4>
<p><code class="language-plaintext highlighter-rouge">terminal/command-prompt</code>首先使用以下命令：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>composer require magento/product-community-edition 2.2.1 --no-update<font>
composer update<font>
</code></pre></div></div>
<p>可能会要求您输入用户名和密码</p>
要生成公钥/私钥对，进入<a href="https://marketplace.magento.com/customer/accessKeys/">Access Keys页面</a>并点击“Create A New Access Key”</p>
<h4 id="step-32-flush-cache">步骤3.2刷新缓存</h4>
<p>现在该删除缓存和generation了。在根文件夹中运行以下命令行：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm -rf var/cache/*<font>
rm -rf var/page_cache/*<font>
rm -rf var/generation/*<font>
</code></pre></div></div>
<h5 id="notes">注意：</h5>
<ul>
<li>您或许安装了Memcached，Redis缓存...，应手动刷新这些缓存。</li>
</ul>
<h4 id="step-33-run-upgrade-magento">步骤3.3运行Upgrade升级Magento</h4>
<p>运行Upgrade模块，数据库架构</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento setup:upgrade
</code></pre></div></div>
<h4 id="step-34-run-complie-reindex">步骤3.4运行complie，reindex</h4>
<p>升级后，应运行编译和重新索引以提高性能。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento setup:di:compile<font>
php bin/magento indexer:reindex<font>
</code></pre></div></div>
<h5 id="notes-1">注意：</h5>
<ul>
<li>在Ubuntu / Debian Linux中，遇到权限问题时，请记住<code class="language-plaintext highlighter-rouge">sudo</code>在每个命令的开头插入<code class="language-plaintext highlighter-rouge">sudo composer update</code>。</li>
</ul>
<h4 id="step-35-disable-maintenance-mode">步骤3.5禁用维护模式</h4>
<p>您已在步骤2中打开了维护模式，现在必须将其关闭。运行以下命令行将其关闭：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento maintenance:disable
</code></pre></div></div>
<h3 id="step-4-check-the-current-magento-2s-version">步骤4：检查当前的Magento 2版本</h3>
<p>接下来，您可以通过运行命令检查Magento 2的版本。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento --version
</code></pre></div></div>
<p>如果系统显示缓存写入权限错误，请添加以下命令以对pub和var目录授予写入权限：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod -R 777 pub var
</code></pre></div></div>
<h2 id="faqs">常见问题</h2>
<h4 id="q-i-cannot-access-to-frontend-after-upgrading">问：升级后我无法访问前端？</h4>
<p>您可能会收到以下消息： <code class="language-plaintext highlighter-rouge">We're sorry, an error has occurred while generating this email.</code></p>
<h4 id="answer">回答：</h4>
<p>那是因为Web服务器的读写权限。运行以下命令来解决该问题：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> find var vendor pub/static pub/media app/etc -type f -exec chmod u+w {} \; &amp;&amp; find var vendor pub/static pub/media app/etc -type d -exec chmod u+w {} \; &amp;&amp; chmod u+x bin/magento
</code></pre></div></div>
<p>再次刷新缓存：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm -rf var/cache/*<font>
rm -rf var/page_cache/*<font>
rm -rf var/generation/*<font>
</code></pre></div></div>
<h2 id="upgrade-magento-2-service">升级Magento 2服务</h2>
<p>360Magento提供升级到最新的Magento 2版本，请<a href="https://www.360magento.com/contacts">与我们联系</a>以获取更多信息。</p>
<p>这就是通过命令行和composer升级/更新Magento 2版本的所有操作。感谢您的阅读，如果有任何麻烦，请<a href="https://www.360magento.com/contacts">与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 10 Sep 2019 04:45:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何重置Magento 2锁定的管理员帐户]]></title>
      <link>https://www.360magento.com/blog/how-to-reset-a-locked-admin-account-in-magento-2/</link>
      <description><![CDATA[<p>黑客可以通过连续尝试许多易于猜测的密码来滥用您的安全墙，这是一种常见的方式。因此，由于多次尝试失败，您的管理员后端已被锁定，Magento 2核心将阻止管理员用户继续登录。</p>
<p>所有登录操作将在一段时间内被阻止。</p>
<p>不幸的是，这对双方都不是好消息。为了确保及时管理后端的过程，您可以利用启动一些命令行的优势，这些命令行使安全的管理员帐户能够尽快重新登录到配置。为了具有执行Linux命令行操作的权限，您必须具有SSH访问权限以安全地连接到服务器。此步骤需要直接从服务器管理器获得许可，因此这将是黑客的最终选择，他们显然无法在您的鼻子底下运行命令行。</p>
<p>继续查看如何重置锁定的管理员用户，并在需要本教程时将其标记为书签。</p>
<h2 id="reset-a-locked-admin-account-in-magento-2">在Magento 2中重置锁定的管理员帐户</h2>
<p>商店所有者可以选择以下列出的方法之一</p>
<ul>
<li><a href="#solution-1-unlock-in-backend">解决方案＃1。解锁后端</a></li>
<li><a href="#solution-2-using-command-lines">解决方案2。使用命令行</a></li>
</ul>
<h2 id="solution-1-unlock-in-backend">解决方案＃1。解锁后端</h2>
<p>假设您要管理几个管理员帐户，但只有一个或两个被锁定，这将是在后端即可完成的最简单方法。</p>
<p>按照<code class="language-plaintext highlighter-rouge">System &gt; Locked Users</code>检查所有当前锁定的用户，然后选择要打开锁定的特定管理员帐户。</p>
<p><img src="https://cdn.mageplaza.com/media/general/T1BS3T2.png" alt="后端"></p>
<h2 id="solution-2-using-command-lines">解决方案2。使用命令行重置</h2>
<ul>
<li>第1步：打开您的Magento 2目录</li>
<li>步骤2：运行命令行。</li>
<li>步骤3：检查结果</li>
</ul>
<h3 id="step-1-open-your-magento-2-dir">第1步：打开您的Magento 2目录</h3>
<p>首先，打开您的Magento 2目录，这是重置管理员用户的常规格式。请注意，您只能手动解锁一个帐户。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento admin:user:unlock {username}
</code></pre></div></div>
<h3 id="step-2-running-command-lines">步骤2：运行命令行。</h3>
<p>要解锁特定的管理员帐户，请将该管理员的名称插入{username}变量中，例如，使用名为的管理员<code class="language-plaintext highlighter-rouge">sam</code>，键入以下命令行：</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>php bin/magento admin:user:unlock sam
</code></pre></div></div>
<h3 id="step-3-check-the-result">步骤3：检查结果</h3>
<p>如果输入的数据有效，则将在界面上发送成功消息。</p>
<p><img src="https://cdn.mageplaza.com/media/general/cQlyZEO.png" alt="解锁成功"></p>
<ul>
<li>如果输入管理员名称有误，此消息将通知：
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Couldn't find the user account "sam"
</code></pre></div> </div>
<p>您应该检查并重新键入步骤1中的命令行以及准确的管理员名称。</p>
</li>
<li>如果帐户从一开始就没有被锁定或无法被解锁，则会显示以下消息</li>
</ul>
<p><img src="https://cdn.mageplaza.com/media/general/6aYkeZr.png" alt="开锁"></p>]]></description>
      <pubDate>Fri, 06 Sep 2019 08:41:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何备份Magento 2网站]]></title>
      <link>https://www.360magento.com/blog/how-to-create-backups-magento-2/</link>
      <description><![CDATA[<p><strong>目录</strong></p>
<ul>
<li><a href="#create-magento-2-backup">创建一个Magento 2备份</a>
<ul>
<li><a href="#system-backup">系统备份</a></li>
<li><a href="#datebase-and-media-backup">数据库和媒体备份</a></li>
<li><a href="#database-backup">数据库备份</a></li>
</ul>
</li>
</ul>
<p><strong>为您的Magento 2创建备份</strong>非常重要且必要，如果站点上有任何更改或中断，您可以通过备份管理保护所有数据免遭丢失。特别是，这些数据库将在需要的正确位置自动恢复。</p>
<p>Backups Management存档的系统部分还包括文件系统，数据库，媒体文件等。同时，数据库备份文件使用.gz格式压缩。对于系统备份以及数据库和媒体备份，使用.tgz格式。</p>
<p>现在，我们将更深入地研究该机制，以便为像您这样的Magento 2网站创建一个完美的备份。</p>
<h2 id="create-magento-2-backup">创建Magento 2备份</h2>
<ul>
<li>在管理控制台上，单击<code class="language-plaintext highlighter-rouge">System</code>。在该<code class="language-plaintext highlighter-rouge">Tools</code>部分中，选择<code class="language-plaintext highlighter-rouge">Backups</code>。</li>
<li>在右上角，点击您要创建的备份类型的按钮：</li>
</ul>
<p><img src="https://cdn.mageplaza.com/media/general/ZZbkuUH.png" alt="如何创建Magento 2备份"></p>
<h3 id="system-backup">系统备份</h3>
<p>创建数据库和文件系统的完整备份。在此过程中，您可以通过<code class="language-plaintext highlighter-rouge">Include Media folder to System Backup</code>选中复选框来选择将媒体文件夹包括在备份中</p>
<h3 id="datebase-and-media-backup">数据库和媒体备份</h3>
<p>创建数据库和媒体文件夹的备份。</p>
<h3 id="database-backup">数据库备份</h3>
<p>创建数据库的备份。</p>
<p><img src="https://cdn.mageplaza.com/media/general/qhvxLFu.png" alt="Magento 2数据库备份"></p>
<ul>
<li>完成后，单击<code class="language-plaintext highlighter-rouge">OK</code>按钮</li>
</ul>]]></description>
      <pubDate>Thu, 05 Sep 2019 03:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何通过Composer安装插件扩展]]></title>
      <link>https://www.360magento.com/blog/magento2-install-extensions-via-composer/</link>
      <description><![CDATA[<p>本文将指导您使用Composer安装Magento 2扩展。</p>
<p><em>注意：按照说明进行操作时，请确保您知道自己在做什么。如果文章中的任何操作或术语引起混淆，请专业人员完成这项工作。</em></p>
<p>要通过Composer安装Magento 2扩展程序，您需要：</p>
<ul>
<li>服务器上已安装Magento 2和Composer</li>
<li>SSH服务器凭证</li>
<li><a href="https://magento.com/" target="_blank" rel="nofollow">https://magento.com/</a> Magento Marketplace帐户</li>
<li>扩展包</li>
</ul>
<h2>步骤1. Magento.com帐户</h2>
<p>如果您之前没有注册过，请访问<a href="https://magento.com/" target="_blank" rel="nofollow">https://magento.com/</a>并创建一个帐户。</p>
<p>登录帐户并转到“Marketplace”选项卡：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/go-to-marketplace.png" alt="前往Magento市场" width="909" height="678"></p>
<p>进入“My Access Keys”菜单项：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/my-access-keys.png" alt="我的访问密钥部分" width="901" height="489"></p>
<p>您可以创建一个新的访问密钥，也可以使用现有的访问密钥：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/use-keys.png" alt="使用密钥" width="1063" height="543"></p>
<p>保存访问密钥，因为它们将在以下步骤中使用。</p>
<h2>准备本地存储库</h2>
<p>通过SSH\SFTP登录到服务器，并在您方便的位置创建一个<em>repo</em>文件夹。在我们的示例中，完整文件夹路径将为<em>/www/private/magento/repo</em></p>
<p><em>注意：您可以为文件夹选择任何名称，但是请确保在执行以下操作时更改名称。</em></p>
<p>将您的扩展程序文件夹复制到此新创建的文件夹中。执行此操作后，以下是repo文件夹的例子：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/folder-contents.png" alt="文件夹内容" width="525" height="259"></p>
<p>如果扩展程序包是从Magento Marketplace网站下载的，则需要将<em>/upload/app/code/Vendor/</em>内容放入新创建的文件夹中。</p>
<p>如果扩展程序包仅包含这些文件夹的内容，则必须手动创建文件夹。要获取正确的文件夹名称，请检查<em>registration.php</em>文件：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/create-folders.png" alt="建立资料夹" width="749" height="297"></p>
<p>&nbsp;</p>
<h2>向Composer添加扩展并安装它们</h2>
<p>使用SSH登录到服务器，然后转到Magento 2文件夹。</p>
<p>在此文件夹中，将以下命令发送到Composer，告诉它将扩展添加到存储库。不要忘记用您自己的名称替换模块名称，文件夹路径和模块文件夹名称：</p>
<pre>
composer config repositories.module_name path /www/private/magento/repo
</pre>
<p><em>module_name</em>  &nbsp;是扩展名，您可以根据需要命名。</p>
<p>现在，我们已将扩展添加到Composer中，我们可以安装它们了。该命令将安装<em>amasty/[module_name]</em>：</p>
<pre>
composer require amasty/[module_name]
</pre>
<p>如果您是第一次运行该命令，则Composer将要求您提供magento.com帐户凭据。在这里，您将使用之前获得的公钥和私钥。</p>
<p>命令输出如下所示：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_267/command-output.png" alt="通过composer安装Magento 2扩展的命令输出" width="598" height="424"></p>
<p>现在，让我们完成安装过程：</p>
<pre>
php bin/magento setup:upgrade
</pre>
<p>恭喜，您的Magento扩展程序现已通过Composer安装。</p>]]></description>
      <pubDate>Tue, 27 Aug 2019 07:19:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[7种方法检测magento系统]]></title>
      <link>https://www.360magento.com/blog/check-magento-version/</link>
      <description><![CDATA[<p>Magento被称为最大的电子商务内容管理平台。三星，Fort，Fox Connect，联想，奥林巴斯，男士健康，Vizio，雀巢，耐克以及全球数百万个中小型商业网站等许多大品牌都使用了该平台。随着时间的推移，Magento 2会不断更新，因此商店的所有者可能会要求更改其当前的Magento版本。但是，在切换到另一个版本之前，他们最初会更好地了解Magento 2版本之间的优缺点，以便最终做出正确的决定。本文将向您介绍<strong>如何检查Magento 2版本</strong>以及其他<strong>版本</strong>。</p>
<p><strong>内容简要</strong></p>
<ul>
<li><a href="#method-1-use-magento-version-checking-tool">1.使用Magento版本检查工具</a></li>
<li><a href="#method-2-checking-version-from-url">2.从URL检查版本</a></li>
<li><a href="#method-3-checking-magento-version-via-online-tools">3.通过在线工具检查Magento版本</a></li>
<ul>
<li><a href="#check-magento-version-at-magescan">在MageScan中检查Magento版本</a></li>
<li><a href="#check-magento-version-and-more-at-magereport">在MageReport中检查Magento版本及更多</a></li>
</ul>
<li><a href="#method-4-check-version-in-admin-dashboard">4.在管理控制台中检查版本 </a></li>
<li><a href="#method-5-check-in-composerjson-file">5.再Composer.json文件中检查版本</a></li>
<li><a href="#method-6-use-php-code-checking">6.使用PHP代码检查</a></li>
<ul>
<li><a href="#check-magento-1-version">检查Magento 1版本 </a></li>
<li><a href="#check-magento-2-version">检查Magento 2版本 </a></li>
</ul>
<li><a href="#method-7-check-magento-version-via-command-line">7.通过命令行检查Magento版本</a></li>
</ul>
<h2 id="7-ways-help-you-check-magento-version">帮助您检查Magento版本的7种方法</h2>
<h3 id="method-2-checking-magento-version-from-url">方法＃1：从URL检查Magento版本</h3>
<p><strong>检查Magento版本的</strong>另一种方法是不使用任何工具，而只是在您的域名URL后面添加<code class="language-plaintext highlighter-rouge">/magento_version</code>然后进行搜索。显示的结果是您的Magento版本以及您网站上运行的版本。</p>
<p>让我们在那里查看示例：<a class="vglnk" href="https://marketplace.magento.com/magento_version" rel="nofollow"><span>https </span><span>：// </span><span>marketplace </span><span>。</span><span>magento </span><span>。</span><span>com </span><span>/ </span><span>magento </span><span>_ </span><span>版本</span></a></p>
<p><img alt="通过URL检查Magento版本" src="https://cdn.mageplaza.com/media/general2/ybI0XAg.png" /></p>
<h3 id="method-3-checking-magento-version-via-online-tools">方法＃3：通过在线工具检查Magento版本</h3>
<p>除了上述方法外，还有三个在线工具也可以免费使用。同样，您要做的就是放入商店的URL，然后在几秒钟内显示选中的Magento版本和版本。</p>
<h4 id="check-magento-version-at-magescan">在MageScan中检查Magento版本</h4>
<p><img alt="使用Magescan检查Magento的版本" src="https://cdn.mageplaza.com/media/general2/6EHyFao.png" /></p>
<p><a href="https://magescan.com/" rel="nofollow" target="_blank">MageScan</a>是服务提供商，可以帮助网店所有者和开发人员根据建议的Magento安全标准测试其站点。因此，该工具为用户提供了有关其Magento商店的各种信息，其中包括安装的Magento的版本。它可以通过分析默认的Magento文件以及它们在版本之间的变化来做到这一点。</p>
<p><img alt="易于通过Magescan在线检查Magento版本" src="https://cdn.mageplaza.com/media/general2/AlwEnnU.png" /></p>
<p>填写商店的URL后，MageScan不仅会为您提供上述所有工具可以显示的两个最重要的结果，而且还可以显示其他信息，例如托管提供商，管理面板，日志，版本控制，开发文件等。</p>
<h4 id="check-version-and-more-at-magereport">在MageReport中检查版本及更多内容</h4>
<p>提供与MageScan相同的功能，<a href="https://www.magereport.com/" rel="nofollow" target="_blank">MageReport</a>还为用户提供商店中使用的Magento版本。此外，它可以扫描网站所面临的安全状态的洞察力，而最有用的是一些补救建议，以解决这些漏洞。</p>
<p><img alt="一分钟内使用Magereport检查Magento版本" src="https://cdn.mageplaza.com/media/general2/al5BeQd.png" /></p>
<p>MageReport由Byte.nl提供，该公司是Magento供应商的托管专业人士。该工具使用基于行为的标识模式。因此，它对大多数商店的经理都是值得信赖和有帮助的。下表列出了MageReport可以为基于Magento的在线商店找到的可检查安全漏洞：</p>
<ul>
<li>当前的Magento版本</li>
<li>Magento版本已过时</li>
<li>默认/管理员位置</li>
<li>安全补丁</li>
<li>勒索软件</li>
<li>不安全的版本控制</li>
<li>过时的服务器软件</li>
</ul>
<h3 id="method-4-check-version-in-admin-dashboard">方法4：在管理控制台中检查版本</h3>
<p>获取Magento版本号的另一种方法太简单了，通常您不会注意到。访问管理面板，然后在仪表板上，在每个后端页面的右下角找到Magento版本。看下面的图片，您会看到它非常熟悉：</p>
<p><img alt="在Magento管理控制台中检查版本" src="https://cdn.mageplaza.com/media/general2/lTQjlAa.png" /></p>
<p><img alt="在管理控制台中检查Magento版本" src="https://cdn.mageplaza.com/media/general2/J8RZ5oB.png" /></p>
<h3 id="method-5-check-in-composerjson-file">方法＃5：再Composer.json文件中检查版本</h3>
<p>您还可以通过<a href="https://github.com/magento/magento2/blob/2.2-develop/composer.json#L5">示例</a>在根composer.json文件第5行中看到Magento 2版本<a href="https://github.com/magento/magento2/blob/2.2-develop/composer.json#L5"></a></p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>{<span>
    "name": "magento/magento2ce",<span>
    "description": "Magento 2 (Open Source)",<span>
    "type": "project",<span>
    "version": "2.2.6-dev",<span>
    "license": [<span>
        "OSL-3.0",<span>
        "AFL-3.0"<span>
    ],<span>
    ...<span>
</span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
</div>
<h3 id="method-6-use-php-code-checking">方法6：使用PHP代码检查</h3>
<h4 id="check-magento-1-version">检查Magento 1版本</h4>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>Mage::getVersion() //will return the magento version
</code></pre>
</div>
</div>
<h4 id="check-magento-2-version">检查Magento 2版本</h4>
<p>您可以在2.0.x版本中使用它：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>echo \Magento\Framework\AppInterface::VERSION;
</code></pre>
</div>
</div>
<p>对于2.1版：</p>
<p>第一种方法，使用DI：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>public function __construct( \Magento\Framework\App\ProductMetadataInterface $productMetadata ) {<span>
	$this-&gt;productMetadata = $productMetadata;<span>
}<span>
public function getMagentoVersion() {<span>
	return $this-&gt;productMetadata-&gt;getVersion();<span>
}<span>
</span></span></span></span></span></span></code></pre>
</div>
</div>
<p>第二种方法，直接使用ObjectManager：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();<span>
$productMetadata = $objectManager-&gt;get('Magento\Framework\App\ProductMetadataInterface');<span>
echo $productMetadata-&gt;getVersion();<span>
</span></span></span></code></pre>
</div>
</div>
<h2 id="method-7-check-magento-version-via-command-line">方法7：通过命令行检查Magento版本</h2>
<p>您可以运行以下命令以获取Magento 2版本：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento --version
</code></pre>
</div>
</div>
<p>实际上，由于Magento 2已利用其composer，因此您无需为此编写任何PHP代码。相反，有两种方法可以找到Magento 2版本：</p>
<p>首先，请尝试composer.json并查找version关键字。如果您更喜欢使用终端，则可以在项目的根目录中添加一些内容。</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>composer licenses | grep Version:
</code></pre>
</div>
</div>
<p>检查Magento 2版本天气的另一种方法是社区版或企业版，请输入以下内容</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>composer licenses | grep Name:
</code></pre>
</div>
</div>
<h2 id="final-words">最后的话</h2>
<p>Magento 2是出色的电子商务解决方案，具有专门用于商业目的的功能和设计的服务。对于曾经在其网站上安装此平台的用户来说，他们很可能曾经想过要设置或更新哪个Magento版本，以使其商店的<a href="https://www.360magento.com/blog/magento-2-performance-optimization/">性能更好</a>。该博客可以通过各种简单的方法帮助您<strong>检查Magento的版本</strong>，希望您可以为在线商店做出正确的选择。</p>]]></description>
      <pubDate>Wed, 21 Aug 2019 08:33:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2性能优化]]></title>
      <link>https://www.360magento.com/blog/magento-2-performance-optimization/</link>
      <description><![CDATA[<p>对于Magento 2商店，<strong><a href="https://www.360magento.com/blog/magento-2-performance-optimization/">Magento 2性能优化</a></strong>是使您的工作取得更大成功的重要因素之一。请记住，如果您希望客户花在您网站上的时间段内带来出色的体验，那么就可以使客户与您在一起的时间更长。因此，快速的在线商店是理想的选择，它对您期望的访问者更为友好，而不是网站的性能不佳。只有当您的商店离消费者更近时,增加转化率以及优化收入的过程才变得越来越容易。</p>
<p>根据<a href="https://magento.com/resources/white-paper-magento-2-site-performance-and-scalability-optimizations" rel="nofollow" target="_blank">Benchmark Testing</a>的比较，可以在Magento Enterprise Edition 2.0和Magento Enterprise Edition 1.14.2的现成支持和推荐配置之间进行比较。测试证明，在所有指标和用例中，Magento 2.0被视为比Magento 1.x更大的平台。使用Magento ver.2，您将处理令人惊讶的结果：</p>
<ul>
<li>每小时处理多达39％的订单</li>
<li>提供几乎即时的服务器响应时间，用于目录浏览</li>
<li>加快购物车服务器响应时间达66％</li>
<li>提供最高51％的端到端结帐时间</li>
</ul>
<p>如今，当人们广泛意识到Magento 2性能时，集成了许多其他技术来支持Magento 2性能优化，例如Varnish，Redis，Nginx甚至是全页缓存解决方案。借助现有工具，开发团队可以轻松地开始功能的解耦，然后通过组件之间的稳定兼容性和可操作性将灵活性升级到新的水平。在服务器响应时间和浏览器端渲染速度上设计更好的界面是一个好主意。毕竟，您将在改善Magento 2性能和增强商店客户体验方面取得重大进展。</p>
<h2 id="how-to-optimize-magento-2-performance">如何优化Magento 2的性能</h2>
<p>作为正常的电子商务页面，加载产品页面需要3秒钟以上的时间。如果您的客户需要浏览网站上的五个类似页面，您是否觉得很烦？当然，他们永远也不会耐心等待延迟。请关注这篇文章，并找到相关的方法来提高网站的性能。</p>
<h2 id="steps-to-optimize-performance">优化性能的步骤</h2>
<ul>
<li><a href="#step-1-enable-flat-categories-and-products">步骤1：启用Flat Categories 和 Products</a></li>
<li><a href="#step-2-merge-css-and-js-files">步骤2：合并CSS和JS文件</a></li>
<li><a href="#step-3-content-delivery-network">步骤3：CDN(内容传送网络)</a></li>
<li><a href="#step-4-caching">步骤4：缓存</a></li>
<li><a href="#step-5-image-optimization">步骤5：图片优化</a></li>
<li><a href="#step-6-enable-compression">步骤6：启用压缩</a></li>
<li><a href="#step-7-reduce-server-response-time">步骤7：减少服务器响应时间</a></li>
<li><a href="#step-8-magento-updates">步骤8：Magento更新</a></li>
</ul>
<p>首先，让我们在Google <a href="https://developers.google.com/speed/pagespeed/insights/" rel="nofollow" target="_blank">PageSpeed Tools中</a>检查分数</p>
<p><img alt="检查Pagespeed" src="https://cdn.mageplaza.com/media/general/O3BImNZ.png" /></p>
<h3 id="step-1-enable-flat-categories-and-products">步骤1：启用Flat Categories 和 Products</h3>
<p>您可能知道，对Magento 2性能的速度产生重大影响的方面之一就是数据库加载的能力。在配置中，启用<strong>Flat Catalog</strong>可以加快速度。Flat Catalog允许在有任何显示产品的请求时卸载数据库的数量。同时，MySQL查询的复杂性将降低。</p>
<p>转到后端，<code class="language-plaintext highlighter-rouge">Stores &gt; Configuration &gt; Catalog &gt; Catalog &gt; Storefront</code>在<strong>Use Flat Catalog Category</strong>字段中选择&ldquo;Yes&rdquo; 。</p>
<p><img alt="Magento 2性能-使用平面目录" src="https://cdn.mageplaza.com/media/general/nfkHXTE.png" /></p>
<h3 id="step-2-merge-css-and-js-files">步骤2：合并CSS和JS文件</h3>
<p>您需要遵循的下一步是合并和最小化CSS和Javascript文件，这意味着使网页尽可能的轻巧，以便快速加载。请将Magento 2置于生产模式。</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>./bin/magento deploy:mode:set production
</code></pre>
</div>
</div>
<h4 id="javascript-file">Javascript文件</h4>
<ul>
<li>去后端 <code class="language-plaintext highlighter-rouge">Stores -&gt; Configuration &gt; Advanced &gt; Developer &gt; JavaScript Settings</code></li>
<li><code class="language-plaintext highlighter-rouge">Merge JavaScript Files</code>设为是</li>
<li><code class="language-plaintext highlighter-rouge">Minify JavaScript Files</code>设为是</li>
</ul>
<p><img alt="Magento 2性能-合并JS文件" src="https://cdn.mageplaza.com/media/general/Kawf9TL.png" /></p>
<h4 id="css-file">CSS文件</h4>
<ul>
<li>去后端 <code class="language-plaintext highlighter-rouge">Stores &gt; Configuration &gt; Advanced &gt; Developer &gt; CSS Settings</code></li>
<li><code class="language-plaintext highlighter-rouge">Merge CSS Files</code>设为是</li>
<li><code class="language-plaintext highlighter-rouge">Minify CSS Files</code>设为是</li>
</ul>
<p><img alt="Magento 2 Performance-合并CSS文件" src="https://cdn.mageplaza.com/media/general/1n9CqRj.png" /></p>
<p>完成后，<code class="language-plaintext highlighter-rouge">Save Config</code>刷新缓存以激活更改。</p>
<h3 id="step-3-content-delivery-network">步骤3：内容传送网络</h3>
<p>内容分发网络（CDN）是一个特殊的系统，可以连接所有缓存服务器。除了受支持的地理位置邻近性外，CDN还将接管交付的Web内容并加快页面加载。</p>
<p>请按照本指南为Magento 2商店设置CDN。去后端<code class="language-plaintext highlighter-rouge">Stores -&gt; Configuration &gt; General &gt; Web &gt; Base URLs (Secure)</code></p>
<p><img alt="Magento 2 Performance-内容交付网络" src="https://cdn.mageplaza.com/media/general/VAQU2in.png" /></p>
<h3 id="step-4-caching">步骤4：缓存</h3>
<p>在后端，<code class="language-plaintext highlighter-rouge">System &gt; Cache Management</code>。</p>
<p><img alt="Magento 2性能-缓存管理" src="https://cdn.mageplaza.com/media/general/ds5MV8n.png" /></p>
<p>在这里，您可以找到许多缓存选项来刷新Magento 2缓存。点击<code class="language-plaintext highlighter-rouge">Enable</code>，然后点击<code class="language-plaintext highlighter-rouge">Submit</code>您需要的选项。</p>
<h3 id="step-5-image-optimization">步骤5：图片优化</h3>
<p>图像是使Magento 2商店的性能更加生动的必要因素。但是，图像大小太大而无法在您的站点上载是超载页面的关键原因之一。因此，<a href="https://www.360magento.com/blog/optimize-img/">压缩图像</a>应在提交任何图像之前完成。您可以将JPEG格式用于产品图像，将PNG或SVG用于布局以及徽标。</p>
<h3 id="step-6-enable-compression">步骤6：启用压缩</h3>
<p>跟随资源启用Google提供的压缩功能。</p>
<p>让我们从以下方式更改nginx压缩指令：</p>
<ul>
<li>gzip_types：gzip_types: text/plain application/x-javascript text/javascript text/xml text/css image/x-icon image/bmp image/png image/gif; to</li>
<li>gzip_types：*;</li>
</ul>
<h3 id="step-7-reduce-server-response-time">步骤7：减少服务器响应时间</h3>
<p>通过Magento 2内置缓存功能，您的站点的响应时间相当不错，大约为0.5秒。但这不是Google期望的理想时间。因此，Magento 2 本身通过Varnish 支持全页缓存。让我们将Varnish设置为在0.1-0.2s左右获得第一个字节。</p>
<p>转到后端，将<code class="language-plaintext highlighter-rouge">Stores &gt; Configuration &gt; Advanced &gt; System &gt; Full Page Cache</code>缓存应用程序转移到Varish Cache。</p>
<p><img alt="Magento 2性能-启用清漆缓存" src="https://cdn.mageplaza.com/media/general/xDoZm0I.png" /></p>
<p>打开<strong>Varnish Configuration</strong>部分，完成设置：</p>
<p><img alt="Magento 2 Performance-清漆配置" src="https://cdn.mageplaza.com/media/general/NUerGt1.png" /></p>
<h3 id="step-8-magento-updates">步骤8：Magento更新</h3>
<p>记得更新您的Magento 2商店。360Magento团队将尽力帮助您优化站点性能。</p>
<h3 id="result-after-optimizing-magento-2-store">优化Magento 2商店后的结果</h3>
<p><img alt="Magento 2 Performace" src="https://cdn.mageplaza.com/media/general/PuL1Yai.jpg" /></p>
<h2 id="performance-toolkit-optional">性能工具包（可选）</h2>
<h3 id="installation">安装</h3>
<p>jMeter：</p>
<p>&ndash;转到<a href="https://jmeter.apache.org/download_jmeter.cgi" rel="nofollow" target="_blank">http://jmeter.apache.org/download_jmeter.cgi</a>并在&ldquo;二进制&rdquo;部分下载jMeter（请注意，需要Java 6或更高版本）&ndash;解压缩存档</p>
<p>插件（仅当您要使用其他报告（例如图形）时）：</p>
<p>&ndash;转到<a href="http://jmeter-plugins.org/downloads/all/" rel="nofollow" target="_blank">http://jmeter-plugins.org/downloads/all/</a>并下载JMeterPlugins-Standard和JMeterPlugins-Extras</p>
<p>&ndash;将它们解压缩到jMeter实例的相应ext目录。</p>
<p>&ndash;现在可以通过GUI添加其他报告。</p>
<h3 id="usage">用法</h3>
<p>在首次运行jMeter测试之前，您需要首先使用bin / magento setup：performance：generate-fixtures命令生成测试数据。</p>
<h4 id="run-via-console">通过控制台运行</h4>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>Scenario can accept parameters that are described bellow in format &lt;parameter_name:default_value&gt;:<span>
<span>
&lt;host:localhost&gt; URL component 'host' of application being tested (URL or IP). Default is 'localhost'.<span>
<span>
&lt;base_path:/&gt; Base path for tested site. Default is '/'.<span>
<span>
&lt;report_save_path:./&gt; Path where reports will be saved. Reports will be saved in current working directory by default. Default is './'.<span>
<span>
&lt;ramp_period:300&gt; Ramp period (seconds). Period the request will be distributed within. Default is '300'.<span>
<span>
&lt;orders:0&gt; Number of orders in the period specified in the current allocation. If &lt;orders&gt; is specified, the &lt;users&gt; parameter will be recalculated. Default is '0'.<span>
<span>
&lt;users:100&gt; Number of concurrent users. Recommended  amount is 100. Minimal amount is 10. Default is '100'.<span>
<span>
&lt;view_product_add_to_cart_percent:62/&gt; Percentage of users that will only reach the add to cart stage. Default is '62'.<span>
<span>
&lt;view_catalog_percent:30/&gt; Percentage of users that will only reach the view catalog stage. Default is '30'.<span>
<span>
&lt;guest_checkout_percent:4/&gt; Percentage of users that will reach the guest checkout stage. Default is '4'.<span>
<span>
&lt;customer_checkout_percent:4/&gt; Percentage of users that will reach the (logged-in) customer checkout stage. Default is '4'.<span>
<span>
&lt;loops:1/&gt; Number of loops to run. Default is '1'.<span>
<span>
&lt;admin_path:admin/&gt; Admin backend path. Default is 'admin'.<span>
<span>
&lt;admin-user:admin/&gt; Admin backend user. Default is 'admin'.<span>
<span>
&lt;admin-password:123123q/&gt; Admin backend password. Default is '123123q'.<span>
<span>
&lt;think_time_deviation:1000&gt; Deviation (ms) for "think time" emulation. Default is '1000'.<span>
<span>
&lt;think_time_delay_offset:2000&gt; Constant delay offset (ms) for "think time" emulation. Default is '2000'.<span>
<span>
Necessary parameters must be passed to [command line](<a class="vglnk" href="https://www.360magento.com/blog/magento-2-command-line-interface-cli.html" rel="nofollow"><span>https</span><span>://</span><span>www</span><span>.</span><span>360magento</span><span>.</span><span>com</span><span>/</span><span>devdocs</span><span>/</span><span>magento</span><span>-</span><span>2</span><span>-</span><span>command</span><span>-</span><span>line</span><span>-</span><span>interface</span><span>-</span><span>cli</span><span>.</span><span>html</span></a>) with "J" prefix: "-J&lt;parameter_name&gt;=&lt;parameter_value&gt;"<span>
<span>
</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></code></pre>
</div>
</div>
<p>例：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&gt; cd /directory_of_jMeter/bin/<span>
<span>
&gt; jmeter -n -t /path_to_benchmark_file/benchmark.jmx -Jhost=magento2.dev -Jbase_path=/ -Jusers=100 -Jramp_period=300 -Jreport_save_path=./<span>
<span>
</span></span></span></span></code></pre>
</div>
</div>
<h4 id="run-via-gui">通过GUI运行</h4>
<ul>
<li>
<p>打开jMeter / bin目录并运行jmeter.bat</p>
</li>
<li>
<p>单击菜单中的文件-&gt;打开（Ctrl + O）并选择文件；或者在打开的GUI中拖放Benchmark.jmx文件。</p>
</li>
</ul>
<p>在第一个标签&ldquo;测试工具包&rdquo;上，您可以更改&ldquo;用户定义的变量&rdquo;，如下所示 <code class="language-plaintext highlighter-rouge">&lt;host&gt;, &lt;users&gt;, &lt;ramp_period&gt;, &lt;orders&gt;, &lt;report_save_path&gt;.</code></p>
<p>要运行脚本，请单击&ldquo;开始&rdquo;（顶部菜单中的绿色箭头）。</p>
<h3 id="results-of-running-report-types">运行结果（报告类型）</h3>
<p>通过GUI运行后，您可以在左侧面板中查看工作结果。选择相应的报告。</p>
<p>通过控制台运行脚本后，将在以下路径中生成报告： <code class="language-plaintext highlighter-rouge">&lt;report_save_path&gt;.</code></p>
<h3 id="threads">线程数</h3>
<p>jMeter脚本包含五个线程。安装程序线程和四个用户线程。</p>
<p>线程之间的百分比比率如下：</p>
<p>浏览，将商品添加到购物车和放弃购物车（报表中的BrowsAddToCart后缀）-62％</p>
<p>仅浏览（报表中的BrowsAddToCart后缀）-30％</p>
<p>浏览，将项目添加到购物车并以访客身份签出（报告中的GuestChkt后缀）-4％</p>
<p>浏览，将商品添加到购物车并以注册客户的身份结帐（报告中的CustomerChkt后缀）-4％</p>
<h3 id="about-reports">关于报告：</h3>
<p>总结报告。</p>
<p>报告包含有关线程的汇总信息。</p>
<p>报告文件名为 <code class="language-plaintext highlighter-rouge">{report_save_path}/summary-report.log</code></p>
<p>细节 <code class="language-plaintext highlighter-rouge"><a class="vglnk" href="http://jmeter.apache.org/usermanual/component_reference.html#Summary_Report" rel="nofollow"><span>http</span><span>://</span><span>jmeter</span><span>.</span><span>apache</span><span>.</span><span>org</span><span>/</span><span>usermanual</span><span>/</span><span>component</span><span>_</span><span>reference</span><span>.</span><span>html</span><span>#</span><span>Summary</span><span>_</span><span>Report</span></a></code></p>
<p>详细的网址报告。</p>
<p>报告包含有关URL的信息。</p>
<p>请注意，URL仅显示在生成的报告文件中（在GUI中，URL不显示）。</p>
<p>报告文件的名称为<code class="language-plaintext highlighter-rouge">{report_save_path}/detailed-urls-report.log</code>（可以以csv格式打开）。细节<code class="language-plaintext highlighter-rouge"><a class="vglnk" href="http://jmeter.apache.org/usermanual/component_reference.html#View_Results_in_Table" rel="nofollow"><span>http</span><span>://</span><span>jmeter</span><span>.</span><span>apache</span><span>.</span><span>org</span><span>/</span><span>usermanual</span><span>/</span><span>component</span><span>_</span><span>reference</span><span>.</span><span>html</span><span>#</span><span>View</span><span>_</span><span>Results</span><span>_</span><span>in</span><span>_</span><span>Table</span></a></code></p>
<p>关于其他类型请继续阅读 <code class="language-plaintext highlighter-rouge"><a class="vglnk" href="http://jmeter.apache.org/usermanual/component_reference.html" rel="nofollow"><span>http</span><span>://</span><span>jmeter</span><span>.</span><span>apache</span><span>.</span><span>org</span><span>/</span><span>usermanual</span><span>/</span><span>component</span><span>_</span><span>reference</span><span>.</span><span>html</span></a></code></p>]]></description>
      <pubDate>Fri, 16 Aug 2019 06:30:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[4种Magento 2重置管理员密码的方法]]></title>
      <link>https://www.360magento.com/blog/how-reset-admin-password-magento-2/</link>
      <description><![CDATA[<p>如果要登录Magento后台，则&ldquo;用户名&rdquo;和&ldquo;密码&rdquo;是必填字段。如果您忘记其中之一，那将是一个麻烦。因此，重置管理员密码对于每个网站都非常重要。使用Magento 2，可以单击&ldquo; 忘记密码&rdquo;链接，然后可以将临时密码立即发送到与该帐户关联的电子邮件地址。如果管理员帐户被锁定，<a href="https://www.360magento.com/blog/how-to-reset-a-locked-admin-account-in-magento-2.html">本教程</a>将对您有所帮助。让我们按照以下步骤在Magento 2中重置您的管理员密码。</p>
<h2 id="to-reset-magento-2-admin-password">重设Magento 2管理员密码</h2>
<p>Magento2中有3种重置管理员密码的方法：</p>
<ul>
<li><a href="#solution-1">解决方案1：在phpmyadmin中重置Magento 2管理员密码</a></li>
<li><a href="#solution-2">解决方案2：从管理控制台重置您的Magento 2密码</a></li>
<li><a href="#solution-3">解决方案3：通过命令行重置Magento 2管理员密码</a></li>
<li><a href="#solution-4">解决方案4：通过电子邮件重置Magento 1管理员密码</a></li>
</ul>
<h3 id="solution-1">解决方案1：在phpmyadmin中重置Magento 2管理员密码</h3>
<p>转到phpmyadmin并复制以下sql查询：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>UPDATE admin_user SET password = CONCAT(SHA2('xxxxxxxYourNewPassword', 256), ':xxxxxxx:1') WHERE username = 'admin';
</code></pre>
</div>
</div>
<p>该<code class="language-plaintext highlighter-rouge">xxxxxxx</code>字符序列的密码，它被保存在<code class="language-plaintext highlighter-rouge">app\etc\env.php</code>文件</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>&lt;?php<span>
return array (<span>
  ...<span>
  'crypt' =&gt; <span>
  array (<span>
    'key' =&gt; '525701df74e6cba74d5e9a1bb3d935ad', //cryptographic salt<span>
  ),<span>
  ...<span>
</span></span></span></span></span></span></span></span></code></pre>
</div>
</div>
<h3 id="solution-2">解决方案2：从管理控制台重置您的Magento 2密码</h3>
<ul>
<li>如果忘记密码，请单击hte <code class="language-plaintext highlighter-rouge">Forgot Your Password?</code>链接。</li>
</ul>
<p><img alt="如何重设管理员密码Magento 2忘记密码" src="https://www.360magento.com/media/wysiwyg/forgotpassword.png" /></p>
<ul>
<li>输入与管理员帐户关联的电子邮件地址。</li>
<li>点击 &nbsp; <code class="language-plaintext highlighter-rouge">Retrieve Password</code>。如果存在与该电子邮件地址关联的帐户，将发送一封电子邮件以重置您的密码。要阻止电子邮件发送到垃圾邮件框，请启用SMTP</li>
</ul>
<h3 id="solution3">解决方案3：通过命令行（CLI）重置Magento 2管理员密码</h3>
<p>我们在Magento 2根文件夹中键入：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>php bin/magento -h
</code></pre>
</div>
</div>
<p>它显示管理员命令行：</p>
<div class="language-plaintext highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>...<span>
 admin<span>
  admin:user:create                        Creates an administrator<span>
  admin:user:unlock                        Unlock Admin Account<span>
...<span>
</span></span></span></span></span></code></pre>
</div>
</div>
<p>Magento 2不支持通过命令行重置密码。但是，我们可以创建一个新的admin帐户，然后使用新帐户重置旧帐户。</p>
<pre>bin/magento admin:user:create
</pre>
<h3 id="solution-4">解决方案4：通过电子邮件重置Magento 1管理员密码</h3>
<ul>
<li>转到Magento管理面板，默认为 <code class="language-plaintext highlighter-rouge">your-domain.com/admin</code></li>
<li>单击<strong>Forgot your password</strong></li>
<li>在<strong>Email Address</strong>输入框中输入与管理员帐户关联的<strong>电子邮件地址</strong></li>
<li>单击<strong>Retrieve Password</strong>以重置密码。</li>
<li>打开您的电子邮件框，然后检查<strong> reset password link</strong>。该链接在24小时内有效。要阻止将电子邮件发送到垃圾邮件框，请启用SMTP。</li>
</ul>]]></description>
      <pubDate>Sun, 11 Aug 2019 09:50:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2通过SSH安装扩展插件]]></title>
      <link>https://www.360magento.com/blog/magento2-install-extensions-via-ssh/</link>
      <description><![CDATA[<h4><strong><span class="step">步骤1：</span></strong></h4>
<p>将下载的插件包解压缩</p>
<h4><strong><span class="step">第2步：</span></strong></h4>
<p>创建另一个名为app/code/Vendor/Modulename/的目录，其中Vendor为开发商名称，Modulename为模块内部标识符。您可以在下载的扩展ZIP文件的“ composer.json”文件中找到它，并查看节点“ psr-4”。例如</p>
<p><img class="alignnone size-full wp-image-4380" src="https://www.360magento.com/media/wysiwyg/blog_266/step2_1.jpg" alt="magento2扩展&插件安装指南-步骤1" width="842" height="564"></p>
<p>例如，它可能在此处为“Bss\AjaxCart”或“Bss\OneStepCheckout”，那么Modulename是\之后和\之前的部分，因此在我们的示例中，AjaxCart”或“ OneStepCheckout”这就是您所谓的Modulename，例如app/code/Bss/AjaxCart，然后将扩展ZIP文件的内容放在其中。</p>
<p><img class="alignnone size-full wp-image-4382" src="https://www.360magento.com/media/wysiwyg/blog_266/step2_2.jpg" alt="magento2扩展&插件安装指南-步骤2" width="619" height="434"></p>
<h4><strong><span class="step">第三步：</span></strong></h4>
<p>将目录 app/code/Bss/Modulename/对应到Magento安装的根目录中。Magento的根目录是包含目录“ app”，“ bin”，“ lib”等的目录。所有目录应与现有目录结构匹配。</p>
<p><img class="alignnone size-full wp-image-4383" src="https://www.360magento.com/media/wysiwyg/blog_266/step3.jpg" alt="magento2扩展&插件安装指南-步骤3" width="497" height="342"></p>
<h4><strong><span class="step">第四步：</span></strong></h4>
<p>转到Magento 2根目录。</p>
<p>执行：php bin/magento setup:upgrade</p>
<p><img class="alignnone size-full wp-image-4384" src="https://www.360magento.com/media/wysiwyg/blog_266/step4.jpg" alt="magento2扩展&插件安装指南-步骤4" width="855" height="535"></p>
<h4><strong><span class="step">步骤5：</span></strong></h4>
<p>执行：php bin/magento setup:static-content:deploy</p>
<p><img class="alignnone size-full wp-image-4385" src="https://www.360magento.com/media/wysiwyg/blog_266/step4-1.jpg" alt="magento2扩展&插件安装指南-步骤5" width="855" height="535"></p>
<h4><strong><span class="step">步骤6：</span></strong></h4>
<p>清除所有缓存</p>
<p>执行：php bin/magento cache:flush</p>
<p><strong><span class="step">*注意</span></strong></p>
<p>如果您是通过composer安装扩展程序，请在完全按照上面的指南安装更新的版本之前，完全删除供应商文件夹中的模块，删除composer.json中的模块行并执行composer更新。</p>
<p>购买插件后，&nbsp;如果您无法自行安装扩展程序，或者您已按照上述所有步骤操作，但扩展名无法正常使用，则可以删除文件或更改模块的文件扩展名，以保持网站正常运行。然后<a href="https://www.360magento.com/contacts/">请与我们联系</a>。360Magento技术支持团队将帮助您安装Magento模块。
<p>请点击查看<a href="https://www.360magento.com/magento2-install-extensions-via-composer">如何通过Composer安装Magento 2扩展</a>的安装指南！</p>]]></description>
      <pubDate>Mon, 05 Aug 2019 10:15:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何通过后台安装扩展插件]]></title>
      <link>https://www.360magento.com/blog/magento2-install-extensions-via-backend/</link>
      <description><![CDATA[<p>Magento 2使您能够通过其Web Setup Wizard工具安装扩展插件。这是用于安装在<a href="https://marketplace.magento.com/" rel="noopener" target="_blank">Magento Marketplace</a>网站购买的扩展程序的主要方法&nbsp; 。</p>
<p>在完成本安装指南之前，请阅读&nbsp; <a href="https://devdocs.magento.com/guides/v2.3/comp-mgr/prereq/prereq_compman-checklist.html" rel="noopener" target="_blank">本文</a>以确认是否满足所有最低服务器要求。然后按照以下步骤操作：</p>
<p>1.登录到您的Magento Marketplace帐户。单击<strong>Developer Portal</strong>选项卡上的&ldquo;My Access Keys&rdquo;链接。</p>
<p><img alt="Magento Marketplace" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-09_om_14.15.48.png" /></p>
<p>2.复制<strong>Public Key</strong>和<strong>Private Key</strong>。请注意，这些是在<strong>Magento 2</strong>标签上提供的。</p>
<p><img alt="Magento Marketplace" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-09_om_14.16.28.png" /></p>
<p>3.登录到Magento后端面板，然后转到<strong>SYSTEM ⟶ Tools ⟶ Web Setup Wizard</strong>。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-10_om_10.24.00.png" /></p>
<p>4.单击&nbsp; <strong>System Configuration</strong>。然后，从您的Marketplace帐户中输入<strong>公钥</strong>和<strong>私钥</strong>。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-30_om_08.08.48.png" /></p>
<p>5.确保您的Magento后端与Magento Marketplace同步。为此，请单击刷新按钮。请注意，处理您的请求可能需要几分钟。将您的Magento后端与Magento Marketplace同步后，您将看到您的Magento扩展概述。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-30_om_08.26.42.png" /></p>
<p>6.单击<strong>Extensions Ready to Install</strong>文本下方的&ldquo;Review and Install&rdquo;按钮。在扩展程序网格中，选中要安装的扩展程序的复选框。确保始终使用最新版本的扩展。单击安装按钮。</p>
<p>安装过程已开始。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-30_om_08.26.51.png" /></p>
<p>7. <strong>准备检查</strong>。检查商店环境的兼容性。准备就绪检查成功完成后，点击下一步按钮。如果您在此处发现任何问题，请修复它们，然后单击&ldquo;Try Again&rdquo;按钮以重试。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-29_om_17.35.48.png" /></p>
<p>8. <strong>创建备份</strong>。默认情况下，备份包括代码，媒体和数据库，但是您可以取消选择您不想包括在备份中的任何内容。单击Create Backup按钮。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-29_om_17.35.58.png" /></p>
<p>该操作完成后，单击&ldquo;Next&rdquo;按钮。</p>
<p>9.此页面显示了将要安装的扩展名和版本。单击安装按钮。</p>
<p>为了保护您的网上商店和客户的数据，您的网站将在安装过程中脱机。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-29_om_17.36.33.png" /></p>
<p>10.如下所示，控制台日志显示当前状态，并为您提供安装进度的直观展示。</p>
<p><img alt="Magento Web Setup Wizard" src="https://www.360magento.com/media/wysiwyg/blog_265/Schermafbeelding_2019-07-29_om_17.36.43.png" /></p>
<p>该过程完成后，将显示成功页面。</p>
<p>11.注销，然后重新登录，以使所有更改生效。您的扩展程序现在可以使用了。</p>
<p>&nbsp;</p>
<h2><strong>如何测试安装是否成功？</strong></h2>
<p>查看你所安装的扩展文档，并检查后台配置部分，以及前台效果。</p>
<p>如果您仍然需要帮助，360Magento提供Magento2扩展安装服务</p>]]></description>
      <pubDate>Tue, 30 Jul 2019 08:35:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何创建一个API请求]]></title>
      <link>https://www.360magento.com/blog/create-api-request-m2/</link>
      <description><![CDATA[<h2><strong>一、创建API请求 </strong></h2>
<p>创建API请求有4个简单步骤：</p>
<h3>第1步：声明API</h3>
<p>在模块的etc文件夹下创建webapi.xml：<br /> /magento/module-customer/etc/webapi.xml</p>
<pre>&lt;route url="/V1/customers" method="POST"&gt;
   &lt;service class="Magento\Customer\Api\AccountManagementInterface" method="createAccount"/&gt;
   &lt;resources&gt;
       &lt;resource ref="anonymous"/&gt;
   &lt;/resources&gt;
&lt;/route&gt;
</pre>
<p>让我们引导您完成上述代码，以确保您了解正在发生的事情：</p>
<ul>
<li>Route - 这是用于调用我们的API URL https://{{MagentoBaseURL}}/index.php/rest/V1/customers.。</li>
<li>Service class - 这是我们API的接口类，将调用主要方法&ldquo;createAccount&rdquo;。</li>
<li>Resources - 定义谁有权限调用此API。它可以是具有特定权限的匿名（每个人）或自己（客户）或特定管理员用户，例如，可以在acl.xml中添加Magento_Customer:: customer。</li>
</ul>
<h3>步骤2：创建webapi.xml中指定的接口文件</h3>
<p>Magento\Customer\Api\CustomerRepositoryInterface</p>
<pre>/**
* Create customer account. Perform necessary business operations like sending email.
*
* @param \Magento\Customer\Api\Data\CustomerInterface $customer
* @param string $password
* @param string $redirectUrl
* @return \Magento\Customer\Api\Data\CustomerInterface
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function createAccount(
   \Magento\Customer\Api\Data\CustomerInterface $customer,
   $password = null,
   $redirectUrl = ''
);
</pre>
<h3>第3步：创建模型类，您可以在其中放置实际的业务逻辑</h3>
<p>您必须在etc文件夹下的di.xml文件中指定它<br /> /module-customer/etc/di.xml</p>
<pre>&lt;preference for="Magento\Customer\Api\AccountManagementInterface"
           type="Magento\Customer\Model\AccountManagement" /&gt;
</pre>
<p>&nbsp;</p>
<h3>步骤4：创建第一个模型类AccountManagement.php以定义createAccount方法</h3>
<pre>/**
* @inheritdoc
*/
public function createAccount(CustomerInterface $customer, $password = null, $redirectUrl = '')
{
   if ($password !== null) {
       $this-&gt;checkPasswordStrength($password);
       $customerEmail = $customer-&gt;getEmail();
       try {
           $this-&gt;credentialsValidator-&gt;checkPasswordDifferentFromEmail($customerEmail, $password);
       } catch (InputException $e) {
           throw new LocalizedException(
               __("The password can't be the same as the email address. Create a new password and try again.")
           );
       
       $hash = $this-&gt;createPasswordHash($password);
   } else {
       $hash = null;
   
   return $this-&gt;createAccountWithPasswordHash($customer, $hash, $redirectUrl);
}
</pre>
<p>&nbsp;</p>
<h2>二、强制请求参数</h2>
<p>我们可以强制webapi.xml中的参数来保证在特定路由上使用特定值。让我们看一下<strong>/V1/carts/mine</strong>的例子</p>
<h3><strong>第1步：在webapi.xml中声明参数</strong></h3>
<p>vendor/magento/module-quote/etc/webapi.xml</p>
<pre>&lt;route url="/V1/carts/mine" method="POST"&gt;
   &lt;service class="Magento\Quote\Api\CartManagementInterface" method="createEmptyCartForCustomer"/&gt;
   &lt;resources&gt;
       &lt;resource ref="self" /&gt;
   &lt;/resources&gt;
   &lt;data&gt;
       &lt;parameter name="customerId" force="true"&gt;%customer_id%&lt;/parameter&gt;
   &lt;/data&gt;
&lt;/route&gt;
</pre>
<p>&nbsp;</p>
<h3>第2步：在di.xml中进行覆盖</h3>
<p>vendor/magento/module-webapi/etc/di.xml</p>
<pre>&lt;type name="Magento\Webapi\Controller\Rest\ParamsOverrider"&gt;
   &lt;arguments&gt;
       &lt;argument name="paramOverriders" xsi:type="array"&gt;
           &lt;item name="%customer_id%" xsi:type="object"&gt;Magento\Webapi\Controller\Rest\ParamOverriderCustomerId&lt;/item&gt;
       &lt;/argument&gt;
   &lt;/arguments&gt;
&lt;/type&gt;
</pre>
<h3>第3步：获取params的值</h3>
<p>vendor/magento/module-webapi/Controller/Rest/ParamOverriderCustomerId.php</p>
<pre>/**
* {@inheritDoc}
*/
public function getOverriddenValue()
{
   if ($this-&gt;userContext-&gt;getUserType() === UserContextInterface::USER_TYPE_CUSTOMER) {
       return $this-&gt;userContext-&gt;getUserId();
   
   return null;
}
</pre>
<p>我们已向您提供了为Magento 2创建API请求的基本指南。希望你能帮助到您。</p>]]></description>
      <pubDate>Fri, 12 Jul 2019 19:00:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在AWS上安装Magento2]]></title>
      <link>https://www.360magento.com/blog/install-magento-on-aws/</link>
      <description><![CDATA[<p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Install-Magento-on-AWS.jpg" alt="在亚马逊服务器安装Magento2" ></p>
<p>根据Magento客户和市场<a href="https://trends.builtwith.com/shop/Magento/Market-Share" target="_blank" rel="noopener">份额报告</a>，流行的内容管理系统（CMS）目前为967,664个网站提供支持。哇，这是一个庞大的数字。如果您拥有电子商务网站，或者您正在考虑建设电子商务网站，那么Magento应该是您设置电子商务平台的首选CMS。</p><p>首先，我们将在Amazon Web Service（AWS）平台上托管Magento。你可能会问，当谷歌也可以使用的时候，我为什么要考虑让AWS托管我的网？因为AWS拥有世界第一的电子商务网站<a href="https://www.amazon.com/" target="_blank" rel="noopener">亚马逊</a>。</p><p>让我们从Magento AWS托管开始。</p><p>您必须按照以下步骤在AWS上安装Magento：</p><ul><li><a href="#1">在亚马逊上设置服务器</a></li><li><a href="#2">在服务器上安装必备工具，运行Magento</a></li><li><a href="#3">设置数据库</a></li><li><a href="#4">在AWS上安装和配置Magento</a></li></ul><h2 style="text-align: center;">使用AWS Magento Hosting启动并运行</h2><h2 id="1">在亚马逊上设置服务器</h2><p><strong>Amazon Developer Console</strong></p><p>转到<a href="https://aws.amazon.com/" target="_blank" rel="noopener">Amazon</a>并设置一个帐户。现在，导航到<strong>AWS Management console</strong>。您将看到以下屏幕：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Amazon-Developer-Console.png" alt="Amazon Developer Console" ></p><p>选择<strong>EC2</strong>。如果你看不到它，不要担心。在<strong>Find Services</strong>搜索它，&nbsp;您将获得它。点击它。现在您将看到以下屏幕：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Find-Services.png" alt="查找服务"><br>单击<strong>Launch Instance</strong>。</p><p>选择具有默认操作系统（OS）的计算机，例如Linux，Ubuntu或Windows等。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Select-a-machine.png" alt="magento服务器系统"></p><p>您将看到以下屏幕。向下滚动，您会看到：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Select-a-machine-2.png" alt="选择一台主机"></p><p>选择Ubuntu服务器。大多数开发人员倾向于使用Linux操作系统来执行他们的任务，因此我更喜欢Ubuntu。如果您是Windows用户，并且想要选择Windows操作系统，你也可以这样做。配置几乎相同。</p><p>根据官方<a href="https://devdocs.magento.com/guides/v2.1/install-gde/system-requirements-tech.html" target="_blank" rel="noopener">Magento 2系统要求，</a>您需要至少<strong>2G的内存。</strong>但是，我建议使用4GB RAM。为了安全起见，如果你想调试或执行一段代码，你可能不想耗尽你的没存。因此，您必须：</p><p>选择<strong>类型</strong> t2 medium</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/T2-Medium.png" alt="T2中等" ></p><p>单击<strong>Configure Instance Details</strong>。现在你会看到：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Configure-Instance-Details.png" alt="配置实例详细信息"></p><p>您可以配置您的机器（即实例）。因为，没有什么可做的，继续添加存储。</p><p>现在，系统会要求您添加存储空间。默认情况下，存储大小足够，但如果要增加，则只需增加大小。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/storage-size.png" alt="存储大小"></p><p>完成此过程后，就可以单击<strong>Add Tags</strong></p><p>目前，我们不需要任何标签，因此，请单击“<strong>configure security group</strong>按钮。这个很重要。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/configure-security-group.png" alt="配置安全组"></p><p>现在，您可以添加有关全球哪些人访问您的服务器的规则。他们是否必须遵循协议才能到达服务器？现在，我正在使我的服务器可以访问所有流量。以后，我们可以提出安全规则。导航到“Type”并选择“ All traffic”。在源中，单击任意位置。它应该如下所示：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/configure-security-group-2.png" alt="" ></p><p>点击查看并启动。然后，您将有机会再次查看您的配置。单击“Launch” 您将看到以下提示。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Click-review-and-launch.png" alt="" ></p><p>在这里，选择一个新密钥对并为其命名。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/existing-key-pair.png" alt="" ></p><p>您可能想知道什么是密钥对？简单来说，它是一个密钥，可以让您安全地连接到您的服务器。它包括的<strong>公钥</strong>和一个<strong>私钥文件</strong>。它们共同允许您安全地连接到您的实例。对于Windows AMI，您必须使用私钥文件来获取实例的登录密码。对于Linux AMI，私钥文件允许您使用SSH登录您的实例。</p><p>下载密钥对并确保其安全，因为没有它，您将无法访问您的服务器。现在点击启动实例。</p><p>将打开一个新屏幕。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Download-the-key-pair.png" alt=""></p><p>单击<strong> View Instance</strong></p><p>在<strong>status check</strong>中，您可以看到它正在初始化：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/status-check.png" alt="状态检查"></p><p>忽略old server。您可能看不到服务器的名称。现在，导航到空白区域，您会注意到铅笔写入图标。单击它并命名您的服务器。您必须等待一段时间，然后刷新屏幕。检查您的<strong>system status</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/system-status.png" alt=""></p><p>现在，您必须连接到您的服务器。在此之前，您确保安装了<a href="https://git-scm.com/" target="_blank" rel="noopener">git</a>，因为我们将使用它连接到我们的服务器。现在，<strong>选择您的新服务器：</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/New-Server.png" alt=""></p><p>单击<strong>Connect</strong>。</p><p>现在您已了解如何连接到新服务器，我们将选择简单的方法。还记得你之前下载的密钥对吗？导航到该文件夹​​。假设您安装了git，右键单击空白区域并选择git bash here选项。现在复制该行，我在以ssh -I ......开头的示例下面加下划线。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/ssh-I.png" alt="" ></p><p><span style="font-size: 14px;">并将其粘贴到</span><strong style="font-size: 14px;">git bash</strong>中：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/git-bash-e1553092336737.png" alt="" ></p><p>按<strong>Enter</strong>键。你会得到一个问题：Are you sure you want to connect？输入<strong>yes</strong>。恭喜，现在你连上你的服务器了。但我们必须满足使Magento工作的要求。因此，是时候建立一个PHP环境了。接下来，我们将在git上运行一些命令来安装必备工具。</p><h2 id="2">在服务器上安装必备工具以运行Magento</h2><p>您必须在终端上执行以下代码才能获得在服务器上安装Magento所需的工具。</p>
<pre>ls -al</pre>
<p>这将显示服务器上的所有目录。</p>
<pre>sudo su </pre>
<p>这将引导您进入<strong>home/ubuntu</strong>目录。这意味着您已以root用户身份登录。</p>
<pre>apt-get update</pre>
<p>这将使用最新工具更新您的服务器。</p>
<pre>sudo apt-get install apache2 php libapache2-mod-php mysql-server php-mysql php-dom php-simplexml php-curl php-intl php-xsl php-mbstring php-zip php-xml composer</pre>
<p>此代码将安装Apache（Web服务器软件），PHP（最新版本，目前为7.2）以及Magento所需的必要额外工具，以及将用作数据库的MySQL服务器。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/serve-as-database.png" alt=""></p><p>&nbsp;如果询问您是否要继续，请按<strong>Y</strong>键？安装完成后，您必须创建一个数据库。</p><p>现在，安装PHP gd扩展</p>
<pre>apt-get install php7.2-gd</pre>
<p>安装PHP mcrypt扩展</p>
<pre>apt-get install php7.2-mcrypt</pre>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Install-PHP-mcrypt-extension.png" alt=""></p>
<pre>sudo a2enmod rewrite</pre>
<p>现在重启Apache：</p>
<pre>systemctl restart apache2</pre>
<p>然后导航</p>
<pre>cd /etc/apache2/</pre>
<pre>sudo nano apache2.</pre><p>按<strong>ctrl + w</strong>并搜索<strong>indexes</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/indexes.png" alt="索引" ></p><p>将<strong>None</strong>替换为<strong>all</strong>，如下所示：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Replace-None.png" alt=""></p><p>按<strong>ctrl + x</strong>，按<strong>y</strong>并按<strong>Enter键</strong>。</p><p><span style="font-size: 14px;">再次重启Apache服务：</span></p>
<pre>systemctl restart apache2.service</pre>
<p>现在转到公共根目录并从Github克隆Magento 2：</p>
<pre>cd /var/www/html</pre>
<pre>git clone https://github.com/Magento/Magento2.git</pre>
<pre>cd Magento2</pre>
<p>现在只需安装composer：</p>
<pre>composer install</pre>
<p>如果您遇到这样的错误：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/composer-install.png" alt="" ></p><p>要解决它，请运行以下命令：</p>
<pre>apt-get install php7.2-bcmath</pre>
<pre>composer install</pre>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_248/composer-install-2.png" alt="作曲家安装2" ></p><p>现在如果仍未安装composer，如上面的屏幕所示，请运行：</p>
<pre>sudo apt-get install php-soap</pre>
<pre>composer install</pre>
<p>现在您必须更改文件夹的权限，以便Magento安装程序可以安装所需的文件：</p>
<pre>
chmod -R 755 /var/www/html/Magento2/
chmod -R 777 /var/www/html/Magento2/var/
chmod -R 777 /var/www/html/Magento2/pub/
chmod -R 777 /var/www/html/Magento2/app/etc
chmod -R 777 /var/www/html/Magento2/generated
</pre>
<pre>sudo service Apache2 restart</pre>
<p>否则，php扩展将会丢失。</p><h2 id="3">设置数据库</h2><p>通过此命令登录MySQL</p>
<pre>mysql -u root -p</pre>
<p>它会询问你一个密码。默认情况下它是none，所以只需按<strong>Enter</strong>键。现在你在MySQL终端。</p><ul><li><strong>show databases:</strong>显示当前表。</li><li><strong>create database Magento:</strong>它将为Magento创建一个数据库</li><li><strong>exit</strong>它将退出MySQL终端</li></ul><h2 id="4">在AWS上安装和配置Magento</h2><p>导航到您的公共IP地址：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/public-IP-address.png" alt="公共IP地址"></p><p>将其复制并粘贴到您的浏览器，如xx.xxx.xxx.xx/Magento2/setup</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/Magento2-setup.png" alt="" ></p><p>您将看到以下屏幕。这意味着您已准备好在AWS上安装设置Magento。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS.png" alt="" ><br> 现在开始安装Magento：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-database.png" alt="在AWS数据库上设置Magento"></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-web.png" alt="" ></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-customize.png" alt="在AWS自定义上设置您的Magento" ></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-create-admin-account.png" alt="" ></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-Install-Now.png" alt="" ></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_248/setup-your-Magento-on-AWS-success.png" alt="" ><br> 以上消息表明您已在AWS上成功安装了Magento了。</p><p>如果需要Magento技术支持，请联系我们</p>]]></description>
      <pubDate>Fri, 12 Jul 2019 09:15:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何提高Magento的安全性]]></title>
      <link>https://www.360magento.com/blog/improve-magento-security/</link>
      <description><![CDATA[<p>Magento是一个流行的电子商务平台，具有许多令人敬畏和有用的功能。它被世界各地的商家广泛使用。当您经营电子商务网站时，您必须非常谨慎地处理有关客户的重要且敏感的信息。虽然Magento已经配备了大量内置安全功能，但您必须遵循最佳实践以获得更好的Magento安全性。</p>
<p>它是一种强制性的电子商务安全实践，由支付卡行业数据安全标准（PCI DSS）严格执行，用于处理客户的信用卡数据。保护数据和客户数据对您来说非常重要，因为它可以帮助您保持与客户的良好声誉，并消除不必要的离线时间。</p>
<p>所以，今天，在本指南中，我将分享保护Magento商店的技巧。</p>
<h2>提高Magento安全性的技巧</h2>
<ul>
<li><a href="#1">选择较强的管理员用户名和密码</a></li>
<li><a href="#2">使用两步验证添加额外的保护层</a></li>
<li><a href="#3">添加Magento reCAPTCHA</a></li>
<li><a href="#4">保持您的商店更新和安全</a></li>
<li><a href="#5">使用SSL保护客户的信息</a></li>
<li><a href="#6">创建Magento商店的定期备份</a></li>
<li><a href="#7">限制对Magento商店的管理员访问权限</a></li>
<li><a href="#8">安装知名的Magento扩展程序</a></li>
<li><a href="#9">唯一的管理URL</a></li>
<li><a href="#10">保护您的开发环境</a></li>
<li><a href="#11">选择性能稳定的magento托管主机</a></li>
</ul>
<h2 id="1">选择较强的管理员用户名和密码</h2>
<p>对于电子商务网站的安全性，选择强密码和复杂的管理员名称至关重要，因为它可以防止未经授权访问您的电子帐户和设备。只需选择一个独特而复杂的管理员名称和密码，以便潜在的在线黑客无法追踪您的Magento商店的登录详细信息。在设置商店密码时，请使用大小写字母，符号和数字的不规则组合（例如-ptU @＃$ * 59 ^）。</p>
<h2 id="2">使用两步验证添加额外的保护层</h2>
<p>Magento安全检查的另一个最佳实践是双因素身份验证（TFA）。它将帮助您保护Magento商店免受攻击。双因素身份验证将您的商店的登录过程分为两个步骤：首先，您必须添加登录凭据，然后您必须通过双因素身份验证步骤。此过程将阻止攻击者访问您商店的管理面板，即使他们已经窃取了登录凭据。要实现它，您可以阅读<a href="https://www.360magento.com/blog/setup-magento-2-two-factor-authentication" rel="noopener noreferrer" target="_blank">有关如何设置Magento 2 TFA的指南</a>。</p>
<h2 id="3">添加Magento reCAPTCHA</h2>
<p>在涉及Magento安全检查时，您不能忽视将reCAPTCHA添加到您的电子商务网站，这对保护您的在线业务起着至关重要的作用。它用于阻止垃圾邮件并使您的商店免受攻击者的攻击。reCAPTCHA将确定尝试登录您商店管理员的用户是人还是BOT，如果不是人，那么它将无法继续进行。</p>
<p>对于Magento 1.x： &nbsp; <a href="https://www.360magento.com/blog/add-recaptcha-to-magento" target="_blank">如何添加reCAPTCHA到Magento</a>对于Magento 2.x： &nbsp;<a href="https://www.360magento.com/blog/setup-magento-2-recaptcha" target="_blank">如何设置Magento 2 reCAPTCHA</a></p>
<h2 id="4">保持您的商店更新和安全</h2>
<p>Magento定期更新，其最新版本仍然充斥着软件中最近发现的安全风险，而不是其前辈。您需要尽快使用最新版本更新Magento商店，因为它可以让您采取最佳安全措施来保护商店免受在线威胁和破坏。</p>
<p>更新Magento还可以帮助您获得新功能，错误修复和其他重要升级。确保您使用的是最新的Magento版本。如果没有，那么请不要担心，请查看这些指南：</p>
<p>对于Magento 1.x：<a href="https://www.360magento.com/blog/upgrade-magento-1-7-to-1-9">如何将Magento 1.7升级到Magento 1.9<br /> </a>对于Magento 2.x：<a href="https://www.360magento.com/blog/update-magento-2-using-composer">如何使用Composer更新Magento 2</a></p>
<h2 id="5">使用SSL保护客户的信息</h2>
<p>没有SSL证书的电子商务网站容易受到黑客攻击。通过未加密的连接发送的数据很容易被攻击者追踪和窃取。如果您尚未在Magento商店中正确实施SSL，那么您的客户敏感信息（如登录凭据，信用卡数据和其他详细信息）将会泄漏。您必须从经过验证的证书颁发机构购买SSL证书，然后必须对其进行配置以强制通过HTTPS加载商店页面。</p>
<h2 id="6">创建Magento商店的定期备份</h2>
<p>定期备份Magento文件和数据库可以在您的商店发生不良事件时提供帮助。在这种情况下，您可以使用最新的未损坏备份来还原信息。使用FTP客户端下载文件，轻松备份您帐户中的文件。</p>
<p>您还可以在phpMyAdmin的帮助下导出Magento数据库，并从控制面板的Databases部分访问它。单击安装Magento的phpMyAdmin（在左侧框架中）中的数据库名称以查看数据库表。</p>
<h2 id="7">限制对Magento商店的管理员访问权限</h2>
<p>限制管理员访问权限将添加一个额外且有用的层来保护Magento商店。它可以作为管理面板上的快速Magento安全修复程序，您和您的其他站点管理员只能使用某个IP地址访问它。攻击者无法从其他IP地址访问管理面板。实施它以保护您的Magento商店。</p>
<h2 id="8">安装知名的Magento扩展程序</h2>
<p>由于您的电子商务网站有许多扩展以增强其体验，有时它可能会损害您的Magento商店的安全性。如果已安装未根据最佳Magento安全实践开发任何的扩展，则它将帮助攻击者进入并破解您的商店。</p>
<p>在将任何第三方Magento扩展程序安装到您的商店之前，请始终查看有关开发人员的跟踪记录，声誉和客户评论。只选择那些来自备受尊重的来源，定期更新和维护并具有良好记录的扩展。</p>
<h2 id="9">唯一的管理URL</h2>
<p>为Magento商店设置唯一的管理URL是保护Magento商店的另一个重要做法。默认情况下，Magento商店的管理URL是www.example.com/admin，很容易被攻击者追踪。</p>
<p>强烈建议将默认管理URL更改为任何人都无法轻易识别的URL，这将使他们难以突破Magento商店的安全性。您可以在本指南中了解有关<a href="https://www.360magento.com/blog/change-magento-admin-url" target="_blank">如何更改Magento管理URL的</a>更多信息。</p>
<h2 id="10">保护您的开发环境</h2>
<p>保护Magento商店的主要技巧之一是保护商店的开发环境。确保所有开发访问仅限于开发人员而不是其他任何人。这是因为，如果开发人员以外的其他人有权进入您商店的开发环境，那么您的Magento商店的安全性就会受到威胁。</p>
<h2 id="11">选择性能稳定的magento托管主机</h2>
<p>除了应用程序安全性之外，服务器安全性是您可能忽略的一个重要问题。如果您认真对待服务器安全性，那么转移到托管主机提供商是一个不错的选择。托管主机涵盖所有服务器安全性和修补，因此您不必担心它。</p>
<h2>总结</h2>
<p>客户总是喜欢在安全平台在线购买产品。因此，当您运营在线业务时，您不能忽视电子商务安全的重要性。因为忽略它可能减少电子商务网站的销售流量。</p>
<p>我现在相信，通过本指南，您可以更轻松地采取必要的步骤来改善Magento商店的安全性。如果您仍有任何疑惑或想要讨论有关本指南的任何内容，请联系我们。</p>]]></description>
      <pubDate>Sun, 07 Jul 2019 07:43:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何修改Magento后台管理URL路径]]></title>
      <link>https://www.360magento.com/blog/change-magento-admin-url/</link>
      <description><![CDATA[<p><span style="font-weight: 400;">Magento是最广泛使用的电子商务平台之一。该CMS系统因其安全性而受到认可，并且在大多数电子商务商店的许多平台中是最安全的。</span></p><p>虽然有许多建议关于<a href="https://www.360magento.com/blog/improve-magento-security" target="_blank" rel="noopener noreferrer">Magento商店的安全性</a>，但一个非常有用的做法就是使用Magento管理面板URL的唯一路径而不是使用默认URL。</p><p>在本教程中，我将教您如何更改Magento后台管理URL。我将向您展示多种方法来更改Magento 1.x和Magento 2.x的管理面板URL。</p><table style="text-align: center; margin: auto; border: 3px solid;"><tbody><tr><th style="background: #ff6e17; color: white;">更改Magento管理面板URL</th><th style="background: #ff6e17; color: white;">更改Magento 2管理面板URL</th></tr><tr><td><a href="#M1-AdminPanel">通过管理面板</a></td><td><a href="#M2-AdminPanel">通过管理面板</a></td></tr><tr><td><a href="#M1-Local">通过编辑local.xml文件</a></td><td>&nbsp;<a href="#M2-Env">通过编辑env.php</a></td></tr><tr><td></td><td><a href="#M2-Command">通过命令行</a></td></tr></tbody></table><h2><span style="font-weight: 400;"><strong><br> 更改Magento管理面板&nbsp;</strong></span></h2><h2 id="M1-AdminPanel"><span style="font-weight: 400;">方法1：通过管理面板</span></h2><p><span style="font-weight: 400;">更改Magento管理URL的第一步是转到Magento商店的管理面板，然后导航到<strong>SYSTEM → Configuration：</strong></span></p><p><img class="aligncenter size-full wp-image-10826 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/system-config-magento-admin-url.png" alt="system-config magento admin url" /><br>现在向下滚动并单击<strong>ADVANCED</strong>选项卡下的<strong>Admin</strong>选项：<strong></strong></p><p><img class="aligncenter size-full wp-image-10827 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/advanced-admin-magento.png" alt="advanced-admin magento">现在展开<strong>Admin Base URL</strong>部分，然后从<strong>Use Custom Admin Path</strong>下拉菜单中选择<strong>Yes</strong>，并输入您选择的管理路径。我将使用<strong>Magento</strong>，您可以根据您的要求进行更改：<strong></strong><strong></strong></p><p><strong>注意：</strong>请勿将<strong>Use Custom Admin URL</strong>选项更改为“<strong>Yes</strong></p><p><img class="aligncenter size-full wp-image-10828 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/admin-base-url-magento.png" alt="admin base url magento"><strong><br> </strong>接下来，只需单击<strong>Save Config</strong>按钮：<br> <img class="aligncenter size-full wp-image-10829 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/save-config-admin-url-magento.png" alt="保存配置管理员url magento" width="126" height="40"></p><h2 id="M1-Local"><span style="font-weight: 400;">方法2：通过编辑local.xml文件</span></h2><p><span style="font-weight: 400;">通过Magento商店根目录下的<strong>app/etc</strong>目录在文本编辑器中打开<strong>local.xml</strong>文件。在这里，您搜索此代码：<br> </span></p>
<pre>
&lt;admin&gt;
        &lt;routers&gt;
            &lt;adminhtml&gt;
                &lt;args&gt;
                    &lt;frontName&gt;&lt;![CDATA[admin]]&gt;&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/adminhtml&gt;
        &lt;/routers&gt;
    &lt;/admin&gt;
</pre>
<p>在上面的代码中，Magento管理员URL被设置为admin，因此将其更改为magento：</p>
<pre>
 &lt;admin&gt;
        &lt;routers&gt;
            &lt;adminhtml&gt;
                &lt;args&gt;
                    &lt;frontName&gt;&lt;![CDATA[magento]]&gt;&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/adminhtml&gt;
        &lt;/routers&gt;
    &lt;/admin&gt;
</pre>
<p><span style="font-weight: 400;">您可以使用上述任何方法来更改Magento Admin URL。最后，不要忘记通过从Magento商店的管理面板导航到<strong>System → Cache Management</strong>来清除缓存。现在让我们转到更改Magento 2管理URL的方法。<br> </span></p><h2 id="M2-AdminPanel"><span style="font-weight: 400;"><strong>更改Magento 2管理面板URL</strong></span></h2><h2><span style="font-weight: 400;">方法1：通过管理面板</span></h2><p><span style="font-weight: 400;">打开商店的管理面板，然后导航到</span><b>STORES → Configuration</b></p><p><img class="aligncenter size-full wp-image-9632 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/2018/08/stores-config-magento-2-recaptcha.png" alt="商店 - 配置magento 2 recaptcha" ></p><p><span style="font-weight: 400;">向下滚动并单击</span><b>ADVANCED </b><span style="font-weight: 400;">下的</span><b>Admin </b><span style="font-weight: 400;">。</span><img class="aligncenter size-full wp-image-5076 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/2017/06/image2.png" alt=""></p><p>现在展开<strong>Admin Base URL</strong>部分并按照我在Magento 1.x教你的方式进行更改：</p><p><img class="aligncenter size-full wp-image-5077 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/2017/06/image3.png" alt=""></p>
<p><span style="font-weight: 400;">然后，只需单击<strong>Save Config：</strong></span><br> <img class="aligncenter size-full wp-image-9674 appear" src="https://www.360magento.com/media/wysiwyg/blog_246/2018/08/save-config-2FA.png" alt="保存配置2FA" width="141" height="64"></p></div><h2 id="M2-Env"><span style="font-weight: 400;">方法2：通过编辑env.php</span></h2><p>通过<strong>app/etc</strong>目录用文本编辑器打开<strong>env.php</strong>文件。现在，您将看到以下代码：</p>
<pre>
&lt;?php
return array (
 'backend' =>
 array (
   'frontName' => 'magento',
 )
</pre>
<p>将以上代码替换为以下代码，将Magento 2管理员URL从admin更改为magento：</p>
<pre>
 'backend' =>
  array (
    'frontName' => 'magento',
  ),
</pre>
<h2 id="M2-Command"><span style="font-weight: 400;">方法3：通过命令行</span></h2><p><span style="font-weight: 400;">使用SSH终端连接您的商店，然后转到Magento 2商店的根目录。现在运行以下命令：</span></p>
<pre>
php bin/magento setup:config:set --backend-frontname="magento"
</pre>
<p>在上面的命令中，我将管理URL路径设置为<strong>magento</strong>，您可以根据需要进行设置。</p><p>我已经提到并详细说明了三种更改Magento 2 Admin URL的方法。使用您选择的方法后，您必须清理缓存。为此，请在Magento 2根目录中运行以下命令</p>
<pre>
rm -rf var/cache/*
php bin/magento cache:clean
php bin/magento cache:flush
</pre>
<h2><span style="font-weight: 400;">总结</span></h2><p>每个电子商务商店都必须拥有安全的管理网址。完成本教程后，您现在应该可以更改Magento管理员URL。如果您仍然有任何困惑或想要讨论任何事情，请随时联系我们！</p><div class="frame"><h2 class="frames">经常问的问题</h2><p><strong>Q1。服务器上找不到Magento管理员URL：为什么？<br> </strong></p><p>您可能遇到此问题，因为您输入了错误的Magento管理面板URL。这很容易纠正。对于Magento 1.x，从app / etc目录转到local.xml，对于Magento 2.x，从app / etc目录转到env.php。</p><p><strong>Q2。为什么Magento Admin URL仍会打开旧网址？</strong></p><p>这是因为您可能尚未清除商店的缓存。清除并刷新它，然后尝试打开Magento管理面板URL。<strong><br> </strong></p></div>]]></description>
      <pubDate>Fri, 05 Jul 2019 08:13:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何设置Magento 2双重身份验证]]></title>
      <link>https://www.360magento.com/blog/setup-magento-2-two-factor-authentication/</link>
      <description><![CDATA[<p>这是另一个Magento 2安全教程。在上一篇指南中，我向您展示了添加<a href="https://www.360magento.com/blog/setup-magento-2-recaptcha" target="_blank" rel="noopener noreferrer">Magento 2 reCAPTCHA</a>的方法，今天，您将学习如何配置Magento 2双重身份验证。</p><p>在这个Magento 2 reCAPTCHA教程中，我提到了Magento的公告，其中他们透露了&nbsp;  <a href="https://docs.magento.com/m2/ce/user_guide/magento/extension-install-two-factor-authentication.html" target="_blank" rel="nofollow noopener">Magento 2双重身份验证</a>被添加到所有Magento 2.1及以上版本中。</p><p>双重身份验证是另一项Magento 2最佳安全实践，旨在保护您的商店免受攻击者攻击。即使攻击者获得了商店的登录凭据，由于附加的安全层，他也无法访问它。</p><p>在进入实施阶段之前，让我们首先了解Magento 2双重身份验证的工作原理：</p><h2>Magento 2双重认证的作用是什么？</h2><p>它会将Magento 2管理面板的登录过程分为两个步骤：</p><ul><li><strong>第一步：</strong>您必须输入登录凭据，用户名和密码。</li><li><strong>第二步：</strong>您必须通过双重身份验证。</li></ul><p>让我们开始设置Magento 2双重身份验证</p><h2>要遵循的步骤</h2><ul><li><a href="#1">安装Magento 2双重身份验证</a></li><li><a href="#2">配置Magento 2双重身份验证</a></li></ul><h2 id="1">安装Magento 2双重身份验证</h2><p>启动SSH终端并连接您的Magento 2商店。然后转到其根目录并运行以下CLI命令：</p>
<pre>composer require msp/twofactorauth:3.0.0</pre>
<p>然后，您必须通过运行此命令启用双重身份验证模块：</p>
<pre>php bin/magento module:enable --all</pre>
<p>完成后，运行此命令升级设置：</p>
<pre>php bin/magento setup:upgrade</pre>
<p>现在运行以下命令编译设置：</p>
<pre>php bin/magento setup:di:compile</pre>
<p>最后，通过运行以下命令来清理和刷新缓存：</p>
<pre>
php bin/magento cache:clean

php bin/magento cache:flush
</pre>
<p>安装已完成，现在转到其配置部分。</p><h2 id="2">配置Magento 2双重身份验证</h2><p>在开始配置之前，让我告诉您，您可以向商店添加四种类型的2FA提供商选项：</p><ul><li>Google Authenticator</li><li>Duo Security</li><li>Authy</li><li>U2F</li></ul><p>我将在Magento 2的商店中添加Google Authenticator 2FA，您可以根据自己的需要使用任何其他提供商。</p><p>在商店的管理面板中添加此双重身份验证后，它将要求使用Google身份验证器应用程序扫描条形码，然后您必须输入提供的代码才能访问管理面板。</p><p>因此，现在登录到商店的管理面板并导航到<strong>STORES → Configuration:</strong></p><p><img class="aligncenter size-full wp-image-9666 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/Stores-Configuration-Magento-2-2FA.png" alt="商店 - 配置Magento 2 2FA"></p><p>点击<strong>SECURITY</strong>标签下的<strong>2FA</strong>：<strong></strong></p><p><img class="aligncenter size-full wp-image-9667 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/click-2FA.png" alt="点击2FA" width="274" height="126"></p><p>现在，在此处展开​​<strong>General </strong>部分，<strong>Enable Two Factor Auth</strong>中选择<strong>Yes</strong>，然后从<strong>Force providers</strong>选择<strong>Google Authenticator</strong>，这意味着它将自动用于所有用户访问管理面板。</p><p><img class="aligncenter size-full wp-image-9668 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/general-2FA.png" alt="一般2FA"></p><p><strong>注意：</strong>如果要为不同的用户设置不同的双重身份验证提供程序，请不要从强制提供程序中选择任何提供程序，并从<strong>SYSTEM → All Users</strong>转到用户列表，以便在启用提供程序后为每个用户选择双重身份验证提供程序。</p><p>现在展开<strong>Google Authenticator</strong>部分，然后从<strong>Enable This Provider</strong>中选择<strong>Yes</strong>。然后<strong>Enable “trust this device” option</strong>该选项有两个选项：</p><ul><li><strong>Yes:</strong>  &nbsp;如果您希望用户不为每个设备的每次登录输入验证码。</li><li><strong>No:</strong>如果您希望用户通过身份验证过程以登录管理面板。</li></ul><p><img class="aligncenter size-full wp-image-9669 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/Google-Authenticator.png" alt="Google身份验证器"></p><p>&nbsp;</p><p>正如我之前提到的那样，我将设置Google身份验证器双重身份验证，现在几乎完成了。但是，您可以通过转到其各个部分来配置不同的提供程序。让我简要介绍一下设置其他提供商的情况。</p><p>展开<strong>U2F设备（Yubikey和其他人）</strong>部分并按照我对Google身份验证器的相同方法：</p><p><img class="aligncenter size-full wp-image-9670 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/U2F-Devices.png" alt="U2F设备"></p><p>展开<strong>U2F Devices(Yubikey and others) </strong>部分，启用它，然后输入您将从Duo帐户获得的所需详细信息<strong>（集成密钥，密钥，API主机名）</strong>：</p><p><img class="aligncenter size-full wp-image-9671 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/Duo-Security.png" alt="二重安全"></p><p>展开<strong>Authy</strong>部分，启用它，然后输入您将从Authy帐户获得的所需详细信息：</p><p><img class="aligncenter size-full wp-image-9672 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/authy.png" alt="authy" ></p><p>现在您必须保存Magento 2双重身份验证配置，只需单击页面顶部的<strong>Save Config</strong>：</p><p><img class="aligncenter size-full wp-image-9674 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/save-config-2FA.png" alt="保存配置2FA" width="141" height="64"></p><p>是时候检查结果，注销并再次登录管理面板，它将通过Google身份验证器扫描条形码来询问您将获得的代码：</p><p><img class="aligncenter size-full wp-image-9673 appear" src="https://www.360magento.com/media/wysiwyg/blog_245/Magento-2-two-factor-authentication-result.png" alt="Magento 2双重认证结果"></p><p>这意味着Magento 2双重身份验证已成功配置。</p>]]></description>
      <pubDate>Wed, 03 Jul 2019 10:31:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何设置Magento 2 Google reCAPTCHA]]></title>
      <link>https://www.360magento.com/blog/setup-magento-2-recaptcha/</link>
      <description><![CDATA[<p>任何电商平台的安全性都至关重要，因为现在客户更喜欢在安全平台上购买商品。因此，您必须要始终保持网站安全。当您谈论可靠和安全的电子商务平台时，您不能忽视Magento。</p><p>但是，为了<a href="https://www.360magento.com/blog/improve-magento-2-security" target="_blank">使您的Magento 2商店更安全</a>，您必须遵循最佳做法，而reCAPTCHA就是其中之一。Magento <a href="https://docs.magento.com/m2/ce/user_guide/magento/extension-install-google-recaptcha.html?mkt_tok=eyJpIjoiTURSa05UVmxPRFF4TnpVMyIsInQiOiJlY2ZtQXhTSys1RnVDNm1LSDJsXC80Vlgzem81K1laN3JnU3owOE5IQlhBR0hpWm5cL3M0Um54cHpYWXJjMEpTc2JcL21IdExkNlwvMjYzNmViWmdxWHFhdG5YcitsODFUT3hYaTNIWHR1U2xKYlwvMThDbWJlc1RyQWxBZTNUb29yWjY3In0%3D" target="_blank" rel="nofollow noopener noreferrer">宣布</a> reCAPTCHA和2FA功能已添加到所有Magento 2.1及以上版本中，这是一个很好的补充。</p><p>所以，今天在本指南中，我将教你如何配置Magento 2 reCAPTCHA。如果您使用的是Magento 1.x版本，则可以查看本指南：<a href="https://www.360magento.com/blog/add-recaptcha-to-magento" target="_blank">如何添加Magento reCAPTCHA</a>。</p><p>开始吧！</p><h2>要遵循的步骤</h2><ul><li><a href="#1">安装Magento 2 reCAPTCHA</a></li><li><a href="#2">生成Google reCAPTCHA密钥</a></li><li><a href="#3">配置Magento 2 reCAPTCHA</a></li></ul><h2 id="1">安装Magento 2 reCAPTCHA</h2><p>启动SSH终端。连接您的Magento 2商店并转到其根目录。</p><p>现在运行以下命令：</p>
<pre>composer require msp/recaptcha:2.0.0</pre>
<p>然后，它会询问您通过转到您的marketplace帐户获得的回购凭据，用户名和密码。</p><p>如果你得到错误<strong>proc_open(): fork failed – Cannot allocate memory’ in phar</strong>那么你可以通过启用Swap空间来解决它，或者你也可以通过运行以下命令来解决它：</p>
<pre>php -d memory_limit=-1 /usr/local/bin/composer require msp/recaptcha:2.0.0</pre>
<p>完成后，通过运行以下命令启用模块：</p>
<pre>php bin/magento module:enable --all</pre>
<p>然后使用以下命令升级安装程序：</p>
<pre>php bin/magento setup:upgrade</pre>
<p>现在只需清理并刷新缓存：</p>
<pre>php bin/magento cache:clean</pre>
<pre>php bin/magento cache:flush</pre>
<h2 id="2">为您的Magento 2商店生成Google reCAPTCHA密钥</h2><p>转到<a href="https://www.google.com/recaptcha/admin" target="_blank" rel="nofollow noopener noreferrer">Google reCAPTCHA网站</a>，确保您已登录自己的帐户。</p><p>现在首先输入密钥的标签，我已经输入了<strong>My Magento CAPTCHA</strong>，你可以添加一个你的选择。然后选择reCAPTCHA的类型，这里有三种类型的reCAPTCHA，其中两种是：</p><ol><li><strong>reCAPTCHA v2：</strong>它通过单击按钮验证请求。</li><li><strong>Invisible reCAPTCHA：</strong>它将在后台验证请求而不进行任何交互。</li></ol><p><img class="aligncenter size-full wp-image-9628 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/label-for-google-recaptcha-keys.png" alt="谷歌recaptcha键的标签"></p><p>选择CAPTCHA类型后，输入要添加reCAPTCHA的Magento商店域和子域：</p><p><img class="aligncenter size-full wp-image-9629 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/google-recaptcha-add-domains.png" alt="google recaptcha添加域名" width="266" height="148"></p><p>现在单击您接受reCAPTCHA服务条款的<strong>复选框</strong>，然后单击<strong>Register</strong>：</p><p><img class="aligncenter size-full wp-image-9630 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/register-google-recaptcha.png" alt="注册google recaptcha"></p><p>您将被重定向到新页面，转到<strong>将reCAPTCHA添加到您的站点</strong>部分，您将看到生成了reCAPTCHA密钥。复制您必须在下一步中使用的<strong>Site Key</strong>和<strong>Secret Key</strong>。</p><p><img class="aligncenter size-full wp-image-9631 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/Adding-reCAPTCHA-to-your-site.png" alt="将reCAPTCHA添加到您的站点"></p><h2 id="3">配置Magento 2 reCAPTCHA</h2><p>转到商店的管理面板，然后导航到<strong>STORES → Configuration</strong></p><p><img class="aligncenter size-full wp-image-9632 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/stores-config-magento-2-recaptcha.png" alt="商店 - 配置magento 2 recaptcha"></p><p>现在点击<strong>Security</strong>标签下的<strong>Google reCaptcha</strong>：</p><p><img class="aligncenter size-full wp-image-9633 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/google-recaptcha-security.png" alt="谷歌recaptcha安全" width="277" height="132"></p><p>首先展开“<strong>General</strong>部分，输入您在上一步中复制的Google reCaptcha key。</p><p><img class="aligncenter size-full wp-image-9634 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/General-section-magento-2-recaptcha.png" alt="一般部分magento 2 recaptcha"></p><p>展开<strong>backend</strong>部分，如果要在管理员登录中启用Google reCAPTCHA，请从“Enable”下拉列表中选择“<strong>Yes</strong>：</p><p><img class="aligncenter size-full wp-image-9635 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/backend-section-Magento-2-recaptcha.png" alt="后端部分Magento 2 recaptcha"></p><p>现在展开最后一节，<strong>frontend</strong>。从<strong>Enable</strong>下拉菜单中选择<strong>Yes</strong>，然后根据需要为您的前端表单设置Google reCaptcha：</p><p><img class="aligncenter size-full wp-image-9636 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/frontend-magento-2-recaptcha.png" alt="前端magento 2 recaptcha"></p><p><img class="aligncenter size-full wp-image-9637 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/frontend-magento-2-recaptcha-2.png" alt="前端magento 2 recaptcha 2"></p><p>最后，只需单击<strong>Save Config</strong>：</p><p><img class="aligncenter size-full wp-image-9638 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/save-config-magento-2-recaptcha.png" alt="保存配置magento 2 recaptcha" width="144" height="61"></p><p>现在转到您商店的任何表单页面，我将转到联系页面，结果如下：</p><p><img class="aligncenter size-full wp-image-9639 appear" src="https://www.360magento.com/media/wysiwyg/blog_244/magento-2-recaptcha-result.png" alt="magento 2 recaptcha结果"></p><p>以上输出表明Magento 2 reCAPTCHA已成功配置。</p><h2>总结</h2><p>您的商店可能在各方面都得到了全面优化，但如果它缺乏客户所需的坚如磐石的安全性，那么您可能会失去客户的信任并看到转换率下降。按照本指南，我希望您现在可以设置Magento 2 reCAPTCHA。由于每天都在实施Magento 2商店的许多安全实践，添加reCAPTCHA就是其中之一。在下一个教程中，我将向您展示在Magento 2中配置双重身份验证的方法。</p><p>如果您仍有任何疑惑或疑问请联系我们</p><p>&nbsp;</p>]]></description>
      <pubDate>Mon, 01 Jul 2019 08:28:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何将reCAPTCHA添加到Magento]]></title>
      <link>https://www.360magento.com/blog/add-recaptcha-to-magento/</link>
      <description><![CDATA[<p>CAPTCHA是<strong>Completely Automated Public Turing Test to Tell Computers and Humans Apart.</strong>的简称，它用于确定您网站上的用户是否是人。它所服务的基本目的是阻止垃圾邮件并防止网站受到攻击，并通过简单易用的工作流程实现这一点。</p><p>用户必须用屏幕上显示的单词或字母填充CAPTCHA。如果CAPTCHA匹配，则允许用户继续，如果不匹配，那么当然，您无法继续。</p><p>联系表单是任何电子商务商店的重要组成部分，因此，它必须具有集成CAPTCHA表单以避免垃圾邮件。</p><p>Magento是一个受欢迎且功能强大的电子商务平台。所以今天我将教你如何在Magento的联系表格中添加谷歌reCAPTCHA。</p><p>在Magento联系表单中添加reCAPTCHA的过程包括以下步骤：</p><ul><li><a href="#create-account">创建Google reCAPTCHA帐户。</a></li><li><a href="#install-captcha-extension">下载并安装Magento reCaptcha Extension。</a></li><li><a href="#configuration">在Magento中配置reCAPTCHA。</a></li></ul><h2 id="create-account">创建Google reCAPTCHA帐户</h2><p style="margin: 0in; margin-bottom: .0001pt;">首先，登录您的Gmail帐户，转到Google reCAPTCHA <a href="https://www.google.com/recaptcha" target="_blank" rel="noopener noreferrer">注册页面</a>，然后单击“SIGN UP”。</p><p><img class="aligncenter size-full wp-image-3080 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/signup.png" alt="注册谷歌验证码" ><br>输入您选择的网站的标签名称，您可以轻松记住，并输入您的在线商店的域名。提供详细信息后，单击<strong>Register</strong></p><p><img class="aligncenter size-full wp-image-3081 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/register.png" alt="注册谷歌验证码帐户"></p><p>现在将出现一个屏幕，您可以从中获取您将在本教程的配置步骤中使用的<strong>Site</strong>和<strong>Secret Key</strong>。</p><p><img class="aligncenter size-full wp-image-3092 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/secret-site-key.png" alt="验证码的密钥和站点密钥"></p>
<h2 id="install-captcha-extension">下载并安装Magento reCaptcha Extension</h2><p>转到&nbsp; <a href="https://github.com/olegkoval/magento-contacts_form_captcha/" target="_blank" rel="nofollow noopener noreferrer">Contacts Form Captcha</a>，下载扩展程序。现在要安装下载的扩展，将下载文件的存档解压缩到网站的根目录。</p><p>完成后，不要忘记清除缓存。</p><h2 id="configuration">在Magento中配置reCAPTCHA</h2><p>返回管理面板，然后导航到<strong>System → Configuration。</strong></p><p><img class="aligncenter size-full wp-image-3086 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/system-configuration.png" alt="naviagate从systemto配置"></p><p>单击<strong>GENERAL</strong>选项卡下的<strong>Contacts</strong>。</p><p><img class="aligncenter size-full wp-image-3087 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/contact-tab.png" alt="点击联系" width="235" height="249"></p><p>在<strong>Enable Captcha</strong>属性选择<strong>是</strong>。然后输入我们在本教程第一步中创建的<strong>Google reCAPTCHA</strong>的<strong>Site Key</strong>和<strong>Secret Key</strong>。现在只需单击<strong>Save Config</strong>保存配置</p><p><img class="aligncenter size-full wp-image-3088 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/save-config.png" alt="保存配置"></p><p>转到Magento商店的联系我们页面，您将看到结果！</p><p><img class="aligncenter size-full wp-image-3089 appear" src="https://www.360magento.com/media/wysiwyg/blog_243/output.png" alt="回到magento"></p><h2>总结</h2><p>reCAPTCHA是一个明智的选择，使您的联系表格更安全，无垃圾邮件。完成本教程后，您应该能够将reCAPTCHA添加到Magento联系表单中。如果您有任何问题请联系我们。不要忘记与朋友分享这篇文章！</p>]]></description>
      <pubDate>Fri, 28 Jun 2019 09:20:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何使用Composer更新升级Magento 2]]></title>
      <link>https://www.360magento.com/blog/update-magento-2-using-composer/</link>
      <description><![CDATA[<p>Magento于2007年由Varien推出，现已成为发展最快的电子商务平台之一。凭借多项优秀和最新的电子商务功能，它在现代电子商务行业中崭露头角。如果您使用流行的CMS并且想知道如何使用Composer更新Magento 2，那么我们为您提供服务！</p><p>如今，由于其模块化架构，完整的可扩展性以及广泛的支持和选择，Magento是超过250,000个在线商店的电子商务平台的首选。</p><p>关于人们在使用Magento时遇到的各种问题的讨论已经开始，Magento 2发布了。但是几位专家提出了他们对该平台的特殊看法，并对Magento 2的改进产生了巨大影响。但是，人们在安装过程中仍遇到问题或陷入其他程序问题！</p><p>与其他电子商务平台一样，Magento不断提供更新，以便与行业趋势和所有用户兼容。这就是为什么强烈建议您始终保持最新版本的Magento的原因。</p><h2>为什么要更新Magento 2？</h2><p>然而，有一个问题不断上升：<a href="https://www.360magento.com/blog/why-m2" title="为什么要升级到Magento 2">“ 我们为什么要更新Magento 2？”</a><p><strong>以下是您真正应该遵循的8个理由：</strong></p><ul><li>安全更新</li><li>UI更新</li><li>功能改进</li><li>Bug修复</li><li>性能改进</li><li>支持最新技术堆栈</li><li>目录，产品，运输和计算改进</li><li>通过Google Analytics，付款方式，网关等第三方服务进行集成改进</li></ul><p>我们熟悉的Magento 2有几个功能。Magento 2命令行界面（CLI）是最好的之一，为开发人员在模块管理，索引管理，缓存管理和更新到最新的Magento 2版本等方面节省了大量时间。</p><p>今天，我们将解释如何使用CLI升级Magento 2版本。请记住，您应首先创建商店的备份，因为不建议您在生产环境中使用此方法。</p><p>此外，您应该知道Magento 2 CLI升级仅在您使用Composer安装Magento 2或从官方Magento网站下载的存档ZIP文件时才有效。如果您从GIT存储库克隆了Magento 2，则此方法不适用于您。</p><h2>更新Magento 2</h2><p>因此，让我们按照以下简单步骤深入了解Magento 2的升级过程：</p><p><strong>步骤1  - &gt;</strong>首先，通过SSH连接到您的Web服务器。使用putty或任何SSH客户端，使用完整的文件系统所有权登录Magento 2服务器。</p><p><strong>步骤2  - &gt;</strong>建立SSH连接后，您需要导航到<strong>Magento 2 ROOT</strong>目录。</p><p><strong>第3步 - &gt;</strong>现在按照顺序使用以下命令：</p>
<pre>composer require magento/product-community-edition 2.3.2 --no-update</pre>
<p><strong>2.3.2是Magento 2.3.x版本的最新版本。如果要升级Magento 2.2.x版本，请相应更改这些编号。</strong></p>
<pre>composer update</pre>
<p><strong>如果出现身份验证，请输入</strong><a href="http://devdocs.magento.com/guides/v3.0/comp-mgr/prereq/prereq_auth-token.html" target="_blank" rel="noopener noreferrer"><strong>magento.repo authentication</strong></a><strong>密钥。</strong></p>
<pre>
rm -rf var/di/* var/generation/* var/cache/* var/log/* var/page_cache/*
php bin/magento cache:clean
php bin/magento cache:flush
</pre>
<p><strong>如果您使用的是Magento 2文件系统以外的缓存存储（例如Varnish，Redis，Memcached等），则还需要手动清除该缓存。</strong></p>
<pre>
php bin/magento setup:upgrad
php bin/magento setup:di:compile
php bin/magento indexer:reindex
</pre>
<p><strong>步骤4  - &gt;</strong>现在转到Magento 2管理面板，并在右下角验证您是否已成功更新Magento 2版本。如果显示任何错误，请尝试重置<a href="http://devdocs.magento.com/guides/v3.0/install-gde/prereq/file-system-perms.html" target="_blank" rel="noopener noreferrer">文件权限</a>并再次清除缓存。</p><h2>结论</h2><p>有多种方法可以更新Magento 2.在上面的方法中，我们使用Magento 2 CLI来执行此任务。这是使用Composer快速升级Magento 2的精确而有用的指南。</p>]]></description>
      <pubDate>Thu, 27 Jun 2019 07:17:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何将Magento 1.7升级到Magento 1.9]]></title>
      <link>https://www.360magento.com/blog/upgrade-magento-1-7-to-1-9/</link>
      <description><![CDATA[<p>虽然Magento2已出来两三年了，比magento1更优秀，虽然magento1明年官方将不支持了，最近遇到一个使用magento1.7版本的客户，因为习惯，坚持要升级到magento1.9.4而不是magento2。下面主要介绍升级的基本步骤。首先，最重要的步骤，强烈建议备份您的网站程序和数据库，并通过magento的管理面板禁用以下选项：</p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;"><b>Magento编译</b>System > Tools > Compilation > Disable</li></ul></li></ul><p><img class="alignnone wp-image-1262 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/disable-compilation.png" alt="Magento 1.7管理面板"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;"><b>Magento缓存</b>System > Cache Management > Select All > Action: Disable > Submit</li></ul></li></ul><p><img class="alignnone wp-image-1264 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/disable-cache.png" alt="Magento缓存管理" ></p><p>现在我们就可以放心的准备在旧版本上执行升级了。从<a href="https://magento.com/tech-resources/download" target="_blank" rel="nofollow noopener noreferrer">https://magento.com/tech-resources/download</a>下载最新的magento v1.9.x 并执行以下步骤：</p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">从Magento v1.7目录中删除所有文件和文件夹（确保将备份保存在安全的地方）并放置Magento v1.9.x软件包中的所有文件和文件夹。</li><li style="font-weight: 400;">打开您喜欢的网络浏览器，转到您的网站链接。系统会要求您安装新的Magento v1.9.x商店，但不要担心，继续操作你将进入<b>Configuration</b>页面。使用您以前在Magento v1.7商店中使用的相同信息填写它，其中包括SQL DB服务器主机名，SQL DB名称，SQL Server用户名，SQL Server密码，基本URL和管理路径。</li></ul></li></ul><p><img class="alignnone wp-image-1266 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/configuration.png" alt="Magento安装和配置"></p><ul><li style="font-weight: 400;">完成安装后，请不要访问前端或后端页面。在Magento v1.7文件和文件夹备份中，将以下文件和文件夹复制并合并到新的Magento v1.9.x商店目录中：<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">Community文件夹：<b>ROOT > app > code > community</b></li></ul></li></ul><p><img class="alignnone wp-image-1268 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/1.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">local文件夹：<b>ROOT > app > code > local</b></li></ul></li></ul><p><img class="alignnone wp-image-1269 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/2.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">根目录中的media文件夹：<b>ROOT > media</b></li></ul></li></ul><p><img class="alignnone wp-image-1270 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/3.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">您的主题文件夹：&nbsp; <b>ROOT > app > design > frontend > default (package name) > “your_theme”</b>（如果您使用的是“default”包，那么只需复制主题文件夹，否则您需要复制包含主题的整个包夹）</li></ul></li></ul><p><img class="alignnone wp-image-1271 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/4.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">根目录中的Skin文件夹：<b>ROOT > skin</b></li></ul></li></ul><p><img class="alignnone wp-image-1272 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/5.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">模块的自定义XML文件：&nbsp; <b>ROOT > app > etc > modules > “your_custom_XML_files”</b></li></ul></li></ul><p><img class="alignnone wp-image-1273 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/6.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">admin主题文件夹：<b>ROOT > app > design > adminhtml > default</b></li></ul></li></ul><p><img class="alignnone wp-image-1274 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/7.png" alt="FTP传输Magento"></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;">自定义JS文件夹：<b>ROOT > app > js</b></li></ul></li></ul><p><img class="alignnone wp-image-1275 size-full appear" src="https://www.360magento.com/media/wysiwyg/blog_241/8.png" alt="FTP传输Magento"></p><ul><li style="font-weight: 400;">现在删除<b>ROOT > var > cache</b>和<b>ROOT > var > sessions</b>所有内容以清除所有会话和缓存。</li></ul></li></ul><p>就是这样，我们已成功将Magento v1.7商店更新到最新的Magento v1.9.x商店。打开Web浏览器，测试商店中的每个细节和所有内容，并解决部分模板和插件的兼容问题。并从<a href="https://www.360magento.com/blog/change-magento-admin-url">magento管理面板</a>验证版本升级.]]></description>
      <pubDate>Tue, 25 Jun 2019 09:09:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2在产品详情页添加自定义选项卡]]></title>
      <link>https://www.360magento.com/blog/m2-add-custom-tab/</link>
      <description><![CDATA[<p>当您希望成功运营电商网站时，客户满意度是主要的。</p><p>我们可以尽可能的去描述产品的特性及其他方面的展示，这样每个客户都可以了解得到他们想要了解的，自然也会提高购买欲望。</p><p>为此，我将教您如何在Magento 2中添加自定义选项卡以获取产品详细信息。</p><h2>添加新属性和添加属性集</h2><p>打开Magento 2的管理面板，进入<strong>Stores → Product</strong>，然后单击<strong>Add New Attribute</strong>按钮。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/add-attribute.png" alt="保存属性" /></p><p>现在插入Attribute的详细信息。将默认标签设置为<strong>Tab</strong>，将属性代码设置为<strong>tab.</strong>现在只需单击<strong>Save Attribute</strong>。</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/save-attribute.png" alt="保存属性" /></p><p>转到<strong>Stores → Attribute Set</strong>，然后单击<strong>Add Attribute Set.</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/add-attribute-sets.png" alt="添加属性集" /></p><p>插入<strong>Laptop</strong>作为<strong>Attribute Set</strong>的名称，然后单击<strong>Save.</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/name-attribute-set.png" alt="属性集名称" /></p><p>现在将<strong>选项卡</strong>从<strong>Unassigned Attributes</strong>移动到<strong>Product Details</strong>，然后单击<strong>Save.</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/drag-attribute.png" alt="" /></p><h2>产品页面配置</h2><p>从商店的管理面板打开产品编辑页面，然后从<strong>Attribute Set</strong>下拉列表中选择“ <strong>Laptop</strong> ” 。<strong></strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/product-attribute.png" alt="产品属性" /></p><p>向下滚动产品编辑页面，您将看到一个新的文本字段<strong>Tab</strong>。添加<strong> Tab Created </strong>到在此文本字段中，然后单击“<strong>Save</strong></p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/tab-text.png" alt="标签文字" /></p><h2>创建模块</h2><p>现在我要创建一个自定义模块。如果您对如何创建一个没有任何知识，可以查看此分步指南：<a href="https://www.360magento.com/blog/create-moudle-m2/" target="_blank">如何在Magento 2中创建模块。</a></p><h2>模块配置</h2><p>在<strong>app/code/Alwayly/Mymodule/etc</strong>创建<strong>module.xml</strong>文件并将此代码粘贴到其中：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
&lt;module name="Alwayly_Mymodule" setup_version="2.0.0" /&gt;
&lt;/config&gt;
</pre>
<h2>模块注册</h2><p>在<strong>app/code/Alwayly/Mymodule</strong>目录下创建<strong>registration.php</strong>文件,并将此代码粘贴：</p>
<pre>
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Alwayly_Mymodule',
__DIR__
);
</pre>
<h2>创建前端布局文件</h2><p>在<strong>app/code/Alwayly/Mymodule/view/frontend/layout</strong>中创建<strong>catalog_product_view.xml</strong>并将此代码添加：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
&lt;body&gt;
&lt;referenceBlock name="product.info.details"&gt;
&lt;block class="Magento\Catalog\Block\Product\View" name="tab.tab" template="Alwayly_Mymodule::extra_tab.phtml" group="detailed_info" &gt;
&lt;arguments&gt;
&lt;argument translate="true" name="title" xsi:type="string"&gt;Extra Tab&lt;/argument&gt;
&lt;/arguments&gt;
&lt;/block&gt;
&lt;/referenceBlock&gt;
&lt;/body&gt;
&lt;/page&gt;
</pre>
<h2>创建模板文件</h2><p>在<strong>app/code/Alwayly/Mymodule/view/frontend/templates</strong>中创建<strong>extra_tab.phtml</strong>文件并将此代码粘贴到其中：<strong></strong></p>
<pre>
&lt;?php
$product = $block->getProduct();
?>
&lt;h1 style="color: #ff6e17"&gt;&lt;?php echo $product-&gt;getData('tab'); ?&gt;&lt;/h1&gt;
</pre>
<p>现在我们需要运行命令。</p><p><strong>注意：</strong>以下所有命令都必须在Magento 2的根目录中运行。</p><p>运行此命令：</p>
<pre>php bin/magento module:status</pre>
<p>如果您在禁用列表中找到该模块，则必须通过运行以下命令来启用它：</p>
<pre>
php bin/magento module:enable Alwayly_Mymodule
</pre>
<p>最后，只需运行下面这些命令：</p>
<pre>
php bin/magento setup:upgrade

php bin/magento cache:clean

php bin/magento cache:clean
</pre>
<p>打开网站的产品页面，您将看到以下的自定义标签：</p><p><img src="https://www.360magento.com/media/wysiwyg/blog_240/output-1.png" alt="Magento 2中添加了自定义选项卡" />]]></description>
      <pubDate>Fri, 21 Jun 2019 11:44:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用KnockoutJS在Magento 2中添加数量加减按钮]]></title>
      <link>https://www.360magento.com/blog/m2-add-qty-increment/</link>
      <description><![CDATA[<p>Knockout是一个遵循<strong>MVVM</strong>（模型 - 视图 - 视图 - 模型）模式的javascript库，用于创建前端。您可以使用Knockout JS轻松处理复杂的数据驱动接口，并且由于它是开源的，因此可以免费使用。</p>
<p>Knockout JS是轻量级的，主要用在Magento 2的结帐页面。但是Knockout JS在Magento 2中实现起来有点复杂，因此，本教程将教你如何在Magento 2产品页面上中实现Knockout JS。</p><p>Magento 2在产品页面上提供了一个简单的数量输入文本，为了使客户更容易操作，您可以在Magento 2中添加增量和减量按钮。我将使用自定义模块实现它，<p>开始吧！</p>
<h2>配置模块</h2>
<p>通过在<strong>app/code/Alwayly/AddQuantityIncrement/etc</strong>中创建<strong>module.xml</strong>文件来配置模块。在其中添加以下代码：
<pre>
	&lt;?xml version="1.0"?&gt;
	&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
	&lt;module name="Alwayly_AddQuantityIncrement" setup_version="1.0.0"&gt;&lt;/module&gt;
	&lt;/config&gt;
</pre>
<h2>模块注册</h2>
<p>现在通过在<strong>app/code/Alwayly/AddQuantityIncrement</strong>中创建<strong>registration.php</strong>来注册模块，并在其中添加以下代码：
<pre>
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
   \Magento\Framework\Component\ComponentRegistrar::MODULE,
   'Alwayly_AddQuantityIncrement',
   __DIR__
);
</pre>
<h2>复制addtocart.phtml</h2><p>从magento安装的根目录转到<strong>vendor/magento/module-catalog/view/frontend/templates/product/view</strong>并将<strong>addtocart.phtml</strong>复制到您自己的模块<strong>pp/code /Alwayly/AddQuantityIncrement/view/frontend/templates/catalog/product/view。</strong>该<strong>addtocart.phtml</strong>文件将是这样的：</p>
<pre>
&lt;?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
/** @var $block \Magento\Catalog\Block\Product\View */
?>

&lt;?php $_product = $block->getProduct(); ?&gt;
&lt;?php $buttonTitle = __('Add to Cart'); ?&gt;
&lt;?php if ($_product-&gt;isSaleable()): ?&gt;
&lt;div class="box-tocart"&gt;
   &lt;div class="fieldset"&gt;
       &lt;?php if ($block-&gt;shouldRenderQuantity()): ?&gt;
       &lt;div class="field qty"&gt;
           &lt;label class="label" for="qty"&gt;&lt;span&gt;&lt;?php /* @escapeNotVerified */ echo __('Qty') ?&gt;&lt;/span&gt;&lt;/label&gt;
           &lt;div class="control"&gt;
               &lt;input type="number"
                      name="qty"
                      id="qty"
                      maxlength="12"
                      value="&lt;?php /* @escapeNotVerified */ echo $block-&gt;getProductDefaultQty() * 1 ?&gt;"
                      title="&lt;?php /* @escapeNotVerified */ echo __('Qty') ?&gt;" class="input-text qty"
                      data-validate="&lt;?php echo $block-&gt;escapeHtml(json_encode($block-&gt;getQuantityValidators())) ?&gt;"
                      /&gt;
           &lt;/div&gt;
       &lt;/div&gt;
       &lt;?php endif; ?&gt;
       &lt;div class="actions"&gt;
           &lt;button type="submit"
                   title="&lt;?php /* @escapeNotVerified */ echo $buttonTitle ?&gt;"
                   class="action primary tocart"
                   id="product-addtocart-button"&gt;
               &lt;span&gt;&lt;?php /* @escapeNotVerified */ echo $buttonTitle ?&gt;&lt;/span&gt;
           &lt;/button&gt;
           &lt;?php echo $block-&gt;getChildHtml('', true) ?&gt;
       &lt;/div&gt;
   &lt;/div&gt;
&lt;/div&gt;
&lt;?php endif; ?&gt;
&lt;script type="text/x-magento-init"&gt;
   {
       "#product_addtocart_form": {
           "Magento_Catalog/product/view/validation": {
               "radioCheckboxClosest": ".nested"
           }
       }
   }
&lt;/script&gt;
&lt;?php if (!$block-&gt;isRedirectToCartEnabled()) : ?&gt;
&lt;script type="text/x-magento-init"&gt;
   {
       "#product_addtocart_form": {
           "catalogAddToCart": {
               "bindSubmit": false
           }
       }
   }
&lt;/script&gt;
&lt;?php endif; ?&gt;
</pre>
<h2>编辑addtocart.phtml</h2>
<p>在<strong>addtocart.phtml中</strong>，创建一个UI组件并对其进行初始化。要做到这一点，首先在数量的input字段上方添加以下脚本：</p>
<pre>
&lt;script type="text/x-magento-init"&gt;
{
   "*": {
           "Magento_Ui/js/core/app": {
               "components": {
                   "qty_change": {
                       "component": "Alwayly_AddQuantityIncrement/js/view/product/view/qty_change",
                       "defaultQty": &lt;?php echo $block-&gt;getProductDefaultQty() * 1 ?&gt;
                   }
               }
           }
   }
}
&lt;/script&gt;
</pre>
<p>现在将组件<strong>qty_change</strong>与以下前端HTML连接：</p>
<pre>
&lt;div class="control" data-bind="scope: 'qty_change'"&gt;
   &lt;button data-bind="click: decreaseQty"&gt;-&lt;/button&gt;
   &lt;input  data-bind="value: qty()"
   type="number"
   name="qty"
   id="qty"
   maxlength="12"
   title="&lt;?php echo __('Qty') ?&gt;"
   class="input-text qty"
   data-validate="&lt;?php echo $block-&gt;escapeHtml(json_encode($block-&gt;getQuantityValidators())) ?&gt;"
   /&gt;
   &lt;button data-bind="click: increaseQty"&gt;+&lt;/button&gt;
&lt;/div&gt;
</pre>
<p><strong>Data-bind 属性</strong>：使用我们的组件qty_change的Javascript函数连接HTML。</p><p>在上面的代码中，有两个按钮，我通过使用Javascript点击事件连接到组件，将用于减少/增加数量值。最终的<strong>addtocart.phtml</strong>文件如下所示：</p>
<pre>
&lt;?php
/**
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
// @codingStandardsIgnoreFile
/** @var $block \Magento\Catalog\Block\Product\View */
?&gt;

&lt;?php $_product = $block-&gt;getProduct(); ?&gt;
&lt;?php $buttonTitle = __('Add to Cart'); ?&gt;
&lt;?php if ($_product-&gt;isSaleable()): ?&gt;
&lt;div class="box-tocart"&gt;
   &lt;div class="fieldset"&gt;
       &lt;?php if ($block-&gt;shouldRenderQuantity()): ?&gt;
       &lt;div class="field qty"&gt;
           &lt;label class="label" for="qty"&gt;&lt;span&gt;&lt;?php /* @escapeNotVerified */ echo __('Qty') ?&gt;&lt;/span&gt;&lt;/label&gt;

&lt;script type="text/x-magento-init"&gt;
{
   "*": {
           "Magento_Ui/js/core/app": {
               "components": {
                   "qty_change": {
                       "component": "Alwayly_AddQuantityIncrement/js/view/product/view/qty_change",
                       "defaultQty": &lt;?php echo $block-&gt;getProductDefaultQty() * 1 ?&gt;
                   }
               }
           }
   }
}
&lt;/script&gt;

&lt;div class="control" data-bind="scope: 'qty_change'"&gt;
   &lt;button data-bind="click: decreaseQty"&gt;-&lt;/button&gt;
   &lt;input  data-bind="value: qty()"
   type="number"
   name="qty"
   id="qty"
   maxlength="12"
   title="&lt;?php echo __('Qty') ?&gt;"
   class="input-text qty"
   data-validate="&lt;?php echo $block-&gt;escapeHtml(json_encode($block-&gt;getQuantityValidators())) ?&gt;"
   /&gt;

   &lt;button data-bind="click: increaseQty"&gt;+&lt;/button&gt;
&lt;/div&gt;
       &lt;/div&gt;
       &lt;?php endif; ?&gt;
       &lt;div class="actions"&gt;
           &lt;button type="submit"
                   title="&lt;?php /* @escapeNotVerified */ echo $buttonTitle ?&gt;"
                   class="action primary tocart"
                   id="product-addtocart-button"&gt;
               &lt;span&gt;&lt;?php /* @escapeNotVerified */ echo $buttonTitle ?&gt;&lt;/span&gt;
           &lt;/button&gt;
           &lt;?php echo $block-&gt;getChildHtml('', true) ?&gt;
       &lt;/div&gt;
   &lt;/div&gt;
&lt;/div&gt;
&lt;?php endif; ?&gt;
&lt;script type="text/x-magento-init"&gt;
   {
       "#product_addtocart_form": {
           "Magento_Catalog/product/view/validation": {
               "radioCheckboxClosest": ".nested"
           }
       }
   }
&lt;/script&gt;
&lt;?php if (!$block-&gt;isRedirectToCartEnabled()) : ?&gt;
&lt;script type="text/x-magento-init"&gt;
   {
       "#product_addtocart_form": {
           "catalogAddToCart": {
               "bindSubmit": false
           }
       }
   }
&lt;/script&gt;
&lt;?php endif; ?&gt;
</pre>
<h2>创建qty_change.js</h2><p>现在在<strong>app/code/Alwayly/AddQuantityIncrement/view/frontend/web/js/view/product/view</strong>中创建<strong>qty_change.js</strong>。在其中添加以下代码：</p>
<pre>
define([
   'ko',
   'uiComponent'
], function (ko, Component) {
   'use strict';
   return Component.extend({
       initialize: function () {
           //initialize parent Component
           this._super();
           this.qty = ko.observable(this.defaultQty);
       },
       decreaseQty: function() {
           var newQty = this.qty() - 1;
           if (newQty < 1) 
           {
               newQty = 1;
           }
           this.qty(newQty);
       },
       increaseQty: function() {
           var newQty = this.qty() + 1;
           this.qty(newQty);
       }
   });
});
</pre>
<h2>创建catalog_product_view.xml</h2><p>最后，只需在app/code/Alwayly/AddQuantityIncrement/view/frontend/layout中创建<strong>catalog_product_view.xml</strong>即可。在其中添加以下代码：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;body&gt;
       &lt;referenceBlock name="product.info.addtocart"&gt;
           &lt;action method="setTemplate"&gt;
               &lt;argument name="template" xsi:type="string"&gt;Alwayly_AddQuantityIncrement::catalog/product/view/addtocart.phtml&lt;/argument&gt;
           &lt;/action&gt;
       &lt;/referenceBlock&gt;
       &lt;referenceBlock name="product.info.addtocart.additional"&gt;
           &lt;action method="setTemplate"&gt;
               &lt;argument name="template" xsi:type="string"&gt;Alwayly_AddQuantityIncrement::catalog/product/view/addtocart.phtml&lt;/argument&gt;
           &lt;/action&gt;
       &lt;/referenceBlock&gt;
   &lt;/body&gt;
&lt;/page&gt;
</pre>
<p>上面代码的目的是更改默认的<strong>addtocart.phtml</strong>模板。</p>
<h2>运行命令</h2><p>使用SSH终端转到magento安装的根目录，然后运行以下命令：</p>
<pre>
rm -rf var/di var/generation var/cache/* var/log/* var/page_cache/*

php bin/magento module:enable Alwayly_AddQuantityIncrement

php bin/magento setup:upgrade

php bin/magento setup:di:compile

php bin/magento indexer:reindex

php bin/magento cache:clean

php bin/magento cache:flush
</pre>
<p>现在转到产品页面，您将看到结果：</p>
<p></p>
<p>Note:我们已在Magento 2.3上测试了上述代码.</p>]]></description>
      <pubDate>Wed, 19 Jun 2019 13:41:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento 2中将产品属性类型从文本更改为下拉列表]]></title>
      <link>https://www.360magento.com/blog/m2-change-product-attribute-type/</link>
      <description><![CDATA[<p>默认情况下，在Magento 2中，后台管理没有选项可以更改创建后的产品属性类型。因此，我们必须创建自定义脚本来更改产品属性类型。以下示例代码将帮助您将产品属性类型从文本更改为Magento 2中的下拉列表。</p>
<blockquote><p>另请阅读：&nbsp; <a href="//www.360magento.com/blog/m2-create-custom-attribute/">通过InstallData.php在Magento 2中创建自定义属性组和产品属性</a></p></blockquote>
<p>以下是我们在以下示例中遵循的步骤，</p>
<ul>
<li>将我们要更改的属性ID从文本更改为下拉列表</li>
<li>获取已存储在数据库中的给定属性Id的产品值</li>
<li>对于给定的属性Id，将先前存储的产品值作为选项插入数据库表“eav_attribute_option”和“eav_attribute_option_value”</li>
<li>使用选项Id将插入的属性选项分配给适当的产品</li>
<li>最后，使用UPDATE查询将属性类型从文本更改为数据库下拉列表</li>
</ul>
<pre>
&lt;?php
use Magento\Framework\App\Bootstrap;
 
/**
 * If the external file is in the root folder
 */
require __DIR__ . '/app/bootstrap.php';
 
$params = $_SERVER;
$bootstrap = Bootstrap::create(BP, $params);
$obj = $bootstrap->getObjectManager();
 
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');
  
/*
 * Instance of object manager
 */
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
 
/*
 * Attribute Id that we want to change from text to dropdown
 */
$attributeId = 155;  
 
$resource = $objectManager->get('Magento\Framework\App\ResourceConnection');
$connection = $resource->getConnection();
  
/*
 * Get the product values that are already stored in the database for given attribute
 */
$catalog_product_entity_varchar = $resource->getTableName('catalog_product_entity_varchar');
$attribute_values = $connection->fetchAll("SELECT DISTINCT attribute_id, value FROM $catalog_product_entity_varchar where attribute_id = $attributeId"); 
if(!empty($attribute_values)) {
    foreach ($attribute_values as $_attribute_values) {
 
        $attribute_values = $connection->fetchRow("SELECT count(*) as cnt FROM `eav_attribute_option` where attribute_id = $attributeId;");
        $count = $attribute_values['cnt'] + 1;
 
        /*
         * Insert previously stored product values as an option on the database for a given attribute
         */
        $eav_attribute_option = $resource->getTableName('eav_attribute_option');
        $sql = "insert into $eav_attribute_option(option_id, attribute_id, sort_order) values (null, $attributeId, $count)";
        try {
            $resp = $connection->query($sql);
        } catch (Exception $e) {
            echo '<pre>';  print_r($e->getMessage());
        }
        $lastInsertId = $connection->lastInsertId();
 
        $eav_attribute_option_value = $resource->getTableName('eav_attribute_option_value');
        $sql = "insert into $eav_attribute_option_value(value_id, option_id, store_id, value) values (null, $lastInsertId, 0, '$_attribute_values[value]')";
        try {
            $resp = $connection->query($sql);
        } catch (Exception $e) {
            echo '<pre>';  print_r($e->getMessage());
        }
 
        $sql = "insert into $eav_attribute_option_value(value_id, option_id, store_id, value) values (null, $lastInsertId, 1, '$_attribute_values[value]')";
        try {
            $resp = $connection->query($sql);
        } catch (Exception $e) {
            echo '<pre>';  print_r($e->getMessage());
        }
    }
}
  
$catalog_product_entity_varchar = $resource->getTableName('catalog_product_entity_varchar');
$attribute_values = $connection->fetchAll("SELECT * FROM $catalog_product_entity_varchar where attribute_id = $attributeId"); 
if(!empty($attribute_values)) {
    foreach ($attribute_values as $_attribute_values) {
 
        /*
         * Get the option id for the specific product
         */
        $option_values = $connection->fetchRow("SELECT * FROM `eav_attribute_option` as eao INNER JOIN `eav_attribute_option_value` as eaov on eao.option_id = eaov.option_id WHERE eao.attribute_id = $attributeId and eaov.store_id = 1 and eaov.value = '$_attribute_values[value]'");
 
        if(!empty($option_values)) {
            $catalog_product_entity_int = $resource->getTableName('catalog_product_entity_int');
            $product_values_exist = $connection->fetchRow("SELECT value_id FROM $catalog_product_entity_int WHERE attribute_id = $attributeId and entity_id = $_attribute_values[entity_id]");
 
            if(empty($product_values_exist)) {
                $sql = "insert into $catalog_product_entity_int(value_id, attribute_id, store_id, entity_id, value) values (null, $attributeId, 0, $_attribute_values[entity_id], $option_values[option_id])";
                try {
                    $resp = $connection->query($sql);
                } catch (Exception $e) {
                    echo '<pre>';  print_r($e->getMessage());
                }
            } else {
                $sql = "Update $catalog_product_entity_int set value = $option_values[option_id] WHERE attribute_id = $attributeId and entity_id = $_attribute_values[entity_id]";
                try {
                    $resp = $connection->query($sql);
                } catch (Exception $e) {
                    echo '<pre>';  print_r($e->getMessage());
                }
            }
        }
    }
}
  
/*
 * Change the attribute type from text to dropdown on database
 */
$eav_attribute = $resource->getTableName('eav_attribute');
$sql = "UPDATE $eav_attribute SET `backend_type` = 'int', `frontend_input` = 'select', `source_model` = 'Magento\\\Eav\\\Model\\\Entity\\\Attribute\\\Source\\\Table' WHERE `attribute_id` = $attributeId";
try {
    $resp = $connection->query($sql);
} catch (Exception $e) {
    echo '<pre>'; print_r($e->getMessage());
}
  
$catalog_eav_attribute = $resource->getTableName('catalog_eav_attribute');
$sql = "UPDATE $catalog_eav_attribute SET `is_filterable` = 1, is_comparable = 1, is_visible_on_front = 1, is_html_allowed_on_front = 1, is_filterable_in_search = 1, used_in_product_listing = 1 WHERE `attribute_id` = $attributeId";
try {
    $resp = $connection->query($sql);
} catch (Exception $e) {
    echo '<pre>'; print_r($e->getMessage());
}
</pre>
<p>希望这可以帮助到你。</p>]]></description>
      <pubDate>Mon, 17 Jun 2019 05:11:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2通过安装脚本创建属性组和产品属性]]></title>
      <link>https://www.360magento.com/blog/m2-create-custom-attribute/</link>
      <description><![CDATA[<p>在Magento 2中，我们可以在后台上创建许多产品属性和属性组。但有时我们可能需要通过可安装脚本创建新的产品属性和属性组。例如，当我们在Magento 2中开发新扩展或自定义Magento 2的原生功能时，我们必须使用可安装脚本来创建新的产品属性和属性组。创建产品属性和属性组不是一件困难的事，本文将帮助您通过InstallData.php在Magento 2中创建新的属性组和产品属性。</p>
<p>假设我们将使用以下脚本创建一个名为&ldquo;My Custom Attribute Group&rdquo;的新属性组和名为&ldquo;My Sample Attribute&rdquo;的产品属性。</p>
<h3>第1步：定义新模块</h3>
<p>为了在Magento 2中创建新的扩展，首先我们必须在下面的文件路径中创建一个名为<strong>module.xml</strong>的文件来定义新模块，</p>
<p><em>文件路径：app/code/Alwayly/MyAttribute/etc/module.xml</em></p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_MyAttribute" setup_version="1.0.0"&gt;
        &lt;sequence&gt;
            &lt;module name="Magento_Catalog"/&gt;
        &lt;/sequence&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>
<p>接下来，在下面的文件路径中创建<strong>registration.php</strong>文件，</p>
<p><em>文件路径：app/code/Alwayly/MyAttribute/registration.php</em></p>
<pre>&lt;?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'Alwayly_MyAttribute',
        __DIR__
    );
</pre>
<h3>第2步：创建安装文件InstallData.php</h3>
<p>然后，在以下文件路径中创建名为<strong>InstallData.php</strong>的文件。在此文件中，我们必须提供新创建的产品属性组的名称和属性信息，</p>
<p><em>文件路径：app/code/Alwayly/MyAttribute/Setup/InstallData.php</em></p>
<pre>&lt;?php
namespace Alwayly\MyAttribute\Setup;
  
use Magento\Eav\Setup\EavSetup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Eav\Model\Config;
  
class InstallData implements InstallDataInterface
{
    private $eavSetupFactory;
   
    public function __construct(EavSetupFactory $eavSetupFactory, Config $eavConfig)
    {
        $this-&gt;eavSetupFactory = $eavSetupFactory;
        $this-&gt;eavConfig = $eavConfig;
    }
  
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $eavSetup = $this-&gt;eavSetupFactory-&gt;create(['setup' =&gt; $setup]);
  
        $eavSetup-&gt;addAttribute(
            \Magento\Catalog\Model\Product::ENTITY,
            'my_sample_attribute',
            [
                'group' =&gt; 'My Custom Attribute Group',
                'type' =&gt; 'varchar',
                'backend' =&gt; '',
                'frontend' =&gt; '',
                'label' =&gt; 'My Sample Attribute',
                'input' =&gt; 'text',
                'note' =&gt; 'My Sample Attribute',
                'class' =&gt; '',
                'source' =&gt; '',
                'global' =&gt; \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
                'visible' =&gt; true,
                'required' =&gt; false,
                'user_defined' =&gt; true,
                'default' =&gt; '',
                'searchable' =&gt; false,
                'filterable' =&gt; false,
                'comparable' =&gt; false,
                'visible_on_front' =&gt; true,
                'used_in_product_listing' =&gt; true,
                'unique' =&gt; false,
                'apply_to' =&gt; 'simple'
            ]
        );
    }
}
</pre>
<h3>第3步：模块设置升级</h3>
<p>最后，我们必须通过在Magento安装的根目录中运行以下SSH命令来启用我们的新扩展，</p>
<blockquote>
<p>php magento module:enable Alwayly_MyAttribute</p>
</blockquote>
<p>然后，在CLI中运行以下命令以升级设置，</p>
<blockquote>
<p>php magento setup:upgrade</p>
</blockquote>
<p>然后，清除缓存并检查您的Magento 2管理员。现在，您可以在管理端查看新创建的产品属性组和产品属性，如下面的参考截图。</p>
<p>参考截图：</p>
<p><img alt="Magento创建属性组和产品属性" src="https://www.360magento.com/media/wysiwyg/blog_236/Create-Custom-Attribute-Group-Product-Attribute-in-Magento-2-via-InstallData.php_.png" /></p>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Sat, 15 Jun 2019 13:53:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2中使用安装/升级脚本创建数据库表]]></title>
      <link>https://www.360magento.com/blog/m2-create-database-table/</link>
      <description><![CDATA[<p>如果要在Magento 2中创建新的自定义模块，在某些情况下，您可能需要创建新的数据库表，修改现有的数据库表，并且可能需要在数据库表中设置一些初始缺省值。您可以通过在Magento 2中创建安装/升级脚本来实现此目的。</p>
<p>以下是安装/升级SQL脚本的列表</p>
<ul>
<li>InstallSchema</li>
<li>InstallData</li>
<li>UpgradeSchema</li>
<li>UpgradeData</li>
<li>Recurring</li>
<li>Uninstall</li>
</ul>
<p>所有这些类都将位于<strong>app/code/<Vendor>/<Module>/Setup</strong>文件夹中。</p>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup</em></p>
<p>在CLI中运行以下命令时，将运行模块的安装/升级脚本：</p>
<blockquote><p>php bin/magento setup:upgrade</p></blockquote>
<h3>InstallSchema：</h3>
<p>InstallSchema用于更改数据库模式，这意味着创建新数据库表或修改现有数据库表结构。InstallSchema类将在模块安装期间运行。</p>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup/InstallSchema.php</em></p>
<pre>
&lt;?php
 
namespace Alwayly\CustomScript\Setup;
 
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class InstallSchema implements InstallSchemaInterface
{
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        if (!$installer->tableExists('comments')) {
            $table = $installer->getConnection()
                     ->newTable($installer->getTable('comments'))
                     ->addColumn(
                         'comment_id',
                         \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                         null,
                         [
                             'identity' => true,
                             'nullable' => false,
                             'primary'  => true,
                             'unsigned' => true,
                         ],
                         'ID'
                     )
                     ->addColumn(
                         'name',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                         255,
                         ['nullable => false'],
                         'Name'
                     )
                     ->addColumn(
                         'email',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                         255,
                         [],
                         'Email'
                     )
                     ->addColumn(
                         'url_key',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                         255,
                         [],
                         'URL Key'
                     )
                     ->addColumn(
                         'message',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                         '18K',
                         [],
                         'Message'
                     )
                     ->addColumn(
                         'status',
                         \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
                         1,
                         [],
                         'Comment Status'
                     )
                     ->addColumn(
                         'created_at',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                         null,
                         ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
                         'Created At'
                     )->addColumn(
                         'updated_at',
                         \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
                         null,
                         ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
                         'Updated At')
                     ->setComment('Comments Table');
            $installer->getConnection()->createTable($table);
 
            $installer->getConnection()->addIndex(
                $installer->getTable('comments'),
                $setup->getIdxName(
                    $installer->getTable('comments'),
                    ['name', 'email', 'url_key', 'message'],
                    \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
                ),
                ['name', 'email', 'url_key', 'message'],
                \Magento\Framework\DB\Adapter\AdapterInterface::INDEX_TYPE_FULLTEXT
            );
        }
        $installer->endSetup();
    }
}
</pre>
<p>InstallSchema安装程序类文件必须继承<strong>\Magento\Framework\Setup\InstallSchemaInterface</strong>并且必须具有一个带有2个参数SchemaSetupInterface和ModuleContextInterface的公共方法<strong>install（）</strong>。</p>
<ul>
<li><strong>SchemaSetupInterface：</strong>它是一个设置对象，它提供了与数据库服务器交互的机制。</li>
<li><strong>ModuleContextInterface：</strong>它有一个名为getVersion（）的方法，用于获取模块的当前版本。</li>
</ul>
<h3>InstallData：</h3>
<p>InstallData用于将数据添加到数据库表。InstallData类也将在模块安装期间运行。但它将在InstallSchema类之后运行。</p>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup/InstallData.php</em></p>
<pre></pre>
<h3>UpgradeSchema：</h3>
<p>UpgradeSchema用于创建或修改现有模块的数据库表。安装脚本和升级脚本之间的主要区别在于，安装脚本将在模块首次安装期间运行。但升级脚本将在每次模块升级时运行。</p>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup/UpgradeSchema.php</em></p>
<pre>
<?php
 
namespace Alwayly\CustomScript\Setup;
 
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) {
        $installer = $setup;
 
        $installer->startSetup();
 
        if(version_compare($context->getVersion(), '1.0.1', '<')) {
            $installer->getConnection()->addColumn(
                $installer->getTable( 'comments' ),
                'user_image',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
                    'nullable' => true,
                    'length' => '254',
                    'comment' => 'Image',
                    'after' => 'url_key'
                ]
            );
        }
 
        $installer->endSetup();
    }
}
</pre>
<p>UpgradeSchema安装程序类文件必须继承<strong>\Magento\Framework\Setup\UpgradeSchemaInterface，</strong> &nbsp;并且必须具有一个带有2个参数SchemaSetupInterface和ModuleContextInterface的公共方法<strong>upgrade（）</strong>。</p>
<h3>UpgradeData：</h3>
<p>UpgradeData用于添加/删除数据库表中的数据。这与UpgradeSchema类相同。</p>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup/UpgradeData.php</em></p>
<pre>
&lt;?php
 
namespace Alwayly\CustomScript\Setup;
 
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class UpgradeData implements UpgradeDataInterface
{
 
    protected $_commentFactory;
 
    public function __construct(\Alwayly\CustomScript\Model\CommentFactory $commentFactory)
    {
        $this->_commentFactory = $commentFactory;
    }
 
    public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        if (version_compare($context->getVersion(), '1.0.1', '<')) {
            $data = [
                'name' => 'Thomus Raj',
                'email' => 'roni_cost@xample.com',
                'url_key' => 'https://www.360magento.com',
                'message' => 'My first comment',
                'status' => 1
            ];
            $post = $this->_commentFactory->create();
            $post->addData($data)->save();
        }
    }
}
</pre>
<h3>Uninstall：</h3>
<p><em>示例文件路径：app/code/Alwayly/CustomScript/Setup/Uninstall.php</em></p>
<pre>
&lt;?php
 
namespace Alwayly\CustomScript\Setup;
 
use Magento\Framework\Setup\UninstallInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\Setup\ModuleContextInterface;
 
class Uninstall implements UninstallInterface
{
    public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
 
        $installer->getConnection()->dropTable($installer->getTable('comments'));
 
        $installer->endSetup();
    }
}
</pre>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Wed, 12 Jun 2019 09:59:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2添加额外费用到订单总计]]></title>
      <link>https://www.360magento.com/blog/m2-add-extra-fee-to-order-totals/</link>
      <description><![CDATA[<p>有时我们可能需要在Magento 2中为订单总额添加额外费用（手续费）。通常，订单总计包括小计，运费，税金和折扣，根据这些值计算总计。现在，如果我们想增加额外的费用，它将影响订单总额。在本文中，我们将指导您如何在没有任何问题的情况下为Magento 2订单额外收费。</p>
<p>在这里，我们将添加一个名为“处理费”的新订单总额，固定成本为10美元。</p>
<p><strong>第1步：</strong>定义新模块，</p>
<p>在以下文件路径中创建<strong>module.xml</strong>文件以定义新模块，</p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/etc/module.xml</em></p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_HandlingFee" setup_version="1.0.0"&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>
<p>接下来，在下面的文件路径中创建<strong>registration.php</strong>文件，</p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/registration.php</em></p>
<pre>
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Alwayly_HandlingFee',
    __DIR__
);
</pre>
<p><strong>第2步：</strong> &nbsp;在以下路径中创建文件<strong>sales.xml</strong>，</p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/etc/sales.xml</em></p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd"&gt;
    &lt;section name="quote"&gt;
        &lt;group name="totals"&gt;
            &lt;item name="handlingfee" instance="Alwayly\HandlingFee\Model\Quote\Address\Total\HandlingFee" sort_order="400"/&gt;
        &lt;/group&gt;
    &lt;/section&gt;
&lt;/config&gt;
</pre>
<p><strong>步骤3</strong>：&nbsp;在以下路径中创建文件<strong>HandlingFee.php</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/Model/Quote/Address/Total/HandlingFee.php</em></p>
<pre>
&lt;?php
namespace Alwayly\HandlingFee\Model\Quote\Address\Total;
class HandlingFee extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
{
    /**
     * @var \Magento\Framework\Pricing\PriceCurrencyInterface
     */
    protected $_priceCurrency;
  
    /**
     * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
     */
    public function __construct(
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
    ) {
        $this->_priceCurrency = $priceCurrency;
    }
  
    public function collect(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
        \Magento\Quote\Model\Quote\Address\Total $total
    ) {
        parent::collect($quote, $shippingAssignment, $total);
        $handlingFee = 10;
        $total->addTotalAmount('handlingfee', $handlingFee);
        $total->addBaseTotalAmount('handlingfee', $handlingFee);
        $quote->setHandlingFee($handlingFee);
        return $this;
    }
  
    public function fetch(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Quote\Model\Quote\Address\Total $total
    ) {
        return [
            'code' => 'Handling_Fee',
            'title' => $this->getLabel(),
            'value' => 10
        ];
    }
  
    /**
     * get label
     * @return string
     */
    public function getLabel() {
        return __('Handling Fee');
    }
}
</pre>
<p><strong>步骤4</strong>：在以下路径中创建文件<strong>checkout_cart_index.xml</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/layout/checkout_cart_index.xml</em></p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;referenceBlock name="checkout.cart.totals"&gt;
            &lt;arguments&gt;
                &lt;argument name="jsLayout" xsi:type="array"&gt;
                    &lt;item name="components" xsi:type="array"&gt;
                        &lt;item name="block-totals" xsi:type="array"&gt;
                            &lt;item name="children" xsi:type="array"&gt;
                                &lt;item name="handlingfee" xsi:type="array"&gt;
                                    &lt;item name="component" xsi:type="string"&gt;Alwayly_HandlingFee/js/view/checkout/summary/handling-fee&lt;/item&gt;
                                    &lt;item name="sortOrder" xsi:type="string"&gt;20&lt;/item&gt;
                                    &lt;item name="config" xsi:type="array"&gt;
                                        &lt;item name="handlingfee" xsi:type="string" translate="true"&gt;Handling Fee&lt;/item&gt;
                                    &lt;/item&gt;
                                &lt;/item&gt;
                            &lt;/item&gt;
                        &lt;/item&gt;
                    &lt;/item&gt;
                &lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
    &lt;/body&gt;
&lt;/page&gt;
</pre>
<p><strong>步骤5</strong>：在同一路径中创建文件<strong>checkout_index_index.xml</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/layout/checkout_index_index.xml</em></p>
<pre>
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;referenceBlock name="checkout.root"&gt;
            &lt;arguments&gt;
                &lt;argument name="jsLayout" xsi:type="array"&gt;
                    &lt;item name="components" xsi:type="array"&gt;
                        &lt;item name="checkout" xsi:type="array"&gt;
                            &lt;item name="children" xsi:type="array"&gt;
                                &lt;item name="sidebar" xsi:type="array"&gt;
                                    &lt;item name="children" xsi:type="array"&gt;
                                        &lt;item name="summary" xsi:type="array"&gt;
                                            &lt;item name="children" xsi:type="array"&gt;
                                                &lt;item name="totals" xsi:type="array"&gt;
                                                    &lt;item name="children" xsi:type="array"&gt;
                                                        &lt;item name="handlingfee" xsi:type="array"&gt;
                                                            &lt;item name="component" xsi:type="string"&gt;Alwayly_HandlingFee/js/view/checkout/cart/totals/handling-fee&lt;/item&gt;
                                                            &lt;item name="sortOrder" xsi:type="string"&gt;20&lt;/item&gt;
                                                            &lt;item name="config" xsi:type="array"&gt;
                                                                &lt;item name="template" xsi:type="string"&gt;Alwayly_HandlingFee/checkout/cart/totals/handling-fee&lt;/item&gt;
                                                                &lt;item name="title" xsi:type="string" translate="true"&gt;Handling Fee&lt;/item&gt;
                                                            &lt;/item&gt;
                                                        &lt;/item&gt;
                                                    &lt;/item&gt;
                                                &lt;/item&gt;
                                                &lt;item name="cart_items" xsi:type="array"&gt;
                                                    &lt;item name="children" xsi:type="array"&gt;
                                                        &lt;item name="details" xsi:type="array"&gt;
                                                            &lt;item name="children" xsi:type="array"&gt;
                                                                &lt;item name="subtotal" xsi:type="array"&gt;
                                                                    &lt;item name="component" xsi:type="string"&gt;Magento_Tax/js/view/checkout/summary/item/details/subtotal&lt;/item&gt;
                                                                &lt;/item&gt;
                                                            &lt;/item&gt;
                                                        &lt;/item&gt;
                                                    &lt;/item&gt;
                                                &lt;/item&gt;
                                            &lt;/item&gt;
                                        &lt;/item&gt;
                                    &lt;/item&gt;
                                &lt;/item&gt;
                            &lt;/item&gt;
                        &lt;/item&gt;
                    &lt;/item&gt;
                &lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
    &lt;/body&gt;
&lt;/page&gt;
</pre>
<p><strong>第6步：</strong>在路径上创建文件<strong>handling-fee.js</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/web/js/view/checkout/cart/totals/handling-fee.js</em></p>
<pre>
define(
    [
        'Alwayly_HandlingFee/js/view/checkout/summary/handling-fee'
    ],
    function (Component) {
        'use strict';
        return Component.extend({
            /**
             * @override
             */
            isDisplayed: function () {
                return true;
            }
        });
    }
);
</pre>
<p><strong>步骤7：</strong>在以下路径中创建文件<strong>handling-fee.js</strong> .</p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/web/js/view/checkout/summary/handling-fee.js</em></p>
<pre>
define(
    [
        'jquery',
        'Magento_Checkout/js/view/summary/abstract-total',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/totals',
        'Magento_Catalog/js/price-utils'
    ],
    function ($,Component,quote,totals,priceUtils) {
        "use strict";
        return Component.extend({
            defaults: {
                template: 'Alwayly_HandlingFee/checkout/summary/handling-fee'
            },
            totals: quote.getTotals(),
               isDisplayedHandlingfeeTotal : function () {
               return true;
            },
            getHandlingfeeTotal : function () {
                var price = 10;
                return this.getFormattedPrice(price);
            }
        });
    }
);
</pre>
<p><strong>步骤8：</strong>在以下路径中创建文件<strong>handling-fee.html</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/web/template/checkout/cart/totals/handling-fee.html</em></p>
<pre>
<!-- ko if: isDisplayedHandlingfeeTotal() -->
<tr class="totals handling-fee excl">
    <th class="mark" colspan="1" scope="row" data-bind="text: title"></th>
    <td class="amount">
        <span class="price" data-bind="text: getHandlingfeeTotal()"></span>
    </td>
</tr>
<!-- /ko -->
</pre>
<p><strong>步骤9</strong>：在以下路径中创建文件<strong>handling-fee.html</strong></p>
<p><em>&lt;Magento_2_Root&gt; /app/code/Alwayly/HandlingFee/view/frontend/web/template/checkout/summary/handling-fee.html</em></p>
<pre>
<!-- ko if: isDisplayedHandlingfeeTotal() -->
<tr class="totals coupon-fee excl">
    <th class="mark" colspan="1" scope="row" data-bind="text: handlingfee"></th>
    <td class="amount">
        <span class="price" data-bind="text: getHandlingfeeTotal(), attr: {'data-th': handlingfee}"></span>
    </td>
</tr>
<!-- /ko -->
</pre>
<p>最后，您可以在购物车和结帐页面上看到额外的费用。</p>
<p>参考截图：</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_235/Magento-2-Add-Extra-Fee-To-Order-Totals.png" alt="Magento2添加额外费用到订单总计" /></p>]]></description>
      <pubDate>Tue, 11 Jun 2019 06:33:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento 2中创建自定义运输方式]]></title>
      <link>https://www.360magento.com/blog/m2-create-custom-shipping-method/</link>
      <description><![CDATA[<p>Magento 2已经有一些内置的运输方式。但在某些情况下，我们可能想在Magento 2中创建自己的运输方式。这不是一个困难的过程。我们可以非常轻松地在Magento 2中创建自定义运输方式。这篇博客可以帮助您在短时间内创建自己的自定义运输方式。</p>
<p>创建自定义运输方法的步骤：</p>
<ul>
<li>创建一个新模块</li>
<li>创建配置文件</li>
<li>定义运输模型</li>
<li>创建运输模型</li>
<li>模块安装</li>
</ul>
<h3>创建一个新模块：</h3>
<p>在下面的文件路径中创建一个&ldquo;registration.php&rdquo;文件来注册我们的新模块，</p>
<p><em>文件路径：&lt;Magento_2_Root&gt; /app/code/Alwayly/CustomShipping/registration.php</em></p>
<pre>&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Alwayly_CustomShipping',
    __DIR__
);
</pre>
<p>接下来，在下面的文件路径中创建一个&ldquo;module.xml&rdquo;文件来定义模块，</p>
<p><em>文件路径：&lt;Magento_2_Root&gt; /app/code/Alwayly/CustomShipping/etc/module.xml</em></p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_CustomShipping" setup_version="1.0.0"&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>
<h3>创建配置文件：</h3>
<p>在Magento 2中，每个运输方式都应该在管理面板中有配置选项。我们可以通过system.xml文件为我们的运输方式创建配置选项。</p>
<p><em>文件路径：&lt;Magento_2_Root&gt; /app/code/Alwayly/CustomShipping/etc/adminhtml/system.xml</em></p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"&gt;
    &lt;system&gt;
        &lt;section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
            &lt;group id="customshipping" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"&gt;
                &lt;label&gt;Custom Shipping Method&lt;/label&gt;
                &lt;field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"&gt;
                    &lt;label&gt;Enabled&lt;/label&gt;
                    &lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt;
                &lt;/field&gt;
                &lt;field id="price" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
                    &lt;label&gt;Shipping Cost&lt;/label&gt;
                    &lt;validate&gt;validate-number validate-zero-or-greater&lt;/validate&gt;
                &lt;/field&gt;
                &lt;field id="name" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"&gt;
                    &lt;label&gt;Method Name&lt;/label&gt;
                &lt;/field&gt;
                &lt;field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
                    &lt;label&gt;Sort Order&lt;/label&gt;
                &lt;/field&gt;
                &lt;field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"&gt;
                    &lt;label&gt;Title&lt;/label&gt;
                &lt;/field&gt;
                &lt;field id="sallowspecific" translate="label" type="select" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1"&gt;
                    &lt;label&gt;Ship to Applicable Countries&lt;/label&gt;
                    &lt;frontend_class&gt;shipping-applicable-country&lt;/frontend_class&gt;
                    &lt;source_model&gt;Magento\Shipping\Model\Config\Source\Allspecificcountries&lt;/source_model&gt;
                &lt;/field&gt;
                &lt;field id="specificcountry" translate="label" type="multiselect" sortOrder="91" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
                    &lt;label&gt;Ship to Specific Countries&lt;/label&gt;
                    &lt;source_model&gt;Magento\Directory\Model\Config\Source\Country&lt;/source_model&gt;
                    &lt;can_be_empty&gt;1&lt;/can_be_empty&gt;
                &lt;/field&gt;
                &lt;field id="showmethod" translate="label" type="select" sortOrder="92" showInDefault="1" showInWebsite="1" showInStore="0"&gt;
                    &lt;label&gt;Show Method if Not Applicable&lt;/label&gt;
                    &lt;source_model&gt;Magento\Config\Model\Config\Source\Yesno&lt;/source_model&gt;
                    &lt;frontend_class&gt;shipping-skip-hide&lt;/frontend_class&gt;
                &lt;/field&gt;
                &lt;field id="specificerrmsg" translate="label" type="textarea" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1"&gt;
                    &lt;label&gt;Displayed Error Message&lt;/label&gt;
                &lt;/field&gt;
            &lt;/group&gt;
        &lt;/section&gt;
    &lt;/system&gt;
&lt;/config&gt;
</pre>
<h3>定义运输模型：</h3>
<p>现在在下面的路径中创建一个&ldquo;config.xml&rdquo;文件，并为我们的自定义运输方式设置默认配置，</p>
<p><em>文件路径：&lt;Magento_2_Root&gt; /app/code/Alwayly/CustomShipping/etc/config.xml</em></p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"&gt;
    &lt;default&gt;
        &lt;carriers&gt;
            &lt;customshipping&gt;
                &lt;active&gt;0&lt;/active&gt;
                &lt;sallowspecific&gt;0&lt;/sallowspecific&gt;
                &lt;price&gt;0&lt;/price&gt;
                &lt;model&gt;Alwayly\CustomShipping\Model\Carrier\Customshipping&lt;/model&gt;
                &lt;name&gt;Custom Shipping&lt;/name&gt;
                &lt;title&gt;Custom Shipping&lt;/title&gt;
                &lt;specificerrmsg&gt;This shipping method is not available. To use this shipping method, please contact us.&lt;/specificerrmsg&gt;
            &lt;/customshipping&gt;
        &lt;/carriers&gt;
    &lt;/default&gt;
&lt;/config&gt;
</pre>
<p>这里，&lt;default&gt;是父节点，其子节点是&lt;carriers&gt;，&lt;customshipping&gt;是我们的运输方式代码。&lt;model&gt;是重要的一个，在这个&lt;model&gt;标签中，我们应该定义我们的运输模型类。</p>
<h3>创建运输模型：</h3>
<p>在&ldquo;config.xml&rdquo;上定义运输模型后，我们需要在下面的文件路径中创建运输模型类&ldquo;Customshipping.php&rdquo;，</p>
<p><em>文件路径：&lt;Magento_2_Root&gt; /app/code/Alwayly/CustomShipping/Model/Carrier/Customshipping.php</em></p>
<pre>&lt;?php
namespace Alwayly\CustomShipping\Model\Carrier;
 
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\DataObject;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Config;
use Magento\Shipping\Model\Rate\ResultFactory;
use Magento\Store\Model\ScopeInterface;
use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
use Magento\Quote\Model\Quote\Address\RateResult\Method;
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Psr\Log\LoggerInterface;
 
class Customshipping extends AbstractCarrier implements CarrierInterface
{
     
    /**
     * @var string
     */
    protected $_code = 'customshipping';
 
    /**
     * @var bool
     */
    protected $_isFixed = true;
 
    /**
     * @var ResultFactory
     */
    protected $_rateResultFactory;
 
    /**
     * @var MethodFactory
     */
    protected $_rateMethodFactory;
 
    /**
     * @param ScopeConfigInterface $scopeConfig
     * @param ErrorFactory $rateErrorFactory
     * @param LoggerInterface $logger
     * @param ResultFactory $rateResultFactory
     * @param MethodFactory $rateMethodFactory
     * @param array $data
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        ErrorFactory $rateErrorFactory,
        LoggerInterface $logger,
        ResultFactory $rateResultFactory,
        MethodFactory $rateMethodFactory,
        array $data = []
    ) {
        $this-&gt;_rateResultFactory = $rateResultFactory;
        $this-&gt;_rateMethodFactory = $rateMethodFactory;
        parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
    }
 
    /**
     * @return array
     * @api
     */
    public function getAllowedMethods()
    {
        return [$this-&gt;getCarrierCode() =&gt; __($this-&gt;getConfigData('name'))];
    }
 
    /**
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     * @param RateRequest $request
     * @return DataObject|bool|null
     * @api
     */
    public function collectRates(RateRequest $request)
    {
        /**
         * Make sure that shipping method is enabled
         */
        if (!$this-&gt;isActive()) {
            return false;
        }
 
        /** @var \Magento\Shipping\Model\Rate\Result $result */
        $result = $this-&gt;_rateResultFactory-&gt;create();
        $shippingPrice = $this-&gt;getConfigData('price');
        $method = $this-&gt;_rateMethodFactory-&gt;create();
 
        /**
         * Set carrier's method data
         */
        $method-&gt;setCarrier($this-&gt;getCarrierCode());
        $method-&gt;setCarrierTitle($this-&gt;getConfigData('title'));
 
        /**
         * Displayed as shipping method under Carrier
         */
        $method-&gt;setMethod($this-&gt;getCarrierCode());
        $method-&gt;setMethodTitle($this-&gt;getConfigData('name'));
        $method-&gt;setPrice($shippingPrice);
        $method-&gt;setCost($shippingPrice);
        $result-&gt;append($method);
        return $result;
    }
}
</pre>
<p><strong>注意：</strong></p>
<ul>
<li>在Magento 2中，每个运输类都应继承<strong>\Magento\Shipping\Model\Carrier\AbstractCarrier</strong>并实现<strong>\Magento\Shipping\Model\Carrier\CarrierInterface</strong>类。</li>
<li><strong>$ _code</strong>的值应与system.xml中的group id相同。</li>
<li>抽象类和接口需要两个函数<strong>getAllowedMethods</strong>和<strong>collectRates</strong>。</li>
<li>在函数collectRates中，我们必须为自定义运费计算实现所有逻辑。</li>
</ul>
<h3>模块安装：</h3>
<p>最后，我们必须启用扩展并安装它。为此，转到[magento_root]/bin目录并在CLI中运行以下命令，</p>
<blockquote>
<p>php magento module:enable Alwayly_CustomShipping</p>
</blockquote>
<p>然后，在CLI中运行以下命令以安装模块，</p>
<blockquote>
<p>php magento setup:upgrade</p>
</blockquote>
<p>然后，使用以下CLI命令清除缓存，</p>
<blockquote>
<p>php magento c:c</p>
</blockquote>
<p>现在，登录到Magento 2管理面板，导航到<strong>STORES</strong> &gt; <strong>Configuration</strong>，从左侧面板展开<strong>SALES</strong>部分，然后单击<strong>Shipping Methods</strong>。您可以看到我们的自定义运输方式配置页面如下，</p>
<p><img alt="Magento2自定义运输方式" src="https://www.360magento.com/media/wysiwyg/blog_234/How-to-Create-Custom-Shipping-Method-in-Magento-2-1-768x471.png" /></p>
<p>在这里，您可以启用我们的自定义运输方式，并根据您的需要设置配置值。</p>
<p>完成配置我们的送货方式后，运输计算将显示在结帐页面上，如下所示，</p>
<p><img alt="Magento2自定义运输方式" src="https://www.360magento.com/media/wysiwyg/blog_234/How-to-Create-Custom-Shipping-Method-in-Magento-2.png" /></p>
<p>最后，运输方式将应用于结账页面，结果将显示如下，</p>
<p><img alt="Magento2自定义运输方式" src="https://www.360magento.com/media/wysiwyg/blog_234/How-to-Create-Custom-Shipping-Method-in-Magento-2-2.png" /></p>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Fri, 07 Jun 2019 09:56:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[通过命令行在Magento 2中创建新的管理员用户]]></title>
      <link>https://www.360magento.com/blog/m2-create-admin-user-via-command/</link>
      <description><![CDATA[<p>通过命令行界面创建一个新的管理员用户是Magento 2中的一个重要功能。当我们忘记Magento 2管理员密码时，这是非常有用和快速的解决方案。</p>
<h3>通过命令行创建管理员用户</h3>
<p>以下是CLI命令，可帮助您在Magento 2中创建新的管理员用户，在Magento 2安装的根目录的路径中运行以下命令，</p>
<pre>php bin/magento admin:user:create --admin-user="admin" --admin-password="Admin@123" --admin-email="admin@360magento.com" --admin-firstname="MyFirstName" --admin-lastname="MyLastName"
</pre>
<p>创建管理员用户帐户后，上面的命令将返回以下成功消息，</p>
<blockquote>
<p>Created Magento administrator user named admin</p>
</blockquote>
<p>当我们在CLI中运行上述命令时，将执行以下文件以创建新的管理员用户，</p>
<p><em>&lt;Magento 2安装根目录&gt; /vendor/magento/magento2-base/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php</em></p>
<p>您还可以从命令行&ldquo;interactively&rdquo;创建管理员用户，该用户包含在最新版本的magento中。 </p>
<p>以下是创建新管理员用户的命令，</p>
<pre>php bin/magento admin:user:create</pre>
<p>它将提示您逐个输入以下必填字段。</p>
<ul>
<li><strong>Admin user：</strong> Magento管理员用户的名字。</li>
<li><strong>Admin password：</strong> Magento管理员用户的姓氏。</li>
<li><strong>Admin email：</strong> Magento管理员用户的电子邮件地址。</li>
<li><strong>Admin first name：</strong> Magento管理员用户名。</li>
<li><strong>Admin last name：</strong> Magento管理员用户密码长度必须至少为7个字符，并且必须至少包含一个字母和至少一个数字字符。</li>
</ul>
<p>这很简单，很酷。</p>
<h3>通过命令行解锁管理员用户</h3>
<p>有时管理员帐户将因多次不正确的登录尝试而锁定。使用以下命令解锁这些类型的管理员用户帐户。</p>
<pre>php bin/magento admin:user:unlock {username}</pre>
<p>例，</p>
<pre>php bin/magento admin:user:unlock admin</pre>
<p>上面的命令将返回以下成功消息，</p>
<blockquote>
<p>The user account &ldquo;admin&rdquo; has been unlocked</p>
</blockquote>
<p>在命令行界面中运行以下命令，以获取在Magento 2中创建管理员用户的所有选项列表，</p>
<pre>php bin/magento admin:user:create --help</pre>
<p>它将返回如下输出，</p>
<pre>Usage:
   admin:user:create [options]
 Options:
       --admin-user=ADMIN-USER                    (Required) Admin user
       --admin-password=ADMIN-PASSWORD            (Required) Admin password
       --admin-email=ADMIN-EMAIL                  (Required) Admin email
       --admin-firstname=ADMIN-FIRSTNAME          (Required) Admin first name
       --admin-lastname=ADMIN-LASTNAME            (Required) Admin last name
       --magento-init-params=MAGENTO-INIT-PARAMS  Add to any command to customize Magento initialization parameters
                                                  For example: "MAGE_MODE=developer&amp;MAGE_DIRS[base][path]=/var/www/example.com&amp;MAGE_DIRS[cache][path]=/var/tmp/cache"
   -h, --help                                     Display this help message
   -q, --quiet                                    Do not output any message
   -V, --version                                  Display this application version
       --ansi                                     Force ANSI output
       --no-ansi                                  Disable ANSI output
   -n, --no-interaction                           Do not ask any interactive question
   -v|vv|vvv, --verbose                           Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 Help:
   Creates an administrator
</pre>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Wed, 05 Jun 2019 08:21:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2创建新用户管理角色权限步骤]]></title>
      <link>https://www.360magento.com/blog/m2-create-new-user-role/</link>
      <description><![CDATA[<p>大多数在线商城平台都有多个管理员用户，如平台所有者，客户服务经理，销售代表等，以简化他们的商店管理流程。此类在线平台的所有者可能希望根据其角色限制管理员用户。为了实现这一目标，Magento 2具有“User Roles”的内置功能，允许平台所有者根据需要为特定的管理员用户组定义权限。</p>
<p>默认情况下，Magento创建名为“Administrators”的用户角色，该角色具有最高访问权限。平台的所有者属于此用户角色。</p>
<h3>在Magento 2中定义新用户角色的步骤</h3>
<p>例如，在下面的演示中，我们将了解如何创建名为“Sales representatives”的新用户角色，并根据其角色限制其访问权限。</p>
<p><strong>步骤1：</strong>在管理员面板上，单击左侧菜单中的“System”。然后，单击“Permissions”部分中的“User Roles”。在这里，您将看到现有用户角色的列表。</p>
<div class="wp-block-image"><figure class="aligncenter is-resized"><a href="#" target="_blank" rel="noreferrer noopener"><img src="https://www.360magento.com/media/wysiwyg/232/Steps-to-Create-New-User-Role-in-Magento-2-1.png" alt="Magento2为新用户添加管理员权限" /></a></figure></div>
<p><strong>步骤2：</strong>在右上角，单击“Add New Role”按钮以添加新用户角色。</p>
<div class="wp-block-image"><figure class="aligncenter"><a href="#" target="_blank" rel="noreferrer noopener"><img src="https://www.360magento.com/media/wysiwyg/232/Steps-to-Create-New-User-Role-in-Magento-2-2-1024x516.png" alt="Magento2为新用户添加管理员权限" /></a></figure></div>
<p><strong>步骤3：</strong>在“Role Information”部分中，输入描述性角色名称，如Sales Representatives。</p>
<p>在“Current User Identity Verification”部分中，输入您当前的管理员密码以验证您是否有权添加新用户角色。</p>
<div class="wp-block-image"><figure class="aligncenter"><a href="#" target="_blank" rel="noreferrer noopener"><img src="https://www.360magento.com/media/wysiwyg/232/Steps-to-Create-New-User-Role-in-Magento-2-3-1024x487.png" alt="Magento2为新用户添加管理员权限" /></a></figure></div>
<p><strong>第4步：</strong>单击左侧面板中的“Role Resources”。在这里，您可以看到以下下拉选项，</p>
<ul><li><strong>All：</strong>如果要授予对新用户角色的完全访问权限，请选择此选项。</li><li><strong>Custom：</strong>如果要授予对新用户角色的限制访问权限，请选择此选项。这将显示所有资源的列表。勾选要分配给新用户角色的资源的复选框。</li></ul>
<div class="wp-block-image"><figure class="aligncenter"><a href="#" target="_blank" rel="noreferrer noopener"><img src="https://www.360magento.com/media/wysiwyg/232/Steps-to-Create-New-User-Role-in-Magento-2-4-1024x518.png" alt="Magento2为新用户添加管理员权限"/></a></figure></div>
<p><strong>步骤5：</strong>最后，单击“Save Role”按钮以创建新用户角色。</p>
<div class="wp-block-image"><figure class="aligncenter"><a href="#" target="_blank" rel="noreferrer noopener"><img src="https://www.360magento.com/media/wysiwyg/232/Steps-to-Create-New-User-Role-in-Magento-2-5-1024x522.png" alt="Magento2为新用户添加管理员权限" /></a></figure></div>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Wed, 05 Jun 2019 08:05:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2以编程方式将产品属性分配到属性集]]></title>
      <link>https://www.360magento.com/blog/m2-assign-productattribute-to-attributeset/</link>
      <description><![CDATA[<p>在Magento中，将单个属性分配给单个属性集是一个快速的过程，我们可以非常轻松地在后台管理完成。但是将大量属性分配给所有属性集（即，属性集大于25个）并不是一个快速的过程，需要花费很多时间。但是我们可以通过使用自定义脚本使过程变得非常简单。在这里，我将向您展示如何使用自定义脚本将产品属性分配给所有属性集。</p>
<h3>将指定属性分配给任意单个属性集：</h3>
<p>以下代码有助于使用属性代码和属性集名称将特定产品属性分配给任意特定属性集，</p>
<pre>
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
 
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');
 
/* Assign Specific Product Attribute to Any Single Attribute Set */
$attributeCode = 'size';
$attributeGroup = 'Product Details';
$attributeSet = 'Bag';
$eavSetup = $objectManager->create(\Magento\Eav\Setup\EavSetup::class);
$config = $objectManager->get(\Magento\Catalog\Model\Config::class);
$attributeManagement = $objectManager->get(\Magento\Eav\Api\AttributeManagementInterface::class);
 
$entityTypeId = $eavSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
$attributeSet = $eavSetup->getAttributeSet($entityTypeId, $attributeSet);
if(isset($attributeSet['attribute_set_id'])) {
     $group_id = $config->getAttributeGroupId($attributeSet['attribute_set_id'], $attributeGroup);
     $attributeManagement->assign(
          'catalog_product',
          $attributeSet['attribute_set_id'],
          $group_id,
          $attributeCode,
          100
     );
}
</pre>
<h3>为所有属性集分配指定属性：</h3>
<p>以下代码将产品属性分配给所有属性集，</p>
<pre>
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
 
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');
 
/* Assign Specific Product Attribute to All the Attribute Sets */
$attributeCode = 'size';
$attributeGroup = 'Product Details';
 
$eavSetup = $objectManager->create(\Magento\Eav\Setup\EavSetup::class);
$config = $objectManager->get(\Magento\Catalog\Model\Config::class);
$attributeManagement = $objectManager->get(\Magento\Eav\Api\AttributeManagementInterface::class);
 
$entityTypeId = $eavSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
$attributeSetIds = $eavSetup->getAllAttributeSetIds($entityTypeId);
foreach ($attributeSetIds as $attributeSetId) {
     if ($attributeSetId) {
          $group_id = $config->getAttributeGroupId($attributeSetId, $attributeGroup);
          $attributeManagement->assign(
               'catalog_product',
               $attributeSetId,
               $group_id,
               $attributeCode,
               100
          );
     }
}
</pre>
<p>希望这可以帮助到你。</p>]]></description>
      <pubDate>Mon, 03 Jun 2019 05:51:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2从可配置产品中获取关联的简单产品信息]]></title>
      <link>https://www.360magento.com/blog/m2-get-simple-from-configurable/</link>
      <description><![CDATA[<p>Magento 2中的可配置产品允许商家创建具有不同类型变体的产品，例如具有不同颜色（即红色，绿色，蓝色），尺寸（即S，M，L）的T恤，这些变化是具有独特SKU，库存，价格等的简单产品。在前端，可配置产品的信息将显示在产品详细信息页面中，所有相关的简单产品将显示为下拉列表或色板。</p>
<p>例如，T恤是一种可配置的产品，它有不同的尺寸，如S，M和L。此尺寸选项与三种不同的简单产品相关联，这些简单产品具有独特的SKU，库存，并且可能根据尺寸具有不同的价格。在产品详细信息页面中，默认情况下，将显示具有此尺寸变化的T恤信息。当我们选择该选项时，将在详细信息页面中更改所选产品SKU和价格。这是Magento2中的默认功能。但有时候，比如我们可能需要从产品详细信息页面或网站其他位置的可配置产品中获取这些相关的简单产品。这时，我们需要扩展Magento2原生功能，这篇简单的博客将帮助您以编程方式从可配置产品中获取相关的简单产品。</p>
<p>为了在Magento 2中获取产品信息，我们可能需要在模块类的构造函数中注入<strong>\Magento\Catalog\Model\ProductRepository</strong>类的对象。</p>
<h3>使用依赖注入（DI）</h3>
<p>以下是使用依赖注入从可配置产品中获取关联简单产品的示例代码。</p>
<pre>protected $productRepository;
...
 
public function __construct(
    ...
    \Magento\Catalog\Model\ProductRepository $productRepository,
    ...
) {
    ...
    $this-&gt;productRepository = $productRepository;
    ...
}
 
public function getAssociatedSimpleProduct($configurable_product_id) {
    $configurableProduct = $this-&gt;productRepository-&gt;getById($configurable_product_id);
    $children = $configurableProduct-&gt;getTypeInstance()-&gt;getUsedProducts($configurableProduct);
    foreach ($children as $child){
        echo "Child Product Id: " . $child-&gt;getId();
        echo "Child Product SKU: " . $child-&gt;getSku();
    }
}
</pre>
<h3>使用对象管理器</h3>
<p>以下是使用对象管理器从Magento 2中的可配置产品获取关联的简单产品的示例代码。</p>
<pre>$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
 
$configurable_product_id = 68;
$configurableProduct = $objectManager-&gt;get('Magento\Catalog\Model\ProductRepository')-&gt;getById($configurable_product_id);
 
$children = $configurableProduct-&gt;getTypeInstance()-&gt;getUsedProducts($configurableProduct);
foreach ($children as $child){
    echo "Child Product Id: " . $child-&gt;getId();
    echo "Child Product SKU: " . $child-&gt;getSku();
}</pre>
<p><strong>Note:</strong>以上代码在Magento 2.3中进行了测试。</p>]]></description>
      <pubDate>Fri, 31 May 2019 07:04:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何创建确认小部件(Widgets)]]></title>
      <link>https://www.360magento.com/blog/m2-create-widgets/</link>
      <description><![CDATA[<p>Magento确认小部件用于显示带有指定消息的对话框，以及确认按钮（即OK）和Cancel按钮。我们可以在下面的路径中找到Magento确认小部件源文件，</p>
<p><em>&lt;Magento安装根目录&gt;/vendor/magento/module-ui/view/base/web/js/modal/confirm.js</em></p>
<p>我们可以使用确认小部件为Admin和storefront实现确认窗口。</p>
<h3>初始化确认小部件：</h3>
<p>可以使用以下两种方法初始化确认小部件，</p>
<p><strong>方法1：</strong></p>
<p>可以通过绑定到某个元素来初始化确认小部件。</p>
<p>示例HTML代码：</p>
<pre>
&lt;a class="action delete" id="delete_image" href="&lt;?php /* @escapeNotVerified */ echo $block->getDeleteUrl($_customer->getEntityId()); ?>"&gt;
    &lt;span&gt;
        &lt;?php /* @escapeNotVerified */ echo __('Delete'); ?&gt;
    &lt;/span&gt;
&lt;/a&gt;
</pre>
<p>示例JS代码：</p>
<pre>
&lt;script&gt;
    require([
        'jquery',
        'Magento_Ui/js/modal/confirm'
    ],
    function($, confirmation) {
        $('#delete_image').on('click', function(event){
            event.preventDefault;
            confirmation({
                title: 'Some title',
                content: 'Some content',
                actions: {
                    /**
                     * Callback always - called on all actions.
                     */
                    always: function () {},
 
                    /**
                     * Callback confirm.
                     */
                    confirm: function () {},
 
                    /**
                     * Callback cancel.
                     */
                    cancel: function () {}
                }
            });
        });
    });
&lt;/script&gt;
</pre>
<p>在这里，确认小部件将在点击&lt;a&gt;标签时被初始化，并且在小部件初始化之后，modal pop-up窗口将打开。</p>
<p><strong>方法2：</strong></p>
<p>可以初始化确认小部件而不绑定到某个元素。</p>
<p>示例JS代码：</p>
<pre>
&lt;script&gt;
    require([
        'Magento_Ui/js/modal/confirm'
    ],
    function($, confirmation) {
        confirmation({
            title: 'Some title',
            content: 'Some content',
            actions: {
                /**
                 * Callback always - called on all actions.
                 */
                always: function () {},
 
                /**
                 * Callback confirm.
                 */
                confirm: function () {},
 
                /**
                 * Callback cancel.
                 */
                cancel: function () {}
            }
        });
    });
&lt;/script&gt;
</pre>
<p>这里，确认小部件将在页面加载时初始化，并且在小部件初始化之后，modal pop-up窗口将打开。</p>
<h3>确认小部件选项：</h3>
<ul>
<li>title:确认弹出窗口的标题。</li>
<li>content: <span style="font-size: 1rem;">确认弹出窗口的内容。</span></li>
<li>actions: 这是确认小部件回调，它有以下三个回调事件，
<ul>
<li>confirm callback:单击确认按钮时将调用它。</li>
<li>cancel callback: 单击取消按钮时将调用它。</li>
<li>always callback:单击确认按钮和取消按钮时将调用它。</li>
</ul>
</li>
</ul>
<p>Magento2确认小部件还有一些其他选项，</p>
<ul>
<li>autoOpen</li>
<li>clickableOverlay</li>
<li>focus</li>
</ul>
<p>您可以在<a href="https://devdocs.magento.com/guides/v2.2/javascript-dev-guide/widgets/widget_confirm.html" target="_blank" rel="noopener">此处</a>找到有关这些选项的详细说明</p>
<p>希望这可以帮助你。</p>]]></description>
      <pubDate>Wed, 29 May 2019 06:49:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2在列表页工具栏中添加自定义排序选项过滤器]]></title>
      <link>https://www.360magento.com/blog/m2-add-sortby/</link>
      <description><![CDATA[<p>在Magento 2默认功能中，类别页面的工具栏上将显示以下三种排序选项，</p>
<ul><li>Sort by “Position”</li><li>Sort by “Product Name”</li><li>Sort by “Price”</li></ul>
<p>但在某些情况下，您可能希望在类别工具栏中添加更多新选项，例如按创建日期（最新），畅销产品等对产品进行分类。在类别工具栏中添加新的排序选项并不困难，这篇博客可以帮助您以更少的时间自定义代码。</p>
<p>在这篇博客中，将展示如何在类别页面的工具栏中添加新的排序选项“Newest”。为了在Magento 2中添加新的排序选项，我们必须使用以下两个类，<strong>Magento\Catalog\Model\Config</strong>和<strong>Magento\Catalog\Block\Product\ProductList\Toolbar</strong></p>
<p><strong>步骤1：</strong>在以下路径中创建名为<strong>registration.php</strong>的文件，</p>
<p><em>文件路径：app/code/Alwayly/NewSorting/registration.php</em></p>
<pre>
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Alwayly_NewSorting',
    __DIR__
);
</pre>
<p><strong>步骤2：</strong>在以下路径中创建名为<strong>module.xml</strong>的文件，</p>
<p><em>文件路径：app/code/Alwayly/NewSorting/etc/module.xml</em></p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_MyAttributeSet" setup_version="1.0.0"&gt;
        &lt;sequence&gt;
            &lt;module name="Magento_Catalog"/&gt;
        &lt;/sequence&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>
<p><strong>步骤3：</strong>在以下文件路径中创建名为<strong>di.xml</strong>的文件，在此文件中，我们必须为以下原生类添加插件，<strong>Magento\Catalog\Model\Config</strong>＆<strong>Magento\Catalog\Block\Product\ProductList\Toolbar</strong></p>
<p><em>文件路径：app/code/Alwayly/NewSorting/etc/frontend/di.xml</em></p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"&gt;
 
    &lt;type name="Magento\Catalog\Model\Config"&gt;
        &lt;plugin name="Alwayly_NewSorting::addNewSortOption" type="Alwayly\NewSorting\Plugin\Model\Config" /&gt;
    &lt;/type&gt;
     
    &lt;type name="Magento\Catalog\Block\Product\ProductList\Toolbar"&gt;
        &lt;plugin name="Alwayly_NewSorting::addNewFilterInToolbar" type="Alwayly\NewSorting\Plugin\Product\ProductList\Toolbar" /&gt;
    &lt;/type&gt;
 
&lt;/config&gt;
</pre>
<p><strong>步骤4：</strong>在以下文件路径中创建名为<strong>Config.php</strong>的文件，在此文件中，我们必须通过插件方法自定义原生代码以添加新的排序选项。</p>
<p><em>文件路径：app/code/Alwayly/NewSorting/Plugin/Model/Config.php</em></p>
<pre>
&lt;?php
namespace Alwayly\NewSorting\Plugin\Model;
 
class Config
{
    const NEWEST_SORT_BY = 'newest';
 
    /**
     * Adding new sort option
     *
     * @param \Magento\Catalog\Model\Config $catalogConfig
     * @param [] $result
     * @return []
     */
    public function afterGetAttributeUsedForSortByArray(
        \Magento\Catalog\Model\Config $subject, 
        $result
    ) {
        return array_merge(
            $result, 
            [
                self::NEWEST_SORT_BY => __('Newest')
            ]
        );
    }
}
</pre>
<p><strong>步骤 5:</strong> 最后，在以下文件路径中创建一个名为<strong>Toolbar.php</strong>的文件，在此文件中我们必须通过插件方法自定义原生代码以添加我们的新排序选项。.</p>
<p><em>文件路径: app/code/Alwayly/NewSorting/Plugin/Product/ProductList/Toolbar.php</em></p>
<pre>
&lt;?php
namespace Alwayly\NewSorting\Plugin\Product\ProductList;
 
class Toolbar
{
    const NEWEST_SORT_BY = 'newest';
 
    /**
     * Around Plugin
     *
     * @param \Magento\Catalog\Block\Product\ProductList\Toolbar $subject
     * @param \Closure $proceed
     * @param \Magento\Framework\Data\Collection $collection
     * @return \Magento\Catalog\Block\Product\ProductList\Toolbar
     */
    public function aroundSetCollection(
        \Magento\Catalog\Block\Product\ProductList\Toolbar $subject,
        \Closure $proceed,
        $collection
    ) {
        $currentOrder = $subject->getCurrentOrder();
        $currentDirection = $subject->getCurrentDirection();
        $result = $proceed($collection);
 
        if ($currentOrder == self::NEWEST_SORT_BY) {
            if ($currentDirection == 'desc') {
                $subject->getCollection()->setOrder('created_at', 'desc');
            } 
            else {
                $subject->getCollection()->setOrder('created_at', 'asc');
            }
        }
 
        return $result;
    }
}
</pre>

<p>完成上述步骤后，在Magento 2安装的根目录中运行以下SSH命令,</p>

<blockquote class="wp-block-quote"><p>php bin/magento setup:upgrade</p></blockquote>

<p>然后，清除所有Magento缓存并检查网站的产品列表页面。</p>

<blockquote class="wp-block-quote"><p><strong>Note:</strong>我们已在Magento 2.3上测试了上述代码.</p></blockquote>]]></description>
      <pubDate>Mon, 27 May 2019 06:28:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2使用AJAX更新购物车的产品数量]]></title>
      <link>https://www.360magento.com/blog/m2-update-qty-cart/</link>
      <description><![CDATA[<p>通过在购物车页面中使用AJAX添加数量更新选项，有助于改善Magento 2网站的用户体验。</p>
<p>按照以下简单步骤在Magento 2中创建新扩展，来添加AJAX功能以更新购物车页面中的商品数量。</p>
<h3>步骤1：</h3>
<p>在以下文件路径中创建一个名为<strong>registration.php</strong>的新php文件，</p>
<p><em>文件路径：app/code/Alwayly/AutoUpdateCartItemQty/registration.php</em></p>
<pre>&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Alwayly_AutoUpdateCartItemQty',
    __DIR__
);
</pre>
<h3>第2步：</h3>
<p>在以下文件路径中创建名为<strong>module.xml</strong>的xml文件以定义新模块，</p>
<p><em>文件路径：app/code/Alwayly/AutoUpdateCartItemQty/etc/module.xml</em></p>
<p>在这里，我们必须指定我们的自定义模块的名称，如<strong>Alwayly_AutoUpdateCartItemQty</strong>和它的安装版本如下，</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt;
    &lt;module name="Alwayly_AutoUpdateCartItemQty" setup_version="1.0.0"&gt;
    &lt;/module&gt;
&lt;/config&gt;
</pre>
<h3>第3步：</h3>
<p>在以下文件路径中创建名为<strong>checkout_cart_index.xml</strong>的xml文件，</p>
<p><em>文件路径：app/code/Alwayly/AutoUpdateCartItemQty/view/frontend/layout/checkout_cart_index.xml</em></p>
<p>在此文件中，我们必须指定自定义模块的模板文件，如下所示，</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
     &lt;body&gt;
          &lt;referenceContainer name="content"&gt;
               &lt;block class="Magento\Framework\View\Element\Template" name="auto.update.cart.item.qty" template="Alwayly_AutoUpdateCartItemQty::script.phtml" after="-"/&gt;
          &lt;/referenceContainer&gt;
     &lt;/body&gt;
&lt;/page&gt;
</pre>
<h3>第4步：</h3>
<p>在以下文件路径中创建名为<strong>script.phtml</strong>的phtml文件，</p>
<p><em>文件路径：app/code/Alwayly/AutoUpdateCartItemQty/view/frontend/templates/script.phtml</em></p>
<p>以下是<strong>script.phtml</strong>文件的代码，该文件将用于在结帐页面加载我们的自定义模块js文件，</p>
<pre>&lt;script&gt;
    require ([
        'jquery'
    ],
    function ($) {
        $(window).on("load", function () {
            require([          
               'Alwayly_AutoUpdateCartItemQty/js/cartItemQtyUpdate'
            ]);
        });
    });
&lt;/script&gt;
</pre>
<h3>第5步：</h3>
<p>最后，在以下文件路径中创建名为<strong>cartItemQtyUpdate.js</strong>的JS文件，</p>
<p><em>文件路径：app/code/Alwayly/AutoUpdateCartItemQty/view/frontend/web/js/cartItemQtyUpdate.js</em></p>
<p>在此文件中，我们必须添加以下代码，用于在更改qty字段值时使用ajax更新购物车的商品数量，</p>
<pre>define([
    'jquery',
    'Magento_Checkout/js/action/get-totals',
    'Magento_Customer/js/customer-data'
], function ($, getTotalsAction, customerData) {
 
    $(document).ready(function(){
        $(document).on('change', 'input[name$="[qty]"]', function(){
            var form = $('form#form-validate');
            $.ajax({
                url: form.attr('action'),
                data: form.serialize(),
                showLoader: true,
                success: function (res) {
                    var parsedResponse = $.parseHTML(res);
                    var result = $(parsedResponse).find("#form-validate");
                    var sections = ['cart'];
 
                    $("#form-validate").replaceWith(result);
 
                    /* This is for reloading the minicart */
                    customerData.reload(sections, true);
 
                    /* This is for reloading the totals summary  */
                    var deferred = $.Deferred();
                    getTotalsAction([], deferred);
                },
                error: function (xhr, status, error) {
                    var err = eval("(" + xhr.responseText + ")");
                    console.log(err.Message);
                }
            });
        });
    });
});
</pre>
<p>完成上述步骤后，在Magento 2安装的根目录下运行以下SSH命令，</p>
<blockquote class="wp-block-quote">
<p>php bin/magento setup:upgrade</p>
</blockquote>
<p>然后，清除所有Magento缓存并检查购物车页面中的数量更新选项。</p>
<blockquote class="wp-block-quote">
<p>Note：我们已经使用Luma主题在Magento 2.3上测试了上述代码。</p>
</blockquote>]]></description>
      <pubDate>Wed, 22 May 2019 21:29:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2在Phtml文件中调用显示静态块]]></title>
      <link>https://www.360magento.com/blog/m2-call-static/</link>
      <description><![CDATA[<p>Magento 2具有CMS静态块的内置功能，允许网站管理员在后台创建/控制静态内容。静态内容可以是促销横幅，退货政策，尺寸图表等。在后台创建CMS静态块后，它将通过使用以下任何一种方法显示在前端，</p>
<ol>
<li>在phtml文件中调用显示CMS静态块。</li>
<li>在CMS内容中调用显示CMS静态块。</li>
<li>在XML文件中调用显示CMS静态块。</li>
</ol>
<h3>在后台创建CMS静态块：</h3>
<p>在前端调用CMS块之前，首先需要创建它。下面是在Magento 2管理面板上创建新的CMS静态块的步骤，</p>
<p><strong>第1步：</strong>登录Magento 2管理面板。</p>
<p><strong>第2步：</strong>从左侧导航部分转到<strong>Content &gt; Blocks</strong>。您将看到Magento CMS静态块列表。</p>
<p><a href="#" rel="noopener noreferrer" target="_blank"><img alt="Magento2如何调用静态文件" src="https://www.360magento.com/media/wysiwyg/blog_226/Magento-2-How-to-Call-CMS-Static-Block-in-Phtml-File-1.png" /></a></p>
<p><strong>第3步：</strong>单击 <strong>&ldquo;Add New Block&rdquo;</strong>按钮。这将打开<strong>New Block</strong> &nbsp;页面。</p>
<p><a href="#" rel="noopener noreferrer" target="_blank"><img alt="Magento2如何调用静态文件" src="https://www.360magento.com/media/wysiwyg/blog_226/Magento-2-How-to-Call-CMS-Static-Block-in-Phtml-File-2-768x392.png" /></a></p>
<p><strong>步骤4：</strong>在<strong>New Block</strong> &nbsp;页面中，输入以下详细信息，然后单击<strong>Save Block</strong> &nbsp;按钮以创建CMS静态块。</p>
<ul>
<li>Enable Block：启用/禁用块。</li>
<li>Block Title：块的名称。（例如：Home Page Block）。</li>
<li>Identifier：块标识符。它必须是独一无二的。（例如:home-page-block）。</li>
<li>Store View：从多选框中选择商店视图。</li>
<li>Content：块的内容。</li>
</ul>
<p>完成上述步骤后，我们可以使用以下方法在前端调用显示CMS静态块，</p>
<h3>在Phtml文件中调用显示CMS静态块：</h3>
<p>这里是在Magento 2中的任意模板（phtml）文件中显示CMS静态块的代码，</p>
<pre>&lt;?php 
    echo $block-&gt;getLayout()
               -&gt;createBlock('Magento\Cms\Block\Block')
               -&gt;setBlockId('block_identifier')
               -&gt;toHtml();
?&gt;
</pre>
<h3>在CMS内容中显示CMS静态块：</h3>
<p>这里是在Magento 2中的任何其他CMS静态块/页面中显示CMS静态块的代码，</p>
<pre>
</pre>
<h3>在XML布局文件中调用显示CMS静态块：</h3>
<p>这里是在Magento 2中的任何布局（XML）文件中显示CMS静态块的代码，</p>
<pre> 
     
         
            block_identifier 
         
     

</pre>]]></description>
      <pubDate>Mon, 20 May 2019 04:01:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何将Magento 1.9.x迁移到2.3.x]]></title>
      <link>https://www.360magento.com/blog/migrate-magento-1-9-x-to-2-3-x/</link>
      <description><![CDATA[<p>您是否知道在过去三年中，超过70％的Magento 1网站已迁移到Magento 2？如果您仍在使用Magento 1，即使您已更新到最新的Magento 1.9.4.1版本，您的网站与当前Magento网站之间在设计与功能也会存在<em>较大差异</em>。因此，我们需尽快将Magento 1.9.x迁移到2.3.x，以至不落后于竞争对手。</p>
<h2>5个让你不再纠结迁移到Magento 2.3.x的理由.</h2>
<p><strong>1. Magento 1.9.x设计和功能都很差</strong></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_225/migrate-magento-1-to-2.3-1024x764.jpg" alt="将magento1.x迁移到magento2" /></p>
<p>Magento 1自发布以来已经很长时间了。因此，不仅是Magento 1.9.x的默认主题，还是这个旧版本市场的主题设计都已经过时了。</p>
<p>如果你坚持使用Magento 1的老式网站设计，那么你很可能会失去很多潜在客户。</p>
<p><strong>2. Magento 2.3.x提供了一种现代且响应迅速的设计</strong></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_225/magento-2-migration-1024x630.png" alt="magento 2迁移" /><br>
与Magento 1.9.x相比，Magento 2.3网站设计更时尚，更引人注目，更重要的是，对用户和移动设备都更加友好。</p>
<p>您可以轻松找到各种美观的Magento 2.3主题， &nbsp;适用于综合型，服装和配饰，电子产品和数字，家具，珠宝店。</p>
<p><strong>3. Magento 2.3.x带来了强大的电子商务功能和性能</strong></p>
<p>Magento在发布Magento 2.3时取得了突破性进展。与Magento 1.9.x相比，Magento 2.3运行速度更快（与PHP 7和HTML 5兼容）并且处理更顺畅。</p>
<p><em> 为什么Magento 2.3.x而不是Magento 2.2.x？</em></p>
<p>虽然Magento 2版本总体来说还是很不错的，但Magento 2.3.x比Magento 2.2.x更受推荐，尤其是2019年3月26日发布的Magento 2.3.1。在最新版本中，有许多令人印象深刻的功能，如 PWA studio，多源库存，页面构建器等。</p>
<p>阅读<a href="https://devdocs.magento.com/guides/v2.3/release-notes/ReleaseNotes2.3.1OpenSource.html" rel="nofollow" target="_blank">这篇文章</a>，了解最新Magento 2.3.1的所有高级功能。</p>
<p><strong>4. Magento 2.3.x的管理面板更直观，用户友好</strong></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_225/magento-1-to-2-migration-1024x554.png" alt="magento1升级到magento2" /></p>
<p>Magento商家将Magento 1.9.x迁移到2.3.x的主要动机之一是Magento 2完美的后端界面。即使您没有很强的技术知识，它也非常易于管理使用。相反，Magento 1的管理面板对于非技术用户来说似乎非常混乱。</p>
<p><strong>5. Magento将停止为Magento 1提供支持</strong></p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_225/upgrade-to-magento-2.3.png" alt="升级到magento 2.3" /></p>
<p>您可能知道，Magento正式宣布从2020年6月开始停止对Magento 1的支持。您对这个过时的平台有什么期望，而且没有其创始人的支持？</p>
<p>对于上述所有事实，没有理由继续使用过时的Magento 1.xx版本，除非......你负担不起<a href="#">Magento 2迁移</a>的<a href="#">费用</a>。<br>
&nbsp;</p>
<h2>将Magento 1.9.x迁移到2.3.x常见挑战的5个步骤</h2>
<p><strong>1.迁移您的数据</strong></p>
<p>您必须将数据库资源（例如：产品，类别，客户信息，订单等）从现有的Magento 1.9.x网站迁移到新网站。</p>
<p>如果您的Magento开发人员在Magento 2迁移方面没有过硬的专业知识，您可能会面临严重数据丢失的风险。让我们想象一下，如果您的买家无法登录他们的注册账户，将会如何！</p>
<p><strong>2.迁移您的主题</strong></p>
<p>由于Magento 1的所有主题都与Magento 2不兼容，因此将现有模板“移动”到新网站是不可能的。</p>
<p>有一些解决方案可以解决Magento主题迁移问题，我们将在下面的部分中提出建议。</p>
<p><strong>3.迁移您的扩展程序</strong></p>
<p>与主题一样，不幸的是，您无法在新商店中重复使用当前的Magento 1扩展程序。此外，即使您进行自定义，这些也无法在Magento 2网站中正常运行。</p>
<p><strong>4.迁移自定义功能</strong></p>
<p>有许多Magento商店开发了一些自定义功能（没有任何扩展获得）。如何将这些功能迁移到新网站对于网站所有者来说也是一个令人头痛的问题。</p>
<p><strong>5.迁移配置</strong></p>
<p>此步骤与在Magento 2网站上重新配置您的语言，货币，运送，电子邮件模板，税金，CMS页面等有关。<br>
&nbsp;</p>
<h2>解决Magento 2迁移问题的5个技巧</h2>
<p><strong>1.仅迁移关键数据库资源</strong></p>
<p>通过仅选择要迁移的重要数据库资源，可以最大程度地降低在Magento 2迁移过程中丢失这些资源的风险。顺便说一句，它为您提供了一个“净化”您网站并提升其性能的绝佳机会。</p>
<p><strong>2.考虑以下3个与网站设计相关的选项</strong></p>
<p>正如我们所提到的，一旦您决定将Magento 1.9.x迁移到2.3.x，就无法继续使用您的Magento 1主题。然而，你可以：</p>
<ul>
<li>克隆您当前的设计，为Magento 2制作类似的设计</li>
<li>为您的新店寻找新的现成主题（如果需要，还可以定制）</li>
<li>从头开始为Magento 2开发一个独特的前端</li>
</ul>
<p>根据时间和预算，您可以选择合适的选项。</p>
<p><strong>3.寻找Magento 2的类似扩展（应该来自相同的供应商）</strong></p>
<p>要将Magento 1.9.x迁移到2.3.x，您需要将所有当前模块替换为Magento 2的新模块。</p>
<p>有一些扩展需要将他们的数据迁移到Magento 2，如奖励积分，博客。这就是为什么我们建议您从同一模块供应商找到替换项，这使扩展数据迁移更加容易。</p>
<p><strong>4.为Magento 2开发类似的自定义功能或使用可用的M2扩展</strong></p>
<p>要在新站点上保留相同的自定义功能，Magento开发人员必须在Magento 2.3环境中重新开发它。</p>
<p>另一种解决方案是搜索可以为您提供类似功能的Magento 2扩展。很多时候，商家无法在执行Magento迁移之后可能为Magento 2找到合适的模块（他们需要的功能）。</p>
<p><strong>5.联系可靠的Magento开发公司来帮助您解决所有问题</strong></p>
<p>如果您发现Magento 2迁移过程有相当大的风险和问题，为什么不找到Magento服务商的帮助？</p>
<p>凭借在Magento的丰富经验，360Magento 以实惠的价格为您提供最佳的<strong><a href="https://www.360magento.com/magento-migration">Magento 2迁移服务</a></strong>。</p>
<p><img src="https://www.360magento.com/media/wysiwyg/blog_225/magento-2-migration-service-1024x454.jpg" alt="magento 2迁移服务" /></p>
<p>我们的Magento迁移服务包括将您的主题，数据，扩展，自定义功能，配置......从Magento 1.9.x平移到2.3.x。没有数据丢失。</p>
<p>特别是，在完成Magento迁移过程后，我们提供3-6个月（基于您的项目规模）的免费技术支持。<br>
&nbsp;</p>
<h2>想要迁移到Magento 2.3.x，但不知道从哪里开始？</h2>
<p>按照以下步骤将Magento 1.9.x成功迁移到2.3.x：</p>
<p>1.将您的迁移请求发送至sales@360magento.com</p>
<p>2.与我们的团队讨论您的项目要求，并从Magento认证工程师那里获得最佳建议</p>
<p>3.等待我们对您项目的全面建议&评估（包括周期和费用）</p>
<p>4.签署我们的网站开发协议</p>
<p>5.开始迁移工作，将您的网站提升到新的水平！</p>]]></description>
      <pubDate>Thu, 16 May 2019 13:35:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento1&2中配置Redis]]></title>
      <link>https://www.360magento.com/blog/configure-redis-magento-2-1/</link>
      <description><![CDATA[<p>首先，Magento 1和2中的Redis缓存配置有几个先决条件：</p>
<ul>
<li>Redis服务</li>
<li>PHP Redis扩展</li>
</ul>
<p><em>注意</em>：建议使用最新版本。</p>
<h2 style="margin: 0in; margin-bottom: .0001pt;">
<b>步骤1：更新并安装Redis-server</b></h2>
<pre style="color: #000020; background: #f6f8ff;">
wget http://download.redis.io/releases/redis-stable.tar.gz
tar xzf redis-stable.tar.gz
cd redis-stable
make
make test
sudo make install
cd utils
sudo ./install_server.sh
sudo service redis_6379 start
sudo update-rc.d redis_6379 defaults
</pre>
<h2>第2步：在Magento中配置Redis</h2>
<h3>A.配置Magento 2以将Redis用作缓存存储</h3>
<p>将以下代码添加到您的应用程序app/etc/env.php：</p>
<pre style="color: #000020; background: #f6f8ff;">
&lt;?php
// app/etc/env.php
return [
    // Other directives
    'cache' => [
        'frontend' => [
            'default' => [
                'backend' => 'Cm_Cache_Backend_Redis',
                'backend_options' => [
                    'server' => '127.0.0.1',
                    'database' => '0',
                    'port' => '6379',
                    'password' => ''
                ]
            ],
            'page_cache' => [
                'backend' => 'Cm_Cache_Backend_Redis',
                'backend_options' => [
                    'server' => '127.0.0.1',
                    'database' => '1',
                    'port' => '6379',
                    'compress_data' => '0',
                    'password' => ''
                ]
            ]
        ]
    ]
];
</pre>
<h3>B.配置Magento 2以将Redis用作会话存储</h3>
<p>首先，您需要找到以下代码段：</p>
<pre style="color: #000020; background: #f6f8ff;">
'session' => [
    'save' => 'files'
],
And replace it with snippet as follows:
'session' => [
    'save' => 'redis',
    'redis' => [
        'host' => '127.0.0.1',
        'port' => '6379',
        'password' => '',
        'timeout' => '2.5',
        'persistent_identifier' => '',
        'database' => '2',
        'compression_threshold' => '2048',
        'compression_library' => 'gzip',
        'log_level' => '3',
        'max_concurrency' => '6',
        'break_after_frontend' => '5',
        'break_after_adminhtml' => '30',
        'first_lifetime' => '600',
        'bot_first_lifetime' => '60',
        'bot_lifetime' => '7200',
        'disable_locking' => '0',
        'min_lifetime' => '60',
        'max_lifetime' => '2592000'
    ] ],
</pre>
<p>其次，通过运行以下命令清除所有缓存会话：</p>
<pre style="color: #000020; background: #f6f8ff;">
bin/magento c:f
</pre>
<h3>C.配置Magento 1使用Redis</h3>
<p>首先，转到您的app/etc/local.xml，然后改变：</p>
<pre style="color: #000020; background: #f6f8ff;">
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;global&gt;
        &lt;install&gt;
            &lt;date&gt;&lt;![CDATA[Tue, 04 Oct 2016 09:53:37 +0000]]&gt;&lt;/date&gt;
        &lt;/install&gt;
        &lt;crypt&gt;
            &lt;key&gt;&lt;![CDATA[e972f3c4e8436052de805bdf1f40de0f]]&gt;&lt;/key&gt;
        &lt;/crypt&gt;
        &lt;disable_local_modules&gt;false&lt;/disable_local_modules&gt;
        &lt;resources&gt;
            &lt;db&gt;
                &lt;table_prefix&gt;&lt;![CDATA[]]&gt;&lt;/table_prefix&gt;
            &lt;/db&gt;
            &lt;default_setup&gt;
                &lt;connection&gt;
                    &lt;host&gt;&lt;![CDATA[localhost]]&gt;&lt;/host&gt;
                    &lt;username&gt;&lt;![CDATA[magento]]&gt;&lt;/username&gt;
                    &lt;password&gt;&lt;![CDATA[magento]]&gt;&lt;/password&gt;
                    &lt;dbname&gt;&lt;![CDATA[magento]]&gt;&lt;/dbname&gt;
                    &lt;initStatements&gt;&lt;![CDATA[SET NAMES utf8]]&gt;&lt;/initStatements&gt;
                    &lt;model&gt;&lt;![CDATA[mysql4]]&gt;&lt;/model&gt;
                    &lt;type&gt;&lt;![CDATA[pdo_mysql]]&gt;&lt;/type&gt;
                    &lt;pdoType&gt;&lt;![CDATA[]]&gt;&lt;/pdoType&gt;
                    &lt;active&gt;1&lt;/active&gt;
                &lt;/connection&gt;
            &lt;/default_setup&gt;
        &lt;/resources&gt;
        &lt;session_save&gt;&lt;![CDATA[files]]&gt;&lt;/session_save&gt;
    &lt;/global&gt;
    &lt;admin&gt;
        &lt;routers&gt;
            &lt;adminhtml&gt;
                &lt;args&gt;
                    &lt;frontName&gt;&lt;![CDATA[admin]]&gt;&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/adminhtml&gt;
        &lt;/routers&gt;
    &lt;/admin&gt;
&lt;/config&gt;
</pre>
<p>为：</p>
<pre style="color: #000020; background: #f6f8ff;">

&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;global&gt;
        // Other directives
        &lt;!-- This is a child node of config/global --&gt;
        &lt;cache&gt;
            &lt;backend&gt;Cm_Cache_Backend_Redis&lt;/backend&gt;
            &lt;backend_options&gt;
                &lt;server&gt;127.0.0.1&lt;/server&gt; &lt;!-- or absolute path to unix socket --&gt;
                &lt;port&gt;6379&lt;/port&gt;                
                &lt;database&gt;0&lt;/database&gt; &lt;!-- Redis database number; protection against accidental data loss is improved by not sharing databases --&gt;
                &lt;password&gt;&lt;/password&gt; &lt;!-- Specify if your server requires authentication --&gt;
            &lt;/backend_options&gt;
        &lt;/cache&gt;
        &lt;!--session_save&gt;&lt;![CDATA[files]]&gt;&lt;/session_save--&gt;
        &lt;session_save&gt;db&lt;/session_save&gt;
        &lt;redis_session&gt;                       &lt;!-- All options seen here are the defaults --&gt;
            &lt;host&gt;127.0.0.1&lt;/host&gt;            &lt;!-- Specify an absolute path if using a unix socket --&gt;
            &lt;port&gt;6379&lt;/port&gt;
            &lt;password&gt;&lt;/password&gt;             &lt;!-- Specify if your server requires authentication --&gt;
            &lt;timeout&gt;2.5&lt;/timeout&gt;            &lt;!-- This is the connection timeout, not the locking timeout --&gt;
            &lt;db&gt;0&lt;/db&gt;                        &lt;!-- Redis database number; protection from accidental loss is improved by using a unique DB number for sessions --&gt;
            &lt;compression_threshold&gt;2048 &lt;/compression_threshold&gt;  &lt;!-- Set to 0 to disable compression (recommended when suhosin.session.encrypt=on); known bug with strings over 64k: https://github.com/colinmollenhour/Cm_Cache_Backend_Redis/issues/18 --&gt;
            &lt;compression_lib&gt;gzip&lt;/compression_lib&gt;              &lt;!-- gzip, lzf, lz4 or snappy --&gt;
            &lt;log_level&gt;1&lt;/log_level&gt;               &lt;!-- 0 (emergency: system is unusable), 4 (warning; additional information, recommended), 5 (notice: normal but significant condition), 6 (info: informational messages), 7 (debug: the most information for development/testing) --&gt;
            &lt;max_concurrency&gt;6&lt;/max_concurrency&gt;                 &lt;!-- maximum number of processes that can wait for a lock on one session; for large production clusters, set this to at least 10% of the number of PHP processes --&gt;
            &lt;break_after_frontend&gt;5&lt;/break_after_frontend&gt;       &lt;!-- seconds to wait for a session lock in the frontend; not as critical as admin --&gt;
            &lt;fail_after&gt;10&lt;/fail_after&gt;                       &lt;!-- seconds after which we bail from attempting to obtain lock (in addition to break after time) --&gt;
            &lt;break_after_adminhtml&gt;30&lt;/break_after_adminhtml&gt;
            &lt;first_lifetime&gt;600&lt;/first_lifetime&gt;                 &lt;!-- Lifetime of session for non-bots on the first write. 0 to disable --&gt;
            &lt;bot_first_lifetime&gt;60&lt;/bot_first_lifetime&gt;          &lt;!-- Lifetime of session for bots on the first write. 0 to disable --&gt;
            &lt;bot_lifetime&gt;7200&lt;/bot_lifetime&gt;                    &lt;!-- Lifetime of session for bots on subsequent writes. 0 to disable --&gt;
            &lt;disable_locking&gt;0&lt;/disable_locking&gt;                 &lt;!-- Disable session locking entirely. --&gt;
            &lt;min_lifetime&gt;60&lt;/min_lifetime&gt;                      &lt;!-- Set the minimum session lifetime --&gt;
            &lt;max_lifetime&gt;2592000&lt;/max_lifetime&gt;                 &lt;!-- Set the maximum session lifetime --&gt;
        &lt;/redis_session&gt;
    &lt;/global&gt;
    &lt;admin&gt;
        &lt;routers&gt;
            &lt;adminhtml&gt;
                &lt;args&gt;
                    &lt;frontName&gt;&lt;![CDATA[admin]]&gt;&lt;/frontName&gt;
                &lt;/args&gt;
            &lt;/adminhtml&gt;
        &lt;/routers&gt;
    &lt;/admin&gt;
&lt;/config&gt;
</pre>
<p>其次，通过运行以下命令清除会话的所有缓存：</p>
<pre style="color: #000020; background: #f6f8ff;">
rm -rf /var/www/html/magento/var/session/*
rm -rf /var/www/html/magento/var/cache/*
</pre>
<p>&nbsp;</p>
<h2>第3步：重新启动并检查结果</h2>
<p>接下来，您应该重新启动：</p>
<pre style="color: #000020; background: #f6f8ff;">
service redis-server restart
</pre>
<p>要检查Redis服务器是否正常工作，请输入：</p>
<pre style="color: #000020; background: #f6f8ff;">
redis-cli ping
</pre>
<p>如果结果是：</p>
<pre style="color: #000020; background: #f6f8ff;">
PONG
</pre>
<p>然后你的服务器正在响应。<br>
此外，您可以通过以下方式监控所有流量：</p>
<pre style="color: #000020; background: #f6f8ff;">
redis-cli monitor
</pre>
<p>然后刷新页面。如果您可以在终端上看到生成的日志，有随机的字母数字字符，这意味着缓存正在运行。<br>
您还可以检查 Redis-server是否能够设置密钥：</p>
<pre style="color: #000020; background: #f6f8ff;">
redis-cli
127.0.0.1:6379> set mykey KEY
OK
127.0.0.1:6379> get mykey
"KEY"
127.0.0.1:6379> exit
</pre>
<p>此外，您可以使用“info”命令获取服务器信息和统计信息：</p>
<pre style="color: #000020; background: #f6f8ff;">
redis-cli info
</pre>
<p>我们已经向您展示了在Magento 1和2中配置Redis的一些简单步骤。如果您有任何需要请联系我们。]]></description>
      <pubDate>Mon, 06 May 2019 14:10:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何设置Magento 2 Cron Job]]></title>
      <link>https://www.360magento.com/blog/setup-cron-job-magento-2/</link>
      <description><![CDATA[<p>Magento 2加载了很多很棒的功能，而Cron Job是其中最有用的功能之一。Cron是一个基于时间的调度程序，在Magento 2中使用预定的时间和日期自动运行命令很有用。</p><div class="magtoc"><h2 class="magtocp">如何配置Magento 2 Cron Job</h2><ol><li><a href="#crontab">创建crontab.xml</a></li><li><a href="#Run">创建Run.php</a></li><li><a href="#Magento-2-Cron">运行Magento 2 Cron Job</a></li></ol></div><h2>为什么要配置Magento 2 Cron Job？</h2><p>Cron是Magento 2中最重要的部分之一。您可以通过cron安排多项活动，如下所示：</p><ul><li>生成Google站点地图</li><li>新闻邮件</li><li>重建索引</li><li>目录价格规则</li><li>客户提醒和通知。</li><li>私人销售（仅限Magento企业版）</li><li>所有Magento电子邮件包括订单确认和交易。</li><li>自动更新货币汇率</li></ul><p>有关更多详细信息，您可以查看有关Cron Job 的<a href="http://devdocs.magento.com/guides/v2.0/config-guide/cli/config-cli-subcommands-cron.html" target="_blank" rel="noopener noreferrer">官方文档</a>。</p><h2>如何配置Magento 2 Cron Job？</h2><p>今天，我将指导您如何用<a href="#" target="_blank" rel="noopener noreferrer">自定义模块在Magento中设置Cron Job </a>。我希望你已经在Magento 2中创建了一个自定义模块。所以，让我们开始吧！</p><h2 id="crontab">创建crontab.xml</h2><p>在<strong>app/code/Alwayly/Mymodule/etc中</strong>创建<strong>crontab.xml</strong>文件，并在其中粘贴以下代码：</p>
<pre>
&lt;?xml version="1.0"?&gt;
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd"&gt;
&lt;group id="default"&gt;
&lt;job name="cron_name" instance="Magenticians\Mymodule\Cron\Run" method="execute"&gt;
&lt;schedule&gt;*/1 * * * *&lt;/schedule&gt;
&lt;/job&gt;
&lt;/group&gt;
&lt;/config&gt;
</pre>
<p>在上面的代码中，我设置了一分钟的计划。我已将组ID设为default和 job name设置为cron_name，您可以根据需要更改它们。</p><h2 id="Run">创建Run.php</h2><p>首先，在自定义模块中创建目录Cron，因此，目录现在将如下所示：<strong>app/code/Alwayly/Mymodule/Cron</strong>。现在在<strong>app/code/Alwayly/Mymodule/Cron</strong>中创建<strong>Run.php</strong>文件并将以下代码粘贴到其中：</p>
<pre>
&lt;?php
namespace Magenticians\Mymodule\Cron;

class Run 
{
   protected $_logger;
   public function __construct(
       \Psr\Log\LoggerInterface $logger
   ) 
    {
     $this->_logger = $logger;
    }

   public function execute()
   {
       //Edit it according to your requirement
       $this->_logger->debug('Cron run successfully');
       return $this;
   }
}
</pre>
<h2 id="Magento-2-Cron">运行Magento 2 Cron Job</h2><p>使用SSH连接您的服务器并转到Magento 2的根目录。现在运行以下命令：</p>
<pre>
php bin/magento cache:flush
php bin/magento cron:run
</pre>
<p>您还可以通过此命令仅为一个组运行Cron Job：</p>
<pre>
php bin/magento cron:run --group="your_group_name"
</pre>
<p>要检查Cron是否正常工作，请转到网站的<strong>var/log/debug.log</strong>，您将看到文本<strong>Cron run successfully</strong>。转到数据库的<strong>cron_schedule</strong>表，您将看到其中包含您的Cron Job名称的新条目。</p>
<p>Cron Job对于Magento 2商店非常重要，通过它可以安排和自动化其活动来节省您的时间。遵循本指南后，我希望您现在能够在Magento 2中轻松设置Cron Job。如果您仍有任何问题或想要讨论与Magento 2 Cron Job相关的内容，可以联系我们！</p>]]></description>
      <pubDate>Mon, 29 Apr 2019 10:08:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2.3 PWA Studio设置教程]]></title>
      <link>https://www.360magento.com/blog/magento2-3-pwa-setup/</link>
      <description><![CDATA[<h2>Magento PWA Studio介绍</h2>
<p>最近公司应用magento2.3.1开发了一个项目，Magento在Magento 2.3版本中引入了PWA（Progressive Web App）Studio项目，当然要折腾下啦。<br>
Magento PWA Studio是一套工具，旨在使开发人员能够将在线商店开发为渐进式Web应用程序。</p>
<h3>什么是Progressive Web Apps？</h3>
<p>PWA的普及在电子商务，在线新闻门户和其他领域的发展非常迅速，因为它具有<br>
如下特点：<br>
<strong>1。更快的用户界面支持</strong><br> 
即使在速度较慢的网络上，Web开发人员现在也可以在一次页面浏览后将整个网站加载到浏览器中。<br>
<strong>2.主屏幕快捷方式</strong><br> 
移动用户可以像手机APP应用程序一样将PWA站点安装到主屏幕。<br>
<strong>3.离线支持</strong><br> 
service worker使其能够脱机工作。即使用户丢失了互联网连接，现在也可以访问网站。PWA站点缓存内容以确保在用户脱机时可以提供某些内容。<br>
<strong>4.背景过程</strong><br>
如果用户面临连接不良或脱机的情况，浏览器会存储所有表单提交数据和请求，当连接正常时，会在后台重新发送所有数据。<br>
<strong>5.安全</strong><br> 
PWA站点使用HTTPS连接来增强安全性。</p>
<p>让我们回到Magento 2设置PWA话题中 ....</p>
<p>PWA Studio项目使用了现代工具和库：<br>
<strong>Webpack</strong><br> 
Webpack的主要功能是从项目模块中的依赖项创建一个或多个bundle。<br>
<strong>ReactJs</strong><br> 
用于构建用户界面的JavaScript库。<br>
<strong>Redux</strong><br> 
用于管理Web应用程序中的状态的JavaScript库。<br>
<strong>GraphQL</strong><br> 
客户端的数据查询语言和服务器端的服务层。</p>
<p><strong>让我们从Magento 2.3安装开始......</strong></p>
<p><strong>注意：</strong>您必须具有<a href="https://nodejs.org/en/">NodeJS的版本&nbsp;&gt; = 10.14.1</a>，并且&nbsp; <a href="https://yarnpkg.com/">Yarn&gt; = 1.13.0</a>。建议使用最新的LTS版本。</p>
<p>1.输入以下命令：</p>
<pre>omposer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition /var/www/html/360mage</pre>
<p><strong>/var/www/html/360mage</strong>是Magento安装目录。</p>
<p>2.通过命令行安装Magento：</p>
<pre>
php bin/magento setup:install --base-url=http://localhost/360mage --db-host=localhost --db-name=360magento --db-user=root --db-password=360magento_pwa --admin-firstname=John --admin-lastname=Doe --admin-email=test@360magento.com --admin-user=admin --admin-password=admin123 --backend-frontname=admin_magento --language=en_US --currency=USD --timezone=Asia/Tbilisi --cleanup-database --use-rewrites=1
</pre>
<p>现在Magento的安装已完成</p>
<p>3.现在克隆pwa-studio存储库</p>
<pre>https://github.com/magento-research/pwa-studio.git</pre>
<pre>git clone https://github.com/magento-research/pwa-studio.git</pre>
<p>我已经在magento根目录<strong>例如： /var/www/html/360mage中</strong>克隆了这个存储库<strong></strong></p>
<p>4.您将在<strong>/var/www/html/360mage中</strong>看到<strong>pwa-studio</strong>目录。
进入这个目录：<strong></strong><br></p>
<pre>cd pwa-studio /</pre>
<p>5.运行</p>
<pre>yarn install</pre>
<p>6.在.env文件中指定Magento后端服务器。你可以在<strong>/var/www/html/360mage/pwa-studio/packages/venia-concept/</strong> 目录中看到<em>.env.dist</em>文件。如果您
看不到，请开启显示隐藏文件。现在复制<em>env.dist</em>创建<em>.env</em>文件<br></p>
<pre>cp packages/venia-concept/.env.dist packages/venia-concept/.env</pre>
<p>7.打开此.env文件并找到<em>MAGENTO_BACKEND_URL</em>。这里配置你的<br>
本地Magento 2.3实例，我的例子是：</p>
<pre>MAGENTO_BACKEND_URL="https://magento2-pwa.com/"</pre>
<p>8.现在让我们为venia-theme <strong>安装样本数据</strong>，以使其看起来更好看。</p>
<p>9. 在<strong>/var/www/html/360mage/pwa-studio/packages/venia-concept/</strong>目录中找到<em>deployVeniaSampleData.sh</em>文件。并将此
文件复制到Magento根目录中。现在它必须看起来如<strong>/var/www/html/360mage/deployVeniaSampleData.sh</strong>现在运行：<br><strong></strong><br><br><strong></strong></p>
<pre>bash deployVeniaSampleData.sh</pre>
<p>10.安装成功后运行：</p>
<pre>bin/magento setup:upgrade</pre>
<pre>bin/magento indexer:reindex</pre>
<pre>bin/magento cache:flush</pre>
<p>打开magento网站，您将能够看到已安装的示例数据，如：<br><img src="https://www.360magento.com/media/wysiwyg/blog_222/Screenshot_pwa.png" alt="magento2 pwa 截图"/></p>
<p>11.现在返回pwa-studio目录<strong>/var/www/html/360mage/pwa-studio</strong>并启动Server。</p>
<pre>yarn run build</pre>
<p>上面的命令可能会出现权限错误，为此使用sudo运行上面的命令。</p>
<pre>sudo yarn run build</pre>
<p>12.运行服务器，从项目根目录中使用以下任意命令启动服务：</p>
<pre>
yarn run watch:venia
yarn run watch:all
yarn run build && npm run stage:venia
<font>
</pre>
<p>上面的命令可能会给出权限错误，为此运行上面的命令要带上sudo。</p>
<p>您可以从<a href="https://magento-research.github.io/pwa-studio/venia-pwa-concept/setup/#run-the-server" target="_blank" rel="nofollow">Venia店面设置中</a>找到有关上述命令的更多信息</p>
<p>12.现在浏览应用程序，您将在终端上看到应用程序的URL，如：</p>
<pre>PWADevServer ready at https://magento-venia.local.pwadev:8001</pre>
<pre>或者</pre>
<pre>
Launching staging server...

https://magento-venia.local.pwadev:51828/

Staging server running at the address above.
</pre>
<p><strong>注意：</strong>您可能会遇到PWA上未加载产品图像的问题。<br>
要解决此问题，请创建一个虚拟主机，因为我创建了<strong>https://magento2-pwa.com</strong>，它必须指向Magento实例的pub目录，而不是指向magento的根目录。</p>
<p>恭喜！您已为Venia主题项目设置了开发环境。</p>]]></description>
      <pubDate>Sat, 20 Apr 2019 09:08:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[20个澳大利亚的Magento知名在线网站]]></title>
      <link>https://www.360magento.com/blog/magento-aus/</link>
      <description><![CDATA[<p>近几年，澳大利亚电子商务市场增速变得迅猛，然而电子商务平台的选择是在线平台的成功关键。 Magento具有许多优势，如开源，搜索引擎优化和移动友好，各种营销工具，高安全性和多个商店; Magento是满足所有在线购物偏好的理想平台。以下是澳大利亚Magento电子商务网站的20个在线示例将告诉你为什么选择Magento是值得的。</p>
<h2>Valley Girl</h2>
<p><img alt="Magento网站AU" class="aligncenter wp-image-11453" height="465" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-site-AU.png" width="950" /></p>
<p style="text-align: center;"><em><strong>valleygirl.com.au</strong></em></p>
<p>Valley Girl于1996年在新南威尔士州Penrith推出，被公认为15至25岁女性的领先快速时尚零售商之一。他们的Magento网站完全响应式，易于使用和导航，同时完美展示产品图片。</p>
<h2>2.Sportsgirl</h2>
<p style="text-align: center;"><img alt="Magento web AU" class="aligncenter wp-image-11454" height="506" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-web-AU.png" width="950" /><em><strong>sportsgirl.com.au</strong></em></p>
<p style="text-align: left;">Sportsgirl是一个澳大利亚标志性品牌，专注于时尚，美容和配饰。在他们的Magento电子商务网站中，客户可以享受快速结账，在他们的类别页面中有一个很棒的导航菜单，可轻松找到他们想要的东西。</p>
<h2 style="text-align: left;">3.Ice Design</h2>
<p style="text-align: center;"><img alt="Magento网站AU" class="aligncenter wp-image-11455" height="499" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-sites-AU.png" width="950" /><em><strong>icedesign.com.au</strong></em></p>
<p style="text-align: left;">ICE Design是澳大利亚年轻女性时尚的主导力量。通过Magento电子商务开发，他们的在线商店通过现代和简洁的设计为客户带来触觉般购物体验。</p>
<h2 style="text-align: left;">4.Australis</h2>
<p style="text-align: center;"><em><strong><img alt="Au的Magento网站" class="aligncenter size-full wp-image-11457" height="762" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-sites-in-Au.png" width="1565" />australiscosmetics.com.au</strong></em></p>
<p>Australis 化妆品是澳大利亚发展最快的十大化妆品品牌。他们提供各种各样的纯素化妆产品。它的Magento网站有一个快速加载页面体验好和具有现代方便的界面。</p>
<h2>5.Forcast</h2>
<p><img alt="Magento在澳大利亚的网站" class="aligncenter wp-image-11459" height="470" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-sites-in-Australia.png" width="950" /></p>
<p style="text-align: center;"><em><strong>forcast.com.au</strong></em></p>
<p>自1992年成立以来，Forcast已经建立了一个强大的全国性零售店，在全国拥有超过50家精品店，以及强大的在线粉丝。访问他们的网站时，您可以体验许多有趣的电子商务功能，支持多种货币，多语言和多商店。</p>
<h2>6.Forever New</h2>
<p><img alt="Magento网站在澳大利亚" class="aligncenter wp-image-11460" height="570" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-site-in-australia.png" width="950" /></p>
<p style="text-align: center;"><strong><em>forevernew.com.au</em></strong></p>
<p style="text-align: left;">Forever New成立于澳大利亚墨尔本，以其轻松穿戴和永恒的系列而闻名，这些系列产品展现了现代女性气质。他们的Magento网站提供了流畅的用户体验和简单的导航，使您可以轻松浏览产品。</p>
<h2 style="text-align: left;"><strong>7. Roxy</strong></h2>
<p style="text-align: center;"><em><strong><img alt="Magento网站在Au" class="aligncenter wp-image-11461" height="454" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-website-in-Au.png" width="950" />roxyaustralia.com.au</strong></em></p>
<p style="text-align: left;">Roxy是一个生活方面品牌，为潮流女孩生活的方方面面提供产品，从手提包到亨利，从潜水衣到潮牌手表。它的在线商店由Magento设计开发，因此它具有出色的设计，智能分类和信息丰富的产品页面。</p>
<h3 style="text-align: left;">8.Bonds</h3>
<p style="text-align: center;"><em><strong><img alt="Magento网站在澳大利亚" class="aligncenter wp-image-11463" height="543" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-web-in-Australia.png" width="950" />bonds.com.au</strong></em></p>
<p style="text-align: left;">来自一家小众女性用品制造商，Bonds已成为澳大利亚最具代表性的品牌之一。他们拥有直观简洁的Magento网站以及智能且用户友好的设计。</p>
<h2 style="text-align: left;">9.Pretty Little Thing</h2>
<p style="text-align: center;"><em><strong><img alt="Magento网AU" class="aligncenter wp-image-11467" height="456" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-webs-AU.png" width="950" />prettylittlething.com.au</strong></em></p>
<p style="text-align: left;">Pretty Little Thing是一个年轻的时尚品牌，旨在为女性时尚带来不一样的杀手锏，实惠的风格。它是在Magento电子商务平台上开发的，具有年轻，自由和现代的外观。</p>
<h2>10. Suzannegrae</h2>
<p style="text-align: center;"><em><strong><img alt="非盟现场网站Magento" class="aligncenter wp-image-11468" height="681" src="https://www.tigren.com/wp-content/uploads/2019/03/Live-website-Magento-in-AU.png" width="950" />suzannegrae.com</strong></em></p>
<p style="text-align: left;">Suzannegrae不仅销售服装，还为女性创造灵感。在Magento的帮助下，该网站提供了一个很好的导航菜单在他们的类别页面中，以帮助客户轻松找到任何产品。</p>
<h2 style="text-align: left;">11.Sussan</h2>
<p style="text-align: center;"><em><strong><img alt="在Au的现场Magento" class="aligncenter wp-image-11469" height="762" src="https://www.tigren.com/wp-content/uploads/2019/03/Live-site-Magento-in-Au.png" width="950" />sussan.com.au</strong></em></p>
<p class="BodyA">为座右铭&ldquo;女行为主,为女性设计，专为女性设计&ldquo;。Sussan是澳大利亚女性最喜欢的时尚品牌。像品牌风格，优雅的店面，方便的产品和目录浏览，这个马根托时尚网站已经吸引了很多女士的注意。</p>
<h2>12. Kath Mandu</h2>
<p style="text-align: center;"><em><strong><img alt="Au的Magento电子商务网站" class="aligncenter wp-image-11470" height="495" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-e-commerce-web-in-Au.png" width="950" />kathmandu.com.au</strong></em></p>
<p style="text-align: left;">Kathmandu设计的装备可以承载起家乡的崎岖景观，并为人们提供冒险精神。他们拥有简单和出色的智能类别，允许内容和产品在网站上巧妙地显示。</p>
<h2 style="text-align: left;">13.Dangerfield</h2>
<p style="text-align: left;"><span style="font-size: 24px; font-weight: bold; text-align: left;"><img alt="Magento开发公司" class="aligncenter size-full wp-image-11471" height="710" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-development-company.png" width="1181" /></span></p>
<p style="text-align: center;"><em><strong>shop.dangerfield.com.au</strong></em></p>
<p style="text-align: left;">美国Magento网站的一个简单而有效的网站，导航中的目录快速排序似乎是一个非常有用的功能。Dangerfield提供大量的制服，装备和精神装。</p>
<p style="text-align: left;"><span style="font-size: 24px; font-weight: bold; text-align: left;">14.Well Made Clothes</span></p>
<p style="text-align: center;"><em><strong><img alt="" class="aligncenter wp-image-11474" height="460" src="https://www.tigren.com/wp-content/uploads/2019/03/Au-website-Magento.png" width="950" />wellmadeclothes.com</strong></em></p>
<p style="text-align: left;">制作精良的服装产品来基于手工制作，极少浪费和可持续发展的要求。这家商店拥有现代而干净的设计，旨在使其时尚产品脱颖而出。</p>
<h2 style="text-align: left;">15. DC Shoes</h2>
<p style="text-align: center;"><strong><img alt="Magento开发公司" class="aligncenter wp-image-11475" height="465" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-developer-company.png" width="950" />dcshoes.com.au</strong></p>
<p style="text-align: left;">DC成立于1994年，迅速发展成为高性能滑板鞋和著名运动品牌的领导者。该网站采用Magento制作，具有高端图像，现代简约设计。</p>
<h2 style="text-align: left;">16. Showpo</h2>
<p style="text-align: center;"><em><strong><img alt="澳大利亚Magento网站" class="aligncenter wp-image-11476" height="418" src="https://www.tigren.com/wp-content/uploads/2019/03/Australia-Magento-web.png" width="950" />showpo.com</strong></em></p>
<p style="text-align: left;">Showpo是一家位于澳大利亚阳光明媚的悉尼的在线时装公司。他们的Magento网站在着陆页面上有各种类别，可以为您提供许多产品和信息。</p>
<h2 style="text-align: left;">17.The Upside Sport</h2>
<p style="text-align: center;"><em><strong><img alt="澳大利亚Magento开发商" class="aligncenter wp-image-11477" height="472" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-developer-in-australia.png" width="950" />theupsidesport.com</strong></em></p>
<p style="text-align: left;">The Upside致力于通过运动服装实现健康生活方式的理念。这是一个优秀的Magento网站，既方便用户使用，又具有视觉吸引力。</p>
<h2 style="text-align: left;">18. Priceline</h2>
<p style="text-align: center;"><em><strong><img alt="Magento公司" class="aligncenter wp-image-11478" height="496" src="https://www.tigren.com/wp-content/uploads/2019/03/Magento-company.png" width="950" />priceline.com.au</strong></em></p>
<p style="text-align: left;">通过Priceline网站，您可以在线商店中播放，探索超过13,000种产品并以前所未有的方式参与在线空间。</p>
<h2 style="text-align: left;">19. King Living</h2>
<p style="text-align: center;"><em><strong><img alt="澳大利亚Magento开发人员" class="aligncenter wp-image-11479" height="486" src="https://www.tigren.com/wp-content/uploads/2019/03/Australia-Magento-developer.png" width="950" />kingliving.com.au</strong></em></p>
<p style="text-align: left;">King Living是澳大利亚领先的家具设计品牌，拥有许多屡获殊荣的产品。它也是澳大利亚Magento电子商务网站的典型例子之一，它具有漂亮的外观设计。</p>
<h2 style="text-align: left;">20. Mocka<img alt="澳大利亚Magento电子商务网站的例子" class="aligncenter wp-image-11480" height="446" src="https://www.tigren.com/wp-content/uploads/2019/03/examples-magento-e-commerce-website-in-Australia.png" width="950" /></h2>
<p style="text-align: center;"><em><strong>mocka.com.au</strong></em></p>
<p>Mocka是澳大利亚的另一个家具品牌，专注于儿童，幼儿园，家居和生活家具。它建立在Magento之上，提供消费者在网上购物时所需的所有功能。</p>
<p>这就是澳大利亚Magento电子商务网站的20个典型例子，我们希望为您的电子商务网站提供启发。如果您正在寻找最好的<a href="https://www.tigren.com/magento-development-australia/">Magento开发公司</a>，我们很乐意帮助您在澳大利亚建立您的Magento电子商务网站。</p>
<p><strong><a href="https://www.360magento.com.com/contacts/"></a></strong>&nbsp;现在就<strong><a href="https://www.360magento.com.com/contacts/">联系我们</a></strong>，获取您的项目详细建议书，并评估时间和费用。</p>]]></description>
      <pubDate>Fri, 05 Apr 2019 11:04:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2  Demo站点在线演示]]></title>
      <link>https://www.360magento.com/blog/magento-2-demo/</link>
      <description><![CDATA[<div class="card">
<div class="card-image"><img alt="Magento 2演示" class="responsive-img" src="https://cdn.mageplaza.com/media/general/VHoUupD.jpg" /></div>
<div class="card-content" id="kb-content">
<p><strong><a href="/magento-2-demo">Magento 2 演示</a></strong>是在线演示站点，它带来了Magento2的真实体验，而不是在localhost上安装Magento 2。带有示例数据的Magento 2 演示Demo允许您作为前端的客户进行交互，并在后端作为管理员进行操作</p>
<p>使用在线<strong>Magento 2后台演示</strong>是一个完美的解决方案，可以帮助您在不进行任何安装的情况下享受Magento 2的所有功能。360Magento技术团队的及时协助确保该演示能够很好地运行。</p>
<p>我们收集互联网上的部分在线演示站点，以帮助商家，开发人员快速了解Magento 2。</p>
<div class="row">
<div class="col s6">
<h2>Magento 2站点演示：＃1 Blackbird</h2>
<div>
<p><a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://demo-acm-2.bird.eu/" rel="nofollow" target="_blank">前端</a> <a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://demo-acm-2.bird.eu/admin" rel="nofollow" target="_blank">后端</a></p>
</div>
</div>
<div class="col s6">
<h2>Magento 2站点演示：＃2 BSS</h2>
<div>
<p><a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://104.237.149.38/magento225/" rel="nofollow" target="_blank">前端</a> <a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://104.237.149.38/magento225/admin" rel="nofollow" target="_blank">后端</a></p>
<ul>
<li>用户名：admin</li>
<li>密码：admin123</li>
</ul>
</div>
</div>
<div class="col s6">
<h2>Magento 2站点演示：＃3 Bublue Demo</h2>
<div>
<p><a class="waves-effect waves-light btn" href="http://blankrefer.com/?https://magento.nublue.co.uk/" rel="nofollow" target="_blank">前端</a> <a class="waves-effect waves-light btn" href="http://blankrefer.com/?https://magento.nublue.co.uk/admin" rel="nofollow" target="_blank">后端</a></p>
<ul>
<li>用户名：admin</li>
<li>密码：nublue2test</li>
</ul>
</div>
</div>
<div class="col s6">
<h2>Magento 2站点演示：＃4 Magedirect</h2>
<div>
<p><a class="waves-effect waves-light btn" href="http://blankrefer.com/?https://demo1-m2.mage.direct/" rel="nofollow" target="_blank">前端</a> <a class="waves-effect waves-light btn" href="http://blankrefer.com/?https://demo1-m2.mage.direct/admin" rel="nofollow" target="_blank">后端</a></p>
<ul>
<li>用户名：demo</li>
<li>密码：demo123</li>
</ul>
</div>
</div>
<div class="col s6">
<h2>＃5 Firebearstudio演示</h2>
<div>
<p><a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://magento2demo.firebearstudio.com/" rel="nofollow" target="_blank">前端</a> <a class="waves-effect waves-light btn" href="http://blankrefer.com/?http://magento2demo.firebearstudio.com/admin_1vbjqf/" rel="nofollow" target="_blank">后端</a></p>
<ul>
<li>用户名：demo</li>
<li>密码：1q2w3e4r5t</li>
</ul>
</div>
</div>
</div>
<div class="row center" style="padding-top: 20px;"><a href="https://www.mageplaza.com/magento-2-one-step-checkout-extension/?utm_source=mageplaza&amp;utm_medium=banner&amp;utm_campaign=kb"> <img alt="Mageplaza为Magento 2一步到位" class="responsive-img" src="https://i.imgur.com/JzvQvQF.jpg" /> </a></div>
<h2 id="magento-2-demo-features">Magento 2演示介绍</h2>
<p>使用管理员权限登录后端，然后密切关注管理后端侧栏。</p>
<p><img alt="Magento 2演示管理员登录" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/UzJUxle.png" style="display: inline;" /></p>
<p>主要部分包括 <strong>Dasboard</strong>, <strong>Sales</strong>, <strong>Products</strong>, <strong>Customers</strong>, <strong>Marketing</strong>, <strong>Content</strong>, <strong>Reports</strong>, <strong>Stores</strong>, <strong>System</strong>, 和 <strong>Find partner extensions</strong>.</p>
<p>我们来看看每个部分的细节。</p>
<h3 id="dashboard">Dasboard</h3>
<p>您在Magento 2后端主页上。在主页的顶部，如果有与Magento 2 后端演示相关的任何更新，您可以按照系统通知进行操作。</p>
<p><img alt="Magento 2 Demo DashBoard" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/cSEefy6.png" style="display: inline;" data-original="https://cdn.mageplaza.com/media/general/cSEefy6.png" /></p>
<ul>
<li>
<p>Magento 2的Dasboard(仪表盘)显示了重要的数据指标，包括：</p>
<ul>
<li>Lifetime Sales-- 终身销售</li>
<li>Average Order-- 平均订单</li>
<li>Last Order -- 最近的订单</li>
<li>Last Search Terms -- 最近搜索词</li>
<li>Top Search Terms -- 热门搜索字词</li>
</ul>
</li>
</ul>
<p>在屏幕截图中是给出的示例，其中包含个人信息和订单信息等示例样本数据。</p>
<ul>
<li>
<p>在DashBoard(仪表盘)上，网站管理员可以跟踪特定时间段内的产品收入，税额，运输和数量。可以在下拉框中按时间过滤。</p>
<ul>
<li>Last 24 hours -- 过去24小时</li>
<li>Last 7 days -- 过去7天</li>
<li>Current Month -- 这个月</li>
<li>Year to Date (YTD) -- 年初至今（年月日）</li>
<li>2 Year to Date (2YTD) -- 2年至今（2YTD）</li>
</ul>
</li>
</ul>
<p>根据统计数据，店主将对每个时间段内的在线销售进行比较。</p>
<ul>
<li>为了获得更好的帮助，您的营销和<a href="https://marketplace.magento.com/mageplaza-magento-2-seo-extension.html">搜索引擎优化</a>团队可以按照畅销产品和观看次数最多的产品列表，这是在下一次建立更好的广告系列的最基本的，如保持最好的产品的稳定，并为不太受欢迎的项目提供折扣。</li>
</ul>
<h3 id="sales">Sales(订单)</h3>
<p>继续<strong>Sales</strong>部分，您可以管理完整的信息</p>
<h4 id="orders">订单</h4>
<ul>
<li>点击<code class="highlighter-rouge">Sales</code>，选择<code class="highlighter-rouge">Orders</code>。</li>
<li>在订单管理网格上，通过以下参数可以很好地控制网站中的所有订单：
<ul>
<li><strong>ID -- 订单ID</strong></li>
<li>Purchase Point（购买点)，如果您拥有多个商店，将指出订单所在的商店</li>
<li><strong>Purchase Date -- 购买日期</strong></li>
<li><strong>Bill-to-Name -- 账单名字</strong></li>
<li><strong>Ship-to-Name --收货人名字</strong></li>
<li><strong>Grand Total</strong>(Base) -- 总计（基数）</li>
<li><strong>Grand Total</strong> -- <strong>总计</strong>（已购买）</li>
<li><strong>Status</strong> -- <strong>状态</strong>可能是Completed, Processing, Pending等，具体取决于您的设置。</li>
</ul>
</li>
<li>在<strong>&ldquo;Action&rdquo;</strong>列下，单击<code class="highlighter-rouge">View</code>链接以导航到其详细信息页面以查看订单。</li>
<li>如果通过线下电话或电子邮件完成订单，可以使用&ldquo; <strong>Create New Order </strong>&rdquo;按钮手动填写订单信息，这将有助于您很好地管理库存。</li>
<li>如果需要，可以将所有数据导出为CSV或XML文件。</li>
</ul>
<p><img alt="Magento 2演示订单管理" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-orders.gif" style="display: inline;" data-original="https://cdn.mageplaza.com/docs/magento-2-demo-orders.gif" /></p>
<h4 id="invoices">Invoices（发票）</h4>
<ul>
<li>点按<code class="highlighter-rouge">Sales</code>，选择<code class="highlighter-rouge">Invoices</code>。</li>
<li>所有发票信息都在网格表上进行管理：
<ul>
<li>Invoice ID -- 发票ID</li>
<li>Invoice Date -- 发票日期</li>
<li>Order ID -- 订单ID</li>
<li>Order Date -- 订购日期</li>
<li>Bill-to-Date --比尔最新</li>
<li>Status -- 状态</li>
<li>Grand Total (Base) -- 总计（基数）</li>
<li>Grand Total (Purchased) -- 总计（已购买）</li>
</ul>
</li>
<li>在<strong>&ldquo;Action&rdquo;</strong>列下，单击<code class="highlighter-rouge">View</code>链接以导航到详细信息页面以查看发票。</li>
<li>如果需要，可以将所有数据导出为CSV或XML文件。</li>
</ul>
<p><img alt="Magento 2演示发票管理" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-invoices.gif" style="display: inline;" data-original="https://cdn.mageplaza.com/docs/magento-2-demo-invoices.gif" /></p>
<h4 id="shipments">Shipments（货物运输）</h4>
<ul>
<li>点按<code class="highlighter-rouge">Sales</code>，选择<code class="highlighter-rouge">Shipments</code>。</li>
<li>所有货件信息都在网格列表上管理：
<ul>
<li>Shipment ID -- 装运ID</li>
<li>Shipment Date -- 发货日期</li>
<li>Order ID -- 订单ID</li>
<li>Order Date -- 订购日期</li>
<li>Ship-to-Name -- 收货人名字</li>
<li>Total Quantity -- 总计数量</li>
</ul>
</li>
<li>在<strong>&ldquo;Action&rdquo;</strong>列下，单击<code class="highlighter-rouge">View</code>链接以导航到详细信息页面以查看货件。</li>
<li>如果需要，可以将所有数据导出为CSV或XML文件。</li>
</ul>
<p><img alt="Magento 2 Demo Shipments Management" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-shipments.gif" style="display: inline;" data-original="https://cdn.mageplaza.com/docs/magento-2-demo-shipments.gif" /></p>
<h4 id="transactions">Transactions(交易)</h4>
<ul>
<li>点按<code class="highlighter-rouge">Sale</code>，选择<code class="highlighter-rouge">Transactions</code>。</li>
<li>您网站上发生的每笔付款都将列在网格下，例如订单，授权，捕获，无效和退款。您可以追踪：
<ul>
<li>ID -- ID</li>
<li>Order ID -- 订单ID</li>
<li>Transaction ID -- 交易ID</li>
<li>Parent Transaction ID -- 父交易ID</li>
<li>Payment Method -- 付款方法</li>
<li>Transaction Type -- 交易类型</li>
<li>Closed -- 已关闭</li>
<li>Created -- 已创建</li>
</ul>
</li>
</ul>
<p><img alt="Magento 2 Demo Transactions Management" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-transactions.gif" style="display: inline;" data-original="https://cdn.mageplaza.com/docs/magento-2-demo-transactions.gif" /></p>
<h3 id="products">Products(产品)</h3>
<p>您可以在产品的类目下详细了解您的库存状态。在这里，如果需要，可以知道库存中的单个产品的数量，添加新的产品，更改或删除任何产品。</p>
<h4 id="catalog">目录</h4>
<ul>
<li>在管理员面板上<code class="highlighter-rouge">Sales &gt; Catalog</code>。</li>
<li></li>
</ul>
<h3 id="customers">Customers -- 客户</h3>
<h3 id="marketing">Marketing -- 营销</h3>
<h3 id="content">Content -- 内容</h3>
<h3 id="reports">Reports -- 报告</h3>
<p>从Magento 2开始，报告可通过5个小节更好地跟踪您的业务：<strong>Marketing</strong>, <strong>Sales</strong>, <strong>Customers</strong>, <strong>Products</strong>, and <strong>Reviews</strong>.</p>
<h4 id="marketing-1">Marketing（营销)</h4>
<p><strong>Product in cart(购物车中的产品)</strong></p>
<p>您将访问的第一份有关营销的报告是购物车报告中的产品，请执行以下操作：</p>
<ul>
<li>在<strong>&ldquo;Report&rdquo;</strong>部分中<code class="highlighter-rouge">Marketing</code>，选择<code class="highlighter-rouge">Product In Cart</code>。</li>
<li>在网格列表中，购物车中的所有最近产品都列出了包括 ID, Product, Price, Carts, 和 Orders选项列。</li>
<li>要查看详细报告，请单击所需项目的行，然后将您定向到其产品页面。</li>
</ul>
<p><img alt="Magento 2演示营销产品在购物车中" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/ohQPfqv.png" style="display: inline;" /></p>
<p><strong>Search Terms(搜索字词)</strong></p>
<p>搜索条件是客户在您的商店进行活动时的搜索查询的完整报告。这有助于调查客户的想法。</p>
<ul>
<li>继续使用<code class="highlighter-rouge">Marketing</code>子选项卡，选择<code class="highlighter-rouge">Search Terms</code>。</li>
<li>通过以下参数显示最近搜索词报告：Search Query, Store, Results, Uses, Redirect URL, Suggested Terms, 和 Action.。</li>
<li>要了解输入搜索词时显示的结果数以及搜索词搜索的次数，请打开<strong>Edit</strong>模式以根据需要跟踪和修改任何信息。</li>
</ul>
<p><img alt="Magento 2演示营销搜索条款" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/Hnyf74B.png" style="display: inline;" /></p>
<p><strong>Abandoned Cart(被遗弃的购物车)</strong></p>
<p>此报告允许您自动存储任何将产品添加到购物车并放弃购买的客户。</p>
<ul>
<li>转到<code class="highlighter-rouge">Abandoned Cart</code>选项。</li>
<li>为了更好地管理，abandonment carts列出了全部信息，其中包含Products, Quantity, Subtotal, 和 Applied Coupon。</li>
</ul>
<p>根据有用的详细信息，您可以得到正确的解决方案并发送具有适当折扣的电子邮件以将其挽回。</p>
<ul>
<li>单击每一行以获取更多信息。</li>
</ul>
<p><img alt="Magento 2演示营销被遗弃的购物车" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/qJaml6T.png" style="display: inline;" /></p>
<p><strong>Newsletter Problem Report（通讯问题报告）</strong></p>
<p>该图表显示了与<a href="https://www.mageplaza.com/magento-2-newsletter-popup/">新闻邮件订阅</a>相关的所有问题。所有这些都保存在时事通讯问题报告中。此外，还可以根据问题报告的日期、错误代码、错误文本和队列主题对它们进行排序。</p>
<p><img alt="Magento 2演示营销通讯问题报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/V95ruyB.png" style="display: inline;" /></p>
<h4 id="sales-1">Sales(销售)</h4>
<p>从Magento 2 Admin Demo，通过以下快捷方式可以很好地记录<a href="https://www.mageplaza.com/magento-2-reports-extension/">销售报告</a>：</p>
<ul>
<li>Orders</li>
<li>Tax</li>
<li>Invoiced</li>
<li>Shipping</li>
<li>Refunds</li>
<li>Coupons</li>
<li>Paypal Settlement</li>
<li>Braintree Settlement.</li>
</ul>
<p>让我们以订单报告为例：</p>
<ul>
<li>在<strong>Filter </strong>部分下，您需要执行以下操作：
<ul>
<li><code class="highlighter-rouge">Date Used</code>为图表设置，它可能是<strong>Order Created</strong>或<strong>Order Updated</strong>。</li>
<li>在<code class="highlighter-rouge">Period</code>字段中选择需要的时间段。</li>
<li>通过点击<code class="highlighter-rouge">From</code>和<code class="highlighter-rouge">To</code>字段中的日历图标来设置特定时间。</li>
<li>选择类型时允许显示顺序<code class="highlighter-rouge">Order Status</code>。如果选择&ldquo;Any&rdquo;，它将应用于除已取消订单之外的所有订单状态。</li>
<li>根据需要设置<code class="highlighter-rouge">Empty Row</code>为&ldquo;Yes&rdquo;或&ldquo;No&rdquo;。</li>
<li>当选择&ldquo;Yes&rdquo;时，使当前的值可见。</li>
</ul>
</li>
<li>完成筛选后，将通过Ajax加载图表。</li>
</ul>
<p><img alt="Magento 2演示订单报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/CnHPrxJ.png" style="display: inline;" /></p>
<h4 id="customers-1">Customers(客户)</h4>
<p>此报告将显示客户创建的订单总数。</p>
<ul>
<li>按日期过滤以加载下面的报告。</li>
<li>单击特定行以获取详细信息。</li>
<li>重复上述指南以报告订单计数报告。</li>
</ul>
<p><img alt="Magento 2演示客户报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/ICL2Tac.png" style="display: inline;" /></p>
<h4 id="products-1">Products(产品)</h4>
<p>在产品报告中，商店所有者可以保存包括大多数已查看产品，畅销商品，低库存，订购和下载的数据。</p>
<ul>
<li>按日期过滤以通过Ajax加载产品报告。</li>
<li>单击特定行以获取详细信息。</li>
<li>重复上述步骤以报告其他图表。</li>
</ul>
<p>基于您可以看到的静态信息，它有助于为您的产品构建一个智能的广告活动。</p>
<p><img alt="Magento 2演示产品报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/7HsmlPR.png" style="display: inline;" /></p>
<h4 id="reviews">Reviews(评价)</h4>
<p>登录Magento 2 Demo，您可以按客户或按产品跟踪审核报告。该报告将列出客户对您产品的全面评价。</p>
<p><img alt="Magento 2演示评论报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/qkLory9.png" style="display: inline;" /></p>
<h4 id="statictis">Statictis(统计)</h4>
<ul>
<li>在<code class="highlighter-rouge">Statictis</code>下面，点击并转到<code class="highlighter-rouge">Refresh Statictis</code>工作场所。</li>
<li>标记相应报告的一个或多个复选框</li>
<li>在左上角，从下拉框中选择刷新类型：刷新生命周期状态或刷新最后一天的状态。</li>
<li>单击<code class="highlighter-rouge">Submit</code>按钮刷新数据。</li>
</ul>
<p><img alt="Magento 2演示刷新Statictis" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/Q1QUtgX.png" style="display: inline;" data-original="https://cdn.mageplaza.com/media/general/Q1QUtgX.png" /></p>
<h3 id="stores">商店</h3>
<p>在<code class="highlighter-rouge">Stores</code>选项卡中，您可以使用5个子选项，如： Settings, Taxes, Currency, Attributes, 和 Other Settings。</p>
<h4 id="settings">设置(Settings)</h4>
<p>在本节中，您将在商店中看到一些常规配置。</p>
<p><strong>All Stores（所有商店）</strong></p>
<p>如果有多家商店，那么非常适合在这里管理，包括网站，商店和商店视图。</p>
<p>在右上角，您可以有3个操作：Create Website, Create Store View, 和 Create Store。</p>
<ul>
<li>要创建新的商店视图，
<ul>
<li>单击<strong>&ldquo;Create Store View</strong>按钮</li>
<li>设置<code class="highlighter-rouge">Store</code>为新商店视图指定商店。</li>
<li>设置<code class="highlighter-rouge">Name</code>为新的。</li>
<li>输入商店视图的<code class="highlighter-rouge">Code</code>。</li>
<li>在字段<code class="highlighter-rouge">Status</code>中选择已<strong>启用</strong>。</li>
<li>如有必要，您可以在商店视图列表中进行设置<code class="highlighter-rouge">Sort Order</code>。</li>
</ul>
</li>
</ul>
<p><img alt="Magento 2 Demo New Store View" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/7DTVtqU.png" style="display: inline;" /></p>
<ul>
<li>去创建新的商店，
<ul>
<li>点击<strong>Create Store</strong>按钮。</li>
<li>选择<code class="highlighter-rouge">Website</code>显示新商店。</li>
<li>设置<code class="highlighter-rouge">Name</code>。</li>
<li>从可用的类别列表中进行选择<code class="highlighter-rouge">Root Category</code>。</li>
</ul>
</li>
</ul>
<p><img alt="Magento 2演示新店" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/7DTVtqU.png" style="display: inline;" /></p>
<ul>
<li>去创建新网站，
<ul>
<li>单击<strong>&ldquo;Create Website &rdquo;</strong>按钮。</li>
<li>输入<code class="highlighter-rouge">Name</code>。</li>
<li>输入新网站<code class="highlighter-rouge">Code</code>。</li>
<li>如有必要，您可以在商店视图列表中进行设置<code class="highlighter-rouge">Sort Order</code>。</li>
</ul>
</li>
</ul>
<p><img alt="Magento 2演示新网站" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/bAT4Y23.png" style="display: inline;" /></p>
<p><strong>Configuration(配置)</strong></p>
<p>您可以从<strong>Configuration</strong>选项卡执行许多操作，但需要关注的主要部分是构建基本的Magento商店：</p>
<ul>
<li>Design(设计)</li>
</ul>
<p>该部分还有助于设计主题，上传Logo和网站标题，默认关键字和其他脚本。特别是，从Design中，您还可以配置搜索引擎机器人以获得更好的SEO。此外，管理员还可以自定义公司徽标的大小，然后将其上传到站点的页眉和页脚。</p>
<p><img alt="Magento 2演示设计" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/it05jKg.png" style="display: inline;" /></p>
<ul>
<li>Contact(联系)</li>
</ul>
<p><img alt="Magento 2演示联系人" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/4dkpROh.png" style="display: inline;" /></p>
<ul>
<li>Reports(报告)</li>
</ul>
<p>报告是高级工具，因此可以评估您的工作效率并以正确的方式推动它。从Magento 2 Admin，您可以设置时间在仪表板上将报告显示为默认值。</p>
<p><img alt="Magento 2演示报告" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/PQCvnbF.png" style="display: inline;" /></p>
<ul>
<li>Content Management(内容管理)</li>
</ul>
<p><strong>Content Management</strong>部分为您提供WYSIWYG编辑器工具，可以帮助您轻松上传新的网页，博客文章等。</p>
<p><img alt="Magento 2演示管理" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/aLx9zfh.png" style="display: inline;" /></p>
<ul>
<li>Catalog(类目)</li>
</ul>
<p>在<strong>Catalog</strong>配置中，您可以自由设置各种选项。例如，您可以在标记SKU，元标题，关键字和描述时完成产品字段自动生成。此外，可以允许客人在产品上进行评论。该部分还可以更好地控制店面，包括网格或列表模式中每页产品的数量，产品列表排序，产品和类别中的动态媒体URL以及每个产品的样本。此外，从本节开始可以配置越来越多的操作，登录Magento Admin以了解详细信息。</p>
<p><img alt="Maento 2演示目录" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/yOZKfzZ.png" style="display: inline;" /></p>
<h3 id="system">System(系统)</h3>
<p>在管理侧栏上，移动到<strong>System</strong>工作区，您可以使用以下部分在系统中创建许多设置。</p>
<p><strong>Data Transfer(数据传输)</strong></p>
<ul>
<li>Import/ Export(导入 / 导出)</li>
</ul>
<p>在<strong>Data Transfer</strong>下，您可以上传任何大小为25Mb的外部文件。这样可以方便地将数据从其他平台导入Magento而不会丢失任何重要信息。</p>
<p><img alt="Magento 2演示导入数据" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/keOCcJd.png" style="display: inline;" /></p>
<p>从该<code class="highlighter-rouge">Entity type</code>字段的下拉列表中，您可以选择其中之一：Advanced Pricing, Products, Customer 和 Addresses,。此外，Magento 2 Demo附带了Sample Data，可帮助您尝试导入数据。</p>
<p>此外，您可以导出任何csv文件。根据导出文件的实体类型，您可以通过标记相应的复选框来考虑需要导出的属性。</p>
<ul>
<li>Import/Export Tax Rates(导入导出税率)</li>
</ul>
<p>在Magento 2 Demo中，管理员可以根据您的需要轻松导入/导出Magento和其他平台之间的税率。</p>
<p><img alt="Magento 2 Demo导入出口税率" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/IcfDXyG.png" style="display: inline;" /></p>
<ul>
<li>Import History(导入历史记录)</li>
</ul>
<p>保存与Magento Admin中导入文件相关的所有活动。多亏了这一点，您始终可以跟踪将哪个文件导入您的网站。</p>
<p><img alt="Magento 2演示导入历史记录" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/C9zTKej.png" style="display: inline;" /></p>
<p><strong>Extension(扩展)</strong></p>
<p>进入子选项<code class="highlighter-rouge">Integration</code>，这使商店管理员可以更好地管理集成到他的商店中的每个模块。</p>
<p>要创建新的集成，您需要执行以下操作：</p>
<ul>
<li>单击<strong>Add New Integration</strong>按钮。</li>
<li>在左侧面板上完成<code class="highlighter-rouge">Integration Info</code>和<code class="highlighter-rouge">API</code>。</li>
</ul>
<p><img alt="Magento 2演示集成" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-integration.gif" style="display: inline;" /></p>
<p><strong>Tools(工具)</strong></p>
<p>在此选项卡中，商店管理员可能刷新缓存以确保所有配置始终是最新的。</p>
<p><img alt="Magento 2演示缓存管理" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/KkZjr4Z.png" style="display: inline;" /></p>
<p>此外，您还可以使用其他工具，包括：Backups, Index Management, 和 Web Setup Wizard.</p>
<p><strong>Permissions(权限)</strong></p>
<p><strong>Permissions</strong>部分显示Magento商店中包含活动用户，锁定用户以及每个用户的特定角色的所有用户的列表。</p>
<p>作为管理员，您可以按照以下指南从Admin Demo添加无限制的新用户：</p>
<ul>
<li>在<strong>Permissions</strong>下，选择<code class="highlighter-rouge">All Users</code>子选项卡。</li>
<li>在右上角，单击<code class="highlighter-rouge">Add New User</code>。</li>
<li>填写新用户的基本信息：User Name, First Name, Last Name, Email, 和 Password。</li>
<li>在<code class="highlighter-rouge">Current User Identity Verification</code>部分中的验证密码</li>
<li>将用户分配到商店中的特定角色。</li>
</ul>
<p><img alt="Magento 2 Demo创建新用户" class="lazy responsive-img" src="https://cdn.mageplaza.com/docs/magento-2-demo-create-new-user.gif" style="display: inline;" /></p>
<p>**其他设置**</p>
<ul>
<li>Notifications(通知)</li>
</ul>
<p>如果Magento有任何更新或您的系统或客户信息黑客漏洞问题，<strong>Notifications</strong>自选项将包括详细通知。根据信息重要性，很重要的它与红色标签一起显示 - &ldquo;CRITICAL&rdquo;，不太紧急的报告附在&ldquo;NOTICE&rdquo;标签上。</p>
<p><img alt="Magento 2演示通知" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/yAA76Nd.png" style="display: inline;" /></p>
<ul>
<li>Custom Variables(自定义变量)</li>
</ul>
<p>允许跟踪产品的所有自定义变量，包括新变量和现有变量。</p>
<p><img alt="Magento 2演示自定义变量" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/myWnbD0.png" style="display: inline;" /></p>
<ul>
<li>Manage Encrytion Key(管理加密密钥)</li>
</ul>
<p>可以保护您的密码以及敏感文档。您可以通过自动或手动生成密钥来加密数据。</p>
<p><img alt="Magento 2演示管理加密密钥" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/nhW4hIi.png" style="display: inline;" /></p>
<h3 id="find-partner--extensions">Find partner &amp; extensions(查找合作伙伴&amp;扩展程序)</h3>
<p><strong>Find partner extension</strong>包括Magento Platinum Partners功能，该功能将为商店管理员提供<strong>Featured Platinum Partners</strong>下的Magento合作伙伴列表。这对您的合作有很大的帮助，使您的电子商务业务有显著的发展。。</p>
<p>此外，您还可以找到更多技术合作伙伴，以帮助商家和品牌提供最佳客户体验的扩展和主题，以在<strong>合作伙伴搜索</strong>和<strong>Magento市场</strong>部分增强您的Magento商店。</p>
<p><img alt="Magento 2 Demo查找合作伙伴和扩展程序" class="lazy responsive-img" src="https://cdn.mageplaza.com/media/general/paLKjce.png" style="display: inline;" /></p>
<h2 id="system-requirements">系统要求</h2>
<h3 id="web-services">Web服务器</h3>
<ul>
<li>Apache 2.2或2.4</li>
<li>Nginx 1.8</li>
</ul>
<h3 id="database-engine">数据库引擎</h3>
<ul>
<li>MySQL 5.6</li>
<li>MariaDB</li>
<li>Percona</li>
</ul>
<h3 id="php">PHP</h3>
<ul>
<li>5.6.x</li>
<li>5.5.x，其中x为22或更大</li>
<li>7.0.2至7.1.0，7.0.5除外。不适用于7.0.5</li>
</ul>
<h3 id="php-extensions-requirements">PHP扩展要求</h3>
<ul>
<li>curl</li>
<li>gd, ImageMagick &gt; 6.3.7</li>
<li>intl</li>
<li>mbstring</li>
<li>mcrypt</li>
<li>mhash</li>
<li>openssl</li>
<li>PDO/MySQL</li>
<li>SimpleXML</li>
<li>soap</li>
<li>xml</li>
<li>xsl</li>
<li>zip</li>
<li>json (PHP 7 only)</li>
<li>iconv (PHP 7 only)</li>
</ul>
<h3 id="cache-system">缓存系统</h3>
<ul>
<li>PHP OPcache</li>
<li>Redis (Recommend)</li>
<li>Vanish (Recommend)</li>
<li>mem-cached (Recommend)</li>
</ul>
<h4 id="email-services">邮件服务</h4>
<ul>
<li>邮件传输代理（MTA）</li>
<li>SMTP服务器</li>
</ul>
<h3 id="ssl">SSL</h3>
<ul>
<li>HTTPS需要有效的安全证书。</li>
<li>不支持自签名SSL证书。</li>
<li>传输层安全性（TLS）要求</li>
</ul>
<h3 id="magento-2-enterprise-requirements">Magento 2企业版要求</h3>
<ul>
<li>PHP extension: bc-math</li>
<li>Apache Solr 4.x</li>
<li>RabbitMQ 3.5</li>
<li>Three master databases</li>
</ul>
<h2 id="how-to-install-magento-2">如何安装Magento 2</h2>
<p>本安装指南将向您<strong>展示如何</strong>在您自己的服务器或共享主机上<strong>安装Magento 2</strong> 最新版本。为您的Magento 2商店选择一个很棒的主机。</p>
<h3 id="getting-started-select-solution">入门：选择解决方案</h3>
<p>我们可以开始使用一些解决方案。</p>
<ul>
<li>从Zip文件安装：易于安装，无需命令行。</li>
<li>Metapackage：使用Composer安装Magento</li>
<li>从Git库安装：开发人员贡献</li>
</ul>
<p>在本指南中，我们将展示如何以＃1解决方案安装Magento2。很容易上手。</p>
<h3 id="install-magento-2-step-by-step">一步一步安装Magento 2：</h3>
<ul>
<li>下载Magento程序包</li>
<li>上传到您的服务器</li>
<li>更新权限</li>
<li>运行Magento安装向导</li>
<li>完成安装过程</li>
</ul>
<h4 id="prerequisites">先决条件</h4>
<p>在继续之前，请确保您已完成以下所有操作：</p>
<ul>
<li>设置符合Magento 2系统要求的服务器</li>
<li>创建了Magento文件<a href="https://devdocs.magento.com/guides/v2.1/install-gde/prereq/file-sys-perms-over.html" rel="nofollow">系统所有者</a></li>
</ul>
<h4 id="download-magento-packages">下载Magento软件包</h4>
<p>现在去<a href="https://magento.com/tech-resources/download" rel="nofollow">下载Magento 2</a>，下载Magento Community Edition（CE）的最新版本。</p>
<p>在此处下载最新的<a href="https://github.com/magento/magento2-sample-data/releases" rel="nofollow">样品数据</a></p>
<h4 id="upload-to-your-server">上传到您的服务器</h4>
<p>让我们下载一个zip文件，现在是时候将它上传到服务器了。您可以使用WinSCP，Filezilla上传它，然后将其解压缩到public_html目录（我们称之为：Magento根目录）。</p>
<p>如果您使用的是共享主机，则可以使用解压缩功能来解压Magento包。</p>
<p>如果您在服务器上运行，请按照以下命令操作：</p>
<h5 id="file-format-and-command">文件格式和命令</h5>
<div class="highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code># File .tar.gz  <span>
tar zxf &lt;filename&gt;<span>
<span>
# File .zip<span>
unzip &lt;filename&gt;<span>
<span>
</span></span></span></span></span></span></code></pre>
</div>
</div>
<h4 id="update-permission">更新权限</h4>
<p>为以下文件夹添加写入权限：</p>
<div class="highlighter-rouge">
<div class="highlight">
<pre class="highlight"><code>var<span>
app/etc<span>
pub<span>
</span></span></span></code></pre>
</div>
</div>
<h4 id="running-the-magento-setup-wizard">运行Magento安装向导</h4>
<p>安装向导是一个多页向导，使您可以一步步完成每一页。您不能跳过页面，必须在每个页面上输入所有必需的信息，然后才能继续下一页。</p>
<ul>
<li>在浏览器地址栏中输入以下URL：</li>
</ul>
<p><code class="highlighter-rouge">http://www.example.com/setup</code></p>
<ul>
<li>在初始页面上，单击<code class="highlighter-rouge">Agree and Set Up Magento</code>。</li>
</ul>
<p>按顺序继续以下主题以完成安装。</p>
<h5 id="step-1-readiness-check">第1步：准备检查</h5>
<p>点击<code class="highlighter-rouge">Start Readiness Check</code>。如果显示任何错误，则必须先解决它们，然后才能继续。如果可以，请单击&ldquo;More detail&rdquo;以查看有关每项检查</p>
<p>点击 <code class="highlighter-rouge">Next</code></p>
<h5 id="step-2-add-a-database">第2步：添加数据库</h5>
<p>填写数据库信息，然后单击下一步</p>
<h5 id="step-3-web-configuration">第3步：Web配置</h5>
<p>输入以下信息：</p>
<p>您的店铺地址： <code class="highlighter-rouge">http://www.example.com</code></p>
<p>Magento管理员地址：输入访问Magento管理员的相对URL。例如：secret, backend</p>
<p>然后点击 <code class="highlighter-rouge">Next</code></p>
<h5 id="step-4-customize-your-store">第4步：自定义您的商店</h5>
<ul>
<li>从商店默认时区列表中，单击商店时区的名称。</li>
<li>从商店默认货币列表中，单击要在商店中使用的默认货币。</li>
<li>从商店默认语言列表中，单击要在商店中使用的默认语言。</li>
<li>在安装Magento软件之前，展开&ldquo;Advanced Modules Configuration&rdquo;以选择性地启用或禁用模块。</li>
</ul>
<p><img class="lazy responsive-img alt=" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" /></p>
<p>点击 <code class="highlighter-rouge">Next</code></p>
<h6 id="important">重要！</h6>
<p>请谨慎使用单个模块跳过依赖性检查。我们建议不要使用它，因为此错误的典型原因是您手动编辑了部署配置。建议不要编辑部署配置，因为将来的Magento软件更新可以撤消您的更改。</p>
<h5 id="step-5-create-admin-account">第5步：创建管理员帐户</h5>
<p>要<a href="https://www.mageplaza.com/kb/how-to-create-new-admin-user-magento-2.html">创建新的管理员帐户，</a>您需要输入管理员信息，例如</p>
<ul>
<li>新用户名</li>
<li>新邮件</li>
<li>新密码</li>
<li>确认密码</li>
<li>然后单击下一步</li>
</ul>
<h5 id="step-6-install">第6步：安装</h5>
<p>完成安装向导中的所有上述步骤后，单击立即安装。</p>
<p>安装成功显示消息Success以指示安装成功。</p>
<p>现在去前端，后端看结果</p>
<p><strong>前端</strong></p>
<p><img alt="Magento 2 Demo前端" class="lazy responsive-img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" /></p>
<p><strong>后端</strong></p>
<p><img alt="Magento 2演示后端" class="lazy responsive-img" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" /></p>
<h3 id="people-also-searched-for">其他人可能也在寻找</h3>
<ul>
<li>magento 2演示</li>
<li>magento 2的演示</li>
<li>magento 2工作演示</li>
<li>magento 2演示网站</li>
<li>magento 2演示访问</li>
<li>带有样本数据的magento 2演示</li>
<li>具有管理员访问权限的magento 2演示</li>
<li>magento 2 luma演示</li>
<li>magento 2前端演示</li>
<li>magento 2.0管理员演示</li>
<li>magento 2 luma主题</li>
<li>magento luma演示</li>
<li>nexcess magento 2演示</li>
<li>magento luma主题</li>
<li>magento luma主题演示</li>
</ul>
<div class="row">
<p>致此：<strong>Magento 2 Demo 演示介绍以已结速了</strong>。</p>
</div>
</div>
</div>]]></description>
      <pubDate>Wed, 13 Mar 2019 11:23:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级到Magento2的十大常见问题]]></title>
      <link>https://www.360magento.com/blog/magento-2-migrations-faq/</link>
      <description><![CDATA[<p>自2018年以来，<a href="https://www.360magento.com/magento-migration"><strong> Magento 1迁移到Magento 2</strong></a>一直是Magento社区中最热门的话题之一。目前，Magento 1超过一半的商店正在计划迁移，因为他们看到了很多Magento 2的潜力。虽然如此，剩下的人仍然想知道是否应将他们的网站从Magento 1迁移到Magento 2。他们不清楚Magento 2升级过程，担心Magento迁移时间和成本，并担心可能的数据丢失。此外，一些商家发现很难找到提供此类服务的优质Magento迁移服务/ Magento开发公司。</p>
<p>因此，我们希望通过一一解答下面10个最常见问题来帮助实施Magento 1到2迁移。这样，商家将会够理解Magento迁移过程中涉及的内容（例如：主题/数据/代码/扩展迁移），部署Magento 2迁移项目的预计时间和成本，以及如何寻找靠谱的专业magento公司等。</p>
<h2>1.我们应该何时将Magento 1迁移到Magento 2？</h2>
<p>我们的大多数客户都关注这个问题。他们经常向我们提出以下问题：</p>
<p><em>&ldquo;Magento 2稳定吗？&rdquo;</em></p>
<p><em>&ldquo;我们应该将Magento 1迁移到2吗？&rdquo;</em></p>
<p><em>&ldquo;Magento 2迁移的适当时机是什么时候？&rdquo;</em></p>
<p><em>&ldquo;永久运行Magento 1是否可能？&rdquo;</em></p>
<p>...</p>
<p>根据我们对Magento 2的经验 - 在尝试了所有版本之后，我们认为现在是将Magento 1迁移到2的最佳时间。回到1 - 2年前，可以说Magento 2是相当的不稳定，只有少量的主题和扩展。但是，随着时间的推移，我们已经看到了明显的改进，特别是<strong>Magento 2.2.5版本</strong>（2018年6月27日发布）以上。目前，Magento 2不仅向我们展示了它的稳定性，而且还提供了具有丰富功能及令人欣喜的性能。如果你能负担得起Magento的迁移成本，没有理由不升级到Magento的2。</p>
<p><img alt="magento 2迁移的时间" class="aligncenter size-full wp-image-7638" src="https://www.tigren.com/wp-content/uploads/2018/06/time-for-magento-2-migration.jpg" /></p>
<p>除此之外，可以在短期内继续运行Magento 1网站; 但从长远来看，您可能会遇到一些问题，例如：</p>
<ul>
<li>不再从Magento官方那里获得现有商店的免费支持</li>
<li>没有更多补丁和平台增强功能</li>
<li>难以从Magento 1模块开发商/提供商那里获得支持</li>
<li>从Magento社区获得较少的帮助</li>
<li>由于过时的设计和性能，被竞争对手抛在后面</li>
</ul>
<h2>2.如何将主题从Magento 1迁移到Magento 2？</h2>
<p>实际上，通过将当前主题移动到新网站，将主题从Magento 1迁移到2是不可能的。因此，我们必须选择以下方式：</p>
<ul>
<li>找到Magento 2的免费主题并将其安装在新网站（如果需要，可以定制）：<em>非常便宜+快速</em></li>
<li>为Magento 2购买优质的现成主题并将其安装在您的网站（如果需要，可以定制）：<em>便宜+快速</em></li>
<li>克隆旧的Magento 1网站，为Magento 2网站建立一个类似的网站（需要Magento 1 PSD设计或原有网站）：<em>费用较高+耗时</em></li>
<li>克隆您最喜欢的网站设计，为您的商店创建一个类似的网站：<em>费用较高+非常耗时</em></li>
<li>从头开始创建独特的设计：<em>非常昂贵+非常耗时</em></li>
</ul>
<p><img alt="magento 1到2迁移" class="aligncenter size-full wp-image-7684" src="https://www.tigren.com/wp-content/uploads/2018/07/magento-1-to-2-migration.png" /></p>
<p>根据您的要求，预算和时间，您可以采取适当的方法。对于预算较小的商家，我们建议您选择第二个选项 - 即用型Magento 2主题。市场上有很多精心设计的M2主题和模板 - 价格非常实惠。通过使用这些主题，您只需花费一周的时间在新网站上安装它，并根据需要进行一些小的自定义。相反，第三，第四和第五选择可能需要超过1个月才能进行，这也会增加相关成本。</p>
<h2>3.如何将扩展从Magento 1迁移到2？</h2>
<p>与主题迁移类似，Magento 2扩展迁移并不意味着将现有的Magento 1扩展转移到新网站。相反，我们需要为Magento 2购买新模块，这些模块提供与Magento 1相同的功能。这意味着如果您的网站高度依赖第三方插件（例如超过50个扩展），则需要购买新的可能是实质性的。因此，您最好修改所有当前模块和插件，然后确定哪些模块和插件需要迁移到Magento 2商店或删除。</p>
<p>购买新的Magento 2扩展后，您必须在新站点上安装它们以及解决可能的冲突。迁移的模块数量越多，花费的时间就越多。</p>
<h2>4.如何将数据从Magento 1迁移到Magento 2？</h2>
<p>Magento 2数据迁移是Magento 1到2迁移过程中最重要的步骤之一。我们需要将产品，类别，客户，销售订单，博客和CMS页面内容，推荐，评级和评论......转移到新网站。幸运的是，Magento为我们提供了免费的Magento数据迁移工具包，使这个过程变得更容易。</p>
<p><img alt="magento 2迁移" class="aligncenter size-large wp-image-7687" src="https://www.tigren.com/wp-content/uploads/2018/07/magento-2-migration-1024x272.png" /></p>
<p>但是，您需要具备强大的数据迁移知识和技能，以确保所有数据库的传输顺利，安全。在某些情况下，迁移由非专业开发人员实施，这会导致严重的客户数据丢失。因此，买家登录网站时需要再次注册一个新帐户，显然不是所有人都愿意。</p>
<h2><span style="font-size: 22px; font-weight: bold;">5.如何将自定义代码从Magento 1迁移到2？</span></h2>
<p>就理论而言，Magento 2代码迁移应该很容易，因为大多数代码在两个平台之间是兼容的。但现实是另一回事。如果您的站点有任何自定义模块，那么通过从头开始为Magento 2开发该模块而不是将其代码迁移到新站点，可以节省时间和精力。简而言之，建议找到一个Magento 2扩展，它可以为您的自定义模块提供相同的功能，或者为Magento 2构建一个类似的扩展。</p>
<h2><span style="font-size: 22px; font-weight: bold;">6.迁移Magento网站需要多长时间？</span></h2>
<p>这是一个棘手的问题。我们无法给您准确的时间来执行Magento 1到2迁移，因为它取决于您现有网站和您未来网站的复杂程度。</p>
<p>例如，如果你有20个新的Magento 2扩展，那么安装和配置肯定比你只有5到10个模块需要更多的时间。平均而言，插件安装和配置需要3-5个小时。</p>
<p>此外，正如我们之前提到的，使用现成主题仅需1周，而Magento主题迁移的其他方法至少需要1个月。</p>
<p><img alt="将magento 1迁移到2需要多长时间" class="aligncenter size-full wp-image-7688" src="https://www.tigren.com/wp-content/uploads/2018/07/how-long-does-it-take-to-migrate-magento-1-to-2.jpg" /></p>
<p>一般而言，您需要为Magento 1至2迁移准备1至5个月。<a href="https://www.360magento.com/migrate-magento-1-to-magento-2/"><strong>这里</strong> </a>是在最短的时间内升级您的网站的一些提示。</p>
<h2><span style="font-size: 22px; font-weight: bold;">7.从Magento 1到2进行迁移的成本是多少？</span></h2>
<p>这是另一个难题，因为有很多因素决定您的Magento迁移成本。如果您聘请Magento服务商迁移您的网站，Magento的总成本将取决于开发人员的每小时费率和完成项目的预计时间。</p>
<p>例如，在360Magento，我们提供极具竞争力的小时费率：Magento 2每小时120元。如果您选择我们的Magento迁移服务，并且您的项目总预计时间为150小时，则总成本为18,000元。然而，如果您与沿海一线城市服务商合作，每小时费率高（从每小时250元起），您的总费用将增加一倍 - 37,500元。</p>
<p><a href="https://www.tigren.com/contact/"><strong><img alt="magento迁移成本" class="aligncenter size-full wp-image-7689" src="https://www.tigren.com/wp-content/uploads/2018/07/magento-migration-cost.png" /></strong></a></p>
<p>现在就<a href="https://www.360magento.com/contacts/"><strong>联系我们</strong></a>，获取Magento迁移项目的<strong>免费咨询和评估报价</strong>！</p>
<h2>8.商家应该自己迁移到Magento 2还是找服务商进行Magento迁移服务？</h2>
<p>许多Magento站点老板想知道他们是否可以自己迁移Magento 1或者寻找Magento迁移服务。对于第一种选择，如果企业拥有专门的Magento开发人员，他们在Magento 1到2迁移方面拥有丰富的经验，那么没有理由将他们的项目外包。相反，如果商家只拥有没有任何技术技能的管理知识，显然他们必须与可靠的Magento开发公司合作来升级他们的网站。</p>
<p>Magento 2升级对于业余爱好者来说是一个非常复杂的过程，但在专业人士眼中却是一个简单的过程。与信誉良好的Magento开发商合作，必将成功有效地将Magento 1迁移到Magento 2。</p>
<h2>9.如何寻找可靠的Magento服务商进行Magento 1到2迁移？</h2>
<p>您选择的Magento开发商将确定您项目成功的90％。选择合作伙伴时有3个最基本的标准：质量，价格和服务：</p>
<ul>
<li>质量：那个Magento服务商有信誉吗？他们有多少年的经验（尤其是Magento和Magento的迁移）？他们所做的Magento迁移项目的质量如何？</li>
<li>价格：该服务商提供的Magento迁移费用在您的预算范围内吗？它是否比市场上的平均价格便宜/更高？价格是否值得来保证质量？</li>
<li>服务：他们是否为您的项目提供合理的建议？它们是否可以方便地跟踪和控制整个迁移过程？您是否创建了具有特定任务和里程碑的详细计划？完成迁移后，他们是否提供支持？</li>
</ul>
<p><img alt="magento迁移服务" src="https://www.360magento.com/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yMTkvbWFnZW50by1taWdyYXRpb24tc2VydmljZS0xMDI0eDU0Ny5qcGcifX0,/key/ba652bef27a996578690acbb4073ea99/" /></p>
<p>凭借在Magento超过7年的经验，<strong>360Magento</strong>有信心在您的预算范围内提供高质量的Magento迁移服务。此外，我们在您的网站上线后提供3个月的免费支持。<strong><a href="https://www.360magento.com/magento-migration">在此处</a>&nbsp;</strong>了解有关我们服务的更多信息或<a href="https://www.360magento.com/contacts/"><strong>联系我们</strong></a>以获取更多信息。</p>
<h2>10.实施Magento 1到2迁移后我们会得到什么？</h2>
<p>如果您的站点成功迁移到Magento 2，您将获得更好的网站设计，性能提升，现代管理界面和更丰富的用户体验等等。<strong><a href="https://www.360magento.com/blog/magento-migration-from-1-to-2/">在这里</a></strong>找到更多优秀的成绩。</p>
<p>综上，Magento 1到2的迁移值得您花费时间，金钱和精力！</p>
<h2>结论</h2>
<p>希望此常见问题解答能帮助您了解有关Magento 1到2迁移过程的更多信息。</p>
<p><em>首先</em>，进行Magento网站迁移的最佳时机是现在，因为Magento 2稳定，与之前的版本相比具有许多有用的功能和增强功能。</p>
<p><em>其次</em>，不可能继续使用Magento 1主题和扩展并将它们移动到Magento 2.相反，你必须为新网站购买新的主题。</p>
<p><em>第三</em>，由于可能的数据丢失，在将数据从Magento 1迁移到2时必须非常小心。</p>
<p><em>第四</em>，您最好重新开发Magento 2的自定义模块，而不是迁移自定义代码。</p>
<p><em>第五</em>，Magento迁移项目的时间和成本取决于现有站点的复杂程度和新站点的要求，以及您选择的Magento服务商的每小时费率。</p>
<p><em>第六</em>，如果您缺乏Magento 2迁移的知识和经验，建议与声誉良好的Magento开发公司合作升级您的网站。</p>
<p><em>第七</em>，选择Magento迁移服务有很多标准，但最重要的标准是质量，成本和服务。</p>
<p><em>最后但同样重要的是</em>，Magento迁移不会让您失望，因为它提供了一个从设计到功能更好的网站。</p>
<p>360Magento是高品质Magento迁移服务的最佳选择之一，价格合理。将您的请求发送至<strong><a href="mailto:sales@360magento.com">sales@360magento.com</a></strong>获取免费报价和咨询！</p>]]></description>
      <pubDate>Mon, 04 Mar 2019 07:13:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 1迁移到Magento2有什么好处？]]></title>
      <link>https://www.360magento.com/blog/magento-migration-from-1-to-2/</link>
      <description><![CDATA[<p>您知道现在有四分之一的电子商务企业正在使用Magento吗？近年来，Magento已成为最流行的电子商务平台之一，在全球拥有超过25万家电商网站。此外，这些电商网站中的大多数都是以Magento为基础或计划将Magento从1迁移到2。虽然Magento 1已经是一个具有各种惊人功能的优秀平台，但Magento 2可以带来<em>更多</em>。如果您对于迁移到Magento 2有分歧，那么这篇博文将通过展示实现从<a href="https://www.360magento.com/magento-migration">Magento1迁移到2</a>后将会得到什么来帮助您更轻松地做出决定。之后，您可以考虑Magento 2升级是否值得。让我们开始吧！</p>
<h2 class="post-title">1.明显的性能提升</h2>
<p>与Magento 1相比，Magento 2具有卓越的性能。具体来说，大多数Magento 2网站在不同页面上的页面加载速度比Magento 1快50％。此外，在Magento 2上开发的网站可以提供更快的结账，同时处理更多订单和页面浏览，等等。为了实现这一目标，Magento 2结合了以下功能：</p>
<ul>
<li><strong>允许全页面缓存：</strong> &nbsp;由于具有整页缓存功能，Magento 2网站中的所有页面都能够在1-2秒内快速加载，没有缓存即可10秒加载。此外，全页缓存提供了以最佳速度同时处理多个目录页面的能力。</li>
<li><strong>包括Varnish缓存：&nbsp;</strong>Varnish缓存是另一个有价值的内置Web应用程序加速器，它在减少相关请求的响应时间和网络带宽利用率方面发挥着重要作用。</li>
<li><strong>支持PHP的最新版本：&nbsp;</strong> Magento 2支持最新版本的PHP（5.x - 7.x），它提供了许多功能以​​提高网页速度。</li>
<li><strong>减少JavaScript：</strong> &nbsp;在Magento 2中，JavaScript的数量被最小化，以便拒绝冗余浏览器的操作。</li>
<li><strong>优化图像：</strong> Magento 2允许我们使用内置工具轻松地直接在服务器上压缩和优化所有图像。</li>
<li><strong>应用MySql的最新版本：</strong> Magento 2使用最新版本的MySql，旨在增强查询，重新索引和缓存过程。</li>
</ul>
<p>&nbsp;</p>
<h2 class="post-title">2.方便的管理界面</h2>
<p>在将Magento从1迁移到2之后，您将获得一个先进，干净且用户友好的管理界面。以下是在Magento 2管理界面上管理商店的一些好处：</p>
<ul>
<li><strong>易于使用：</strong>与Magento 1管理面板相比，即使您没有技术背景，这个新界面看起来更现代，更易于使用。从新的调色板到智能结构，所有这些都使得直观地导航和管理商店变得更加方便。</li>
</ul>
<p style="text-align: center;"><em>Magento 1管理员面板</em></p>
<p><img alt="将magento 1迁移到magento 2" class="aligncenter size-large wp-image-7424" src="https://www.tigren.com/wp-content/uploads/2018/06/migrate-magento-1-to-magento-2-1024x745.png" /></p>
<p><img alt="magento 1到magento 2" class="aligncenter size-large wp-image-7425" src="https://www.tigren.com/wp-content/uploads/2018/06/magento-1-to-magento-2-1024x700.png" /></p>
<p>&nbsp;</p>
<p style="text-align: center;"><em>Magento 2仪表板</em></p>
<p><img alt="magento 2迁移" class="aligncenter size-large wp-image-7426" src="https://www.tigren.com/wp-content/uploads/2018/06/magento-2-migration-1024x745.png" /></p>
<p><img alt="magento商店迁移" class="aligncenter size-large wp-image-7427" src="https://www.tigren.com/wp-content/uploads/2018/06/magento-store-migration-1024x700.png" /></p>
<ul>
<li><strong>可自定义：</strong> Magento 2管理界面的一个特殊之处在于它允许我们选择将要/不要显示哪种类型的信息以便快速访问所需信息。例如，在&ldquo;产品管理&rdquo;页面中，您可以通过在&ldquo;列&rdquo;复选框上进行标记来选择要显示的不同产品数据（ID，类型，价格，状态，缩略图，SKU等）。</li>
</ul>
<p><img alt="比较magento 2和magento 1" class="aligncenter size-large wp-image-7428" src="https://www.tigren.com/wp-content/uploads/2018/06/compare-magento-2-and-magento-1-1024x569.jpg" /></p>
<ul>
<li><strong>响应：</strong>此管理面板的另一个有用功能是它针对各种屏幕尺寸进行了优化。由于这个原因，商店所有者可以使用从台式机，笔记本电脑到智能手机的任何设备轻松管理他们的商店。特别是，在出差时，他们仍然可以在平板电脑上轻松监控商店的运营。</li>
<li><strong>更快：</strong>在Magento 2后端，我们可以轻松快速地批量创建，导入，编辑产品或客户信息。</li>
</ul>
<p>总体而言，Magento 2管理面板针对开发人员和商家进行了优化，以有效管理网站。</p>
<h2 class="post-title">3.响应式和适合移动设备的网站设计</h2>
<p>如今，人们倾向于使用各种设备进行在线购物，特别是在他们的移动手机上。因此，优化网站设计以使其在各种设备上都能很好地呈现是至关重要的。幸运的是，Magento 2店面具有响应性和移动友好性。因此，移动和桌面用户都可以享受用户友好和吸引人的商店外观以及快速的页面加载速度。</p>
<h2 class="post-title"><img alt="magento 2响应式设计" class="aligncenter size-large wp-image-7430" src="https://www.tigren.com/wp-content/uploads/2018/06/magento-2-responsive-design-1024x296.png" /></h2>
<h2 class="post-title"></h2>
<p>&nbsp;</p>
<h2 class="post-title">4.良好的用户体验</h2>
<p>为购物者带来更好的体验将为促进Magento商店的销售和提高转换率做出巨大贡献。由于Magento从1迁移到2，您的用户体验将显著提升：</p>
<ul>
<li><strong>快速且用户友好的结账：</strong>结账是Magento 2最出色的功能之一。它是一个平稳而简单的两步流程，帮助客户尽快完成订单。因此，Magento 2商店结账的时间最小化，导致购物车放弃率显著下降，同时提高销售转化率。</li>
</ul>
<p><img alt="为什么magento 2" class="aligncenter size-full wp-image-7431" src="https://www.tigren.com/wp-content/uploads/2018/06/why-magento-2.jpg" /></p>
<p>此外，Magento 2提供&ldquo;访客结账&rdquo;功能，以便非注册购买者仍然可以轻松下订单并在结账后创建新帐户（如果需要）。此外，对于注册用户，他们只需要在结账页面输入他们的电子邮件地址，然后自动填写他们保存的信息（姓名，运送和账单地址，电话号码）。</p>
<ul>
<li><strong>个性化内容：</strong>在迁移到Magento 2网站中，您将能够跟踪用户的行为，他们喜欢的项目和搜索历史记录。基于该有价值的信息，商店所有者可以提供更适当的产品和服务，并为他们的不同客户群举行适当的促销活动。因此，买家可能会感到更受尊重并对商店更加忠诚。</li>
<li><strong>持久购物车：</strong>这是一个有趣的Magento 2电子商务商店。一旦买家登录他们的帐户，所有与他们所查看的产品，产品比较，愿望清单以及特别是购物车相关的信息将保留用于下次访问。这样，购物者不需要在最后一次访问时再次搜索他们喜欢的物品，而是立即继续他们的购物。</li>
<li><strong>方便的搜索和分层导航：</strong>对于任何电子商务网站，搜索和导航菜单至关重要，因为它为客户打开了一扇门，可以发现各种各样的产品。在Magento 2中，有用的搜索功能允许用户快速有效地查找喜欢的项目。此外，分层导航使买家能够轻松过滤产品并获得相关结果。</li>
<li><strong>内容丰富的产品页面：</strong> Magento 2的产品页面提供非常丰富的信息，包括视频，带缩放和色板的图像，评级和评论，......</li>
</ul>
<p>&nbsp;</p>
<h2 class="post-title">5.多种支付方式</h2>
<p>说Magento 2平台拥有多个流行支付网关的最佳支付系统之一，这是真的：<br /> <img alt="magento 2付款方式" class="aligncenter size-large wp-image-7434" src="https://www.tigren.com/wp-content/uploads/2018/06/magento-2-payment-methods-1024x576.png" /></p>
<ul>
<li>PayPal</li>
<li>Braintree</li>
<li>Amazon Pay</li>
<li>Klarna Payments</li>
<li>Authorize.net</li>
</ul>
<p>通过这种多样化的选择，客户可以快速，安全地完成付款。此外，Magento 2企业版还与Cyber​​Source和WorldPay集成，以确保所有交易都以最高的安全性进行。</p>
<h2 class="post-title">结论</h2>
<p>虽然Magento从1迁移到2可能需要你的时间和金钱，但值得你的努力。实施升级后，您将获得最高的网站性能，现代便捷的管理界面，响应和移动友好的设计，改善的客户体验和各种安全支付方式。顺便说一句，如果您正在寻找一个可靠的Magento开发公司将您的网站迁移到Magento 2，360Magento是最好的选择之一。凭借在Magento电子商务开发方面的丰富经验，我们有信心帮助您顺利地以可承受的成本<a href="https://www.360magento.com/magento-migration">从1到2进行Magento迁移</a>。现在就<em><strong><a href="http://www.360magento.com/contacts/">联系我们</a></strong></em>，获取您项目的免费报价。</p>]]></description>
      <pubDate>Fri, 01 Mar 2019 07:16:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何建立Magento电商网站？分步指南]]></title>
      <link>https://www.360magento.com/blog/build-magento-website/</link>
      <description><![CDATA[<p>许多调查显示，电子商务网站在电子商务行业中占据了很大的一部分，仅次于时尚行业。此外，预计电子商务网站数量将在2019年大幅增加，这篇如何从头开始创建电商网站的指南将非常有用。希望成为您的参考。</p>
<h2>7个步骤开发电子商务网站</h2>
<p>实际上，创建一个电子商务网站是一个漫长的过程，可能需要大量的时间，金钱和精力。有各种各样的大事和小事可做。但是，在这篇博文中，我们讲从头开始开展电子商务业务的七个基本步骤！</p>
<h3><em>第1步：为您的电子商务网站选择合适的平台</em></h3>
<p>谈到电子商务平台，有各种各样的选择（例如：Shopify，WooCommerce，Magento，Prestashop，OpenCart，Wix，3dCart，osCommerce，Drupal等）。关于<a href="https://www.360magento.com/blog/top-ecommerce-platforms/">开源电子商务平台</a> &nbsp;（免费）将有超过30个选项供您选择。</p>
<p><img alt="在magento上开发电子商务电子商店" class="size-full wp-image-10516" src="https://www.tigren.com/wp-content/uploads/2019/02/develop-electronics-ecommerce-store-on-magento.jpg" /></p>
<p>尽管如此，我们认为Magento将是您电子电子商务网站的最佳选择，原因如下：</p>
<ul>
<li>Magento是目前最受欢迎的电子商务平台之一</li>
<li>Magento有两个版本：Magento Open Source（免费）和Magento Commerce（商业版）</li>
<li>Magento提供电子网站所需的所有基本电子商务功能</li>
<li>Magento灵活且易于定制</li>
<li>Magento网站设计是移动友好的，默认响应性设计</li>
<li>Magento允许多种货币，多语言，多商店</li>
<li>Magento提供专业的站点管理仪表板</li>
<li>Magento对搜索引擎优化非常友好，这对于电子商务网站来说至关重要</li>
<li>有许多<a href="http://www.magego.com/" target="_blank">Magento模板和主题</a>供您选择</li>
<li>Magento的官方支持非常及时</li>
</ul>
<p>您可以在我们之前的博客文章中找到<a href="https://www.360magento.com/blog/magento-advantages/">Magento电子商务网站开发的</a>更多优势。</p>
<p>选择合适的平台将在您的电子商务网站开发中发挥重要作用，因此您需要投入时间！</p>
<h3><em>第2步：根据您选择的电子商务平台准备预算</em></h3>
<p>你知道建立一个电子商务网站需要多少钱吗？这是一个棘手的问题，不是吗？</p>
<p>实际上，创建一个在线销售电子产品的电子商务网站的价格是多种多样的，这取决于您选择的平台、您对网站设计和功能的要求，以及您的网站开发公司的工时费等因素的组合。</p>
<p><img alt="从头开始开展电子商务业务" class="aligncenter size-full wp-image-10515" src="https://www.tigren.com/wp-content/uploads/2019/02/starting-an-ecommerce-business-from-scratch.jpg" /><br /> 例如，假设您决定使用Magento开发网站并与360Magento合作开发一个简单的Magento电子商务网站（使用现成的主题并采用Magento默认功能），它可能需要花费12,000-30,000元人民币。此外，创建您的电子商务网站可能需要1-3个月。<a href="https://www.360magento.com/contacts/">联系我们</a>以获取项目的详细建议（包括预估的时间和费用）。</p>
<h3><em>第3步：提出有关电子电子商务网站设计的想法</em></h3>
<p>毫无疑问，规划网站设计是开始开发过程之前的第一步。通常，电子商务网站设计有两种选择：</p>
<ul>
<li style="list-style-type: none;">
<ul>
<li><em>基于电子商务网站模板开发您的网站。</em>从主题市场或主题提供商处购买或下载模板后，您只需将其安装在网站上并在必要时进行一些自定义。有免费和付费电子商务电子商务模板供您选择。对于预算紧张或需要快速设计解决方案的中小型电子商务来说，这是一种完美的方法。</li>
</ul>
</li>
</ul>
<p><img alt="免费电子magento主题" class="aligncenter size-full wp-image-10517" src="https://s3u.tmimgcdn.com/124595-1542621099785_4.jpg?width=1440" /></p>
<ul>
<li><em>从头开始设计新的电子商务网站设计。</em>如果您需要的是一种独特的设计，使您的电子商务网站与竞争对手不同并脱颖而出，这是一个理想的解决方案。但是，使用网页设计师全新设计需要花费大量时间，并且开发人员需要更多时间将PSD设计转换为实际网站模板。因此，比使用现成的网站模板设置电商网站所需的成本会高得多。</li>
</ul>
<h3><em>第4步：考虑电子商务网站的必备功能</em></h3>
<p><img alt="如何在线销售电子产品" class="aligncenter size-full wp-image-10519" src="https://www.tigren.com/wp-content/uploads/2019/02/how-to-sell-electronics-online.png" /><br /> 每个电子商务网站都有一定的要求列表，您需要在其他步骤之前澄清该列表。以下是您在电子商务网站功能方面需要考虑的一些要素：</p>
<ul>
<li>语言</li>
<li>货币</li>
<li>支付网关，支付方式</li>
<li>送货方式，运输公司</li>
<li>结帐流程</li>
<li>页面速度</li>
<li>电邮模板</li>
<li>横幅管理</li>
<li>社交登录，访客登录</li>
<li>第三方整合</li>
<li>...</li>
</ul>
<h3><em>第5步：购买并注册您的域名，主机，支付网关，运输公司</em></h3>
<p>据我们所知，一些店主甚至在开始他们的电子商务网站设计和开发之前很长一段时间都已经购买和注册了他们的域名，以避免丢失给任何人。一般来说，获取新域名的成本并不重要，除了一些热门和理想的域名，因此您应该尽快注册您喜欢的域名。</p>
<p>与域名不同，您不需要立即选择主机托管，而是列出可靠托管服务列表供以后选择。值得注意的是，如果您选择托管平台，则可以忽略此步骤。</p>
<p><img alt="如何创建电子商店电子商务网站" class="aligncenter size-full wp-image-10522" src="https://www.tigren.com/wp-content/uploads/2019/02/how-to-create-electronic-store-ecommerce-website.png" /><br /> 此外，选择支付网关和运输公司对您的电子商务网站也至关重要。您必须先定义这些，然后找到将它们集成到您的在线商店的方法。例如，您的网站基于Magento，您选择Stripe作为支付网关，然后您必须找到将Stripe集成到您网站的扩展程序。</p>
<h3><em>第6步：寻找值得信赖的电子商务网站设计和开发公司</em></h3>
<p>完成上述所有步骤后，您可以想象您的电子商务网站将如何运作。但是，它们都只是你头脑中或文档中的想法和计划。要将这些想法变为现实，您必须找到一个优秀的网站开发服务商来实施您的项目。</p>
<p>问题是你不应该寻找一般的&ldquo;电子商务网站开发公司&rdquo;或&ldquo;电子商务网站设计公司&rdquo;，因为你会被大量的网络代理商所淹没。</p>
<p>相反，如果你确定Magento是你的平台，那么寻找&ldquo;Magento开发公司，Magento服务商，Magento电子商务网站开发商，Magento开发商，Magento专家......&rdquo;。</p>
<p>顺便说一下，如果您正在寻找一家价格合理且实力强的Magento网页设计和开发公司，360Magento是首选之一。凭借在Magento开发方面超过7年的经验，我们一定会帮助您建立一个令您满意的电子商务网站，满足您的所有需求和要求。</p>
<p>不要犹豫<a href="https://www.360magento.com/contacts/">与我们联系，</a>并告诉您的电子商务网站开发项目需求！</p>
<h3><em>第7步：部署您的电子商务电子商店设计和开发流程</em></h3>
<p>一旦您有一个良好的电子商务网站开发计划，并选择合适的开发服务商，项目实施将更容易。</p>
<p>在大多数情况下，该服务商将负责在开始之前为您提供详细的项目建议和时间表（时间表）。因此，您只需向他们提供所需的信息和材料（例如：主题，扩展，支付网关帐户），并按照截止日期测试结果。</p>
<h2>那么，我们如何开始为电子商务制作电子商务网站？</h2>
<p>如前所述，我们在Magento以及电子商务开发方面拥有超过7年的经验。如果您给我们机会建立您的电子商务网站，并为您的电子商务从头开始奠定坚实的基础，我们永远不会让您失望。</p>]]></description>
      <pubDate>Mon, 25 Feb 2019 10:05:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento电子商务发展的20大优势]]></title>
      <link>https://www.360magento.com/blog/magento-advantages/</link>
      <description><![CDATA[<p class="ui_qtext_para">&nbsp;随着过去几年Magento电子商务发展的爆发，网上购物已经变得非常普遍&nbsp; 。虽然有许多电子商务平台，如Shopify，BigCommerce，3Dcart，Volusion，但Magento仍然处于领先地位，全球用户超过25万。</p>
<p class="ui_qtext_para">必然有一些原因。在本文中，我想提供20个使Magento电子商务网站开发成为趋势的理由。</p>
<h2><strong>Magento是开源的</strong></h2>
<p class="ui_qtext_para">您可能知道，Magento是一个开源平台，这意味着：</p>
<ul>
<li>它为您提供了大量的自定义和集成选项。</li>
<li>它甚至会在未来发展得更多。</li>
<li>它可以免费为所有商家获得。只需在您的服务器上下载并安装Magento，无需支付任何许可费用。</li>
</ul>
<h2><strong>2.自定义网页设计/界面</strong></h2>
<p>在Magento中，有各种CSS自定义选项可供您的网页设计使用。此外，Magento支持团队可能会为您提供有关响应式网站设计的最新趋势和提示的宝贵信息。</p>
<h2><strong>3.适合移动设备的特性</strong></h2>
<p>了解现在人们倾向于使用智能手机购买东西，Magento允许您构建可在平板电脑，智能手机和其他移动设备上查看的响应式网站，而不会有任何复杂度。</p>
<p><img alt="使用magento的好处" class="aligncenter size-full wp-image-10157" src="https://s.tmimgcdn.com/scr/62000/62000-en_10.jpg" /></p>
<h2><strong>4. SEO支持</strong></h2>
<p>在搜索引擎优化方面，Magento为您的产品和服务提供了大量机会，可以在Google和其他热门的SERP上展示。更具体地说，它允许您创建SEO所需的友好URL和Meta元素选项。因此，Magento帮助我们解决页面流量，重复内容，索引等不同的SEO问题。</p>
<h2><strong>5.快速的页面加载</strong></h2>
<p>Magento以其令人难以置信的快速网页加载而闻名。您的网络加载速度越快，商店访问者就能收到的信息越快，这会让您的销售和转化率显着提高。</p>
<h2><strong>6.灵活的托管选项</strong></h2>
<p>与其他平台不同，&nbsp;Magento电子商务开发&nbsp;使您可以自由选择任何托管解决方案提供商。</p>
<h2><strong>7.允许多网站生成</strong></h2>
<p>Magento为您提供了在单个后端/管理面板上托管多个网站的强大功能。换句话说，使用Magento，您的商店可以通过其独特的产品目录，设计和相互业务结构中的功能单独设置。</p>
<p><img alt="为什么Magento是最好的电子商务平台" class="aligncenter size-full wp-image-10158" src="https://www.tigren.com/wp-content/uploads/2019/01/Why-is-Magento-best-ecommerce-platform.png" /></p>
<h2><strong>8.多种货币和语言支持</strong></h2>
<p>目前大多数电子商务平台在各种货币和语言方面都没有选择，但Magento电子商务网站开发支持全球所有货币和语言。对于面向广泛地理受众的网站而言，此功能非常有价值。</p>
<h2><strong>9.第三方整合</strong></h2>
<p>通过使用Magento，您可以轻松地将您的网站与不同的支付网关和Web应用程序集成，如PayPal，Google Shopping，MailChimp，eBay，QuickBooks等等。</p>
<h2><strong>10.惊人的默认功能</strong></h2>
<p>Magento包含了您在电子商务网站中所期望的一切，包括高级搜索，愿望清单，收藏夹，产品比较，电子邮件列表，以及不同类型的产品等。这些功能将为您提供坚实的基础。为您的用户提供卓越的体验和满意度。</p>
<h2><strong>11. Magento很灵活</strong></h2>
<p>无论您的业务规模，预算，要求如何，您仍然可以找到适当版本的Magento。例如，Magento Go适合小公司，Magento Enterprise是中型和大型公司的完美匹配。</p>
<h2 class="ui_qtext_para"><strong>12.方便开发人员和管理员</strong></h2>
<p>在Magento电子商务开发中，开发人员能够轻松更新内容，向网站添加新页面，将页面链接到子导航或主导航。同时，对于网站所有者/管理员来说，即使他们缺乏高级编程技能和专业知识，它也很容易使用。但是，如果您在管理Magento网站时遇到任何困难，可以向可靠的Magento电子商务网站开发公司寻求帮助。</p>
<p><img alt="我为什么要使用Magento" class="aligncenter size-full wp-image-10159" src="https://www.tigren.com/wp-content/uploads/2019/01/Why-should-I-Use-Magento.png" /></p>
<h2 class="ui_qtext_para">13.方便快捷的结账</h2>
<p>智能Magento购物车将帮助您的客户逐步完成购买所需产品的过程。通常，结账过程简单快捷，因此可以最大限度地减少购物车的放弃。</p>
<h2 class="ui_qtext_para"><strong>14.轻松与Google服务集成</strong></h2>
<p>关于Magento网站开发的另一个好处是，Google Analytics，Google Checkout和Google Base等大多数Google服务都可以毫不费力地集成到您的网站中。</p>
<h2><strong>15.简单而智能的编码</strong></h2>
<p>与其他平台相比，可以说Magento核心代码并不太复杂，因为它可以很容易地与第三方编码集成。更重要的是，Magento不会受到未来升级的扩展或附件的干扰。</p>
<h2><strong>16.有效的报告制度</strong></h2>
<p>从后端，您可以获得有关网站性能的详细报告，指出现在的&ldquo;热门产品&rdquo;或缺货的内容，等等。这样，您的企业可以提出更好的策略来促进销售。</p>
<p><img alt="Magento是一个很好的电子商务平台" class="aligncenter size-full wp-image-10160" src="https://www.tigren.com/wp-content/uploads/2019/01/Is-Magento-a-good-ecommerce-platform.png" /></p>
<h2><strong>17.适合营销</strong></h2>
<p>Magento电子商务网站&nbsp;为您提供一系列有用的工具来推广您的业务。优惠券，私人销售，目录定价，阶梯定价等等。此外，您还可以展示一些相关产品，以加强交叉销售和追加销售。</p>
<h2><strong>18.有用的内容管理</strong></h2>
<p>Magento配备了一个直观且高度可视化的页面编辑器，名为&ldquo;所看即所得（WYSIWYG）&rdquo;。由于这个完美的工具，Magento商店所有者可以在没有技术知识的情况下轻松地更改他们的网页。</p>
<h2><strong>19.安全的电子商务网站</strong></h2>
<p>通过Magento开发，您可以使用多级安全权限保护您的网站并有效管理内部访问。您可以生成二级密码以禁止意外泄露。此外，Magento还具有CAPTCHA和PCI数据安全性，可提供最大程度的保护。</p>
<h2><strong>20. 强大的Magento社区</strong></h2>
<p>截至目前，已有超过375,000名会员参与Magento电子商务开发<a href="https://magento.com/community">社区</a>。因此，当您发现网站出现任何问题时，寻求帮助并不困难。</p>
<p><img alt="为什么选择magento开发" class="aligncenter size-full wp-image-10165" src="https://www.tigren.com/wp-content/uploads/2019/01/why-magento-development-1.jpg" /></p>
<h2><em><strong>你现在需要Magento电子商务网站开发吗？</strong></em></h2>
<p class="ui_qtext_para">毫无疑问，Magento是一个近乎完美的电子商务平台，可满足所有在线购物偏好。&nbsp;Magento电子商务开发&nbsp;带来了无限的优势，从安全的购物体验，无缝的产品管理到简单的第三方集成，这些都有助于推动业务增长。</p>
<p class="ui_qtext_para">作为最负盛名的Magento开发公司之一，360Magento将帮助您以最低的成本在一到三个月后建立一个令您满意的电子商务网站。现在就<a href="https://www.360magento.com/contacts/"><strong>联系</strong> </a>我们的团队，为您的企业获得全面的Magento网站开发计划！</p>]]></description>
      <pubDate>Thu, 10 Jan 2019 09:59:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[2019年排名前30位的开源电子商务平台]]></title>
      <link>https://www.360magento.com/blog/top-ecommerce-platforms/</link>
      <description><![CDATA[<p>近年来，我们看到了电子商务行业的强劲增长。从我们的角度来看，这种绽放的贡献者之一是当大多数电子商务平台可以免费获得时，该行业的容易进入。在本文中，我们将向您展示30个开源电子商务平台的列表，这些平台目前已广泛使用。所有这些都为您提供了各种自定义选项，可扩展性和巨大的社区支持。我们现在发现吧！</p>
<h2>顶级开源电子商务平台为您的在线业务提供动力</h2>
<h3><a href="https://magento.com/products/open-source" rel="nofollow">1. Magento开源（原Magento社区版）</a></h3>
<p><strong><img alt="magento社区开源电子商务平台" class="aligncenter size-full wp-image-6125" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-community-open-source-ecommerce-platform.png" /></strong></p>
<p>您可能知道，Magento是当今最强大的电子商务平台之一，在全球拥有超过25万名店主，150,000名开发人员和300多个解决方案合作伙伴。</p>
<p>如果您梦想拥有像三星，耐克或联想这样令人惊讶的电子商务网站，它们使用Magento企业版，每年的成本为16,000美元，如果只有中小型预算，那么请使用Magento开源平台。</p>
<p>尽管只是Magento的免费版本，但该平台为您提供了大量专门用于电子商务的功能，如响应式设计，快速加载页面，多商店/语言/货币，SEO支持等。</p>
<p>而且，Magento Open Source非常灵活，允许您自由定制平台，构建一个独特而充满活力的网站。</p>
<p>可以说，这个开源电子商务平台不仅适用于中小型电子商务的预算，而且能够从头开始推动这些公司的发展。</p>
<p><strong>Magento电子商务商店：</strong></p>
<ul>
<li>Christian Louboutin</li>
<li>Grenson</li>
<li>Erdem</li>
<li>Varley</li>
<li>Bucherer</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://woocommerce.com/" rel="nofollow">&nbsp;2. WooCommerce</a></h3>
<p><img alt="woocommerce开源平台" class="aligncenter size-full wp-image-6130" src="https://www.tigren.com/wp-content/uploads/2018/03/woocommerce-open-source-platfrom.png" /></p>
<p>我们要提到的第二个开源购物车平台是WooCommerce，这是一个非常免费的WordPress插件 - 全球最大的内容管理系统（CMS）。WooCommerce的下载量约为3100万，现在已经为所有电子商务商店的四分之一提供了动力。</p>
<p>WooCommerce是一个完全开源，高度可定制和灵活的电子商务平台。它提供了大量的电子商务功能，包括各种类型的产品和支付网关，税控，交付设置，库存跟踪，折扣和优惠券系统等。</p>
<p>一个有趣的事情是，这个平台使公司可以通过安装附加组件轻松地为他们的商店创建移动应用程序。</p>
<p>然而，WooCommerce的最大优势也是它的劣势。对于那些使用WordPress的人来说，这只是一个合适的电子商务解决方案。</p>
<p><strong>WooCommerce电子商务商店</strong></p>
<ul>
<li>New Balance</li>
<li>Subaru</li>
<li>Hemline</li>
<li>AB Aeterno</li>
<li>Wakami</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.prestashop.com/en" rel="nofollow">3. PrestaShop</a></h3>
<p><img alt="prestashop电子商务平台开源" class="aligncenter size-full wp-image-6132" src="https://www.tigren.com/wp-content/uploads/2018/03/prestashop-ecommerce-platfrom-open-source.png" /></p>
<p>与Magento类似，PrestaShop吸引了全球超过250,000名商家，并得到了广大社区的支持（超过100万会员）</p>
<p>PrestaShop是一个免费的电子商务平台，可帮助电子商务成功开发和运营其在线商店。</p>
<p>安装和自定义此平台只需要一点点努力，因为大多数事情都是直观的。有3,000种功能和2,000种模板供您选择。此外，您可以下载完全托管或自托管的PrestaShop版本。</p>
<p>然而，一些用户抱怨说，没有很多东西可以用Prestashop定制，除非你购买了额外的主题并深入挖掘其代码。</p>
<p><strong>PrestaShop电子商务商店</strong></p>
<ul>
<li>McDonald</li>
<li>Zippo</li>
<li>Bolina Sail</li>
<li>Atelier81</li>
<li>Pop-line</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://wpecommerce.org/addons/" rel="nofollow">4. WP电子商务</a></h3>
<p><img alt="开源wp电子商务平台" class="aligncenter size-full wp-image-6135" src="https://www.tigren.com/wp-content/uploads/2018/03/open-source-wp-ecommerce-platform.png" /></p>
<p>尽管比WooCommerce知名度低，但WP电子商务也是为WordPress用户开发的最好的开源电子商务平台之一。它获得了令人印象深刻的下载量 - 在过去几年中超过300万次。</p>
<p>WP电子商务为我们提供了一系列有用的电子商务功能，例如多层定价，营销工具，送货方式。此外，它使您可以灵活地选择从PayPal，Worldpay，ProPay到Authorize.net或Stripe的支付网关。</p>
<p>更重要的是，专业和专注的支持团队是WP电子商务的巨大优势。在大多数情况下，他们对您的查询反应非常快（平均在6小时内）。</p>
<p><strong>WP电子商务商店</strong></p>
<ul>
<li>Mayrun&rsquo;s Goods</li>
<li>MollyMeg</li>
<li>Cronut</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.3dcart.com/" rel="nofollow">5. 3dcart</a></h3>
<p><img alt="3dcart开源平台" class="aligncenter size-full wp-image-6136" src="https://www.tigren.com/wp-content/uploads/2018/03/3dcart-open-source-platform.png" /></p>
<p>谈到开源电子商务平台，3dcart将是您考虑的可靠选择。这个平台几乎包含您在线商店所需的一切：为商店所有者提供便利的管理系统，为购物者提供有吸引力的店面以及为搜索引擎提供友好的网站。</p>
<p>由于这些功能，您可以轻松克服运行在线商店的所有挑战，尤其是从一开始。</p>
<p>此外，3dcart提供24/7免费高级技术支持，快速设置和无交易费用 - 我们都需要从电子商务平台获得的东西。</p>
<p><strong>3dcart电子商务商店</strong></p>
<ul>
<li>Blue Diamond Almonds</li>
<li>Cool Gem Shop</li>
<li>TC Life Safety</li>
<li>Mill Supplies</li>
<li>KBS Coatings</li>
</ul>
<h3><a href="https://drupalcommerce.org/" rel="nofollow">6. Drupal Commerce</a></h3>
<p><img alt="drupal商务平台" class="aligncenter size-full wp-image-6138" src="https://www.tigren.com/wp-content/uploads/2018/03/drupal-commerce-platform.png" /></p>
<p>我们想要介绍的另一个全球开源电子商务平台是Drupal Commerce，它是在Drupal上构建的。</p>
<p>Drupal Commerce支持多种货币，多语言，智能管理系统，简单的购物车和结账。此外，该平台具有高度的灵活性和SEO友好性。</p>
<p>此外，Drupal Commerce已经与几个方便的第三方应用程序集成。</p>
<p><strong>Drupal商店</strong></p>
<ul>
<li>Guerlain</li>
<li>Lush</li>
<li>Cartier</li>
<li>EuroCentres</li>
<li>Bordas</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.opencart.com/" rel="nofollow">7. OpenCart</a></h3>
<p><img alt="opencart平台" class="aligncenter size-full wp-image-6141" src="https://www.tigren.com/wp-content/uploads/2018/03/opencart-platform.png" />如果我们在这个顶级开源电子商务平台列表中没有提到OpenCart，那将是一个很大的错误。到目前为止，OpenCart已被超过550K的电子商务商店广泛使用。</p>
<p>这个平台用PHP编写，非常适用于那些没有很多编程经验的电子商务初创公司（小公司）。此外，OpenCart还提供了大量的插件和主题，以提升您的商店设计和功能。</p>
<p>在功能方面，OpenCart支持多种货币，多语言，支持8种送货方式和多达20种不同的支付网关。</p>
<p>此外，活跃的社区是这个平台的优势。您可以轻松地从全球超过110k的OpenCart用户那里获得支持。</p>
<p><strong>OpenCart </strong> <strong>电子商务商店：</strong></p>
<ul>
<li>Missy Empire</li>
<li>British Red Cross</li>
<li>Shore Lines</li>
<li>Arrowfile</li>
<li>Kleshna</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.oscommerce.com/" rel="nofollow">8. osCommerce在线商家</a></h3>
<p><img alt="oscommerce平台" class="aligncenter size-full wp-image-6152" src="https://www.tigren.com/wp-content/uploads/2018/03/oscommerce-platform.png" /></p>
<p>osCommerce是最长期的开源电子商务平台之一，经过近20年的发展。随着时间的推移，它已经建立了一个大约9,000个免费附加组件的银行，并为超过20,000个电子商务商店提供支持。</p>
<p>osCommerce正在与超过30万的店主，开发商和解决方案提供商一起成长。因此，只要您的网站出现问题，就可以快速轻松地从社区寻求帮助。</p>
<p>此外，您将享受各种自定义选项，以增强您的店面外观和功能。</p>
<p>另一方面，与其他开源电子商务平台相比，这个平台相当陈旧且停滞不前。例如，它的前端演示看起来像亚马逊的古老网站。因此，没有</p>
<p><strong>osCommerce商店：</strong></p>
<ul>
<li>Ubuntu</li>
<li>Lanbo&rsquo;s Armory</li>
<li>Bio Manantial</li>
<li>Mopar</li>
<li>Moto Parts Max</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://virtuemart.net/" rel="nofollow">9. VirtueMart</a></h3>
<p><img alt="美德市场电子商务解决方案" class="aligncenter size-full wp-image-6154" src="https://www.tigren.com/wp-content/uploads/2018/03/virtue-mart-ecommerce-solution.png" /></p>
<p>正如WooCommerce是专有的WordPress和Drupal Commerce是Drupal独有的，VirtueMart只能与Joomla一起使用。</p>
<p>尽管功能比其他开源电子商务平台少，但VirtueMart仍然为您提供必要的功能，以使您的商店启动和运行。例如，它允许您创建多语言商店以满足全球需求。此外，这个平台是SEO友好的，帮助您的网站增加流量，并在搜索引擎上获得最佳位置。</p>
<p>当您知道VirtueMart仅由一个非常小的团队开发和运营时，您可能会感到惊讶 - 只有3-5名开发人员积极参与其中。然而，该平台吸引了近35万用户，主要是在美国和俄罗斯。</p>
<p><strong>VirtueMart电子商务商店：</strong></p>
<ul>
<li>Terre des Thes</li>
<li>Hanz de Fuko</li>
<li>Cerjo USA</li>
<li>Ayoka</li>
<li>Envirocon</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://oroinc.com/orocommerce/" rel="nofollow">10. </a><a href="https://oroinc.com/orocommerce/">OroCommerce</a></h3>
<p><img alt="orocommerce开发" class="aligncenter size-full wp-image-6157" src="https://www.tigren.com/wp-content/uploads/2018/03/orocommerce-development.png" /></p>
<p>与其他开源电子商务平台略有不同，OroCommerce专注于B2B而非B2C市场。其主要目的是通过最小化所有权总成本和促进这些业务的增长来满足中型和大型企业的需求。</p>
<p>OrocCommerce使您能够管理多个公司帐户和仓库，应用特定的价格手册和产品目录，为每组客户定制工作流程，显示多种货币等。</p>
<p>OroCommerce是一个开源B2B电子商务平台，可帮助推动在线业务增长，改善客户体验，降低总体拥有成本并缩短产品上市时间。它有社区版和企业版。功能包括购物清单管理，买卖双方互动，多种货币，多仓库管理，可扩展性，Elasticsearch，论坛等。</p>
<h3><a href="http://getsaleor.com/" rel="nofollow">11. Saleor</a></h3>
<p><img alt="销售商电子商务网站开发" class="aligncenter size-full wp-image-6160" src="https://www.tigren.com/wp-content/uploads/2018/03/saleor-e-commerce-website-development.png" /></p>
<p>与之前的电子商务解决方案相比，Saleor可能是一个不太知名的平台，但在开发电子商务网站时仍然是一个不错的选择。它可以满足开发人员，商店经理或客户的需求。</p>
<p>Saleor运行在Python 3.4上，具有清晰的架构，无需全面缓存，直接的本地开发和轻松定制。它结合了一流的技术，如Django，ElasticSearch，PostgreSQL，Docker和GraphQL。</p>
<p>对于商店所有者，Saleor提供直观的仪表板，多个支付网关和SEO支持。同时，它通过地理位置功能，快速结账流程和便捷的搜索工具为客户带来了极佳的购物体验。</p>
<h3><strong><a href="https://spreecommerce.org/" rel="nofollow">12.狂欢</a></strong></h3>
<p><img alt="狂欢电子商务发展" class="aligncenter size-full wp-image-6161" src="https://www.tigren.com/wp-content/uploads/2018/03/spree-e-commerce-development.png" /></p>
<p>Spree Commerce是一个基于Ruby on Rails构建的可扩展的开源电子商务平台。由于其灵活性，Spree可以满足不同电子商务类型的需求和要求，从内容驱动的网站，电子商务商店到多供应商市场。</p>
<p>Spree将帮助您建立一个具有吸引力的设计和精益功能的综合在线商店。关于这个平台的一个特殊之处是API omnichannel与多库存位置的结合，这意味着它可以在您的业务成长时随您扩展。</p>
<p>到目前为止，Spree Commerce已经建立了超过45,000家电子商务商店。</p>
<p><strong>狂欢电子商务商店：</strong></p>
<ul>
<li>Me Undies</li>
<li>Quarterly</li>
<li>R Polo Shirts</li>
<li>Prize Candle</li>
<li>Lula Lu</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.nopcommerce.com/" rel="nofollow">13. nopCommerce</a></h3>
<p><img alt="nopcommerce平台免费" class="aligncenter size-full wp-image-6166" src="https://www.tigren.com/wp-content/uploads/2018/03/nopcommerce-platform-free.png" /></p>
<p>自2008年开始，nopCommerce可以被认为是用ASP.NET编写的先驱开源电子商务平台之一。在过去10年中，其下载量已超过180万次。</p>
<p>nopCommerce为您提供了广泛的功能和功能，可以创建电子商务商店，从多商店，多供应商，库存管理，快速单页结账，SEO支持，折扣和优惠券，到Web服务API等。</p>
<p>到目前为止，nopCommerce已经发布了35个正式版本，所有版本都可以轻松下载和安装。</p>
<p><strong>nopCommerce商店：</strong></p>
<ul>
<li>Volvo</li>
<li>Puma</li>
<li>Reebok</li>
<li>DHC Skincare</li>
<li>Columbia</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://reactioncommerce.com/" rel="nofollow">14.Reaction Commerce</a></h3>
<p><img alt="反应商业开源" class="aligncenter size-full wp-image-6168" src="https://www.tigren.com/wp-content/uploads/2018/03/reaction-commerce-open-source.png" /></p>
<p>Reaction Commerce是一个快速，可扩展，实时反应和开源的Node.js商务平台。它基于HTML，CSS和JavaScript。通过实时分析为每个用户创建个人体验。商品基于位置，天气，市场趋势和其他数据点。Reaction Commerce是GitHub上最顶尖的开源商务项目之一。</p>
<p>Reaction Commerce是一个开源，易于使用和100％可定制的电子商务平台，用Node.js编写。该平台使您可以完全访问其代码库。</p>
<p>此外，由于Reaction是基于事件驱动的技术构建的，因此即使不重新加载页面也可以获得即时更新。</p>
<p><strong>Reaction Commerce商店：</strong></p>
<ul>
<li>Next Level</li>
<li>It Furniture</li>
<li>Easy Wine</li>
<li>Artlimes</li>
<li>Stephen Kenn</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://pimcore.com/en" rel="nofollow">15. Pimcore</a></h3>
<p><img alt="pimcore电子商务" class="aligncenter size-full wp-image-6169" src="https://www.tigren.com/wp-content/uploads/2018/03/pimcore-ecommerce.png" /></p>
<p>7年前，Pimcore构建于100％API驱动架构之上，基于MySQL，Mongo DB，PHP，Symfony，Varnish和Elastic Search的技术堆栈。该平台凭借其出色的设计和功能，可以满足B2B和B2C企业家的不同需求。</p>
<p>可以说，Pimcore现在已成为最有效的开源电子商务平台之一，为全球众多电子商务提供动力。</p>
<p><strong>Pimcore电子商务商店：</strong></p>
<ul>
<li>Martha White</li>
<li>Smuckers</li>
<li>Crisco</li>
<li>Nikonians</li>
<li>Pillsbury</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://simplecartjs.org/" rel="nofollow">16. SimpleCart JS</a></h3>
<p><img alt="开源simplecart" class="aligncenter size-full wp-image-6172" src="https://www.tigren.com/wp-content/uploads/2018/03/open-source-simplecart.png" /></p>
<p>与此列表中的其他开源电子商务平台相比，SimpleCart JS可能是最用户友好，易于使用且轻量级的。虽然大多数以前的平台要求商店所有者具有一定的专业水平，但SimpleCart JS只要求其用户获取基本的HTML知识。</p>
<p>只需几分钟即可建立一个基于SimpleCart JS的完整网站，具有多语言和多支付网关选项。</p>
<p><strong>SimpleCart JS网站：</strong></p>
<ul>
<li>Alpin</li>
<li>Libero</li>
<li>Purple Thistle Dairy Goats</li>
<li>Sleeping Monk Farm</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.jigoshop.com/" rel="nofollow">17. Jigoshop</a></h3>
<p><img alt="jigoshop电子商务发展" class="aligncenter size-full wp-image-6177" src="https://www.tigren.com/wp-content/uploads/2018/03/jigoshop-ecommerce-development.png" /></p>
<p>与WooCommerce一样，Jigoshop是另一个适用于WordPress的开源电子商务平台。它包含了您开始电子商务所需的几乎所有内容，从简单的产品管理，便捷的后端监控，SEO支持，各种营销工具到集成的社交媒体。</p>
<p>到目前为止，它已被来自不同国家的超过50万用户下载。</p>
<p>但是，Jigoshop有一些局限性。例如，创建可配置产品很复杂，您必须支付一定的费率才能获得Jigoshop社区的支持。</p>
<p><strong>JigoShop电子商务商店：</strong></p>
<ul>
<li>Tsaldaris</li>
<li>Tri-rail</li>
<li>Jime Jinak</li>
<li>Renlearn</li>
<li>Sebastian</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.zen-cart.com/index.php" rel="nofollow">18. Zen Cart</a></h3>
<p><img alt="zen cart电子商务平台" class="aligncenter size-full wp-image-6181" src="https://www.tigren.com/wp-content/uploads/2018/03/zen-cart-ecommerce-platform.png" /></p>
<p>继承自osCommerce的代码，Zen Cart自2003年以来已成为最令人印象深刻的免费下载开源电子商务平台之一。它得到了超过15万名成员的大型社区的支持，他们迄今为止贡献了20万个线程。</p>
<p>现在，这个平台提供了超过1,800个插件，分为16个不同的类别。Zen Cart及其附加组件都可以轻松安装，即使是谁拥有基本的网站开发专业知识。</p>
<p>另一方面，Zen Cart平台有一些缺点。例如，它的店面不够好看，不足以吸引客户，如果您上传大量产品，网站速度将非常慢。</p>
<p><strong>Zen Cart</strong>电子商务<strong>商店：</strong></p>
<ul>
<li>Mini In The Box</li>
<li>Tiny Deal</li>
<li>Yeti</li>
<li>Isabel Harris</li>
<li>Katiepie</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://en.shopware.com/" rel="nofollow">19.商品</a></h3>
<p><img alt="商品电子商务开源" class="aligncenter size-full wp-image-6187" src="https://www.tigren.com/wp-content/uploads/2018/03/shopware-ecommerce-opensource.png" /></p>
<p>自2000年以来，Shopware已为全球数千家各种规模的电子商务提供支持。毫无疑问，Shopware Community Edition是一个理想的解决方案，适合希望在预算有限的情况下使用高级电子商务网站的企业家。</p>
<p>通过使用此框架，您将拥有许多自定义选项以及对一组插件和模板的访问权限，从而创建一个独特的商店。</p>
<p>得益于Shopware的高端软件架构，您将从ElasticSearch，API和PHP7中获得巨大的收益。</p>
<p>此外，它的后端经过精心设计，旨在简化您的日常管理工作并节省您的时间。</p>
<p><strong>Shopware电子商务商店：</strong></p>
<ul>
<li>Sportalm</li>
<li>Salewa</li>
<li>Green Cup Coffee</li>
<li>Ames</li>
<li>Elten</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://www.konakart.com/" rel="nofollow">20. KonaKart</a></h3>
<p><img alt="konacart电子商务" class="aligncenter size-full wp-image-6189" src="https://www.tigren.com/wp-content/uploads/2018/03/konacart-e-commerce.png" /></p>
<p>无论您的公司规模如何，KonaKart都将提供适合您的需求和要求的电子商务解决方案。将KonaKart与其他开源电子商务平台区分开来的一件事是它通过诸如Javascript，JSON，POJO和SOAP等API提供的功能。</p>
<p>这些API的目的是帮助您将电子商务功能合并到当前网站中。KonaKart API的另一个惊人优势是在将您的网站升级到最新版本时节省您的时间，金钱和精力。</p>
<p>此外，值得注意的是，您或您的开发人员必须具备扎实的Java开发知识和经验，以便监控基于Konakart的商店。</p>
<p><strong>KonaKart电子商务商店：</strong></p>
<ul>
<li>博纳</li>
</ul>
<p>&nbsp;</p>
<h3><a class="broken_link" href="https://www.shoop.io/en/" rel="nofollow">&nbsp;21. Shoop</a></h3>
<p>Shoop平台采用Python和Django编写，带来了自定义和多存储生成的自由。此外，它还提供简单的结账流程，包括Stripe支付网关，SEO友好功能和简单的内容管理。目前还没有，Shoop可以满足现代零售商的需求，因为它具有可扩展性和灵活性。</p>
<p>现在，Shoop有两个办事处，一个在芬兰，另一个在美国。</p>
<p><strong>Shoop电子商务商店：</strong></p>
<ul>
<li>Mastermark</li>
<li>Ottobock</li>
<li>Aalto</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://www.x-cart.com/" rel="nofollow">22. X-Cart</a></h3>
<p><img alt="xcart电子商务开发" class="aligncenter size-full wp-image-6192" src="https://www.tigren.com/wp-content/uploads/2018/03/xcart-ecommerce-development.png" /></p>
<p>与所有提及的开源电子商务平台类似，X-Cart完全可定制，包含商家期望拥有的所有电子商务功能。它接受多种货币，多语言，以便您可以接触全球受众。此外，搜索引擎将喜欢基于X-Cart的商店，因为它具有SEO友好性。</p>
<p>您可能想要了解的有关此平台的另一件事是X-Cart为我们提供了托管和自托管选项。</p>
<p><strong>X-Cart电子商务商店：</strong></p>
<ul>
<li>Relax Home</li>
<li>Circa Max</li>
<li>Zeff Zone</li>
<li>Coast Furniture</li>
<li>Behind The Mask</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://www.tomatocart.com/" rel="nofollow">23.Tomato Cart</a></h3>
<p><img alt="tomatocart开源演示" class="aligncenter size-full wp-image-6194" src="https://www.tigren.com/wp-content/uploads/2018/03/tomatocart-open-source-demo.png" /></p>
<p>TomatoCart是一个osCommerce分支，应用ExtJS RIA框架。它具有很多优点，例如100％可定制，轻量级，功能负载，多功能和SEO友好。此外，它允许您的商店与多个支付网关集成，应用各种营销活动（销售和折扣）等。</p>
<p>这个TomatoCart的一个缺点是它仍然是一个年轻的平台，插件和主题的选项较少。</p>
<p><strong>TomatoCart电子商务商店：</strong></p>
<ul>
<li>ACI Hellas</li>
<li>Foto De Vakman</li>
<li>Doman</li>
<li>Kalafarsh</li>
<li>Lanternas</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://www.afcommerce.com/" rel="nofollow">24. AF Commerce</a></h3>
<p><img alt="电子商务发展" class="aligncenter size-full wp-image-6205" src="https://www.tigren.com/wp-content/uploads/2018/03/afcommerce-development.png" /></p>
<p>自2007年以来，AFCommerce已为超过25万家全球电子商务商店提供支持。看来这个平台没有定制的限制; 可以根据需要修改所有添加的PHP脚本以满足您的要求。</p>
<p>AFCommerce为我们提供了一系列&ldquo;开箱即用&rdquo;的功能。该平台适用于多语言和多种货币，可以轻松创建联盟计划，并实现单页结账。此外，还有一些独特的功能，如DHTML网页效果，快速购物篮（跟踪买家并说服他们完成购买）。</p>
<h3><a href="http://oscarcommerce.com/" rel="nofollow">25.Oscar</a></h3>
<p><img alt="奥斯卡电子商务平台开发" class="aligncenter size-full wp-image-6206" src="https://www.tigren.com/wp-content/uploads/2018/03/oscar-e-commerce-platform-development.png" /></p>
<p>Oscar是Django令人印象深刻的开源电子商务平台。使用奥斯卡有一些突出的好处。</p>
<p>首先，由于该框架是域驱动的，因此它便于自定义功能开发和维护过程。其次，虽然奥斯卡没有像其他开源电子商务平台那样庞大的用户社区，但它提供了一个非常全面和详细的文档，供您找到如何处理常见问题。第三，该平台最多支持9个不同的支付网关。</p>
<p><strong>Oscar Ecommerce Stores</strong><br /> &bull; Namhah<br /> &bull; Acquolina<br /> &bull; Giftingnation<br /> &bull; 500 accessories<br /> &bull; Chocolatebox</p>
<h3><a class="broken_link" href="http://zeuscart.com/" rel="nofollow">26. Zeuscart</a><br /> <img alt="zeuscart免费平台" class="aligncenter size-full wp-image-6208" src="https://www.tigren.com/wp-content/uploads/2018/03/zeuscart-free-platform.png" /></h3>
<p>Zeuscart是一个基于Web的PHP开源电子商务框架，用作脚本语言，帮助开发人员创建动态网站。它简单易用，但功能强大，具有很多电子商务功能。特别是，该平台提供了多种营销定制功能，这将有助于提高您的销售和转换率，并提高您的客户满意度。</p>
<p>即使您不是技术人员，也可以快速学习如何使用Zeuscart并在此平台上构建新站点。</p>
<h3><a href="https://sylius.com/" rel="nofollow">27.西利乌斯</a></h3>
<h3><img alt="sylius电子商务开源平台" class="aligncenter size-full wp-image-6209" src="https://www.tigren.com/wp-content/uploads/2018/03/sylius-e-commerce-open-source-platform.png" /></h3>
<p>Sylius开源平台于2016年发布。仅仅2年后，它就获得了令人难以置信的400万次下载。这是一个灵活的平台，设计时考虑了集成，易于托管和扩展。更具体地说，它可以部署在大多数众所周知的托管平台上（例如：Google Cloud，Heroku和Platform.sh）。因此，它可以节省时间和金钱，以便在确保高性能的同时扩展和实现新功能。</p>
<p>Sylius利用PHP并将学说作为ORM，数据库抽象和TWIG - PHP的安全模板引擎。在自定义方面，您可以修改核心数据模型，表单，控制器，存储库或插入新字段。</p>
<p>最后，Sylius提供了非常全面的技术文档，不仅包括烹饪书，还包括详细的教程。</p>
<p><strong>Sylius电子商务商店：</strong></p>
<ul>
<li>Axelprint</li>
<li>Balloti</li>
<li>Bi-Rite</li>
<li>Bogler</li>
</ul>
<p>&nbsp;</p>
<h3><a class="broken_link" href="http://www.ubercart.org/" rel="nofollow">28. Ubercart</a></h3>
<p><img alt="ubercart平台" class="aligncenter size-full wp-image-6210" src="https://www.tigren.com/wp-content/uploads/2018/03/ubercart-platform.png" /><br /> Ubercart可被视为Drupal最受欢迎的开源电子商务平台之一。它提供了从头开始在线业务的基本功能。然而，与前30名的其他框架相比，Ubercart似乎被抛在后面。它没有很多不规则的更新。</p>
<p><strong>Ubercart电子商务商店：</strong></p>
<ul>
<li>Brass Exchange</li>
<li>JAS Oceania</li>
<li>MJ Toys</li>
<li>Clob Ponds</li>
<li>SG Ammo</li>
</ul>
<p>&nbsp;</p>
<h3><a href="https://www.cubecart.com/" rel="nofollow">29. CubeCart</a></h3>
<p><img alt="opensource cubecart平台" class="aligncenter size-full wp-image-6212" src="https://www.tigren.com/wp-content/uploads/2018/03/opensource-cubecart-platform.png" /><br /> CubeCart是一个引人注目的英国免费电子商务平台，为数千家全球电子商务提供在线销售产品。它100％可定制和响应 - 很好地显示在从台式机，笔记本电脑到平板电脑和智能手机的所有设备上。此外，该平台允许您上传和管理无限的产品/客户/订单，集成社交媒体附加组件和一些流行的插件，如Mailchimp。</p>
<p><strong>CubeCart电子商务商店：</strong></p>
<ul>
<li>Avazzia</li>
<li>Planet BMX</li>
<li>Mata Traders</li>
<li>Richo Soft2</li>
<li>Peugeot</li>
</ul>
<p>&nbsp;</p>
<h3><a href="http://www.rockettheme.com/docs/joomla/extensions/rokquickcart/setup.md" rel="nofollow">30. RokQuickCart</a></h3>
<p><img alt="rokquickcart电子商务发展" class="aligncenter size-full wp-image-6213" src="https://www.tigren.com/wp-content/uploads/2018/03/rokquickcart-e-commerce-development.png" /></p>
<p>我们想提到的最后一个免费电子商务解决方案是RokQuickCart。此平台适用于一些常见的支付网关，如PayPal，Google Checkout和亚马逊。在网页上，产品将显示为网格中的块（由用户选择）。</p>
<p>此外，该软件重量轻，为您提供快速的加载速度。在后端，管理控件直观且易于使用。最后但同样重要的是，RokQuickCart接受多种货币（最多23种不同的货币）。</p>
<p><strong>RokQuickCart电子商务商店：</strong></p>
<ul>
<li>Byk Bikes</li>
<li>Skydive Moab</li>
<li>Simply Survival</li>
</ul>
<p>最后，我们向您展示了Top 30中所有潜在的开源电子商务平台。希望您能为您的商店选择合适的解决方案。</p>]]></description>
      <pubDate>Tue, 18 Dec 2018 09:55:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何上传和优化Magento 2中的产品图像和视频？]]></title>
      <link>https://www.360magento.com/blog/optimize-img/</link>
      <description><![CDATA[<p>首先，了解如何上传以及优化Magento 2中产品的图像和视频是至关重要的。大多数Magento 2网站都有各种各样的产品以及相关的图像和视频; 如果他们不知道如何有效地使用他们的资源，网站的性能将受到负面影响。因此，您的客户可能会在您的商店中获得糟糕的购物体验。</p>
<p>因此，在本文中，我们将逐步介绍如何在您的Magento2网站上传图像/视频，并为您提供一些有用的技巧，以优化您的资源并获得最佳性能。让我们开始吧！</p>
<h2>1.在Magento 2中上传和优化图像</h2>
<p>以下是在Magento 2后端上传产品图像的3个简单步骤：</p>
<p>首先，导航到要为其添加图像的产品。打开管理面板，导航到<strong>CATALOG</strong>，然后选择<strong>Products</strong>。</p>
<p><img alt="如何上传产品图片magento 2" src="https://www.tigren.com/wp-content/uploads/2018/08/how-to-upload-product-image-magento-2.png" /></p>
<p>然后，您可以选择要添加/更改图像的产品或创建新产品并上传其图像：</p>
<p><img alt="magento 2上传图片" class="aligncenter size-full wp-image-8254" src="https://www.tigren.com/wp-content/uploads/2018/08/magento-2-upload-image.png" /></p>
<p>在产品详细信息配置页面中，展开"<strong>Images And Videos</strong>"部分。单击"<strong>Browse to find or drag image here</strong>",以从计算机上传产品图像。</p>
<p><img alt="在产品详细信息m2中上传图片" src="https://www.tigren.com/wp-content/uploads/2018/08/upload-images-in-product-detail-m2.png" /></p>
<p>接下来，单击您上传的图像以添加图像详细信息。请记住添加适合SEO 的<strong>Alt Text</strong>，选择将决定网站上图像显示位置的<strong>Role</strong>（Base/ Small/ Swatch/ Thumbnail）。值得注意的是，图像可以同时具有多个角色。</p>
<p><img alt="magento 2产品图片" src="https://www.tigren.com/wp-content/uploads/2018/08/magento-2-product-images.png" /></p>
<p>保存配置以完成。</p>
<p>除此之外，以下是一些有用的建议，可以优化Magento 2中产品的图像：</p>
<ul>
<li><strong>以正确的格式准备图像：</strong> PNG是透明和高质量图像的最佳和通用格式。但是，如果您的网站高度依赖图像，则可以将PNG和JPEG格式结合使用，以免对网站性能产生性能影响。</li>
<li><strong>在图像大小和分辨率之间取得平衡：</strong>图像的分辨率必须与Web上显示的大小相对应。例如，您不需要为小缩略图使用高质量图片。</li>
<li><strong>使用专业工具处理图像：</strong>现在有许多工具（免费和付费）允许我们压缩和优化图像以减少文件的大小，同时质量不会受到明显影响。</li>
<li><strong>请您的开发人员/设计人员为网站上的每个图像/横幅提供标准图像大小：</strong>如果您找专业的Magento开发公司来构建您的网站，他们可以帮助您为您网站上的所有图像定义特定大小。凭借他们的经验，他们可以向您提供最佳尺寸，以最高质量显示图像，同时仍然保证网站速度。</li>
</ul>
<h2><img alt="最佳图像尺寸magento 2" src="https://www.tigren.com/wp-content/uploads/2018/08/optimal-image-size-magento-2.jpg" /></h2>
<p><span style="font-size: 24px; font-weight: bold;">2.在Magento 2中上传和优化视频</span></p>
<p>在Magento 1中，上传视频非常复杂，但如果您的网站基于Magento 2，则更容易。Magento 2允许我们默认在产品页面上嵌入Youtube或Vimeo的视频。以下是将视频上传到Magento 2产品页面的几个步骤：</p>
<ul>
<li>第1步：创建Youtube API密钥</li>
</ul>
<p>首先，您必须访问Google Developers Console：<a href="https://console.developers.google.com/" rel="nofollow" target="_blank">https//console.developers.google.com/</a>并登录到您的帐户。然后，搜索&ldquo;Youtube Data API v3&rdquo;。<img alt="如何上传视频magento 2" src="https://www.tigren.com/wp-content/uploads/2018/08/how-to-upload-video-magento-2.png" /></p>
<p>在下一页中，单击<strong>ENABLE</strong>。</p>
<p><img alt="magento 2上传视频" src="https://www.tigren.com/wp-content/uploads/2018/08/magento-2-upload-video.jpg" /></p>
<p>然后，在左侧菜单中选择<strong>Credentials</strong>，然后单击<strong>+ CREATE CREDENTIAL</strong>。<br /> <img alt="magento 2产品视频" class="aligncenter size-full wp-image-8264" src="https://www.tigren.com/wp-content/uploads/2018/08/product-video-magento-2.jpg" /></p>
<p>在这里，您必须选择从哪里调用API以及如何访问数据。<br /> <img alt="嵌入youtube video magento 2" src="https://www.tigren.com/wp-content/uploads/2018/08/embed-youtube-video-magento-2.jpg" /></p>
<p>之后，单击&nbsp; <strong> What credentials do I need?</strong>按钮以获取您的API密钥。复制密钥以在后端配置。<br /> <img alt="获取magento 2的youtube api密钥" src="https://www.tigren.com/wp-content/uploads/2018/08/get-youtube-api-key-for-magento-2.jpg" /></p>
<ul>
<li><strong>第2步：</strong>继续在Magento 2后端配置</li>
</ul>
<p>首先，打开管理面板，导航到<strong>STORES</strong>，选择<strong>Settings</strong>下的<strong>Configuration</strong>。</p>
<p><img alt="magento 2视频配置" src="https://www.tigren.com/wp-content/uploads/2018/08/video-configuration-magento-2.jpg" /></p>
<p>在左侧菜单中，展开<strong>CATALOG</strong>并选择<strong>Catalog</strong>。然后，展开"<strong>Product Video</strong>"部分，并输入你在第一步中复制的<strong>Youtube API Key</strong>。</p>
<p><img alt="在magento 2中添加youtube api密钥" src="https://www.tigren.com/wp-content/uploads/2018/08/add-youtube-api-key-in-magento-2.jpg" />之后，导航到&nbsp; <strong>CATALOG</strong>，然后选择&nbsp; <strong>Products</strong>。</p>
<p><img alt="如何上传产品图片magento 2" src="https://www.tigren.com/wp-content/uploads/2018/08/how-to-upload-product-image-magento-2.png" /></p>
<p>然后，您可以选择要添加/更改视频的产品或创建新产品并上传其视频：</p>
<p><img alt="magento 2上传图片" class="aligncenter size-full wp-image-8254" src="https://www.tigren.com/wp-content/uploads/2018/08/magento-2-upload-image.png" /></p>
<p>在产品详细信息配置页面中，展开&nbsp; <strong>Images And Videos</strong> &nbsp;部分。单击&nbsp; &ldquo;<strong> Add Video</strong>&rdquo;按钮。</p>
<p><img alt="m2在产品详细信息中上传图片" src="https://www.tigren.com/wp-content/uploads/2018/08/upload-images-in-product-detail-m2.png" /></p>
<p>在这里，您必须输入要嵌入网站的Youtube视频的网址。输入URL后，视频<strong>Title, Description</strong>和<strong>Preview Image</strong>将自动填充（但您可以编辑）。此外，您可以选择视频的<strong>Role</strong>（类似于图像）。</p>
<p><img alt="magento 2上传新视频" src="https://www.tigren.com/wp-content/uploads/2018/08/upload-new-video-magento-2.jpg" /></p>
<p>保存配置并清除缓存以完成。</p>
<p><strong>注意：</strong>如果您想从计算机上传视频（而不是通过Youtube）会更复杂。您需要做的是使用第三方扩展程序，允许您上传不同的视频格式，然后您可以将视频上传到媒体文件夹并附加到特殊产品。</p>
<p>此外，以下是优化Magento 2产品视频的一些建议：</p>
<ul>
<li><strong>我们强烈建议使用嵌入式视频：</strong>从Youtube / Vimeo嵌入视频不仅更容易，而且还有利于您的网站性能。如果您将视频上传到媒体（即使是短片），也可能会降低网页播放速度。如果您不希望别人在Youtube上看到您的视频，只需将其设置为个人视频并将其隐藏。</li>
<li><strong>优化您的自托管视频：</strong>如果您仍想使用自托管视频，则必须在上传前优化这些视频。建议不要上传超过1分钟的视频。</li>
</ul>
<p>我们已向您展示如何上传以及优化Magento 2网站中的图像和视频。希望它对你有用！</p>]]></description>
      <pubDate>Wed, 05 Dec 2018 01:20:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento2中CMS页面添加联系表单]]></title>
      <link>https://www.360magento.com/blog/m2-cms-contact/</link>
      <description><![CDATA[<div class="post-body">
<p>在这个Magento 2教程中，我们将向您展示在Magento 2中向CMS页面添加联系表单的五个简单步骤（例如：联系我们页面）。让我们开始吧！</p>
<h2>第1步：添加新的CMS页面</h2>
<p>打开Magento 2管理面板，导航到<strong>CONTENT</strong>，选择<strong>Pages</strong>（在<strong>Element</strong>下），然后单击<strong>Add New Page</strong>按钮。</p>
<p>（管理员面板CONTENT &gt; Pages &gt; Add New Page）</p>
<p><img alt="magento 2在cms页面上添加联系表格" height="792" src="https://www.360magento.com/index.php/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yMTQvYWRkLWNvbnRhY3QtZm9ybS1vbi1jbXMtcGFnZS1tYWdlbnRvLTItMTAyNHg3OTIucG5nIn19/key/bcacc48a0c0348a7cb928c2f9a89e42d/" width="1024" /></p>
<h2>第2步：添加CMS页面的信息</h2>
<p>在这里，您需要输入页面Title, URL Key, Meta Title, Meta Keyword, Meta Description，并选择页面所属的商店视图。</p>
<p><img alt="magento 2在cms页面上添加联系表格" height="896" src="https://www.360magento.com/index.php/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yMTQvbWFnZW50by0yLWFkZC1jb250YWN0LWZvcm0tMTAyNHg4OTYucG5nIn19/key/bcacc48a0c0348a7cb928c2f9a89e42d/" width="1024" /></p>
<h2>第3步：将内容（HTML）添加到CMS页面：</h2>
<p>您可以在&ldquo;Content&rdquo;部分添加更多信息。</p>
<p><img alt="magento 2联系表格" height="582" src="https://www.360magento.com/index.php/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yMTQvY29udGFjdC1mb3JtLW1hZ2VudG8tMi5wbmcifX0,/key/bcacc48a0c0348a7cb928c2f9a89e42d/" width="987" /></p>
<p>例如，您可以按以下方式插入Google地图：首先，访问Google地图，搜索您的位置; 其次，单击&ldquo;Share&rdquo;，选择&ldquo;Embed a map&rdquo;，然后单击&ldquo;COPY HTML&rdquo;; 最后，将链接粘贴到您的HTML内容。</p>
<h2><img alt="magento 2如何创建联系表格" height="549" src="https://www.360magento.com/index.php/alwayly@360mg/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvYmxvZ18yMTQvbWFnZW50by0yLWhvdy10by1jcmVhdGUtY29udGFjdC1mb3JtLnBuZyJ9fQ,,/key/bcacc48a0c0348a7cb928c2f9a89e42d/" width="867" /><br /> 第4步：将联系表单添加到CMS页面</h2>
<p>您可以更改联系表单中每个字段的标题。</p>
<p>在您的源代码中：<br /> app/design/frontend/company/name_theme/ new folder: Magento_Contact <br /> app/design/frontend/company/name_theme/Magento_Contact/ new folder: templates<br /> app/design/frontend/company/name_theme/Magento_Contact/templates/ new file: form.phtml。</p>
<p>在此文件中，您可以根据需要自定义表单。</p>
<p>然后，要将联系表单插入到我们正在创建的CMS页面，您只需要添加：&nbsp; <em></em>到<strong>Content </strong>部分。</p>
<h2>第5步：保存页面</h2>
<p>最后，记得保存配置并刷新缓存（或运行命令：<em>php bin/magento cache:flush</em>）。</p>
<p>我们已向您提供了详细说明，可以轻松地将自定义联系表单添加到CMS页面。</p>
</div>]]></description>
      <pubDate>Wed, 07 Nov 2018 09:57:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2与Shopify哪个好，如何选择？]]></title>
      <link>https://www.360magento.com/blog/m2-vs-shopify/</link>
      <description><![CDATA[<div class="post-body">
<p>Magento 2 对比 Shopify，这两个都是目前比较好的电子商务平台，近年来已成为一个备受争议的话题。关于这一点有很多相反的意见，这使得商家在为他们的商店选择时会很困惑。如果你是其中之一，这篇博文将通过从15个不同方面全面比较Magento 2和Shopify来帮助你更轻松地进行最佳选择。许多人误解这两个平台是相似的，但实际上，它们在每个方面几乎都有很大的不同。我们现在具体的讲解一下：</p>
<h2>1.平台的普及率</h2>
<p>毫无疑问，Magento 2和Shopify是当今非常流行的电子商务平台。Magento 2授权的电子商务超过250,000个，Shopify建立了大约600,000个在线商店。Magento全球社区由大约60,000名开发人员和300多个解决方案合作伙伴组成，从而不断改进和增强该平台。由于Magento拥有最大和最强大的社区，因此它始终领先于所有其他平台。Magento 2似乎是大多数中大型企业的首选，而小型企业对Shopify更感兴趣。</p>
<p>但是，这两个平台都是为大中小型公司服务的，无论规模。从我的角度来看，Magento 2未来不仅可以在大型电商平台上拓展业务，也会是小型电商平台的理想选择。</p>
<p><em>Magento：</em></p>
<p><img alt="magento 2" height="535" src="https://www.360magento.com/media/wysiwyg/blog_212/magento-2-1024x535.png" width="1024" /></p>
<p><em>Shopify：</em></p>
<p><img alt="shopify" height="366" src="https://www.360magento.com/media/wysiwyg/blog_212/shopify-1024x366.png" width="1024" /></p>
<p><strong>得分（Magento 2 vs Shopify）：1-1</strong></p>
<p>&nbsp;</p>
<h2>2.前期成本</h2>
<p>首先，Magento为我们提供了两个版本，两个选择，即Magento Open Source（免费）和Magento Commerce。因此，如果您选择Magento开源平台，则可以从0.00美元起。同时，Shopify提供14天的免费试用，但在此之后，您将需要付费。</p>
<p>尽管如此，基于两个平台从头开发新网站的前期成本却大不相同。要建立Magento网站，您需要具备过硬的技术知识和经验; 否则，你必须寻找一个专业的Magento技术服务商来做这件事，这需要付出以一定费用。一般而言，在亚洲找一家网站开发公司建立外贸网站需要花费2,500至10,000美元，而在美国，英国等公司合作至少需要15,000美元。</p>
<p>另一方面，Shopify商店没有安装费。您需要做的是选择一个月度计划开始，然后自己配置网站，因为它不需要很多技术技能。更具体地说，Shopify提供了网站构建拖放工具; 因此，您可以根据需要在页面上移动元素来自定义商店。</p>
<p>这就是为什么大多数小公司因为早期投资预算较低而选择Shopify。但是，对于大中型电子商务商城而言，Magento的开发成本可能不是什么大问题，也有助于他们长期发展。继续阅读以了解原因。</p>
<p><strong>得分（Magento 2 vs Shopify）：0-1</strong></p>
<p>&nbsp;</p>
<h2>3.运营费用</h2>
<p>正如我所提到的，Shopify用户必须选择月度计划，他们将继续按月支付账单，直到他们......关闭网店。有三种Shopify版本 - Basic Shopify，Shopify和Advanced Shopify，每月花费29美元，79美元和299美元。值得注意的是，网站托管已经包含在这些软件包中。</p>
<p>而Magento方面，您不用每月支付费用使用Magento 2，而是支付托管费（根据您的需要，每月3-100美元）。虽然它确实有成本，但您可以自由选择最适合您商店的托管解决方案。</p>
<p>除此之外，如果您使用外部支付网关而不是Shopify Payments，Shopify还会按每次销售收取2％，1％或0.5％（交易费用）。例如，如果您想在使用Basic Shopify套餐时加入PayPal，Braintree，Authorize.net等热门支付网关，那么每购买100美元的订单，您将需要支付2美元。因此，假设您的收入为每年100,000美元，那么您将向Shopify支付2000美元。</p>
<p>相反，Magento 2不收取外部支付网关的额外费用，也默认在网站上集成PayPal，Braintree，Authorize.net，....</p>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>4.易于使用</h2>
<p>在这里，我不再谈论如何建立网站，而是管理整个网站的便利性。</p>
<p>客观地说，Magento 2和Shopify都为管理员提供了用户友好且易于使用的管理仪表板，无论他们的技术知识水平如何。多亏了这一点，我们可以有效地管理产品，客户，订单，CMS页面和创建销售报告等。但是，相比之下，我更喜欢<a href="https://docs.magento.com/m2/ce/user_guide/stores/admin-dashboard.html" rel="nofollow">Magento 2仪表板</a>的现代风格外观。</p>
<p><em>Magento：</em></p>
<p>&nbsp;</p>
<p><img alt="magento 2仪表板" height="862" src="https://www.360magento.com/media/wysiwyg/blog_212/magento-2-dashboard.png" width="815" /></p>
<p><em>Shopify：</em></p>
<p><img alt="shopify管理仪表板" height="899" src="https://www.360magento.com/media/wysiwyg/blog_212/shopify-admin-dashboard-733x899.png" width="733" /></p>
<p><strong>得分（Magento 2 vs Shopify）：1-1</strong></p>
<p>&nbsp;</p>
<h2>5.功能</h2>
<p>这两种流行的平台都提供了启动和维护您的电子商务业务的基本功能。以下是一些比较示例：</p>
<p>在<em>折扣和优惠券代码方面</em>，Magento 2允许您默认生成任意数量的代码。虽然Shopify也提供此功能，但它不包含在基本计划中。</p>
<p>在<em>库存管理方面</em>，Magento用户可以控制无限数量的商品。Shopify商店也提供相同的功能，但使用基本计划的人除外 - 只允许25件商品。</p>
<p>在<em>运输</em>方面，两个平台都提供灵活的运输方式，并自动计算运费。</p>
<p>转向<em>多语言</em>设置，您可以通过轻松安装语言包向Magento 2商城添加任意数量的语言。对于Shopify，您必须寻找一些语言应用程序。</p>
<p>电子商务网店的另一个常见功能是<em>博客</em>，可以在Shopify上找到，可以使用免费或付费的扩展程序添加到Magento。</p>
<p>两个平台提供的最基本功能都与<em>SEO和营销有关</em>。事实上，Magento 2和Shopify为我们提供了类似的SEO能力，例如编辑元标记，元标题，元关键字，URL密钥，替代文本等，这有助于提高SERP上的网站排名。</p>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>6.设计和定制</h2>
<p>网站设计是决定网站成功的最重要因素之一。有许多Magento 2和Shopify主题供您选择，包括免费和付费。通常，大多数模板都具有响应式和移动友好性，因此无论客户使用何种设备，都可以很好地呈现。</p>
<p><img alt="响应式网站设计" height="640" src="https://www.360magento.com/media/wysiwyg/blog_212/responsive-website-design-1024x640.jpg" width="1024" />问题是你只能改变Shopify主题中的基本颜色和字体。而Magento 2是一个灵活且可扩展的平台，它允许您根据自己的创造力定制和创建美丽而独特的设计。</p>
<p>关于代码，Magento 2使用PHP，而Shopify使用Liquid; Magento是开源的，而Shopify是闭源的。由于是开源的，Magento 2使您能够自由开发定制代码以满足您的需求，而您无法修改Shopify的代码。</p>
<p>因此，Shopify仅适用于接受具有共同外观和视觉的简单网站的小公司。同时，Magento 2可以满足中型和大型电子商务企业的需求，这些企业往往需要独特而复杂的商店。</p>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>7.速度和性能</h2>
<p>网站速度是电子商务商店的关键因素。许多调查表明，即使1秒延迟也可能导致转换率降低7％。如果客户遇到网页加载速度缓慢，他们很可能会离开您的网站。</p>
<p>由于Shopify是托管解决方案，其网站性能由公司保证。诚然，Shopify网站在大多数情况下都具有稳定可靠的性能。</p>
<p>对于Magento 2网站，其网站速度主要取决于所选的托管服务。如果您选择具有适当网站优化功能的强大主机（整个站点中的代码和图像），则无需担心站点性能。</p>
<p><strong>得分（Magento 2 vs Shopify）：1-1</strong></p>
<p>&nbsp;</p>
<h2>8.用户体验</h2>
<p>评估电子商务平台时最重要的一个方面是用户体验，特别是结账方便。</p>
<p>Magento 2为我们提供了一个简单快速的两步结账流程（包括运输信息，预览和付款信息），以及一些出色的功能，如访客结账和一键创建帐户。此外，折扣代码框直接放在结帐页面上。</p>
<p>Shopify还提供便捷的单页结账。问题是，在Basic Shopify计划中，它从一开始就没有显示实时运费，这可能导致结账时放弃购物车的比率更高。</p>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>9.模块和插件</h2>
<p>尽管Magento 2和Shopify已经提供了网店所需的几乎所有内容，但强烈建议您考虑使用某些第三方扩展来增强网站性能和功能。</p>
<p>截至目前，Shopify在其商店中提供了超过2,300个应用程序，这比目前市场上的Magento 2扩展数量（超过3,000个）要少。相比之下，Magento 2不仅在数量上提供了更多插件，而且在质量方面也是更有保证。其扩展列表涵盖了商店改进和增强的所有方面，包括会计和财务，营销，内容和定制，客户支持，支付和安全，报告和分析等。</p>
<h3><img alt="magento 2扩展" height="616" src="https://www.360magento.com/media/wysiwyg/blog_212/magento-2-extensions-1024x616.png" width="1024" /></h3>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>10.可扩展性</h2>
<p>毫无疑问，Magento 2比Shopify更适合拥有数千种产品的中型和大型电子商务商店。如果你只想建立一个没有长期计划的小网站，Shopify可能是一个不错的选择。但是，如果您希望开发一个可能在未来发展壮大的在线业务，Magento 2将是首先。</p>
<p><strong>得分（Magento 2 vs Shopify）：1-0</strong></p>
<p>&nbsp;</p>
<h2>Magento 2 vs Shopify。谁是赢家？</h2>
<p>考虑到所有因素，最终得分为9-4，获胜者为Magento 2.但是，对于所有电子商务业务而言可能并非如此。为了找到最适合您公司的平台，您需要在平台的潜力与目标和预算之间取得平衡。</p>
<p>如果您需要在短时间内建立一个包含少量产品的商店，Shopify正是您所需要的。相反，如果您期望的是具有强大功能，可扩展性和自定义的在线商店，Magento是最佳选择。</p>
<p>对我来说，我更倾向于Magento 2.你呢？</p>
</div>]]></description>
      <pubDate>Sat, 03 Nov 2018 02:51:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[升级到Magento2的最佳时间到了]]></title>
      <link>https://www.360magento.com/blog/m2-upgrade/</link>
      <description><![CDATA[<p>2018年9月6日，Magento官方宣布他们将继续Magento 1的支持，直到2020年6月。该公告是为了纠正Magento先前声称他们将在发布Magento 2三年后停止为Magento 1提供支持（直到2018年11月） ）。与此同时，Magento强烈建议所有商家尽快<a href="https://www.360magento.com/magento-migration" title="Magento 1升级到Magento 2">升级到Magento 2</a>，原因有几个，我们将在这篇博文中讨论。</p>
<p>首先，延长Magento 1支持时间的目的既不是继续改进其功能，也不是为了吸引更多用户，而是让商家有更多时间来计划和实施他们升级到Magento 2.这方面是显而易见的。一方面，Magento仅为Magento Commerce 1(以前称之为Magento1企业版)提供高质量的修复和安全补丁，为Magento Open Source 1(以前称之为Magento1社区版)提供安全补丁。另一方面，magento将每三个月发布一次Magento 2的新版本，增加增强功能，修复bug以及安全更新。</p>
<blockquote>
<p><strong>For Magento Commerce 1 (formerly known as Enterprise Edition)</strong>:<br /> For Magento Commerce 1, we are providing software support through June 2020. Depending on your version, software support may include both quality fixes and security patches. Please review our&nbsp;Magento Software Lifecycle Policy&nbsp;to see how your version of Magento Commerce 1 is supported.</p>
<p><strong>For Magento Open Source 1 (formerly known as Community Edition)</strong>:<br /> For Magento Open Source 1, we are providing software security patches through June 2020 to ensure those sites remain secure and compliant. Please visit our&nbsp;Legal Terms page&nbsp;and review our Magento Open Source Software Maintenance Policy to see which versions of Magento Open Source 1 continue to receive software security maintenance.</p>
</blockquote>
<p>此外，毫无疑问，相比之下，Magento 1的默认功能逐渐变得贫瘠过时，而Magento 2应用了许多现代技术和改进。据Magento称，Magento 2为我们提供了卓越的云托管性能和强大的功能。此外，大多数Magento用户都认为Magento 2在很多方面都超过了以前的平台，从网站设计，网站性能到用户体验（管理员和买家）。因此，不仅是Magento官方并且整个Magento社区都将注意力转向Magento 2。</p>
<p>回到几年前Magento 2刚刚发布时，这是一个不稳定的电子商务平台，有很多bug，并且只有少数相关的主题和扩展。时间过得真快，一切都在不知不觉中发生了巨大变化。现在，Magento 2已经成为国际电商平台的首选之一。它不仅提供可靠的性能，还提供持续的丰富功能。截至目前，市场上已有超过2,000个Magento 2扩展，以及各种免费和付费magento 2主题模板。</p>
<p>长远考虑，如果您的企业有足够的预算，没有比现在升级到Magento 2更好的时间了。相反，如果您负担不起Magento迁移成本，那么我们为小公司提供一些方案方法可以有效地升级到Magento 2，而无需花费大量预算。不要等待Magento 1"生命终结"再开始从Magento 1迁移到Magento 2！</p>
<p>顺便说一句，如果您正在寻找Magento 2迁移服务提供商，360Magento是一个值得信赖的品牌。我们在Magento开发方面拥有超过6年的专业知识经验，可以帮助您成功迁移到Magento 2并且不会出现任何问题。此外，由于劳动力成本的竞争优势，我们能够提供非常合理的Magento迁移价格，适合大多数企业的预算。现在就<a href="https://www.360magento.com/contacts">联系我们</a>获取免费的magento迁移建议，详细的报价和时间表！</p>]]></description>
      <pubDate>Tue, 18 Sep 2018 04:01:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2添加SOLR和ELASTICSEARCH搜索引擎]]></title>
      <link>https://www.360magento.com/blog/m2-add-solr/</link>
      <description><![CDATA[<p>Magento 2社区版仅支持MySQL搜索引擎，但有些项目需要更好的搜索引擎才能提高销售额或转换率。 在这种情况下，我们可以选择实施Solr或Elasticsearch搜索引擎。magento2商业自带支持Solr,请查看<a href="https://www.360magento.com/blog/ce-vs-ee">magento2社区办和magento2企业版的比较</a></p>
<p>在这篇文章中，我们将创建一个框架代码和简单的示例，它将介绍实现其他搜索引擎（如Solr或Elasticsearch）的主要类和方法。如果你进入到Magento 2 后台管理，您可以在这个位置找到搜索引擎配置：Stores -&gt; Configuration -&gt; Catalog -&gt; Catalog Search 然后下拉 &ldquo;Search Engine&rdquo;选项。</p>
<p>在下拉列表中，您将注意到您只有MySQL引擎，我们的第一步是在此下拉列表中添加标签为&ldquo;Solr&rdquo;的额外选项。那么，现在开始吧。</p>
<p>在你的模块etc文件夹中，您需要使用以下xml代码创建文件di.xml：</p>
<pre>&lt;type name="Magento\Search\Model\Adminhtml\System\Config\Source\Engine"&gt;
  &lt;arguments&gt;
     &lt;argument name="engines" xsi:type="array"&gt;
         &lt;item name="solr" xsi:type="string"&gt;Solr&lt;/item&gt;
     &lt;/argument&gt;
  &lt;/arguments&gt;
&lt;/type&gt;
</pre>
<p>使用此xml代码，现在我们已经在下拉列表中添加了一个新选项，其选项名称为&ldquo;Solr&rdquo;。如果您正确创建并清理了Magento缓存，您将能够在下拉列表中看到它，其中会有一个新选项&ldquo;Solr&rdquo;。如果您看到它，则表示您已正确添加它。</p>
<p>在下一步中，我们将从php类开始，这些类负责将数据索引到搜索服务器。</p>
<p>首先，我们要implement Engine类，在di.xml中放入以下代码：</p>
<pre>&lt;type name="Magento\CatalogSearch\Model\ResourceModel\EngineProvider"&gt;
  &lt;arguments&gt;
     &lt;argument name="engines" xsi:type="array"&gt;
        &lt;item name="solr" xsi:type="string"&gt;Search\Solr\Model\ResourceModel\Engine&lt;/item&gt;
     &lt;/argument&gt;
  &lt;/arguments&gt;
&lt;/type&gt;
</pre>
<p>您可以看到我们为&ldquo;Seach\Solr\Model\ResourceModel\Engine&rdquo; 引入了我们自己的Engine类。引擎类负责在数据进入我们的indexerHandler类（solr服务器之前的最后一个端点）之前准备数据，而Engine类必须实现接口：\Magento\CatalogSearch\Model\ResourceModel\EngineInterface。</p>
<p>接口类包含以下四种方法： - processAttributeValue 准备要存储在solr索引中的属性值 - getAllowedVisibility 检索当前引擎允许的可见性值 - allowAdvancedIndex 定义当前搜索引擎是否支持高级索引 - prepareEntityIndex 将索引数组作为分隔符粘贴的字符串</p>
<p>这些方法是必需的，必须在Engine类中实现。为了更好地理解，您可以在类似的MySQL类中检查/比较逻辑：Magento\CatalogSearch\Model\ResourceModel\Engine</p>
<p>我们的框架类示例如下：</p>
<pre>&lt;?php
namespace Search\Solr\Model\ResourceModel;
use Magento\CatalogSearch\Model\ResourceModel\EngineInterface;
class Engine implements EngineInterface
{
    protected $catalogProductVisibility;
    private $indexScopeResolver;
 
    public function __construct(
        \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility,
        \Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver $indexScopeResolver
    ) {
        $this-&gt;catalogProductVisibility = $catalogProductVisibility;
        $this-&gt;indexScopeResolver = $indexScopeResolver;
    }
 
    public function getAllowedVisibility()
    {
        return $this-&gt;catalogProductVisibility-&gt;getVisibleInSiteIds();
    }
 
    public function allowAdvancedIndex()
    {
        return false;
    }
 
    public function processAttributeValue($attribute, $value)
    {
        return $value;
    }
 
    public function prepareEntityIndex($index, $separator = ' ')
    {
        return $index;
    }
 
    public function isAvailable()
    {
        return true;
    }
}
?&gt;
</pre>
<p>下一步是创建名为&ldquo;Seach\Solr\Model\Indexer\IndexerHandler&rdquo;的indexerHandler，它将实现Magento\Framework\Indexer\SaveHandler\IndexerInterface。 要实现IndexerHandler，您需要在di.xml文件中添加以下代码：</p>
<pre>&lt;type name="Magento\CatalogSearch\Model\Indexer\IndexerHandlerFactory"&gt;
    &lt;arguments&gt;
        &lt;argument name="handlers" xsi:type="array"&gt;
            &lt;item name="solr" xsi:type="string"&gt;Search\Solr\Model\Indexer\IndexerHandler&lt;/item&gt;
        &lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/type&gt;
</pre>
<p>如果打开IndexerInterface，您将看到四个必须实现的方法： - saveIndex 将实体数据添加到索引 - deleteIndex 从索引中删除实体数据 - cleanIndex 从索引中删除所有数据 - isAvailable 定义引擎是否可用（您可以ping到solr服务器和检查它是否连接）。</p>
<p>我们的IndexerHandler框架类示例如下：</p>
<pre>&lt;?php
namespace Search\Solr\Model\Indexer;
 
use Magento\Eav\Model\Config;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Indexer\SaveHandler\IndexerInterface;
use Magento\Framework\Indexer\IndexStructureInterface;
use Magento\Framework\Search\Request\Dimension;
use Magento\Framework\Search\Request\IndexScopeResolverInterface;
use Magento\Framework\Indexer\SaveHandler\Batch;
use Magento\Framework\Indexer\ScopeResolver\IndexScopeResolver;
 
class IndexerHandler implements IndexerInterface
{
    private $indexStructure;
    private $data;
    private $fields;
    private $resource;
    private $batch;
    private $eavConfig;
    private $batchSize;
    private $indexScopeResolver;
    public function __construct(
        Batch $batch,
        array $data,
        $batchSize = 50
    ) {
        $this-&gt;batch = $batch;
        $this-&gt;data = $data;
        $this-&gt;batchSize = $batchSize;
    }
 
    public function saveIndex($dimensions, \Traversable $documents)
    {
        foreach ($this-&gt;batch-&gt;getItems($documents, $this-&gt;batchSize) as $batchDocuments)
        {
        }
    }
 
    public function deleteIndex($dimensions, \Traversable $documents)
    {
        foreach ($this-&gt;batch-&gt;getItems($documents, $this-&gt;batchSize) as $batchDocuments) 
        {
        }
    }
 
    public function cleanIndex($dimensions)
    {
    }
 
    public function isAvailable()
    {
        return true;
    }
}
</pre>
<p>在这些方法中，您应该实现Solr PHP客户端，它将对SOLR服务器进行列表操作。经常用到的是<a href="http://www.solarium-project.org/" rel="nofollow">Solarium PHP客户端</a>。</p>
<p>通过此步骤，我们将结束向搜索服务器索引数据的过程。</p>
<p>现在您可以检查您的索引器是否可以使用以下命令（在magento2 后台将搜索引擎设置为SOLR之前）：</p>
<pre>php /bin/magento indexer:reindex catalogsearch_fulltext
</pre>
<p>在接下来的最后一步中，我们将了解如何在Magento 2前端实现新的搜索引擎。所以，我们必须修改di.xml并添加以下代码：</p>
<pre>&lt;type name="Magento\Search\Model\AdapterFactory"&gt;
    &lt;arguments&gt;
        &lt;argument name="adapters" xsi:type="array"&gt;
            &lt;item name="solr" xsi:type="string"&gt;Search\Solr\SearchAdapter\Adapter&lt;/item&gt;
        &lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/type&gt;
</pre>
<p>我们的新适配器类是Seach\Solr\SearchAdapter\Adapter。适配器类需要实现Magento\Framework\Search\AdapterInterface。在我们的适配器中，我们必须实现方法<strong>query</strong> - 此方法接受查询请求并处理它。看看我们的例子，一切都会更清晰。</p>
<pre>&lt;?php
namespace Search\Solr\SearchAdapter;
use Magento\Framework\Search\AdapterInterface;
use Magento\Framework\Search\RequestInterface;
use Magento\Framework\Search\Response\QueryResponse;
use Search\Solr\SearchAdapter\Aggregation\Builder;
 
class Adapter implements AdapterInterface
{
    protected $responseFactory;
    protected $connectionManager;
    protected $aggregationBuilder;
 
    public function __construct(
        ResponseFactory $responseFactory,
        Builder $aggregationBuilder,
        ConnectionManager $connectionManager
    ) {
        $this-&gt;responseFactory = $responseFactory;
        $this-&gt;aggregationBuilder = $aggregationBuilder;
        $this-&gt;connectionManager = $connectionManager;
    }
    /**
     * @param RequestInterface $request
     * @return QueryResponse
     */
    public function query(RequestInterface $request)
    {
        $client = $this-&gt;getConnection();
        $documents = [];
        $documents[1007] = array('entity_id'=&gt;'1007', 'score'=&gt;46.055);
        $documents[1031] = array('entity_id'=&gt;'1031', 'score'=&gt;45.055);
        $documents[1120] = array('entity_id'=&gt;'1120', 'score'=&gt;44.055);
 
        $aggregations = $this-&gt;aggregationBuilder-&gt;build($request, $documents);
        $response = [
            'documents' =&gt; $documents,
            'aggregations' =&gt; $aggregations,
        ];
        return $this-&gt;responseFactory-&gt;create($response);
    }
 
    public function getConnection(){
        return $this-&gt;connectionManager-&gt;getConnection();
    }
}
?&gt;
</pre>
<p>在我们的示例适配器类中，我我们有一串产品entity_ids：1007,1031,1120来自于我们的数据库产品id，仅用于测试目的。如果你想深入挖掘，我建议你检查MySQL适配器的工作原理。</p>
<p>通过这一步，我们结束了我们的示例。即使事情看起来很复杂，但当你开始工作时，一切都会好起来的。我希望您能喜欢Magneto 2新搜索引擎的编码。</p>]]></description>
      <pubDate>Fri, 14 Sep 2018 03:21:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento1&2颜色选择color swatches设置详细介绍]]></title>
      <link>https://www.360magento.com/blog/magento-color-swatches/</link>
      <description><![CDATA[<div class="post-entry entry std">
<p>视觉感知对购买行为具有很大影响。93％的客户认为视觉外观是购买决策的关键因素。第一次印象不会随着时间而改变。</p>
<p>在构建magento电子商务网站期间，选择color swatches作为用户视觉体验的战斗工具。 color swatches提供了一种友好的方式来显示可配置产品的选择属性。我们想与您分享一些关于如何通过使用 color swatches获得最大利润的提示。</p>
<p>我们的教程将分别为Magento和Magento 2清楚的介绍color swatches。这将有助于你：</p>
<ul>
<li>浏览创建color swatches的过程</li>
<li>在分层导航块（左侧属性筛选）中显示色板</li>
<li>将color swatches集成到自定义主题中</li>
</ul>
<h2>让我们从创建color swatches开始......</h2>
<p>Magento附带Swatch配置，允许您在产品和类别页面以及分层导航中将产品属性显示为颜色样本。您可以更改样本的宽度和高度值。</p>
<p>注意：自Magento 1.9.1版本发布以来，颜色样本内置于可配置的样本功能中。</p>
<p>如果您运行较旧的Magento版本，我们建议您升级或使用Magento插件，以便轻松添加颜色样本。</p>
<p>我们将分别为Magento和Magento 2制作样本。</p>
<h2>创建颜色样本</h2>
<h3>Magento1的步骤</h3>
<p>1.首先，您需要创建将与可配置样本一起使用的属性。您可以在Admin&gt; Catalog&gt;Attribute&gt;Manage Attributes中执行此操作。请确保在&ldquo;Properties&rdquo;选项卡中看到以下值并设置：</p>
<ul>
<li>Scope设置为&ldquo;Global&rdquo;</li>
<li>Catalog Input Type for Store Owner设置为&ldquo;Dropdown&rdquo;</li>
<li>Apply to设置为&ldquo;Configurable Product&rdquo;</li>
<li>Use To Create Configurable Product设置为&ldquo;Yes&rdquo;。</li>
</ul>
<p>要添加新颜色，请查看&ldquo;Manage Label / Options&rdquo;选项卡。您必须按添加选项按钮。在&ldquo;Admin&rdquo;列中，指定颜色的名称。然后，为支持的每种语言定义颜色的名称。这些名称将显示在前端。您还可以设置颜色显示的顺序。请前往查找<a href="https://docs.magento.com/m1/ce/user_guide/catalog/attributes.html" rel="nofollow">有关magento创建属性</a>的更多详细信息</p>
<p>2.现在，您必须在Admin &gt; System &gt; Configuration &gt; CATALOG &gt; Configurable Swatches &gt; General Settings中启用magento可配置样本。然后在&ldquo;Product Attributes to Show as Swatches in Product Detail&rdquo;中选择&ldquo;颜色值&rdquo;以在产品详细页中显示为&ldquo;样本&rdquo;，在&ldquo;Product Attributes to Show as Swatches in Product Detail&rdquo;字段中选择颜色值以便在产品列表中使用样本。</p>
<p>3.保存后，请导航到Admin &gt; Catalog &gt; Manage Products并创建新的可配置产品。如果您在创建可配置产品时需要帮助，请阅读<a href="https://docs.magento.com/m1/ce/user_guide/catalog/product-configurable.html" rel="nofollow">使用说明</a>。</p>
<p>4.最后，您需要上传色板图像和相应的产品图像。</p>
<p>添加色板图像有两种方法。第一种方法是将图像上传到/ media / wysiwyg / swatches文件夹。第二个是将产品图像作为样本图像。重要的细节是：</p>
<ul>
<li>上传的图像必须是.png格式。</li>
<li>上传的图像名称应与其显示的相应属性值完全匹配。</li>
<li>上传到Media Storage的Swatch图像是全局可用的，可用于任何其他产品。</li>
</ul>
<p>您可以在Magento Swatches手册中阅读更多相关信息：</p>
<p><a href="https://docs.magento.com/m1/ce/user_guide/catalog/product-configurable-swatch.html" rel="nofollow">http://docs.magento.com/m1/ce/user_guide/catalog/product-configurable-swatch.html</a></p>
<p>5.重复所有步骤，以便根据需要设置多个样本。</p>
<p>6.重新索引并清除缓存。</p>
<h3>Magento 2的步骤</h3>
<p>在Magento 2中创建色样的过程已经简化。</p>
<p>1.转到Admin &gt; Stores &gt; Attributes &gt; Product，然后单击添加新属性按钮。填写&ldquo;Properties&rdquo;选项卡中的所有必填字段。确保你看到：</p>
<ul>
<li>在Catalog Input Type for Store Owner中选择Visual Swatch。</li>
<li>Update Product Preview Image设置为&ldquo;Yes&rdquo;。</li>
<li>Use Product Image for Swatch if Possible，如果可能，则将产品图像用于样本，将值设置为&ldquo;No&rdquo;。如果要在产品页面上将产品图像显示为可点击样本，可以选择&ldquo;Yes&rdquo;。</li>
</ul>
<p>注意：您可以在此处了解有关<a href="https://docs.magento.com/m2/ce/user_guide/catalog/product-attributes.html" rel="nofollow">创建属性的更多信息</a></p>
<p>2.现在，您需要单击&ldquo; Swatch button&rdquo;按钮。添加您的属性值。</p>
<p>3.指定色板名称。</p>
<p>4.您可以选择颜色单击颜色框附近的箭头。您还可以使用色板图像替换颜色。请单击上传文件。</p>
<p>5.继续填写&ldquo;Advanced Attribute Properties&rdquo;字段以及&ldquo;Manage Labels&rdquo;和&ldquo; Storefront properties&rdquo;选项卡中的字段。保存并清除缓存。</p>
<p>现在，您需要将新创建的属性分配给产品。如果您需要先创建产品，请<a href="https://docs.magento.com/m2/ce/user_guide/catalog/product-create-configurable.html" rel="nofollow">查看用户指南。</a></p>
<p>请继续关注 - 我们会不定期更新我们的博文。</p>
</div>]]></description>
      <pubDate>Fri, 07 Sep 2018 08:21:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2创建自定义模块步骤/教程]]></title>
      <link>https://www.360magento.com/blog/create-moudle-m2/</link>
      <description><![CDATA[<p>
Magento2模块开发是magento开发人员必备的技能，此片文章中我们将一步一步教您在Magento2中创建一个HelloWorld模块，
</p>
<h2>基本要求</h2>
<p>在Magento 2中启动模块开发过程之前，请确保满足以下要求：</p>
<ul>
<li>安装最新版本的Magento 2，即2.1（如果您使用的是旧版本）。</li>
<li>如果您不想在每次更改编码时从Web存储中删除缓存，则应禁用Magento缓存。这将节省您的时间并加快您的模块开发过程。要禁用缓存，您需要转到Admin » System » Cache Management » 选择所有缓存类型并禁用它们。</li>
<li>将Magento切换到开发人员模式。这将帮助您轻松查看网站中的所有错误和漏洞。要打开开发人员模式，您需要访问终端并在Magento 2根目录执行如下命令：
<pre>php bin/magento deploy:mod:set developer</pre>
</li>
</ul>
<p>现在，让我们开始在Magento 2中创建新的自定义模块。</p>
<h2>1.创建模块文件夹</h2>
<p>在Magento 2中创建模块的过程与我们在旧版Magento中使用的过程完全不同。在Magento 2中，没有代码池文件夹。并且所有模块都按命名空间分组并放在<code>app/code</code>文件夹中。这意味着您需要在<code>app/code</code>目录中直接创建模块：<code>app/code/&lt;Vendor&gt;/&lt;ModuleName&gt;</code></p>
<h2>1.1模块设置</h2>
<p>要设置模块，我们需要创建模块文件夹和其他基本文件。这一特定步骤将帮助您轻松地为最新版本的Magento注册新模块</p>
<h3>创建这两个文件夹:</h3>
<p><code>app/code/webstore</code></p>
<p><code>app/code/Webstore/HelloWorld</code></p>
<p>注意：这里'Webstore'是模块的命名空间，而'Helloworld'是模块的名称。</p>
<h3>1.1.2创建module.xml文件以声明模块</h3>
<p>创建模块文件夹后，您需要使用以下代码在<code>app/code/Webstore/HelloWorld/etc</code>文件夹中创建<code>module.xml</code>文件：</p>
<pre>
&lt;?xml version="1.0"?&gt;

&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"&gt; 
&lt;module name="webstore_HelloMagento" setup_version="1.0.0" /&gt;
&lt;/module&gt;
&lt;/config&gt;
</pre>
<p>这将在模块etc目录中创建一个配置，让Magento 2轻松识别模块的名称和版本。</p>
<p>在此特定文件中，我们将声明一个名为webstore_Helloworld且版本为1.0.0 的模块</p>
<h3>1.1.3注册模块</h3>
<p>在Magento 2中，您需要通过Magento <code>ComponentRegistrar</code>类在Magento系统中注册所有模块。因此，您需要在<code>app/code/Webstore/Helloworld</code>文件夹中创建<code>registration.php</code>文件：</p>
<pre>
&lt;?php
\Magento\Framework\Component\ComponentRegistrar::register(\Magento\Framework\Component\ComponentRegistrar::MODULE,'webstore_Helloworld',__DIR__);
</pre>
<h3>1.1.4启用模块</h3>
<p>注册模块后，您可以在Magento 2环境中启用它。要检查Magento是否已识别新模块，您需要运行以下命令行：</p>
<pre>php bin/magento module:status1</pre>
<p>上面的步骤将显示以下结果：</p>
<pre>
List of disabled modules:
Webstore_HelloWorld
</pre>
<p>这意味着系统已识别该模块，但未在Magento系统中启用。为此，您需要运行以下命令来启用该模块：</p>
<pre>
php bin/magento module:enable Webstore_HelloWorld
</pre>
<p>这将启用系统中的模块，并显示如下结果：</p>
<pre>
The following modules has been enabled:
- Webstore_HelloWorld
</pre>
<p>由于您是第一次在系统中启用此模块，因此请确保运行此命令以让Magento轻松检查和升级模块数据库：</p>
<pre>php bin/magento setup:upgrade</pre>
<p>注意：进入Admin » Stores » Configuration » Advanced » Advanced以检查新模块的可用性</p>
<h2>2.创建控制器</h2>
<h3>2.1为新模块创建routes.xml文件</h3>
<p>
在此步骤中，您需要通过在Magento根目录中创建<code>routes.xml</code>文件来为新模块定义路由器。在<code>app/code/Webstore/HelloWorld/frontend</code>文件夹中添加以下代码：
</p>
<pre>
&lt;?xml version="1.0" ?&gt;  
&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"&gt;
&lt;router id="standard"&gt;
&lt;route id="helloworld" frontName="helloworld"&gt;
&lt;module name="Webstore_Helloworld"/&gt;
&lt;/route&gt;
&lt;/router&gt;
&lt;/config&gt;
</pre>
<p>注意：上面的代码将帮助您定义前端路由器和路由HelloWorld</p>
<p>在Magento 2中，frontName属性成为URL的第一部分。这意味着您的URL将生成如下：</p>
<pre>&lt;frontname&gt;/&lt;controller_folder-name&gt;/&lt;controller_class_name&gt;</pre>
<p>举个例子：</p>
<pre>helloworld/index/index</pre>
<h3>2.2创建index.php控制器文件</h3>
<p>在此步骤中，您将需要创建控制器和action的index.php控制器文件来显示HelloWorld模块。为此，在app/code/Webstore/HelloWorld/Controller/Index文件夹中添加以下代码：</p>
<pre>
&lt;?php

namespace Webstore\Helloworld\Controller\Index;

use Magento\Framework\App\Action\Context;

class Index extends \Magento\Framework\App\Action\Action 
{
    protected $_resultPageFactory;

    public function __construct(Context $context, \Magento\Framework\View\Result\PageFactory $resultPageFactory){
        $this->_resultPageFactory = $resultPageFactory; 
        parent::__construct($context); 
    }

    public function execute() {
        $resultPage = $this->_resultPageFactory->create(); 
        return $resultPage; 
    }
}
</pre>
<h2>3.创建一个Block块</h2>
<p>你需要创建一个block累，使用<code>getHelloWorldTxt()</code>方法,然后返回“Hello world” 字符串</p>
<h3>3.1创建HelloWorld.php文件</h3>
<p>在<code>app/code/Webstore/HelloWorld/Block </code>文件夹下创建HelloWorld.php，并写入以下代码</p>
<pre>
&lt;?php

namespace Webstore\Helloworld\Block;   

class Helloworld extends \Magento\Framework\View\Element\Template 
{
    public function getHelloWorldTxt(){ 
        return'Hello world!'; 
    } 
}
</pre>
<h2>4.创建一个布局和模板文件</h2>
<p>在Magento 2中，您可以在模块内的视图文件夹中找到布局文件和模板。在此文件夹下，您可以看到三个子文件夹：</p>
<ul>
<li>adminhtml：用于后端文件</li>
<li>frontend文件夹：用于前端文件，和</li>
<li>Base文件夹：用于admin和frontend文件。</li>
</ul>
<p>因此，首先，我们将在前端布局中创建布局和模板文件。</p>
<h3>4.1创建helloworld_index_index.xml文件</h3>
<p>请在<code>app/code/Webstore/Helloworld/view/forntend/layout</code>文件夹中创建布局文件<code>helloworld_index_index.xml</code>并写入以下代码：</p>
<pre>
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd" layout="1column"&gt;
&lt;body&gt;
&lt;referenceContainer name="content"&gt;
&lt;block class="Webstore\Helloworld\Block\Helloworld" name="helloworld" template="helloworld.phtml"/&gt;
&lt;/referenceContainer&gt;
&lt;/body&gt;
&lt;/page&gt;
</pre>
<p>注意：确保将块添加到内容容器并将块的模板设置为helloworld.phtml,然后创建下一步。</p>
<h3>4.2在前端模板文件夹中创建helloworld.phtml文件</h3>
<p>在<code>app/code/Webstore/Helloworld/view/frontend/templates</code>文件夹中创建模板文件<code>helloworld.phtml</code>并写入下面代码：</p>
<pre>
&lt;h1&gt;&lt;?php echo $this->getHelloWorldTxt(); ?>&lt;/h1&gt;
</pre>
<p>注意： $this变量被视为块类，调用方法为getHelloWorldTxt()。</p>
<p>现在，在浏览器中访问/helloworld/index/index URL以在Magento 2中查看您的全新模块。该URL将如下所示：http://xyz.com/helloworld/index/display</p>

<p>如果您仔细遵循上述步骤，在Magento 2中创建新模块可能是一个简单的过程。您可以轻松使用我们的源代码并为您的Magento网上商店开发一流的模块。</p>
<br>
<p>想要为您的Magento2平台增加更多特色功能模块，请<a href="https://www.360magento.com/contacts">提交您的需求</a></p>]]></description>
      <pubDate>Sun, 02 Sep 2018 15:40:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2 获取base url , media url 和 static url]]></title>
      <link>https://www.360magento.com/blog/magento2-get-url/</link>
      <description><![CDATA[<p>在Magento2开发过程中经常会用到Base Url,Media Url,Static Url,下面就讲下在Magento2的不同文件中调用Base Url,Media Url,Static Url</p>
<h2>在phtml文件中获取Base Url,Media Url,Static Url</h2>
<pre>&lt;?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$storeManager = $objectManager-&gt;get('\Magento\Store\Model\StoreManagerInterface');
/* Get base url with index When index.php enable at Url */
$baseUrl = $storeManager-&gt;getStore()-&gt;getBaseUrl();
/* Result  http://www.example.com/ or http://www.example.com/index.php  depends SEo rewite settng*/
/* it always give the URL without Index.php either index.php enable for Url */ 
$baseUrlWithOutIndexPhp = $storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB);
// $baseUrl  result = http://example.com/

/* It is give url with index.php whenever  seo rewrite not enable mean when  Index.php show at Url  */

$linkUrl= $storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK);
 
 /* $linkUrl  result = http://example.com/index.php/
 		 whenever  seo rewrite not enable mean when  Index.php show at Url
		
		but when  SEO Rewrite enabled
		
		Then it show result = http://example.com/
 
 */

$statiContenteUrl =$storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_STATIC);
/* Result $statiContenteUrl = http://example.com/pub/static/version1507042743/
 	In this part  version1507042743 is 1507042743 static content version which dynamcically created
*/

$mediaUrl =  $storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
/* Result $mediaUrl = http://example.com/pub/media/

*/</pre>
<p>直接使用对象管理器不是一个好主意</p>
<p>如果在您的Block/helper/controller/Model中有Store Manager Object类，你就可以用下面的代码获取Base Url,Media Url,Static Url，注意，你讲通过Magento\Store\Model\StoreManagerInterface注入类获取商店管理器对象</p>
<h2>获取Base Url</h2>
<pre>/* it always give the URL  Index.php either index.php enable for Url */ 
/*  result   is http://example.com/  or http://example.com/index.php depends Magento Setting SEO Rewrite  */
$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl()
</pre>
<p>你将得到如下结果</p>
<p>http://www.example.com (如果Seo rewrite 开启) 和 http://www.example.com/index.php (如果Seo rewrite 未开启)</p>
<p>如果你想获取的Base Url不带index.php,用下面的代码</p>
<pre>$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB)
</pre>
<h2>获取Media Url</h2>
<pre>$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl()
</pre>
<h2>获取链接 Url</h2>
<pre> /* $linkUrl  result = http://example.com/index.php/ whenever  seo rewrite not enable mean when  Index.php show at Url
		but when  SEO Rewrite enabled Then it show result = http://example.com/
 */
  $this-&gt;_storeManager-&gt;getStore()
               -&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK);
</pre>
<h2>获取Static Url</h2>
<pre>/* Result $statiContenteUrl = http://example.com/pub/static/version1507042743/
 	In this part  version1507042743 is 1507042743 static content version which dynamcically created

$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_STATIC);
</pre>
<p>在Magento1中你可以用Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB))来获取Base Url，<a href="https://www.360magento.com/blog/magento-get-url" title="Magento1获取Base Url , Skin Url , Media Url , Js Url , Store Url 和 Current Url">Magento1获取Base Url , Skin Url , Media Url , Js Url , Store Url 和 Current Url链接</a></p>
<p>在Magento2中，没有使用工厂模式，所以没有像Mage :: getBaseUrl()的代码，你可以使用StoreManager object，然后用$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl()你就可以获得Base Url了。</p>
<p>Magento2中，使用接口、注入类，你应该注入</p>
<p>Magento\Store\Model\StoreManagerInterface</p>
<p>在Model，Resource model，Helper类中获取Base URL。</p>
<p>在下面的示例类中，我已经为我的类注入了StoreManagerInterface</p>
<pre>&lt;?php
namespace {MyClassNameSpace};
class {ClassName} 
{
    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;
 
    public function __construct(
		 ......
        \Magento\Store\Model\StoreManagerInterface $storeManager
			 .......
    ) {
 		.....
        $this-&gt;_storeManager = $storeManager;
 		.....
    }
 
    public function mygStoreBaseUrl(){
		
		$statiContenteUrl = $this-&gt;_storeManager-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_STATIC);
		$mediaUrl = $this-&gt;_storeManager-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA);
		$linkUrl = $this-&gt;_storeManager-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_LINK);
		$baseUrlwithoutIndexPhp = $this-&gt;_storeManager-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB);

 		return $this-&gt;_storeManager-&gt;getStore()
					-&gt;getBaseUrl();
					
    }
    public function myStoreUrl(){
 
 		return $this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl()
    }
    
}
</pre>
<p>请注意：如果您使用了任何块类扩展基本块模板</p>
<pre>\Magento\Framework\View\Element\Template</pre>
<p>应该避免为该情况注入商店管理器接口，因为extends类已经有商店管理器对象</p>
<pre> \Magento\Store\Model\StoreManagerInterface
</pre>
<p>尝试下面的代码来获取magento2 BaseURL</p>
<pre>$this-&gt;_storeManager-&gt;getStore()-&gt;getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB)</pre>
<p>如何通过对象管理器获取magento2 Base URL 使用对象管理器获取magento2 Base URL然后尝试下面：</p>
<pre>$this-&gt;_objectManager-&gt;get('Magento\Store\Model\StoreManagerInterface')
            -&gt;getStore($storeId)
            -&gt;getBaseUrl();
</pre>
<p>假设您的类具有对象管理器。</p>
<p>如果没有对象管理器，那么试试这个：</p>
<pre>
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$storeManager = $objectManager->get('\Magento\Store\Model\StoreManagerInterface');
$storeManager->getStore()->getBaseUrl();
</pre>
<p>但是这种类型的对象管理器调用真的很糟糕。</p>]]></description>
      <pubDate>Wed, 29 Aug 2018 08:42:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2如何获取订单商品总数量]]></title>
      <link>https://www.360magento.com/blog/m2-get-order-item/</link>
      <description><![CDATA[<p>电子商务由几个丰富的元素组成，Magento已成功覆盖了所有这些元素，也许这就是为什么它成为世界500强的的选择。但通常情况下，每个Magento项目都会通过定制来为商城提供个性化的功能效果。</p>
<p>从事magento定制开发工作，我们遇到了太多的不同的定制要求，有时我们听到客户的一些需求感到震惊，每个企业都有自己的故事，自己的需求和个性化需求，这就是它独特的原因。</p>
<p>最近，其中一位客户告诉我们，他花了大量时间来确定订单中有多少产品数量。他想节省时间，以便将宝贵的时间投入到其他业务中。也许你也需要知道订单产品总数量，所以这段代码可以帮助你节省时间。因此，我们已经确定了使用以下两种方法快速完成其工作的两种方法。</p>
<h2>方法1：标准Magento方法</h2>
<pre>public function __construct(\Magento\Sales\Model\OrderFactory $orderFactory)
{
    $this-&gt;orderFactory = $orderFactory;
}
 
public function execute()
{
     $orderId = 5;  //PASS YOUR ORDER ID HERE
     $order = $this-&gt;orderFactory-&gt;create()-&gt;load($orderId);
     $orderItems = $order-&gt;getAllItems();
     $total_qty = 0;
     foreach ($orderItems as $item)
     {
          $total_qty = $total_qty + $item-&gt;getQtyOrdered();
     }
     return $total_qty;
}
</pre>
<h2>方法2：使用对象管理器</h2>
<pre>$order_id = 5;  //PASS YOUR ORDER ID HERE
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$order = $objectManager-&gt;create('Magento\Sales\Model\Order')-&gt;load($order_id);
$orderItems = $order-&gt;getAllItems();
$total_qty = 0;
foreach ($orderItems as $item)
{
   $total_qty = $total_qty + $item-&gt;getQtyOrdered();
}
 
echo $total_qty;
</pre>]]></description>
      <pubDate>Mon, 27 Aug 2018 12:54:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2命令行大全]]></title>
      <link>https://www.360magento.com/blog/magento2-cli/</link>
      <description><![CDATA[<article class="article-content">
			<p>在本教程中，我们将讨论<strong><a class="no-text-color" href="http://blog.magego.com/m2dev-tutorials15/" data-original-title="" title="">Magento 2中的命令行接口（CLI）</a></strong>。如你所知，Magento 2在<code class="highlighter-rouge">bin/magento</code>添加了许多命令。</p>
<p>当你在终端运行命令时：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento</span></li></ol></pre>
<p>要么</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">bin</span><span class="pun">/</span><span class="pln">magento</span></li></ol></pre>
<p>你将得到可用的Magento 2命令行列表，这个列表包括<a href="/m2dev-tutorials14" data-original-title="" title="">自定义的命令行</a></p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="typ">Usage</span><span class="pun">:</span><span class="pln">                                                                                                                      </span></li><li class="L1"><span class="pln"> command </span><span class="pun">[</span><span class="pln">options</span><span class="pun">]</span><span class="pln"> </span><span class="pun">[</span><span class="pln">arguments</span><span class="pun">]</span><span class="pln">                                                                                              </span></li><li class="L2"><span class="pln">                                                                                                                            </span></li><li class="L3"><span class="typ">Options</span><span class="pun">:</span><span class="pln">                                                                                                                    </span></li><li class="L4"><span class="pln"> </span><span class="pun">--</span><span class="pln">help </span><span class="pun">(-</span><span class="pln">h</span><span class="pun">)</span><span class="pln">           </span><span class="typ">Display</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> help message                                                                            </span></li><li class="L5"><span class="pln"> </span><span class="pun">--</span><span class="pln">quiet </span><span class="pun">(-</span><span class="pln">q</span><span class="pun">)</span><span class="pln">          </span><span class="typ">Do</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> output any message                                                                            </span></li><li class="L6"><span class="pln"> </span><span class="pun">--</span><span class="pln">verbose </span><span class="pun">(-</span><span class="pln">v</span><span class="pun">|</span><span class="pln">vv</span><span class="pun">|</span><span class="pln">vvv</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Increase</span><span class="pln"> the verbosity of messages</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> normal output</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> more verbose output </span><span class="kwd">and</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="kwd">for</span><span class="pln"> debug   </span></li><li class="L7"><span class="pln"> </span><span class="pun">--</span><span class="pln">version </span><span class="pun">(-</span><span class="pln">V</span><span class="pun">)</span><span class="pln">        </span><span class="typ">Display</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> application version                                                                     </span></li><li class="L8"><span class="pln"> </span><span class="pun">--</span><span class="pln">ansi                </span><span class="typ">Force</span><span class="pln"> ANSI output                                                                                    </span></li><li class="L9"><span class="pln"> </span><span class="pun">--</span><span class="kwd">no</span><span class="pun">-</span><span class="pln">ansi             </span><span class="typ">Disable</span><span class="pln"> ANSI output                                                                                  </span></li><li class="L0"><span class="pln"> </span><span class="pun">--</span><span class="kwd">no</span><span class="pun">-</span><span class="pln">interaction </span><span class="pun">(-</span><span class="pln">n</span><span class="pun">)</span><span class="pln"> </span><span class="typ">Do</span><span class="pln"> </span><span class="kwd">not</span><span class="pln"> ask any interactive question                                                                  </span></li><li class="L1"><span class="pln">                                                                                                                            </span></li><li class="L2"><span class="typ">Available</span><span class="pln"> commands</span><span class="pun">:</span><span class="pln">                                                                                                         </span></li><li class="L3"><span class="pln"> help                                      </span><span class="typ">Displays</span><span class="pln"> help </span><span class="kwd">for</span><span class="pln"> a command                                                      </span></li><li class="L4"><span class="pln"> list                                      </span><span class="typ">Lists</span><span class="pln"> commands                                                                   </span></li><li class="L5"><span class="pln">admin                                                                                                                       </span></li><li class="L6"><span class="pln"> admin</span><span class="pun">:</span><span class="pln">user</span><span class="pun">:</span><span class="pln">create                         </span><span class="typ">Creates</span><span class="pln"> an administrator                                                         </span></li><li class="L7"><span class="pln"> admin</span><span class="pun">:</span><span class="pln">user</span><span class="pun">:</span><span class="pln">unlock                         </span><span class="typ">Unlock</span><span class="pln"> </span><span class="typ">Admin</span><span class="pln"> </span><span class="typ">Account</span><span class="pln">                                                             </span></li><li class="L8"><span class="pln">cache                                                                                                                       </span></li><li class="L9"><span class="pln"> cache</span><span class="pun">:</span><span class="pln">clean                               </span><span class="typ">Cleans</span><span class="pln"> cache type</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">                                                             </span></li><li class="L0"><span class="pln"> cache</span><span class="pun">:</span><span class="pln">disable                             </span><span class="typ">Disables</span><span class="pln"> cache type</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">                                                           </span></li><li class="L1"><span class="pln"> cache</span><span class="pun">:</span><span class="pln">enable                              </span><span class="typ">Enables</span><span class="pln"> cache type</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">                                                            </span></li><li class="L2"><span class="pln"> cache</span><span class="pun">:</span><span class="pln">flush                               </span><span class="typ">Flushes</span><span class="pln"> cache storage used </span><span class="kwd">by</span><span class="pln"> cache type</span><span class="pun">(</span><span class="pln">s</span><span class="pun">)</span><span class="pln">                                      </span></li><li class="L3"><span class="pln"> cache</span><span class="pun">:</span><span class="pln">status                              </span><span class="typ">Checks</span><span class="pln"> cache status                                                              </span></li><li class="L4"><span class="pln">catalog                                                                                                                     </span></li><li class="L5"><span class="pln"> catalog</span><span class="pun">:</span><span class="pln">images</span><span class="pun">:</span><span class="pln">resize                     </span><span class="typ">Creates</span><span class="pln"> resized product images                                                   </span></li><li class="L6"><span class="pln"> catalog</span><span class="pun">:</span><span class="pln">product</span><span class="pun">:</span><span class="pln">attributes</span><span class="pun">:</span><span class="pln">cleanup        </span><span class="typ">Removes</span><span class="pln"> unused product attributes</span><span class="pun">.</span><span class="pln">                                               </span></li><li class="L7"><span class="pln">cron                                                                                                                        </span></li><li class="L8"><span class="pln"> cron</span><span class="pun">:</span><span class="pln">run                                  </span><span class="typ">Runs</span><span class="pln"> jobs </span><span class="kwd">by</span><span class="pln"> schedule                                                            </span></li><li class="L9"><span class="pln">customer                                                                                                                    </span></li><li class="L0"><span class="pln"> customer</span><span class="pun">:</span><span class="pln">hash</span><span class="pun">:</span><span class="pln">upgrade                     </span><span class="typ">Upgrade</span><span class="pln"> customer</span><span class="str">'s hash according to the latest algorithm                        </span></li><li class="L1"><span class="str">deploy                                                                                                                      </span></li><li class="L2"><span class="str"> deploy:mode:set                           Set application mode.                                                            </span></li><li class="L3"><span class="str"> deploy:mode:show                          Displays current application mode.                                               </span></li><li class="L4"><span class="str">dev                                                                                                                         </span></li><li class="L5"><span class="str"> dev:source-theme:deploy                   Collects and publishes source files for theme.                                   </span></li><li class="L6"><span class="str"> dev:tests:run                             Runs tests                                                                       </span></li><li class="L7"><span class="str"> dev:urn-catalog:generate                  Generates the catalog of URNs to *.xsd mappings for the IDE to highlight xml.    </span></li><li class="L8"><span class="str"> dev:xml:convert                           Converts XML file using XSL style sheets                                         </span></li><li class="L9"><span class="str">i18n                                                                                                                        </span></li><li class="L0"><span class="str"> i18n:collect-phrases                      Discovers phrases in the codebase                                                </span></li><li class="L1"><span class="str"> i18n:pack                                 Saves language package                                                           </span></li><li class="L2"><span class="str"> i18n:uninstall                            Uninstalls language packages                                                     </span></li><li class="L3"><span class="str">indexer                                                                                                                     </span></li><li class="L4"><span class="str"> indexer:info                              Shows allowed Indexers                                                           </span></li><li class="L5"><span class="str"> indexer:reindex                           Reindexes Data                                                                   </span></li><li class="L6"><span class="str"> indexer:reset                             Resets indexer status to invalid                                                 </span></li><li class="L7"><span class="str"> indexer:set-mode                          Sets index mode type                                                             </span></li><li class="L8"><span class="str"> indexer:show-mode                         Shows Index Mode                                                                 </span></li><li class="L9"><span class="str"> indexer:status                            Shows status of Indexer                                                          </span></li><li class="L0"><span class="str">info                                                                                                                        </span></li><li class="L1"><span class="str"> info:adminuri                             Displays the Magento Admin URI                                                   </span></li><li class="L2"><span class="str"> info:backups:list                         Prints list of available backup files                                            </span></li><li class="L3"><span class="str"> info:currency:list                        Displays the list of available currencies                                        </span></li><li class="L4"><span class="str"> info:dependencies:show-framework          Shows number of dependencies on Magento framework                                </span></li><li class="L5"><span class="str"> info:dependencies:show-modules            Shows number of dependencies between modules                                     </span></li><li class="L6"><span class="str"> info:dependencies:show-modules-circular   Shows number of circular dependencies between modules                            </span></li><li class="L7"><span class="str"> info:language:list                        Displays the list of available language locales                                  </span></li><li class="L8"><span class="str"> info:timezone:list                        Displays the list of available timezones                                         </span></li><li class="L9"><span class="str">maintenance                                                                                                                 </span></li><li class="L0"><span class="str"> maintenance:allow-ips                     Sets maintenance mode exempt IPs                                                 </span></li><li class="L1"><span class="str"> maintenance:disable                       Disables maintenance mode                                                        </span></li><li class="L2"><span class="str"> maintenance:enable                        Enables maintenance mode                                                         </span></li><li class="L3"><span class="str"> maintenance:status                        Displays maintenance mode status                                                 </span></li><li class="L4"><span class="str">module                                                                                                                      </span></li><li class="L5"><span class="str"> module:disable                            Disables specified modules                                                       </span></li><li class="L6"><span class="str"> module:enable                             Enables specified modules                                                        </span></li><li class="L7"><span class="str"> module:status                             Displays status of modules                                                       </span></li><li class="L8"><span class="str"> module:uninstall                          Uninstalls modules installed by composer                                         </span></li><li class="L9"><span class="str">sampledata                                                                                                                  </span></li><li class="L0"><span class="str"> sampledata:deploy                         Deploy sample data modules                                                       </span></li><li class="L1"><span class="str"> sampledata:remove                         Remove all sample data packages from composer.json                               </span></li><li class="L2"><span class="str"> sampledata:reset                          Reset all sample data modules for re-installation                                </span></li><li class="L3"><span class="str">setup                                                                                                                       </span></li><li class="L4"><span class="str"> setup:backup                              Takes backup of Magento Application code base, media and database                </span></li><li class="L5"><span class="str"> setup:config:set                          Creates or modifies the deployment configuration                                 </span></li><li class="L6"><span class="str"> setup:cron:run                            Runs cron job scheduled for setup application                                    </span></li><li class="L7"><span class="str"> setup:db-data:upgrade                     Installs and upgrades data in the DB                                             </span></li><li class="L8"><span class="str"> setup:db-schema:upgrade                   Installs and upgrades the DB schema                                              </span></li><li class="L9"><span class="str"> setup:db:status                           Checks if DB schema or data requires upgrade                                     </span></li><li class="L0"><span class="str"> setup:di:compile                          Generates DI configuration and all missing classes that can be auto-generated    </span></li><li class="L1"><span class="str"> setup:install                             Installs the Magento application                                                 </span></li><li class="L2"><span class="str"> setup:performance:generate-fixtures       Generates fixtures                                                               </span></li><li class="L3"><span class="str"> setup:rollback                            Rolls back Magento Application codebase, media and database                      </span></li><li class="L4"><span class="str"> setup:static-content:deploy               Deploys static view files                                                        </span></li><li class="L5"><span class="str"> setup:store-config:set                    Installs the store configuration                                                 </span></li><li class="L6"><span class="str"> setup:uninstall                           Uninstalls the Magento application                                               </span></li><li class="L7"><span class="str"> setup:upgrade                             Upgrades the Magento application, DB data, and schema                            </span></li><li class="L8"><span class="str">theme                                                                                                                       </span></li><li class="L9"><span class="str"> theme:uninstall                           Uninstalls theme                                                                 </span></li></ol></pre>
<h2 id="command-line-category">命令行类别</h2>
<p>我们可以把这个列表分成以下几类：</p>
<ul>
<li>Cache</li>
<li>Indexer</li>
<li>Cron job</li>
<li>Code compiler</li>
<li>Set the Magento mode</li>
<li>i18n translation</li>
<li>Run unit tests</li>
<li>Maintenance</li>
<li>module management</li>
<li>Setup: Install, Upgrade, Uninstall, Backup , Rollback</li>
<li>Theme</li>
<li>Deployment</li>
</ul>
<p>接下来我们将举几个例子。</p>
<h2 id="cache-command-line">缓存命令行</h2>
<h5 id="how-to-check-status-of-cache-types">如何检查缓存类型的状态</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">status</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">                    config</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L1"><span class="pln">                    layout</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L2"><span class="pln">                block_html</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L3"><span class="pln">               collections</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L4"><span class="pln">                    db_ddl</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L5"><span class="pln">                       eav</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L6"><span class="pln">                 full_page</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L7"><span class="pln">                 translate</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L8"><span class="pln">        config_integration</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L9"><span class="pln">    config_integration_api</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li><li class="L0"><span class="pln">         config_webservice</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span></li></ol></pre>
<h5 id="how-to-clean-cache-types">如何清理缓存类型</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">clean</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">clean                  </span></li><li class="L1"><span class="typ">Cleaned</span><span class="pln"> cache types</span><span class="pun">:</span><span class="pln">                           </span></li><li class="L2"><span class="pln">config                                         </span></li><li class="L3"><span class="pln">layout                                         </span></li><li class="L4"><span class="pln">block_html                                     </span></li><li class="L5"><span class="pln">collections                                    </span></li><li class="L6"><span class="pln">reflection                                     </span></li><li class="L7"><span class="pln">db_ddl                                         </span></li><li class="L8"><span class="pln">eav                                            </span></li><li class="L9"><span class="pln">customer_notification                          </span></li><li class="L0"><span class="pln">full_page                                      </span></li><li class="L1"><span class="pln">config_integration                             </span></li><li class="L2"><span class="pln">config_integration_api                         </span></li><li class="L3"><span class="pln">translate                                      </span></li><li class="L4"><span class="pln">config_webservice</span></li></ol></pre>
<h5 id="how-to-flush-cache-types">如何刷新缓存类型</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">flush</span></li></ol></pre>
<h5 id="how-to-check-enable-disable-cache-types">如何检查启用，禁用缓存类型</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">enable</span></li><li class="L1"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">disable</span></li></ol></pre>
<p>高级命令：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">enable </span><span class="pun">[</span><span class="pln">type</span><span class="pun">]</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">[</span><span class="pln">type</span><span class="pun">]</span></li><li class="L1"><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">disable </span><span class="pun">[</span><span class="pln">type</span><span class="pun">]</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">[</span><span class="pln">type</span><span class="pun">]</span></li></ol></pre>
<p>例如禁用整页缓存</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">magento cache</span><span class="pun">:</span><span class="pln">disable full_page</span></li></ol></pre>
<h2 id="indexer-command-line">索引器命令行</h2>
<p>通过以下命令检查索引器状态</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="pln">info</span></li></ol></pre>
<p>我们会得到结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">design_config_grid                       </span><span class="typ">Design</span><span class="pln"> </span><span class="typ">Config</span><span class="pln"> </span><span class="typ">Grid</span></li><li class="L1"><span class="pln">customer_grid                            </span><span class="typ">Customer</span><span class="pln"> </span><span class="typ">Grid</span></li><li class="L2"><span class="pln">catalog_category_product                 </span><span class="typ">Category</span><span class="pln"> </span><span class="typ">Products</span></li><li class="L3"><span class="pln">catalog_product_category                 </span><span class="typ">Product</span><span class="pln"> </span><span class="typ">Categories</span></li><li class="L4"><span class="pln">catalog_product_price                    </span><span class="typ">Product</span><span class="pln"> </span><span class="typ">Price</span></li><li class="L5"><span class="pln">catalog_product_attribute                </span><span class="typ">Product</span><span class="pln"> EAV</span></li><li class="L6"><span class="pln">catalogsearch_fulltext                   </span><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Search</span></li><li class="L7"><span class="pln">cataloginventory_stock                   </span><span class="typ">Stock</span></li><li class="L8"><span class="pln">catalogrule_rule                         </span><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Rule</span><span class="pln"> </span><span class="typ">Product</span></li><li class="L9"><span class="pln">catalogrule_product                      </span><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Product</span><span class="pln"> </span><span class="typ">Rule</span></li></ol></pre>
<h5 id="how-to-reindexe-data">如何重建数据</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="pln">reindex</span></li></ol></pre>
<h5 id="how-to-reset-indexer-status-to-invalid">如何将索引器状态重置为无效</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="pln">reset</span></li></ol></pre>
<h5 id="how-to-show-index-mode">如何显示索引模式</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="pln">show</span><span class="pun">-</span><span class="pln">mode</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="pln">show</span><span class="pun">-</span><span class="pln">mode</span></li><li class="L1"><span class="pln">&nbsp;</span></li><li class="L2"><span class="typ">Design</span><span class="pln"> </span><span class="typ">Config</span><span class="pln"> </span><span class="typ">Grid</span><span class="pun">:</span><span class="pln">                                </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L3"><span class="typ">Customer</span><span class="pln"> </span><span class="typ">Grid</span><span class="pun">:</span><span class="pln">                                     </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L4"><span class="typ">Category</span><span class="pln"> </span><span class="typ">Products</span><span class="pun">:</span><span class="pln">                                 </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L5"><span class="typ">Product</span><span class="pln"> </span><span class="typ">Categories</span><span class="pun">:</span><span class="pln">                                </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L6"><span class="typ">Product</span><span class="pln"> </span><span class="typ">Price</span><span class="pun">:</span><span class="pln">                                     </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L7"><span class="typ">Product</span><span class="pln"> EAV</span><span class="pun">:</span><span class="pln">                                       </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L8"><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Search</span><span class="pun">:</span><span class="pln">                                    </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L9"><span class="typ">Stock</span><span class="pun">:</span><span class="pln">                                             </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L0"><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Rule</span><span class="pln"> </span><span class="typ">Product</span><span class="pun">:</span><span class="pln">                              </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li><li class="L1"><span class="typ">Catalog</span><span class="pln"> </span><span class="typ">Product</span><span class="pln"> </span><span class="typ">Rule</span><span class="pun">:</span><span class="pln">                              </span><span class="typ">Update</span><span class="pln"> on </span><span class="typ">Save</span></li></ol></pre>
<h5 id="how-to-set-index-mode-type">如何设置索引模式类型</h5>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento indexer</span><span class="pun">:</span><span class="kwd">set</span><span class="pun">-</span><span class="pln">mode </span><span class="pun">{</span><span class="pln">realtime</span><span class="pun">|</span><span class="pln">schedule</span><span class="pun">}</span><span class="pln"> </span><span class="pun">[</span><span class="pln">indexer</span><span class="pun">]</span></li></ol></pre>
<p>例如：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">magento indexer</span><span class="pun">:</span><span class="kwd">set</span><span class="pun">-</span><span class="pln">mode schedule catalog_category_product catalog_product_category</span></li></ol></pre>
<h2 id="deploy-command-line">部署命令行</h2>
<p>命令语法：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento setup</span><span class="pun">:</span><span class="kwd">static</span><span class="pun">-</span><span class="pln">content</span><span class="pun">:</span><span class="pln">deploy </span><span class="str">&lt;lang&gt;</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="str">&lt;lang&gt;</span><span class="pln"> </span><span class="pun">[--</span><span class="pln">dry</span><span class="pun">-</span><span class="pln">run</span><span class="pun">]</span></li></ol></pre>
<h4 id="how-to-run-deploy-static-content">如何运行部署静态内容</h4>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento setup</span><span class="pun">:</span><span class="kwd">static</span><span class="pun">-</span><span class="pln">content</span><span class="pun">:</span><span class="pln">deploy</span></li></ol></pre>
<p>它将显示如下：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento setup</span><span class="pun">:</span><span class="kwd">static</span><span class="pun">-</span><span class="pln">content</span><span class="pun">:</span><span class="pln">deploy</span></li><li class="L1"><span class="pln">&nbsp;</span></li><li class="L2"><span class="typ">Requested</span><span class="pln"> languages</span><span class="pun">:</span><span class="pln"> en_US</span></li><li class="L3"><span class="pun">===</span><span class="pln"> frontend </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Magento</span><span class="pun">/</span><span class="pln">blank </span><span class="pun">-&gt;</span><span class="pln"> en_US </span><span class="pun">===</span></li><li class="L4"><span class="pun">........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................</span></li></ol></pre>
<p>默认情况下，它将运行部署默认语言的静态内容：&nbsp;<code class="highlighter-rouge">en_EN</code></p>
<p>如果您想部署其他语言的静态内容，例如：&nbsp;<code class="highlighter-rouge">pt_BR</code></p>
<p>运行</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento setup</span><span class="pun">:</span><span class="kwd">static</span><span class="pun">-</span><span class="pln">content</span><span class="pun">:</span><span class="pln">deploy pt_BR</span></li></ol></pre>
<p>然后得到结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="typ">Requested</span><span class="pln"> languages</span><span class="pun">:</span><span class="pln"> pt_BR</span></li><li class="L1"><span class="pun">===</span><span class="pln"> frontend </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Magento</span><span class="pun">/</span><span class="pln">luma </span><span class="pun">-&gt;</span><span class="pln"> pt_BR </span><span class="pun">===</span></li><li class="L2"><span class="pun">...</span><span class="pln"> progress indicator </span><span class="pun">...</span></li><li class="L3"><span class="typ">Successful</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1613</span><span class="pln"> files</span><span class="pun">;</span><span class="pln"> errors</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span></li><li class="L4"><span class="pln">&nbsp;</span></li><li class="L5"><span class="pun">===</span><span class="pln"> frontend </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Magento</span><span class="pun">/</span><span class="pln">blank </span><span class="pun">-&gt;</span><span class="pln"> pt_BR </span><span class="pun">===</span></li><li class="L6"><span class="pun">...</span><span class="pln"> progress indicator </span><span class="pun">...</span></li><li class="L7"><span class="typ">Successful</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1620</span><span class="pln"> files</span><span class="pun">;</span><span class="pln"> errors</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span></li><li class="L8"><span class="pln">&nbsp;</span></li><li class="L9"><span class="pun">===</span><span class="pln"> adminhtml </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Magento</span><span class="pun">/</span><span class="pln">backend </span><span class="pun">-&gt;</span><span class="pln"> pt_BR </span><span class="pun">===</span></li><li class="L0"><span class="pun">...</span><span class="pln"> progress indicator </span><span class="pun">...</span></li><li class="L1"><span class="typ">Successful</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1626</span><span class="pln"> files</span><span class="pun">;</span><span class="pln"> errors</span><span class="pun">:</span><span class="pln"> </span><span class="lit">0</span></li><li class="L2"><span class="pln">&nbsp;</span></li><li class="L3"><span class="pun">===</span><span class="pln"> </span><span class="typ">Minify</span><span class="pln"> templates </span><span class="pun">===</span></li><li class="L4"><span class="pun">...</span><span class="pln"> progress indicator </span><span class="pun">...</span></li><li class="L5"><span class="typ">Successful</span><span class="pun">:</span><span class="pln"> </span><span class="lit">858</span><span class="pln"> files modified</span></li><li class="L6"><span class="pun">---</span></li></ol></pre>
<h2 id="how-to-get-admin-path-via-command-line">如何通过命令行获取管理路径</h2>
<p>你知道吗？您可以获取管理路径而不访问<code class="highlighter-rouge">etc/env.php</code>文件。</p>
<p>运行</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento info</span><span class="pun">:</span><span class="pln">adminuri</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento info</span><span class="pun">:</span><span class="pln">adminuri</span></li><li class="L1"><span class="pln">&nbsp;</span></li><li class="L2"><span class="typ">Admin</span><span class="pln"> URI</span><span class="pun">:</span><span class="pln"> </span><span class="pun">/</span><span class="pln">admin</span></li></ol></pre>
<p>所以<code class="highlighter-rouge">/admin</code>现在的路径是，将您的浏览器导航到domain.com/admin以访问Magento 2后端。</p>
<h2 id="how-to-enable-maintenance-mode-via-command-line">如何通过命令行启用维护模式</h2>
<h4 id="enable-maintenance-mode">启用维护模式</h4>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento maintenance</span><span class="pun">:</span><span class="pln">enable</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento maintenance</span><span class="pun">:</span><span class="pln">enable</span></li><li class="L1"><span class="typ">Enabled</span><span class="pln"> maintenance mode</span></li></ol></pre>
<h4 id="disable-maintenance-mode">禁用维护模式</h4>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento maintenance</span><span class="pun">:</span><span class="pln">disable</span></li></ol></pre>
<h4 id="allow-ips-to-access-to-the-store">允许IP访问商店</h4>
<p>设置维护模式仅允许ip</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento maintenance</span><span class="pun">:</span><span class="pln">allow</span><span class="pun">-</span><span class="pln">ips</span></li></ol></pre>
<p>例如：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento maintenance</span><span class="pun">:</span><span class="pln">allow</span><span class="pun">-</span><span class="pln">ips </span><span class="lit">168.168</span><span class="pun">.</span><span class="lit">168.168</span></li><li class="L1"><span class="typ">Set</span><span class="pln"> exempt IP</span><span class="pun">-</span><span class="pln">addresses</span><span class="pun">:</span><span class="pln"> </span><span class="lit">168.168</span><span class="pun">.</span><span class="lit">168.168</span></li></ol></pre>
<h2 id="how-to-set-magento-developer-mode-or-product-mode">如何设置Magento Developer模式或Product模式</h2>
<p>显示当前的Magento 2模式</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento deploy</span><span class="pun">:</span><span class="pln">mode</span><span class="pun">:</span><span class="pln">show</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento deploy</span><span class="pun">:</span><span class="pln">mode</span><span class="pun">:</span><span class="pln">show</span></li><li class="L1"><span class="typ">Current</span><span class="pln"> application mode</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">default</span><span class="pun">.</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Note</span><span class="pun">:</span><span class="pln"> </span><span class="typ">Environment</span><span class="pln"> variables may </span><span class="kwd">override</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> value</span><span class="pun">.)</span></li></ol></pre>
<p>目前，我们处于默认模式，让我们切换到开发人员模式</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">php bin</span><span class="pun">/</span><span class="pln">magento deploy</span><span class="pun">:</span><span class="pln">mode</span><span class="pun">:</span><span class="kwd">set</span><span class="pln"> developer</span></li></ol></pre>
<p>结果：</p>
<pre class="prettyprint linenums"><ol class="linenums"><li class="L0"><span class="pln">$ php bin</span><span class="pun">/</span><span class="pln">magento deploy</span><span class="pun">:</span><span class="pln">mode</span><span class="pun">:</span><span class="kwd">set</span><span class="pln"> developer</span></li><li class="L1"><span class="typ">Enabled</span><span class="pln"> developer mode</span><span class="pun">.</span></li></ol></pre>
<p>恭喜！现在您的商店正在开发人员模式下运行。快乐编码;）</p>
<hr><div style="display:none;" align="center" class="open-message"><i class="fa fa-bullhorn"></i></div>		      
<div class="article-social">
			<a href="javascript:;" data-action="ding" data-id="278" id="Addlike" class="action" data-original-title="" title=""><i class="fa fa-heart-o"></i>喜欢 (<span class="count">0</span>)</a></div>
	</article>]]></description>
      <pubDate>Fri, 24 Aug 2018 11:24:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2.2系统服务器环境要求]]></title>
      <link>https://www.360magento.com/blog/magento2_requires/</link>
      <description><![CDATA[<div class="content-wrap">
<h3 id="operating-systems-linux-x86-64">操作系统（Linux x86-64）</h3>
<p>Linux发行版，如RedHat Enterprise Linux（RHEL），CentOS，Ubuntu，Debian等。</p>
<h3 id="memory-requirement">内存要求</h3>
<p>升级和安装Magento2系统可能需要高达2GB的RAM。如果您使用的RAM少于2GB的系统，我们建议您创建一个<a href="https://devdocs.magento.com/guides/v2.2/comp-mgr/trouble/cman/out-of-memory.html" rel="nofollow">交换文件</a> ; 否则，您的升级可能会失败。</p>
<h3 id="composer-latest-stable-version">Composer（最新稳定版）</h3>
<p><span class="glossary-term" data-toggle="popover"></span> Magento开发人员需要Composer来开发扩展或提交到版本库</p>
<h3 id="web-servers">Web服务器</h3>
<ul>
<li>
<p><a href="http://httpd.apache.org/download.cgi" rel="nofollow" target="_blank">Apache 2.2或2.4</a></p>
<p>此外，您必须启用Apache <code class="highlighter-rouge">mod_rewrite</code>和<code class="highlighter-rouge">mod_version</code>模块。该<code class="highlighter-rouge">mod_rewrite</code>模块使服务器能够执行URL重写。该<code class="highlighter-rouge">mod_version</code>模块为不同<code class="highlighter-rouge">httpd</code>版本提供灵活的版本检查。</p>
</li>
<li>
<p><a href="https://nginx.org/en/download.html" rel="nofollow" target="_blank">nginx 1.x</a></p>
</li>
</ul>
<h3 id="database">数据库</h3>
<p>MySQL 5.6,5.7</p>
<p>Magento还兼容MySQL NDB Cluster 7.4.*，MariaDB 10.0,10.1,10.2，Percona 5.7以及其他二进制兼容的MySQL技术。</p>
<p class="bs-callout">Magento仅使用与MariaDB兼容的MySQL功能。但是，MariaDB可能不兼容MySQL的所有功能，因此在使用Magento模块中的功能之前，请务必研究兼容性问题。</p>
<h3 id="php">PHP支持</h3>
<div>
<table>
<tbody>
<tr>
<td>7.0.0-7.0.12</td>
<td>7.0.13-7.0.x</td>
<td>7.1.x</td>
</tr>
<tr>
<td><img alt="不支持" src="https://devdocs.magento.com/common/images/red-x.png" /></td>
<td><img alt="支持（2.1.2及更高版本）" src="https://devdocs.magento.com/common/images/green-check.png" /></td>
<td><img alt="支持（2.1.2及更高版本）" src="https://devdocs.magento.com/common/images/green-check.png" /></td>
</tr>
</tbody>
</table>
<style><!--
tr td {
    font-size: 14px;
    padding: 13px 14px;
    vertical-align: top;
    border-bottom: 1px solid #ccc;
    word-wrap: break-word;
    vertical-align: initial;
}
--></style>
</div>
<h4 id="required-php-extensions">必需的PHP扩展</h4>
<p class="bs-callout">在CentOS的和Ubuntu的PHP安装说明中包括用于安装这些扩展。</p>
<ul>
<li><a href="http://php.net/manual/en/book.bc.php" rel="nofollow" target="_blank">bc-math</a> (Magento Commerce 仅适用 2.2.0 - 2.2.3. Magento Commerce 和 Magento Open Source 适用 2.2.4.)\</li>
<li><a href="http://php.net/manual/en/book.ctype.php" rel="nofollow" target="_blank">ctype</a></li>
<li><a href="http://php.net/manual/en/book.curl.php" rel="nofollow" target="_blank">curl</a></li>
<li><a href="http://php.net/manual/en/book.dom.php" rel="nofollow" target="_blank">dom</a></li>
<li><a href="http://php.net/manual/en/book.image.php" rel="nofollow" target="_blank">gd</a>, <a href="http://php.net/manual/en/book.imagick.php" rel="nofollow" target="_blank">ImageMagick 6.3.7</a> (或最新)</li>
<li><a href="http://php.net/manual/en/book.intl.php" rel="nofollow" target="_blank">intl</a></li>
<li><a href="http://php.net/manual/en/book.mbstring.php" rel="nofollow" target="_blank">mbstring</a></li>
<li><a href="http://php.net/manual/en/book.mcrypt.php" rel="nofollow" target="_blank">mcrypt</a></li>
<li><a href="http://php.net/manual/en/book.hash.php" rel="nofollow" target="_blank">hash</a></li>
<li><a href="http://php.net/manual/en/book.openssl.php" rel="nofollow" target="_blank">openssl</a></li>
<li><a href="http://php.net/manual/en/ref.pdo-mysql.php" rel="nofollow" target="_blank">PDO/MySQL</a></li>
<li><a href="http://php.net/manual/en/book.simplexml.php" rel="nofollow" target="_blank">SimpleXML</a></li>
<li><a href="http://php.net/manual/en/book.soap.php" rel="nofollow" target="_blank">soap</a></li>
<li><a href="http://php.net/manual/en/book.spl.php" rel="nofollow" target="_blank">spl</a></li>
<li><a href="http://php.net/manual/en/book.libxml.php" rel="nofollow" target="_blank">libxml</a></li>
<li><a href="http://php.net/manual/en/book.xsl.php" rel="nofollow" target="_blank">xsl</a></li>
<li><a href="http://php.net/manual/en/book.zip.php" rel="nofollow" target="_blank">zip</a></li>
<li><a href="http://php.net/manual/en/book.json.php" rel="nofollow" target="_blank">json</a></li>
<li><a href="http://php.net/manual/en/book.iconv.php" rel="nofollow" target="_blank">iconv</a></li>
</ul>
<h4 id="php-opcache">PHP OPcache</h4>
<p>我们强烈建议您出于性能原因验证是否启用了<a href="http://php.net/manual/en/intro.opcache.php" rel="nofollow" target="_blank">PHP OPcache</a>。许多PHP发行版都启用了OPcache。</p>
<p>如果必须单独安装，请参阅<a href="http://php.net/manual/en/opcache.setup.php" rel="nofollow" target="_blank">PHP OPcache文档</a>。</p>
<h4 id="php-settings">PHP设置</h4>
<p>我们建议使用特定的PHP配置设置，例如<code class="highlighter-rouge">memory_limit</code>，可以避免使用Magento时的常见问题。</p>
<p>有关更多信息，请参阅<a href="/guides/v2.2/install-gde/prereq/php-settings.html">必需的PHP设置</a>。</p>
<h3 id="ssl">SSL</h3>
<ul>
<li>HTTPS需要有效的 <span>安全证书</span>。</li>
<li>不支持自签名SSL证书。</li>
<li>
<p>传输层安全性（TLS）要求 - PayPal和<code class="highlighter-rouge">repo.magento.com</code>都需要TLS 1.1或更高版本：</p>
</li>
</ul>
<h3 id="mail-server">邮件服务器</h3>
<p>邮件传输代理（MTA）或SMTP服务器</p>
<h3 id="magento-can-use-the-following-technologies">Magento可以使用以下技术：</h3>
<ul>
<li>Redis版本3.2（与2.4+兼容）用于页面缓存和会话存储</li>
<li>Varnish版本4.x或5.0</li>
<li>用于会话存储的memcached最新稳定版本，带有<code class="highlighter-rouge">memcache</code>或者<code class="highlighter-rouge">memcached</code>PHP扩展（最新的稳定版本）</li>
</ul>
</div>]]></description>
      <pubDate>Thu, 23 Aug 2018 08:01:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[常见的Magento SSL配置问题解决方法]]></title>
      <link>https://www.360magento.com/blog/magento-ssl-issues/</link>
      <description><![CDATA[<div class="post-content description ">
<p>安全套接字层（SSL）已成为电子商务网站的一个重要方面。SSL确保客户与网站之间的双向通信在整个交易期间保持安全。</p><p>使用SSL保护网站表明网站所有者非常重视保护客户的个人信息。就SERP(搜索引擎结果页面)的标准而言，拥有SSL的网站排名越来越高。</p><div class="magtoc"><h2>常见的Magento SSL问题及其解决方案</h2><ol><li><a href="#SSL-Not-Working">Magento SSL无效 </a></li><li><a href="#SSL-Redirects" title="SSL 重定向">Magento SSL将结账重定向到其他页面</a></li><li><a href="#Local-Issuer">无法获得本地颁发者证书</a></li><li><a href="#Installing-Magento-SSL">安装Magento SSL会使管理员无法访问</a></li><li><a href="#Magento-404" title="Magento 404">安装Magento SSL后面临404页面未找到错误</a></li><li><a href="#403-error">在Magento Admin中使用SSL时出现403(Forbidden)错误</a></li><li><a href="#HTTP">HTTP与Https重复内容问题</a></li><li><a href="#Enabling-SSL">在Magento Admin中启用SSL后无限重定向循环</a></li><li><a href="#layout">Magento前端布局问题</a></li><li><a href="#Magento-Admin">安装SSL后无法登录Magento Admin</a></li><li><a href="#Warnings">结帐时Magento SSL相关警告</a></li></ol></div><p>安装和维护SSL证书可能是网站所有者的麻烦。如果处理不当，该问题可能严重妨碍访客的体验。结果是网站的收入和声誉显著降低。</p><p>使用Magento SSL时，网站所有者应确保：</p><ul><li>SSL已正确安装</li><li>安全URL已设置</li><li>安全URL在前端和后端实现</li><li>SSL证书设置为包括www</li><li>网站里没有不安全的链接</li></ul><p>现在将讨论困扰网站的最常见的Magento SSL相关问题。此外，我还将提供解决问题的方法。</p><h2 id="SSL-Not-Working">1. Magento SSL无效</h2><p>按照以下步骤从Magento后台激活SSL ：</p><ul><li>导航到 System > Configuration > General > Web</li><li>单击"Secure"选项卡</li><li>启用"Use Secure URLs in the frontend"选项为"yes"</li><li>启用"Use Secure URLs in the Admin" 选项为"yes"</li><li>检查offload header为"SSL_OFFLOADED"</li></ul><p>激活Magento SSL后，网站的URL将从"HTTP" &nbsp;更改为"HTTPS" </p><p>如果问题仍然存在，则问题可能出在数据库层上。请按照以下步骤来解决问题：</p><ul><li>选择数据库表"core_config_data"</li><li>运行查询："Select * from core_config_data where path = ‘%web/secure/base_url%’;"</li><li>检查列值。如果是"HTTPS"，则表示后台设置已完成。</li></ul><p>如果SSL仍无效，则您的网站的SSL设置存在问题。有时，在成功安装和激活SSL后会出现此问题。Ajax调用或第三方URL调用中的问题也可能导致此问题。以下是如何解决这些问题：</p><p><strong>Ajax 调用</strong></p><p>如果Ajax调用中存在任何设置问题，请更改以下代码：</p><pre>echo Mage::getUrl(‘MYMODULE/MYCONTROLLER/MYACTION’, array(‘_secure’ => Mage::app()->getStore()->isCurrentlySecure()));</pre><p><strong>第三方URL调用</strong></p><p>替换掉不是"https"的第三方URL,比如"HTTPS://www.example.com"，替换成"HTTPS://www.example.com"</p><h2 id="SSL-Redirects">2.Magento SSL结账页面重定向</h2><p>当Magento SSL无法正常工作时，会出现此问题。在许多情况下，结帐页面会被重定向到其他页面，例如主页或index页面。</p><p>以下是修复结帐重定向问题的过程：</p><ul><li>在Magento网站中安装SSL证书。</li><li>导航到 Admin >  System > Configuration > General > Web</li><li>转到"secure settings"并将base URL更改为"HTTPS://"</li><li>保持"Base link URL"为“{{secure_base_url}}”</li><li>保持Skin, Media, and JavaScript设置为“{{secure_base_url}}skin/etc”</li><li>选择“Use Secure URL for frontend”为"yes"</li><li>最后，单击"Save"以应用设置。</li></ul><p>以上过程适用于所有Magento版本。</p><h2 id="Local-Issuer">3.无法获得本地颁发者证书</h2><p>若要解决此问题，请按照下列步骤操作：</p><ul><li>创建证书到本地副本并将其保存在服务器上的安全位置。</li><li>如果您使用的是Linux，请将文件保存在："/etc/ssl/example_com.crt "</li><li>在服务器(以apache为例)中正确配置：<br><pre><VirtualHost *:443> 
ServerName example.com 
DocumentRoot /var/www/

SSLEngine on 
SSLCertificateFile /etc/ssl/example_com.crt 
SSLCertificateKeyFile /etc/ssl/private/example_com.key 
SSLCertificateChainFile /etc/ssl/example_com.ca-bundle 
</VirtualHost></pre></li><li>根据保存文件的位置更新文件。</li><li>最后，重启服务器以更改应用配置。</li></ul><h2 id="Installing-Magento-SSL">4.安装Magento SSL使后台无法访问</h2><p>有两种方法可以解决这个问题：</p><ul><li>手动将"core_config_data"表中的"web/secure/use_in_adminhtml"值更改为"0";或执行SQL语句"INSERT INTO core_config_data (scope,scope_id,path,value) VALUES ('default',0,'web/secure/use_in_adminhtml',1);"<ul><li>改回表中的URL为“HTTP://your.domain.com/”</li></ul><p>通过删除“/var/cache”文件清除magento缓存</p><h2 id="Magento-404">5.使用SSL ，magento页面显示404 Page Not Found</h2><p><em>SSL有自己的配置文件，有时当SSL不能正常工作时，它可能会给出404（Page not found）错误。通常，文件如下：</em></p>“sudonano /etc/apache2/sites-available/default-ssl”</p><p>您需要将“AllowOverride None”更改为“AllowOverride All”，然后重新启动服务器。</p><p><pre>sudo /etc/init.d/apache2 restart</pre></p><p>重新启动服务器后，您将看到所有页面都正常工作。如果您收到任何与页面内容相关的错误，请检查页面上的任何外部URL。尝试消除外部URL并仅包含相对URL。</p><h2 id="403-error">6.在后台使用Magento SSL时出现403（Forbidden）错误</h2><p>在以下情况下，有时会故意返回错误代码403（Forbidden）：</p><ul><li>用户没有进去特定页面的权限。</li><li>用户正在尝试访问已将autoindex设置为<strong>off</strong>的目录。</li><li>用户正在尝试访问只能在内部访问的文件。</li></ul><p>但是，出于本文的目的，我将讨论无意中发生错误的情况。</p><p><strong>权限未正确设置</strong></p><p>这是此问题背后最常见的原因。如果要提供文件，则服务器必须读取并执行文件的分层目录中的权限。例如：</p><p>对于<em>/usr/share/myfiles/image.jpg，</em>服务器应具有<em>/，/ usr，/ usr / share</em>和<em>/ usr / share / myfiles</em>的读取和执行权限。如果您不希望看到此错误，则需要对目录使用标准755，对文件使用644。</p><p>您可以使用<strong><em>namei</em></strong>来检查路径的权限：</p><pre>f: /var/www/vhosts/example.com
 
drwxr-xr-x root     root     /
 
drwxr-xr-x root     rootvar
 
drwxr-xr-x www-data www-data www
 
drwxr-xr-x www-data www-datavhosts
 
drwxr-xr-xmconnectmconnect    example.com</pre><p><strong>目录索引尚未正确定义</strong></p><p>标准PHP设置的索引指令是：</p><p> "index index.html index.htm index.php;"</p><p>在上面的示例中，服务器将首先提供index.html，然后是index.htm，最后是index.php。如果找不到所有上述目录或没有响应，则返回403 forbidden错误。</p><h2 id="HTTP">7. HTTP与Https重复内容问题</h2><p>Http和HTTPS被视为单独的端口。但是，搜索引擎会将这两个版本的内容视为重复内容。从SEO的角度来看，这是一个严重的问题。此问题有3中修复方法：</p><p><strong>规范链接元素</strong></p><p>规范链接元素被添加到网页的head标签中：</p><pre>&lt;link rel="canonical" href="HTTP://www.domain.com/star-wars/toys/cut-outs/luke-skywalker.html"/&gt;</pre><p>这些链接元素突出显示内容的规范位置。因此，当搜索引擎抓取网站时，只有Https版本会显示在搜索结果中。</p><p><strong>为Https提供不同的Robots.txt</strong></p><p>在此解决方案中，您允许搜索引擎抓取网站的HTTPS版本。这是你应该做的：</p><ul><li>使用<strong>.htaccess</strong>提供两个不同的<strong>Robots.txt</strong>文件。将常规非安全HTTP文件另存为<strong>robots.txt</strong>，并将安全HTTPS文件另存为<strong>robots_ssl.txt</strong></li><li>在<strong>htaccess</strong>文件中添加一下代码：</li></ul><p><pre>
RewriteEngine on
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^robots\.txt$ robots_ssl.txt [L]
RewriteEngine on
RewriteCond %{SERVER_PORT} ^443$
RewriteRule ^robots\.txt$ robots_ssl.txt [L]</pre></p><ul><li>这将改写服务<strong>robots_ssl.txt</strong>为<strong>robots.txt的</strong>。</li></ul><p><strong>元机器人标签</strong></p><p>如果上述两种方法无法解决问题，可以使用Meta Robots标记。此标记允许对页面进行抓爬但不对其编制索引。要使用该标记，以下代码将添加到网页的<strong>Head</strong>标记中：</p><p><pre>

&lt;?php

if(isset($_SERVER['HTTPS']) &&strtolower($_SERVER['HTTPS']) == 'on') {

echo'<meta name="robots" content="noindex,follow" />'. "\n";

}

?&gt;
&lt;?php
 
if(isset($_SERVER['HTTPS']) &&strtolower($_SERVER['HTTPS']) == 'on') {
 
echo'<meta name="robots" content="noindex,follow" />'. "\n";
 
}
 
?&gt;</pre></p><h2 id="Enabling-SSL">8.在Magento管理区域中启用SSL时的无限重定向循环</h2><p>当您在Magento管理面板中打开SSL时，可能会遇到此问题。</p><p>问题可能出在模型<em>app/code/core/Mage/Core/Model/Store.php</em>中
<pre>
public function isCurrentlySecure()

{  

            if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {

            return true;

            }  

            if (Mage::isInstalled()) {

                        $secureBaseUrl = Mage::getStoreConfig('web/secure/base_route_url');

                        if (!$secureBaseUrl) {

                                    return false;

                        }  

                        $uri = Zend_Uri::factory($secureBaseUrl);

                        $isSecure = ($uri->getScheme() == 'HTTPS' ) &&isset($_SERVER['SERVER_PORT']) && ($uri->getPort() == $_SERVER['SERVER_PORT']);

                        return $isSecure;

             } else {

                        $isSecure = isset($_SERVER['SERVER_PORT']) && (443 == $_SERVER['SERVER_PORT']);

                        return $isSecure;

             }  

}
</pre>
<p>当在"core_config_data"表中没有"web/secure/base_route_url",默认的响应"isCurrentlySecure"总是返回<strong>false</strong> </p><p>您可以通过添加服务器变量"HTTPS" &nbsp;值来修复它&nbsp;  。</p><p>如Nginx与PHP-FPM一起使用，将这些行添加到“nginx.conf”：</p><pre>fastcgi_param HTTPS on;</pre><p>重新加载服务器，一切都应该正常工作。</p><h2 id="layout">9. SSL-HTTPS Magento前端布局问题</h2><p>使用HTTPS对工作站点的更改包括：<br>在配置中，<br>在不安全部分中<br>基本URL：删除"HTTP"</p><p>在安全部分<br>基本URL：添加"HTTPS"</p><p>然后刷新缓存。</p><h2 id="Magento-Admin">10.启用Magento SSL后，管理员登录失败</h2><p>在Magento Admin中启用SSL后，通常会出现此问题。以下步骤将解决此问题：</p><ul><li>进入数据库并进入"core_config_data"表中，&nbsp; 更新"web/secure/use_in_admindata"path中的value为"0"</li><li>将"web/secure/use_in_frontend"path中的"value"设置为"0"</li><li>通过使用SSH，登录到主机帐户，并运行命令"rm -rf ~/public_html/magento/var/cache"</li></ul><p>使用共享服务器或主机时，需要更改缓存目录。</p><p><strong>如何更改Magento基本URL？</strong></p><p>可以根据网站的要求设置Magento基本URL。要更改基本URL，请登录Magento管理面板，导航到"System > Configuration > Web > Unsecure > Base URL  and System > Configuration > Web > Secure > Base URL"</p><p>完成更改后，您需要进入“System > Cache Management”刷新缓存</p><p>如果Magento管理面板无法访问，则需要在数据库中进行更改。登录"phpMyAdmin",导航到"core_config_data"表，改变"web/unsecure/base_url"  和 "web/secure/base_url"中的value值</p><p>要应用更改，请通过删除var/cache目录中的所有内容来刷新Magento中的缓存</p><h2 id="Warnings">11.结帐时Magento SSL相关警告</h2><p>当您使用Magento网站时，结帐过程可能需要多次修复和调试。在测试网页时，请密切关注页眉和页脚中的图像，因为它们可以创建大量问题。</p><p>要解决此问题，您应该使用图像的直接链接，而不是使用参考或源链接。</p><p><imgsrc=/media/wysiwyg/image1.jpg"}}" alt="" />（简写图片源链接）</p><p><imgsrc="//yoursite.com/media/wysiwyg/image1.jpg" alt="" />(接图像源链接)</p><p>这会通知浏览器它应该按照当前区域加载重要的资源。特别是，使用Chrome测试网站，因为它可以检测任何网站中的大多数错误。</p><p>这些是一些常见的Magento SSL相关问题的解决方案。我希望您能够自己应用修复程序而不会出现任何问题。如果您遇到问题，请随时与我们联系。</p><hr><div class="frame"><h2 class="frames">经常问的问题</h2><p><strong>Q1。什么是SSL？<br> </strong></p><p>SSL表示用于使网站安全的安全套接字层。它应该安装在每个电子商务网站中，以确保用户和网站之间的交易过程安全。</p><p><strong>Q2。SSL完全免费使用吗？<br> </strong></p><p>许多SSL证书提供商对此收费，但是如果您想要免费且可靠的SSL证书，那么请选择Let's Encrypt。</p><p><strong>Q3。什么是Robots.txt？</strong></p><p>您网站的一个文本文件，用于与网络抓取工具和其他网络机器人进行通信，称为Robots.txt。</p></div></div>]]></description>
      <pubDate>Tue, 21 Aug 2018 08:50:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 1和magento2的比较]]></title>
      <link>https://www.360magento.com/blog/m1-m2vs/</link>
      <description><![CDATA[<div class="card-content">
<h2 id="overview">概述</h2>
<p><a href="https://magento.com/" target="_blank" rel="nofollow">Magento</a>是一个开源的电子商务网站系统，于2008年3月31日推出。包括出色的功能，它使网店所有者几乎可以做任何像类型的网店。Magento 1迅速占据电子商务市场的主导地位，市场份额约为26％（2014年）。但是，安装其他应用程序非常复杂，并且经常遇到许多错误。因此，Magento在2015年升级到2.0版本，这使得更多扩展的安装变得更加容易。Magento 2旨在帮助商家实现目标。它允许商家建立在线销售网站，下载和服务等。此外，让我们与以前的版本进行比较，事实是Magento 2升级了技术，改变了目录结构，架构，后端改进了平台的界面以支持移动版本。借助创新技术，它有助于实现性能和安全功能的改进。</p>
<h2 id="comparison">对照</h2>
<h3 id="1-performance">1. 表现</h3>
<p>在页面加载速度或查询执行时间上，由于缓存（Varnish）和数据库优化，Magento完全优于竞争对手。这也是许多用户在Magento 1中面临的问题，而在agento 2中的重大改进。</p>
<ul>
<li>Magento 2支持最新版本的PHP（从PHP 5.5x开始），也包括PHP 7。这些版本包括安全修复程序和新增强功能。</li>
<li>Magento 2的加载时间比标准版本的加载时间快2到3秒。要加载主页，类别页面和产品页面，即使不使用用户界面缓存，Magento 2也会在不到1.5秒的时间内加载。</li>
<li>页面内容显示得更快。在查看主要内容时，用户无需等待加载整个页面。</li>
<li>在服务端，Magento 2添加了一个模块来清除缓存。因此用户无需像Magento 1那样安装第三方模块。</li>
<li>Magento 2最小化并打包Javascript，从而减少客户端请求数。</li>
<li>压缩图像：Magento 2构建工具以直接在服务器上优化图像，而不是像Magento 1手动执行。</li>
<li>使用静态内容改进缓存处理过程。</li>
</ul>
<h3 id="2--admin">2. 管理员</h3>
<p>与Magento 1相比，Magento 2中的管理界面非常直观且用户友好。</p>
<h4 id="21-general-admin-interface">2.1常规管理界面</h4>
<p>管理面板非常易于配置和使用，并包含一个现代且用户友好的界面。它的组织更多，分为主要类别，如销售，产品，客户，营销等。此外，它只需点击主菜单即可查看所有子类别。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/30hMTf3.png" alt="Imgur" class="responsive-img"></p>
<p>Magento 2的另一个重要特性是网格管理。管理员可以主动隐藏网格中的某些列作为网格订单或网格客户。您还可以从管理页面上的可用列表中选择列。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/DtEozef.png" alt="Imgur" class="responsive-img"></p>
<h4 id="22-dashboard">2.2 仪表盘</h4>
<p>在新系统中，您可以在一个地方找到基本信息。“仪表盘”页面概述了终身销售，平均订单金额，最后订单，热门搜索条件，查看次数最多的产品，新客户等。它还显示了财务数据，因此您可以查看业务的总体状态。一目了然。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/Or4Ktcs.png" alt="Imgur" class="responsive-img"></p>
<h4 id="23-manage-products">2.3 管理产品</h4>
<p>创造更多新产品也更简单。新系统将指导您完成一个简单的分步过程。这里的一个突出创新是Magento 2不仅允许管理员上传产品图像，还可以上传该产品的宣传视频。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/arlTYZM.png" alt="Imgur" class="responsive-img"></p>
<h4 id="24-manage-orders">2.4 管理订单</h4>
<p>您的订单页面显示商店中所有订单的列表。您可以按“状态”列中的状态对它们进行排序。如果您想批量更新或查看所有待处理订单或处理订单，您可以快速轻松地找到它们。</p>
<p>您还可以为订单执行某些操作，例如“暂停”，“取消”或“打印订单”。如果您想在电子表格中查看所有订单信息，它还可以通过订单右上角的CSV导出订单。</p>
<p>订单的订单将以0000000001开头，并为每个后续订单增加至1。这使管理员可以轻松找出您收到的订单号。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/XaaxG9Z.png" alt="Imgur" class="responsive-img"></p>
<h4 id="25-manage-customers">2.5 管理客户</h4>
<p>在Magento 2中，您可以将客户列表视为产品或订单列表，添加/删除列，更改默认视图，导出到CSV文件或执行许多操作，例如删除客户或分配客户组。特别是，如果您想通过电话沟通接收订单，也可以手动添加客户。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/PkYEB7j.png" alt="Imgur" class="responsive-img"></p>
<h4 id="26-marketing-section">2.6 营销部分</h4>
<p>在“营销”部分，您可以找到Magento 1中用于促销，通信，搜索引擎优化和搜索，用户内容的所有可用工具。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/Fcwuij0.png" alt="Imgur" class="responsive-img"></p>
<h4 id="27-content">2.7 内容</h4>
<p>内容管理界面还使用Magento 2的指定网格，它可以帮助您更好地管理您的帖子。这有助于管理员创建更多内容页面，而无需将WordPress或Drupal添加到Magento站点。</p>
<p><img src="https://cdn.mageplaza.com/media/general2/37DaL5X.png" alt="Imgur" class="responsive-img"></p>
<h3 id="3-frontend">3. 前端</h3>
<h4 id="31-luma-theme">3.1 Luma主题</h4>
<p>Magento 2中的Luma Theme看起来比Magento 1中的主题更漂亮。</p>
<p>以下是Magento 1中的主题：</p>
<p><img src="https://cdn.mageplaza.com/media/general2/Akh2ILz.png" alt="Imgur" class="responsive-img"></p>
<p>这是Magento 2中的主题：</p>
<p><img src="https://cdn.mageplaza.com/media/general2/6aQ3zIX.png" alt="Imgur" class="responsive-img"></p>
<h4 id="32-responsive-design">3.2 响应式设计</h4>
<p>通过响应式Web设计，Magento 2使用户可以通过任何计算机或移动设备轻松连接到商店。这是一个很大的优势，因为自2015年4月21日起，Google算法已正式优先考虑适合移动设备的网站。</p>
<p>这种响应式设计还极大地增强了用户体验。</p>
<h4>3.3 改善结账（6个步骤 - &gt; 2个步骤</h4>
<p>在Magento 2中，支付流程对客户来说变得更加容易和快捷。Magento 2没有采取6个步骤来结账，而是仅通过2个步骤缩短了流程。
<p>Magento 1包括6个步骤结帐如下：</p>
<p><img src="https://cdn.mageplaza.com/media/general2/vLs1pwC.png" alt="Imgur" class="responsive-img"></p>
<p>Magento 2只需2个步骤即可结账：</p>
<p><img src="https://cdn.mageplaza.com/media/general2/SG346cS.png" alt="Imgur" class="responsive-img"></p>
<p>通过分析客户的电子邮件地址，在填写结帐电子邮件时，Magento 2可以自动识别哪些客户已注册或未注册帐户。对于没有帐户的客户，如果他们想在付款成功后立即创建帐户，则在此运输步骤中输入的信息将成为基础。帐户注册过程比以往更直接。</p>
<h4 id="34-ajax-cart-loading">3.4 Ajax购物车加载</h4>
<p>购物车是一个帮助客户获取有关他们打算快速购买的产品的信息的地方。每次将产品添加到Magento 1中的购物车时，系统都会重新加载页面，从而对其性能产生负面影响。对于脾气暴躁的客户，等待几秒钟就会导致他们放弃购物车。</p>
<p>Magento 2集成了Ajax购物车加载功能，允许用户快速查看购买的商品，而不是等到整个页面重新加载。这也有助于增强用户体验。如果您销售的是价值较低的产品，或者您的客户经常在购物车中添加更多产品，这是一个您不能忽视的问题。</p>
<h3 id="4-seo-and-security">4. SEO和安全</h3>
<h4 id="41-support-seo-better">4.1。更好地支持SEO</h4>
<p>SEO是网上商店的关键因素之一; 你永远不会忘记在你的网站上设置SEO。Magento 1.X在搜索引擎优化中遇到了一些缺陷，其中大部分都是在Magento 2开发时修复的.Magento 2的突出SEO功能包括：</p>
<ul>
<li><strong>重复内容</strong>：Magento 2提供Canonical标签以避免重复内容。它位于<code class="highlighter-rouge">Stores &gt; Configuration &gt; Catalog &gt; Catalog &gt; Search Engine Optimization</code>。</li>
<li><strong>XML站点地图</strong>：XML站点地图是包含站点所有页面的文件。Magento 2配备了更好的XML图形。要启用XML站点地图，请转到<code class="highlighter-rouge">Stores &gt; Settings &gt; Configuration &gt; Catalog &gt; XML Sitemap</code>。</li>
<li><strong>Alt产品图片</strong>：为产品图片添加alt也有助于提升您在搜索引擎上的排名。转到<code class="highlighter-rouge">Catalog &gt; Products &gt; select one Product &gt; add Alt in Images and Videos field</code>。</li>
<li><strong>Robots.txt文件</strong>：帮助网站管理员更灵活地允许或不允许搜索引擎（SE）上的机器人为您网站的某个区域编制索引。要修改Magento 2中的Robots.txt，请转到<code class="highlighter-rouge">Content &gt; Design &gt; Configuration &gt; Edit one Store &gt; Search Engine Robots</code>。</li>
<li><strong>元标题，元描述，元关键字</strong>：Magento 2允许管理员为每个产品/类别添加元标记。管理员只需在编辑或添加新产品/类别时输入搜索引擎优化。</li>
<li><strong>搜索友好的URL</strong>：启用URL友好的最快方法是转到<code class="highlighter-rouge">Stores&gt; Configuration &gt; General &gt; Web &gt; Search Engine Optimization and turn on Use Web Server Rewrites</code>。</li>
</ul>
<p><strong>注意</strong>：如您所知，新手使用Magento 2来实现如何最好地管理SEO是具有挑战性的。因为SEO分散在Magento的不同位置。</p>
<h4 id="42-security">4.2安全</h4>
<p>Magento 2改进了整体架构，尤其是安全性。通过定期更新软件，Magento 2比旧版本更安全。</p>
<p>使用散列算法（SHA-256）还可以改进密码，从而最大限度地降低暴力攻击和其他安全攻击的风险。</p>
</div>]]></description>
      <pubDate>Thu, 16 Aug 2018 09:57:08 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中实现黏性边栏(悬浮边栏)]]></title>
      <link>https://www.360magento.com/blog/sticky-sidebar/</link>
      <description><![CDATA[<p>因为在Magento1上的一个项目激发了我写这篇博客。重要的信息或按钮操作悬浮在电商网站（PC网站和移动网站）中极为重要，他可以提高您的转换率。这篇博客着重讲解magento详细页中将添加购物的选项按钮悬浮在边栏。悬浮边栏的目的是是侧边栏元素始终在视窗口中显示(或者在满足某些条件时)。<span>这是移动产品选项（magento可配置产品的下拉菜单，颜色，尺寸等），添加到购物车按钮或任何其他对您的产品很重要的元素的理想场所。</span><span>也就是说，您的客户可以自由浏览产品上的所有内容，一旦决定购买产品，&ldquo;添加到购物车&rdquo;按钮就显示在眼前等着点击！</span></p>
<p><span><span><span>让我们开始在代码中进行更改以启用此功能。</span><span>为了这篇博文的目的，我创建了一个自定义主题&nbsp; Alwayly</span></span><em><span><span>/StickySidebar</span></span></em><span><span>。</span></span></span></p>
<p><span>LESS代码</span></p>
<p><span>在<span>app/design/frontend/Alwayly/StickySidebar/web/css/source/</span>里面创建_extend.less文件并复制/粘贴下面的代码：</span></p>
<pre class="ish"><code class="language-bookmark">.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) {
  .box-tocart .action.tocart {
    width: 100%;
    margin-right: 0;
  }
&nbsp;
  .sidebar {
    &amp;.fixed {
      position: fixed;
    }
  }
}</code></pre>
<p><span>确保运行Grunt命令来创建符号链接并编译此代码（仅在PC上，它将侧边栏定位为固定元素，并使"添加到购物车"按钮占用全部宽度）。</span></p>
<p><span>XML代码</span></p>
<p><span>在<span>app/design/frontend/Alwayly/StickySidebar/Magento_Catalog/layout/&nbsp;</span>中创建catalog_product_view.xml，然后复制/粘贴以下代码片段：</span></p>
<pre class="ish"><code class="language-xml"><span class="sc3"><span class="re1">&lt;page</span> <span class="re0">layout</span>=<span class="st0">"2columns-right"</span> <span class="re0">xmlns:xsi</span>=<span class="st0">"http://www.w3.org/2001/XMLSchema-instance"</span> <span class="re0">xsi:noNamespaceSchemaLocation</span>=<span class="st0">"urn:magento:framework:View/Layout/etc/page_configuration.xsd"</span><span class="re2">&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;referenceBlock</span> <span class="re0">remove</span>=<span class="st0">"true"</span> <span class="re0">name</span>=<span class="st0">"catalog.compare.sidebar"</span> <span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;referenceBlock</span> <span class="re0">remove</span>=<span class="st0">"true"</span> <span class="re0">name</span>=<span class="st0">"wishlist_sidebar"</span> <span class="re2">/&gt;</span></span>
&nbsp;
    <span class="sc3"><span class="re1">&lt;move</span> <span class="re0">element</span>=<span class="st0">"product.info"</span> <span class="re0">destination</span>=<span class="st0">"sidebar.additional"</span> <span class="re2">/&gt;</span></span>
&nbsp;
    <span class="sc3"><span class="re1">&lt;referenceContainer</span> <span class="re0">name</span>=<span class="st0">"sidebar.additional"</span><span class="re2">&gt;</span></span>
        <span class="sc3"><span class="re1">&lt;block</span> <span class="re0">class</span>=<span class="st0">"Magento\Framework\View\Element\Template"</span></span>
<span class="sc3">               <span class="re0">name</span>=<span class="st0">"sticky.sidebar.wrapper"</span></span>
<span class="sc3">               <span class="re0">template</span>=<span class="st0">"Magento_Catalog::sticky-sidebar-js.phtml"</span></span>
<span class="sc3">               <span class="re0">after</span>=<span class="st0">"-"</span> <span class="re2">/&gt;</span></span>
    <span class="sc3"><span class="re1">&lt;/referenceContainer<span class="re2">&gt;</span></span></span>
<span class="sc3"><span class="re1">&lt;/page<span class="re2">&gt;</span></span></span></code></pre>
<p><span>这段代码负责以下内容：</span></p>
<ul>
<li><span>将页面布局从一列更改为右栏侧栏的两列</span></li>
<li><span>删除使用此页面布局时包含的两个块（比较和愿望清单块）</span></li>
<li><span>更改包含产品选项的块的位置并将其添加到侧边栏</span></li>
<li><span>添加将用于调用AMD组件的模板文件，以处理悬浮边栏逻辑和计算</span></li>
</ul>
<p><span>PHTML代码</span></p>
<p><span>在<span>app/design/frontend/Alwayly/StickySidebar/Magento_Catalog/templates/</span>中创建sticky-sidebar-js.phtml并复制/粘贴以下代码片段：</span></p>
<pre class="ish"><code class="language-html5"><span class="sc2">&lt;<span class="kw2">script</span> <span class="kw3">type</span><span class="sy0">=</span><span class="st0">"text/javascript"</span> data-mage-init<span class="sy0">=</span><span class="st0">'{"stickySidebar":{}}'</span>&gt;&lt;<span class="sy0">/</span><span class="kw2">script</span>&gt;</span></code></pre>
<p><span><span>RequireJS</span>代码</span></p>
<p><span>在<span>app/design/frontend/Alwayly/StickySidebar/</span>内部创建requirejs-config.js并复制/粘贴以下代码片段：</span></p>
<pre class="ish"><code class="language-javascript"><span class="kw1">var</span> config <span class="sy0">=</span> <span class="br0">{</span>
    map<span class="sy0">:</span> <span class="br0">{</span>
        <span class="st0">"*"</span><span class="sy0">:</span> <span class="br0">{</span>
            stickySidebar<span class="sy0">:</span> <span class="st0">"js/sticky-sidebar"</span><span class="sy0">,</span>
        <span class="br0">}</span>
    <span class="br0">}</span>
<span class="br0">}</span><span class="sy0">;</span></code></pre>
<p><span>jQuery代码</span></p>
<p><span>在<span>app/design/frontend/Alwayly/StickySidebar/web/js/sticky-sidebar.js</span>中创建sticky-sidebar.js并粘贴以下代码片段：</span></p>
<pre class="ish"><code class="language-jquery">define<span class="br0">(</span><span class="br0">[</span><span class="st0">"jquery"</span><span class="sy0">,</span> <span class="st0">"matchMedia"</span><span class="sy0">,</span> <span class="st0">"domReady!"</span><span class="br0">]</span><span class="sy0">,</span> <span class="kw2">function</span> <span class="br0">(</span><span class="sy1">$</span><span class="sy0">,</span> mediaCheck<span class="br0">)</span> <span class="br0">{</span>
    <span class="st0">"use strict"</span><span class="sy0">;</span>
&nbsp;
    <span class="kw2">var</span> sidebar <span class="sy0">=</span> <span class="br0">{</span><span class="br0">}</span><span class="sy0">;</span>
    <span class="kw2">var</span> a2c <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".product-add-form"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> a2c_mobile_target <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".product-info-main &gt; .price-box"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="co1">// nodes required to calculate sidebar params: width, left, padding-left</span>
    <span class="kw2">var</span> page_main <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".page-main"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> page_main_w<span class="sy0">;</span>
    <span class="kw2">var</span> main <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".main"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> main_w<span class="sy0">;</span>
    <span class="co1">// nodes required to calculate sidebar params: top</span>
    <span class="kw2">var</span> header <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".page-header"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> nav <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".nav-sections"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> breadcrumbs <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".breadcrumbs"</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="co1">// luma specific css values</span>
    <span class="kw2">var</span> a2c_mb <span class="sy0">=</span> parseInt<span class="br0">(</span><span class="sy1">$</span><span class="br0">(</span><span class="st0">"#product-addtocart-button"</span><span class="br0">)</span>.<span class="kw8">css</span><span class="br0">(</span><span class="st0">"margin-bottom"</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> main_pb <span class="sy0">=</span> parseInt<span class="br0">(</span>main.<span class="kw8">css</span><span class="br0">(</span><span class="st0">"padding-bottom"</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="kw2">var</span> tabs_mb <span class="sy0">=</span> parseInt<span class="br0">(</span><span class="sy1">$</span><span class="br0">(</span><span class="st0">".product.info.detailed"</span><span class="br0">)</span>.<span class="kw8">css</span><span class="br0">(</span><span class="st0">"margin-bottom"</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
    sidebar.<span class="me1">el</span> <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span><span class="st0">".sidebar"</span><span class="br0">)</span><span class="sy0">;</span>
    sidebar.<span class="me1">padding_ratio</span> <span class="sy0">=</span> parseFloat<span class="br0">(</span>sidebar.<span class="me1">el</span>.<span class="kw8">css</span><span class="br0">(</span><span class="st0">"padding-left"</span><span class="br0">)</span><span class="br0">)</span> <span class="sy0">/</span> page_main.<span class="kw8">width</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
    sidebar.<span class="me1">updateHorizontalParams</span> <span class="sy0">=</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
        <span class="kw1">if</span> <span class="br0">(</span>sidebar.<span class="me1">el</span>.<span class="kw5">hasClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
            page_main_w <span class="sy0">=</span> parseFloat<span class="br0">(</span>page_main.<span class="kw8">width</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
            main_w <span class="sy0">=</span> parseFloat<span class="br0">(</span>main.<span class="kw8">width</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
            sidebar.<span class="kw8">width</span> <span class="sy0">=</span> page_main_w <span class="sy0">-</span> main_w<span class="sy0">;</span>
            sidebar.<span class="me1">left</span> <span class="sy0">=</span> <span class="br0">(</span><span class="sy1">$</span><span class="br0">(</span>window<span class="br0">)</span>.<span class="kw8">width</span><span class="br0">(</span><span class="br0">)</span> <span class="sy0">-</span> page_main_w<span class="br0">)</span> <span class="sy0">/</span> <span class="nu0">2</span> <span class="sy0">+</span> main_w<span class="sy0">;</span>
            sidebar.<span class="me1">p_left</span> <span class="sy0">=</span> parseInt<span class="br0">(</span>page_main_w <span class="sy0">*</span> sidebar.<span class="me1">padding_ratio</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
            sidebar.<span class="me1">el</span>.<span class="kw8">css</span><span class="br0">(</span><span class="br0">{</span>
                <span class="st0">"width"</span><span class="sy0">:</span> sidebar.<span class="kw8">width</span> <span class="sy0">+</span> <span class="st0">"px"</span><span class="sy0">,</span>
                <span class="st0">"left"</span><span class="sy0">:</span> sidebar.<span class="me1">left</span> <span class="sy0">+</span> <span class="st0">"px"</span><span class="sy0">,</span>
                <span class="st0">"padding-left"</span><span class="sy0">:</span> sidebar.<span class="me1">p_left</span> <span class="sy0">+</span> <span class="st0">"px"</span>
            <span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span>
    <span class="br0">}</span><span class="sy0">;</span>
    sidebar.<span class="me1">updateVerticalParams</span> <span class="sy0">=</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
        sidebar.<span class="kw8">height</span> <span class="sy0">=</span> sidebar.<span class="me1">el</span>.<span class="kw8">height</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
        <span class="kw2">var</span> scrolled_from_top <span class="sy0">=</span> <span class="sy1">$</span><span class="br0">(</span>window<span class="br0">)</span>.<span class="kw8">scrollTop</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="kw2">var</span> header_h <span class="sy0">=</span> header.<span class="kw8">outerHeight</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span> <span class="sy0">||</span> <span class="nu0">0</span><span class="sy0">;</span>
        <span class="kw2">var</span> nav_h <span class="sy0">=</span> nav.<span class="kw8">outerHeight</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span> <span class="sy0">||</span> <span class="nu0">0</span><span class="sy0">;</span>
        <span class="kw2">var</span> breadcrumbs_h <span class="sy0">=</span> breadcrumbs.<span class="kw8">outerHeight</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span> <span class="sy0">||</span> <span class="nu0">0</span><span class="sy0">;</span>
        <span class="kw2">var</span> content_h <span class="sy0">=</span> main.<span class="kw8">outerHeight</span><span class="br0">(</span><span class="kw2">true</span><span class="br0">)</span> <span class="sy0">||</span> <span class="nu0">0</span><span class="sy0">;</span>
        <span class="kw2">var</span> sidebar_limit_top <span class="sy0">=</span> header_h <span class="sy0">+</span> nav_h <span class="sy0">+</span> breadcrumbs_h<span class="sy0">;</span>
        <span class="kw2">var</span> sidebar_limit_bottom <span class="sy0">=</span> sidebar_limit_top <span class="sy0">+</span> content_h<span class="sy0">;</span>
        <span class="kw2">var</span> sidebar_limit_bottom_criteria <span class="sy0">=</span> scrolled_from_top <span class="sy0">+</span> sidebar.<span class="kw8">height</span> <span class="sy0">+</span> main_pb <span class="sy0">+</span> a2c_mb <span class="sy0">-</span> tabs_mb<span class="sy0">;</span>
&nbsp;
        <span class="kw1">if</span> <span class="br0">(</span>sidebar_limit_bottom <span class="sy0">&lt;</span> sidebar_limit_bottom_criteria<span class="br0">)</span> <span class="br0">{</span>
            <span class="co1">// sidebar should start drifting out of viewport on the top</span>
            sidebar.<span class="me1">top</span> <span class="sy0">=</span> sidebar_limit_bottom <span class="sy0">-</span> sidebar_limit_bottom_criteria<span class="sy0">;</span>
&nbsp;
            sidebar.<span class="me1">el</span>.<span class="kw8">css</span><span class="br0">(</span><span class="br0">{</span><span class="st0">"top"</span><span class="sy0">:</span> sidebar.<span class="me1">top</span> <span class="sy0">+</span> <span class="st0">"px"</span><span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span> <span class="kw1">else</span> <span class="kw1">if</span> <span class="br0">(</span>scrolled_from_top <span class="sy0">&gt;</span> sidebar_limit_top<span class="br0">)</span> <span class="br0">{</span>
            <span class="co1">// header and breadcrumbs are now above viewport</span>
            <span class="kw1">if</span> <span class="br0">(</span><span class="sy0">!</span>sidebar.<span class="me1">el</span>.<span class="kw5">hasClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span><span class="br0">)</span> <span class="br0">{</span>
                sidebar.<span class="me1">el</span>.<span class="kw5">addClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span><span class="sy0">;</span>
                sidebar.<span class="me1">updateHorizontalParams</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
            <span class="br0">}</span>
            sidebar.<span class="me1">top</span> <span class="sy0">=</span> <span class="nu0">0</span><span class="sy0">;</span>
&nbsp;
            sidebar.<span class="me1">el</span>.<span class="kw8">css</span><span class="br0">(</span><span class="br0">{</span><span class="st0">"top"</span><span class="sy0">:</span> sidebar.<span class="me1">top</span> <span class="sy0">+</span> <span class="st0">"px"</span><span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
            sidebar.<span class="me1">el</span>.<span class="kw5">removeClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span>.<span class="kw5">removeAttr</span><span class="br0">(</span><span class="st0">"style"</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span>
    <span class="br0">}</span><span class="sy0">;</span>
&nbsp;
    <span class="kw2">var</span> <span class="kw3">onResize</span> <span class="sy0">=</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
        <span class="sy1">$</span><span class="br0">(</span>window<span class="br0">)</span>.<span class="me1">on</span><span class="br0">(</span><span class="st0">"resize"</span><span class="sy0">,</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
            sidebar.<span class="me1">updateHorizontalParams</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="br0">}</span><span class="sy0">,</span> onScroll <span class="sy0">=</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
        <span class="sy1">$</span><span class="br0">(</span>window<span class="br0">)</span>.<span class="me1">on</span><span class="br0">(</span><span class="st0">"scroll"</span><span class="sy0">,</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
            sidebar.<span class="me1">updateVerticalParams</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
        <span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="br0">}</span><span class="sy0">,</span> onInit <span class="sy0">=</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
        mediaCheck<span class="br0">(</span><span class="br0">{</span>
            media<span class="sy0">:</span> <span class="st0">"(min-width: 768px)"</span><span class="sy0">,</span>
            entry<span class="sy0">:</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
                sidebar.<span class="me1">el</span>
                    .<span class="kw5">addClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span>
                    .<span class="kw7">prepend</span><span class="br0">(</span>a2c.<span class="me1">detach</span><span class="br0">(</span><span class="br0">)</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
                sidebar.<span class="me1">updateHorizontalParams</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
                sidebar.<span class="me1">updateVerticalParams</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
&nbsp;
                <span class="kw3">onResize</span><span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
                onScroll<span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
            <span class="br0">}</span><span class="sy0">,</span>
            exit<span class="sy0">:</span> <span class="kw2">function</span> <span class="br0">(</span><span class="br0">)</span> <span class="br0">{</span>
                a2c.<span class="me1">detach</span><span class="br0">(</span><span class="br0">)</span>.<span class="kw7">insertAfter</span><span class="br0">(</span>a2c_mobile_target<span class="br0">)</span><span class="sy0">;</span>
&nbsp;
                sidebar.<span class="me1">el</span>
                    .<span class="kw5">removeClass</span><span class="br0">(</span><span class="st0">"fixed"</span><span class="br0">)</span>
                    .<span class="kw5">removeAttr</span><span class="br0">(</span><span class="st0">"style"</span><span class="br0">)</span><span class="sy0">;</span>
            <span class="br0">}</span>
        <span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span>
    <span class="br0">}</span><span class="sy0">;</span>
&nbsp;
    onInit<span class="br0">(</span><span class="br0">)</span><span class="sy0">;</span>
<span class="br0">}</span><span class="br0">)</span><span class="sy0">;</span></code></pre>
<p><span>下面我为您讲解代码的逻辑：</span></p>
<ul>
<li><span>onInit()方法用于初始化逻辑</span></li>
<li><span><span>通过使用matchMedia库，产品选项可以在移动和pc布局之间切换位置（这种元素的分离是必需的，因为在移动设备上，侧边栏将是页脚之前的最后一个元素，并且不会让页面到达页面的下方）。</span><span>此媒体查询还负责添加（在PC上）或删除（在手机上）CSS类名&ldquo;<span>fixed</span>&rdquo;</span></span></li>
<li><span><span>当只在PC上时，JS会计算四个CSS属性（updateHorizo​​ntalParams（） - &gt; width，left，padding-left属性，updateVerticalParams（） - &gt; top属性）的值。</span><span>并加载事件监听器（在页面调整大小和页面滚动进行相同的计算)</span></span></li>
<li><span>侧栏的显示可以分为三种不同的状态：</span>
<ul>
<li><span>状态＃1 - 只要面包屑在视口中可见，侧栏就会相对定位</span></li>
<li><span>状态＃2 - 一旦面包屑在视口外滚动，侧栏被定位为固定元素并将保持在视口中</span><br /><img alt="悬浮边栏 - 使边栏固定" height="612" src="https://www.360magento.com/media/wysiwyg/blog_200/treshold-1.jpg" /></li>
<li><span>状态＃3 - 一旦侧栏的底部与内容的底部对齐，侧栏开始在视口外滑动，就像页面的其余部分一样</span><img alt="粘滞边栏 - 保持固定，但向上滚动" class="alignnone wp-image-31994 size-full lazyloaded" height="443" src="https://inchoo.net/wp-content/uploads/2018/03/threshold-2.jpg" width="1209" data-src="https://inchoo.net/wp-content/uploads/2018/03/threshold-2.jpg" /></li>
</ul>
</li>
</ul>
<p><span>此代码已经过优化，可与Luma主题一起使用，因此您可能需要添加/清除此处所述的一些代码。</span></p>]]></description>
      <pubDate>Tue, 12 Jun 2018 01:28:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[7种方法让你的Magento 2主题模板速度加快]]></title>
      <link>https://www.360magento.com/blog/make-theme-faster/</link>
      <description><![CDATA[<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>Magento 2作为功能强大且功能丰富的电子商务平台。</span><span>它提供了不错的页面加载速度，但在大量定制下可能会非常缓慢。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>部分性能问题可能是一个开发不标准的自定义主题引起的（在这里重声下，magento有两大主题模板市场，一个$89,一个$179,作为技术的我深知两大模板的优劣，总之不要图一时便宜）。</span><span>一方面，默认的Luma和Blank主题相当快。</span><span>另一方面，一些定制的主题很慢，可能会让你的网上商店成为一个噩梦。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>我将分享一些技巧来优化Magento2主题模板让他更快。</span><span>这些小技巧都是经过实践验证的，他们真的很有用。</span><span>我已经在各个项目中使用它们，以使Magento 2网站有一个不错的页面加载时间速度。</span></span></p>
<h2 style="font-size: 1.5em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>加快Magento 2主题模板的7个技巧</span></h2>
<ol style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<li><span>切勿在循环中加载Magento模型。</span></li>
<li><span>缩小HTML。</span></li>
<li><span>切勿使用JS捆绑。</span></li>
<li><span>合并和缩小CSS / JS。</span></li>
<li><span>避免CSS / JS框架。</span></li>
<li><span>优化图像。</span></li>
<li><span>尽量减少第三方扩展的数量。</span></li>
</ol>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>1.永远不要将Magento模型加载到循环中</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>这事儿常常发生。</span><span>我经常看到这样的PHP代码：</span></span></p>
<pre class="brush: php; gutter: true hljs" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span class="hljs-keyword">foreach</span><span>（$ productCollection </span><span class="hljs-keyword">as</span><span> $ product）{</span><span></span>
<span></span><span>
$ _product = $ productModelFactory-&gt; create（） - &gt; load（$ product-&gt; getId（））</span><span></span>
<span></span><span>
...。</span></pre>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>您可能会</span><span>在Magento 2迭代集合的</span><span>各种</span></span><em>list.phtml</em><span><span>模板中</span><span>看到该结构</span><span>。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>我会解释为什么这对性能不好。</span><span>Magento 2模型负载很重，需要太多时间。</span><span>再加上集合不断的循环可能会显著减慢站点的速度。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>另外，不需要加载模型，因为一个集合已经具有可能需要的所有数据。</span><span>所以你最好检查一下你的主题模板文件和重构代码部分是否包含模型循环。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>如何找出要检查的主题模板？</span><span>使用Magento 2分析器 - 它将显示最慢的代码块。</span><span>要启用Magento 2分析器，只需将以下代码添加到</span></span><em>index.php</em><span>和</span><em>pub/index.php</em><span>：</span></p>
<pre class="brush: php; gutter: true hljs bash" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span class="hljs-variable">$ _SERVER</span><span> ['MAGE_PROFILER'] = 1;</span></pre>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>重新加载网站页面，您将在底部看到配置文件跟踪：</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><img alt="Magento 2探查器跟踪" height="600" src="http://www.360magento.com/media/wysiwyg/blog_199/Magento-2-profiler-trace.png" style="border: 0px; cursor: default; vertical-align: middle;" width="1349" /></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>研究跟踪，你会看到哪些模板花费时间最多。</span></p>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>2.缩小HTML</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>如果可以缩小页面大小，可以使主题更快。</span><span>其中一种方法是缩小HTML。</span></span><br /><span><span>Magento 2支持开箱即用页面缩小。</span><span>您可以转至<em>Stores &gt; Configuration &gt; Advanced &gt; Developer &gt; Template Settings &gt; Minify HTML</em></span></span><span>并将其打开（在Magento 2.2+上，此设置仅在开发人员模式下可见）：</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><img alt="在Magento中缩小HTML" height="744" src="http://www.360magento.com/media/wysiwyg/blog_199/Minify-HTML.png" style="border: 0px; cursor: default; vertical-align: middle;" width="1356" /></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>有一点要记住 - 这种配置更改仅适用于生产和默认模式。</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>你可能会问 - 这些模式是什么？</span><span>Magento 2有三种运行模式：<span>default（默认模式）, developer（开发者模式） 和 production（生产模式）</span>。</span><span>生产模式是最快的，它用于为上线网站提供动力。</span><span>另一方面，为了调整和更改商店，您可能需要打开开发人员模式。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>要了解网站的模式，可以在Magento根文件夹中运行此SSH命令：</span></p>
<pre class="brush: php; gutter: true hljs nginx" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span class="hljs-attribute">php</span> bin/magento deploy:mode:show</pre>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>要切换到生产模式，请运行：</span></p>
<pre class="brush: php; gutter: true hljs bash" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">php bin/magento deploy:mode:<span class="hljs-built_in">set</span> production</pre>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>HTML缩小可以缩小到高达原始页面大小的50％，因此您可以尝试一下。</span></p>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>3.永远不要使用JS捆绑</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>JS捆绑是Magento 2的一个特殊功能，它将JS文件分组在一起，以减少Web浏览器加载页面所需的HTTP请求数量。</span><span>在HTTP1下可以使网站更快，但它对于HTTP2是没有用的。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>由于其他原因，JS捆绑也没用。</span><span>发生的情况是，这个庞大的捆绑</span></span><a href="https://github.com/magento/magento2/issues/4506" rel="noopener" target="_blank">JavaScript文件</a>&nbsp;大小<span>为5-12Mb，显着降低了商店的速度（尤其是在网络较慢的情况下）。</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>所以去<em>Stores &gt; Configuration &gt; Advanced &gt; Developer &gt; Javascript Settings</em></span><span>并且设置启用JS捆绑为NO：</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><img alt="JS捆绑在Magento中 " height="778" src="http://www.360magento.com/media/wysiwyg/blog_199/JS-Bundling.png" style="border: 0px; cursor: default; vertical-align: middle;" width="1361" /></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>我建议使用HTTP / 2的强大功能，而不是JS捆绑。</span><span>HTTP协议的新版本设计时考虑到了性能，并且可以真正加速任何站点，包括Magento。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>另一个解决方法是使用CDN（内容分发网络）。</span><span>用它来加载静态文件比服务器加载的时间快了很多，而且它具有动态图像优化功能和各种缓存选项。</span></span></p>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>4.合并和缩小CSS和JS文件</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>Magento 2具有缩小CSS和JavaScript的内置功能。</span><span>这对性能有好处，因为它可以减少页面负载。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>要设置缩小和合并，请转至后端菜单<span>S</span><em>tores &gt; Configuration &gt; Advanced &gt; Developer &gt; CSS and Javascript settings</em></span><span>：</span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><img alt="在Magento admin中缩小CSS JS" height="779" src="http://www.360magento.com/media/wysiwyg/blog_199/Minify-CSS-JS.png" style="border: 0px; cursor: default; vertical-align: middle;" width="1351" /></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>请注意，JS / CSS minification仅适用于生产和默认运行模式。</span></p>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>5.避免第三方CSS/JS框架</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>我建议在构建Magento 2主题时避免使用任何外部前端库（除了那些最初与M2一起提供的库）。</span><span>第三方框架可能使网站变慢。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>与Magento 2一起提供的jquery应该足以满足任何javascript需求。</span><span><br /></span></span></p>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>6.优化图像</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>电子商务网站往往有很多图像。</span><span>保持它们的优化和尽可能小的尺寸是非常重要的。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>我会在这里强调3种方式来照顾您的目录图片：</span></p>
<ol style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<li><span>CDN（内容分发网络）</span><span><span>&nbsp;- 几乎所有这样的网站都具有某种图像优化功能。</span><span>如果您的预算允许，您可以试一试。</span></span></li>
<li><span><span><a href="https://developers.google.com/speed/pagespeed/module/" rel="noopener" target="_blank">Google PageSpeed Module</a><span>&nbsp;</span>- 此服务器扩展（由Google开发）可以压缩图像并自动执行其他速度优化。</span><span>您可能需要系统管理员帮助进行正确设置和配置。</span></span></li>
<li><span>各种在线工具</span><span><span>&nbsp;- 如果您没有那么多的图片，您可以逐个手动优化它们。</span><span>有不少在线工具可以压缩图片。</span></span></li>
</ol>
<h3 style="font-size: 1.17em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>7.保持第三方扩展的数量最少</span></h3>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>根据我的经验，如果有一个缓慢的Magento网站，在大多数情况下，有很多自定义插件。</span><span>市场上的一些第三方扩展可能会显著影响性能。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>自定义模块的问题在于，它们通常是在没有速度基准的情况下编写的。</span><span>编码质量差是我建议将第三方扩展数量保持在最低限度的首要原因。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>如果你已经安装了一堆插件，那么该做一个审查了。</span><span>逐个禁用它们并测量页面加载时间。</span><span>如果扩展在第一个字节（TTFB）中超过100毫秒的时间，则可能需要联系其供应商并寻求补丁。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span><span>如何找到安装的模块列表？</span><span>在Magento根文件夹中运行这个SSH命令：</span></span></p>
<pre class="brush: php; gutter: true hljs ruby" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">php bin/magento <span class="hljs-class"><span class="hljs-keyword">module</span>:<span class="hljs-title">status</span></span></pre>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>忽略以</span><em>Magento_</em><span><span>开头的模块</span><span>- 这些是核心扩展。</span></span></p>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>要禁用扩展，您可以简单地从app/code中删除它的文件夹并运行：</span></p>
<pre class="brush: php; gutter: true hljs nginx" style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; margin: 8px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span class="hljs-attribute">php</span> bin/magento setup:upgrade</pre>
<h2 style="font-size: 1.5em; color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>总结</span></h2>
<p style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span>Magento 2自定义主题可能会很慢，但有一些方法可以使其更快速：</span></p>
<ul style="color: #2f2f2f; font-family: Arial, Helvetica, sans-serif; font-size: 12px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
<li><span>注意第一个字节的时间，并尝试使用分析器来降低它。</span></li>
<li><span>保持页面大小最小并始终压缩图像。</span></li>
<li><span>检查主题模板并纠正不良的PHP代码块。</span></li>
<li><span>缩小HTML，CSS，JS。</span></li>
<li><span>不要使用JS捆绑 - 它有害无益。</span></li>
</ul>]]></description>
      <pubDate>Fri, 08 Jun 2018 04:02:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[详细说明Magento2的所有产品类型]]></title>
      <link>https://www.360magento.com/blog/magento-2-product-types/</link>
      <description><![CDATA[<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">默认情况下，Magento 2中有6种产品类型：</span></span><em style="box-sizing: border-box; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">Simple, Configurable, Virtual, Downloadable, Grouped 和 Bundle&nbsp;Products</em><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">。</span><span style="box-sizing: border-box; vertical-align: inherit;">它们与Magento 1中产品类型一样。如果您使用过Magento 1，我想您非常熟悉这些类型的产品。</span><span style="box-sizing: border-box; vertical-align: inherit;">然而，如果你仍然好奇并想更多地了解它们，</span><span style="box-sizing: border-box; vertical-align: inherit;">这篇博客会为您提供每种产品类型的详细说明。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; font-size: 25px;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">1.简单产品(Simple Products)</span></span></strong></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">这是Magento商店中使用最广泛的产品类型。</span><span style="box-sizing: border-box; vertical-align: inherit;">简单产品是具有单个SKU的实物产品。</span><span style="box-sizing: border-box; vertical-align: inherit;">简单产品可以单独销售，也可以作为可配置(Configurable)、分组(Virtual)或捆绑(Bundle)产品的一部分销售。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">实际上，大多数商店都使用简单产品，例如：书，包，手表......</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento产品类型简单的产品" height="764" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-simple-product.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="1770" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; font-size: 25px;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">2.可配置产品(Configurable Products)</span></span></strong></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">一个可配置产品似乎是一个单一产品，每个变体都有选项列表。</span><span style="box-sizing: border-box; vertical-align: inherit;">但是，每个选项代表一个独立的简单产品，具有不同的SKU，这使得可以跟踪每个变体的库存。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">可配置产品的一个最好示例是T恤。</span><span style="box-sizing: border-box; vertical-align: inherit;">购买一件T恤，顾客可以选择不同的颜色或不同的尺寸。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento产品类型可配置产品" height="938" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-configurable-product.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="1830" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; font-size: 25px;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">3.虚拟产品(Virtual Products)</span></span></strong></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">虚拟产品没有实体存在，通常用于诸如服务，保证和订阅等事情。</span><span style="box-sizing: border-box; vertical-align: inherit;">这些类型的产品不需要运输，交付或下载。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento产品类型虚拟产品" height="463" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-virtual-product.png.jpg" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="1280" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">4.可下载的产品(Downloadable Products)</span></span></strong></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">一个电子下载产品包含一个或多个下载的文件。</span><span style="box-sizing: border-box; vertical-align: inherit;">这些文件可以存储在您的服务器上，也可以从其他服务器提供的URL作为下载。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">示例：软件，视频，电子书，...</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento 2产品类型可下载的产品" height="1028" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-downloadable-product.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="1736" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; font-size: 25px;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">5.分组产品(套)</span></span></strong></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">分组产品只是一组单一产品。</span><span style="box-sizing: border-box; vertical-align: inherit;">您可以提供单个产品的变体，或将它们分组以供升级。</span><span style="box-sizing: border-box; vertical-align: inherit;">产品可以单独购买，也可以分组购买。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">实际上，您可以使用此产品为想要一次购买多种产品的客户提供促销。</span><span style="box-sizing: border-box; vertical-align: inherit;">或者您可以将其用于一组产品。</span><span style="box-sizing: border-box; vertical-align: inherit;">例如：一套家具，一套行李如下：</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento产品类型分组产品" height="421" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-grouped-product.jpg" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="851" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">&nbsp;</p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; font-size: 25px;"><strong style="box-sizing: border-box; font-weight: bold;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">6.捆绑产品(Bundle Products)</span></span></strong></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">一个捆绑产品可以让客户从各种选项中&ldquo;建立自己想要的&rdquo;。</span><span style="box-sizing: border-box; vertical-align: inherit;">该捆绑包可以是礼品篮，电脑或任何可以定制的东西。</span><span style="box-sizing: border-box; vertical-align: inherit;">捆绑包中的每个物品都是独立的产品。</span></span></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><img alt="magento 2产品类型捆绑产品" height="348" src="http://www.360magento.com/media/wysiwyg/blog_198/magento-product-types-bundle-product.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; max-width: 100%; height: auto; display: block; margin: 0px auto;" width="735" /></p>
<p style="box-sizing: border-box; margin: 0px 0px 24px; color: #303c40; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"><span style="box-sizing: border-box; vertical-align: inherit;"><span style="box-sizing: border-box; vertical-align: inherit;">根据具体的商品和服务，每个商店可以使用不同的Magento 2产品类型。</span><span style="box-sizing: border-box; vertical-align: inherit;">如果您仍然对这些Magento 2产品类型感到困惑，请<a href="http://www.360magento.com/contacts/" title="联系我们">联系我们</a>，我们将举出更多例子为您解答，并根据您的产品特性指定不同的产品类型。。</span></span></p>]]></description>
      <pubDate>Thu, 07 Jun 2018 09:03:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何保护Magento 2中的原始产品图像？]]></title>
      <link>https://www.360magento.com/blog/protect-product-images/</link>
      <description><![CDATA[<h2><span>问题：</span></h2>
<p><span>开发人员启用了Magento 2的水印功能，但仍可从URL访问没有水印的原始产品图像。</span></p>
<p><em>例如：</em></p>
<p><span>缓存的带有水印的图片地址：</span></p>
<p><span><span>/pub/media/catalog/product</span><span>/cache/df484df48ez74849c15sd4f7780</span><span>/f/f/dsf-8f48d4f.jpg</span></span></p>
<p></p>
<p><span>没有水印的原始图片地址：</span></p>
<p><span>/pub/media/catalog/product/f/f/dsf-8f48d4f.jpg</span></p>
<p><span><span>因此，如果有人</span><span>&nbsp;从URL中</span><span>删除<span>/</span><span>cache/df484df48ez74849c15sd4f7780/</span><span>&nbsp;</span></span></span><span>仍然可以访问无水印的原始照片来窃取图像。</span></p>
<p><span>开发者如何保护他的原始产品图像？</span></p>
<h2><span>解决方案：</span></h2>
<p><span>这里的简单解决方案是修改和使用以下<span>/var/media/catalog</span>目录中.htaccess文件：</span></p>
<pre>Options <span>+</span>FollowSymLinks
RewriteEngine on

<span>#</span><span>The next coding </span><span>line</span><span> permits the original images to be accessed by admin end directly</span>

RewriteCond <span>%</span><span>{</span>HTTP_REFERER<span>}</span> <span>!</span><span>^</span>http<span>:</span><span>//</span><span>www.yourwebsite.com/</span><span>.*$ [NC]</span>

<span>#</span><span>The next coding </span><span>line</span><span> permits the watermarked images to be accessed directly</span><span>.</span><span> It is according to the rule where the URL does not contain a cache</span><span>.</span>

RewriteCond <span>%</span><span>{</span>REQUEST_URI<span>}</span> <span>!</span><span>(</span><span>/</span>cache<span>/</span><span>)</span> <span>[</span>NC<span>]</span>

<span>#</span><span>It is the page where your store visitor will be redirected </span><span>if</span><span> they will attempt to access images directly</span><span>.</span>

RewriteRule \<span>.</span><span>(</span>gif<span>|</span>jpg<span>)</span>$ http<span>:</span><span>//en.wikipedia.org/wiki/You_shall_not_steal [R,L]</span></pre>
<p></p>
<p><span>上述安全措施将帮助开发人员防止他的Magento产品图像被盗，下载和复制。</span></p>
<p><span><span>我们向您展示了一种简单的方法来保护Magento 2中的原始图像文件。如果您在遵循该指示时遇到任何问题，请联系我们</span><span>！</span></span></p>]]></description>
      <pubDate>Wed, 06 Jun 2018 01:34:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何修复在Magento 2中重新索引时的死锁错误？]]></title>
      <link>https://www.360magento.com/blog/error-reindexing-m2/</link>
      <description><![CDATA[<h2><span>问题：</span></h2>
<p><span>Magento版本：2.1.9&nbsp;</span><br /><span>模式：<span>Production</span></span><br /><span>索引模式：<span>Update on save</span></span></p>
<p><span>总产品：18k&nbsp;</span><br /><span>总客户：54k&nbsp;</span><br /><span>总订单：18k</span></p>
<p><span><span>开发人员尝试重新建立索引后，会生成exception.log文件，其中包含此文件中的以下错误。</span><span>同时，服务器被卡住，需要重新启动。</span><span>然后，该网站才可以照常运行。</span></span></p>
<p><span>&ldquo;PDOException: SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction&rdquo;</span></p>
<p><span>那么，如何解决这个死锁错误以及手动重新编制索引的最佳方法？</span></p>
<h2><span>解决方案：</span></h2>
<p><span>有3个简单的步骤来处理这个Magento 2死锁错误：</span></p>
<ul>
<li>
<ul>
<li>
<h3><span><em>第1步：在本地打开数据库，然后运行SQL：</em></span></h3>
</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<pre style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, 'Courier New', monospace; font-size: 14px; line-height: 1.2; margin: 0px 0px 11.5px; word-break: normal; word-wrap: break-word; color: #000020; background: #f6f8ff; border: 0px; border-radius: 0px; padding: 11px; hyphens: none; text-shadow: none;">DROP TABLE `catalog_category_product_index`<span style="box-sizing: border-box; color: #406080;">;</span>
DROP TABLE `catalog_category_product_index_tmp`<span style="box-sizing: border-box; color: #406080;">;</span>


CREATE TABLE `catalog_category_product_index` <span style="box-sizing: border-box; color: #308080;">(</span>
  `category_id` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">10</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Category ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `product_id` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">10</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Product ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `position` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">11</span><span style="box-sizing: border-box; color: #308080;">)</span> DEFAULT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Position'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `is_parent` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Is Parent'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `store_id` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Store ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `visibility` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Visibility'</span>
<span style="box-sizing: border-box; color: #308080;">)</span> ENGINE<span style="box-sizing: border-box; color: #308080;">=</span>InnoDB DEFAULT <span style="box-sizing: border-box; color: #003060;">CHARSET</span><span style="box-sizing: border-box; color: #308080;">=</span>utf8 COMMENT<span style="box-sizing: border-box; color: #308080;">=</span><span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Catalog Category Product Index'</span><span style="box-sizing: border-box; color: #406080;">;</span>
ALTER TABLE `catalog_category_product_index`
  ADD PRIMARY KEY <span style="box-sizing: border-box; color: #308080;">(</span>`category_id`<span style="box-sizing: border-box; color: #308080;">,</span>`product_id`<span style="box-sizing: border-box; color: #308080;">,</span>`store_id`<span style="box-sizing: border-box; color: #308080;">)</span><span style="box-sizing: border-box; color: #308080;">,</span>
  ADD KEY `CAT_CTGR_PRD_IDX_PRD_ID_STORE_ID_CTGR_ID_VISIBILITY` <span style="box-sizing: border-box; color: #308080;">(</span>`product_id`<span style="box-sizing: border-box; color: #308080;">,</span>`store_id`<span style="box-sizing: border-box; color: #308080;">,</span>`category_id`<span style="box-sizing: border-box; color: #308080;">,</span>`visibility`<span style="box-sizing: border-box; color: #308080;">)</span><span style="box-sizing: border-box; color: #308080;">,</span>
  ADD KEY `CAT_CTGR_PRD_IDX_STORE_ID_CTGR_ID_VISIBILITY_IS_PARENT_POSITION` <span style="box-sizing: border-box; color: #308080;">(</span>`store_id`<span style="box-sizing: border-box; color: #308080;">,</span>`category_id`<span style="box-sizing: border-box; color: #308080;">,</span>`visibility`<span style="box-sizing: border-box; color: #308080;">,</span>`is_parent`<span style="box-sizing: border-box; color: #308080;">,</span>`position`<span style="box-sizing: border-box; color: #308080;">)</span><span style="box-sizing: border-box; color: #406080;">;</span>
CREATE TABLE `catalog_category_product_index_tmp` <span style="box-sizing: border-box; color: #308080;">(</span>
  `category_id` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">10</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Category ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `product_id` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">10</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Product ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `position` <span style="box-sizing: border-box; color: #200080; font-weight: bold;">int</span><span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">11</span><span style="box-sizing: border-box; color: #308080;">)</span> NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Position'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `is_parent` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Is Parent'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `store_id` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> DEFAULT <span style="box-sizing: border-box; color: #1060b6;">'0'</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Store ID'</span><span style="box-sizing: border-box; color: #308080;">,</span>
  `visibility` smallint<span style="box-sizing: border-box; color: #308080;">(</span><span style="box-sizing: border-box; color: #008c00;">5</span><span style="box-sizing: border-box; color: #308080;">)</span> UNSIGNED NOT <span style="box-sizing: border-box; color: #7d0045;">NULL</span> COMMENT <span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Visibility'</span>
<span style="box-sizing: border-box; color: #308080;">)</span> ENGINE<span style="box-sizing: border-box; color: #308080;">=</span>MEMORY DEFAULT <span style="box-sizing: border-box; color: #003060;">CHARSET</span><span style="box-sizing: border-box; color: #308080;">=</span>utf8 COMMENT<span style="box-sizing: border-box; color: #308080;">=</span><span style="box-sizing: border-box; color: #ffffff; background: #dd9999; font-weight: bold; font-style: italic;">'Catalog Category Product Indexer Temp Table'</span><span style="box-sizing: border-box; color: #406080;">;</span>
ALTER TABLE `catalog_category_product_index_tmp`
  ADD KEY `CAT_CTGR_PRD_IDX_TMP_PRD_ID_CTGR_ID_STORE_ID` <span style="box-sizing: border-box; color: #308080;">(</span>`product_id`<span style="box-sizing: border-box; color: #308080;">,</span>`category_id`<span style="box-sizing: border-box; color: #308080;">,</span>`store_id`<span style="box-sizing: border-box; color: #308080;">)</span><span style="box-sizing: border-box; color: #406080;">;<br /><br /></span></pre>
<ul>
<li>
<ul>
<li>
<h3><span><em>第2步：尝试在本地重新索引</em></span></h3>
</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>
<h3><span><em>步骤3：如果您可以在本地重新编制索引，然后再在服务器上重新编制索引</em></span></h3>
</li>
</ul>
</li>
</ul>
<p>&nbsp;</p>
<p><span><span>我们向您展示了3个步骤来解决在Magento CE 2.1.9中重新索引时发生的死锁错误。</span><span>如果您在按照说明进行操作时遇到任何问题，请联系我们</span><span>。</span></span></p>]]></description>
      <pubDate>Tue, 05 Jun 2018 01:33:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[2018年Magento电子商务网站20大免费网站速度测试工具（第2部分）]]></title>
      <link>https://www.360magento.com/blog/website-speed-test-2/</link>
      <description><![CDATA[<p><span>在</span><a href="http://www.360magento.com/blog/website-speed-test/">上一篇博客文章中</a><span><span>，我们向您展示了Magento电子商务商店的前10款免费网站速度测试工具。</span><span>今天，我们将继续推荐给您可以免费获得的剩余10个有用的测试工具。</span><span>让我们开始吧！</span></span></p>
<h2><span>所有Magento电子商务网站都应该知道</span>20个推荐的免费网站速度测试工具...</h2>
<h3><span><a href="https://developer.chrome.com/devtools" rel="nofollow" target="_blank">11. Chrome DevTools</a></span></h3>
<p><img alt="google devtools" height="690" src="http://www.360magento.com/media/wysiwyg/blog_195/chrome-devtools.png" width="1300" /></p>
<p><span>这是开发人员最熟悉的免费网站速度测试工具之一，因为它很容易在本地环境中测试和调试。</span></p>
<p><span>要启动DevTools，只需打开Chrome浏览器，然后按下组合键即可：</span></p>
<ul>
<li><span>对于Window / Linux：Ctrl + Shift + I</span></li>
<li><span>对于Mac：Cmd + Opt + I</span></li>
</ul>
<p><span><span>之后，将会显示您的Magento电子商务网站的详细分析。</span><span>以下是关于Chrome DevTools您可能想要了解的更多信息：</span></span></p>
<ul>
<li><span>通过使用Devetools，您将能够增强您的网络连接，禁用缓存，检测缓慢的第一个字节时间，获取页面渲染截图等。</span></li>
<li><span><span>此外，您可以计算出确切的DOMContentLoaded时间，其总加载时间，或阻止资源以及如何处理它。</span><span>（<span>Network -&gt; Show Overview -&gt; Ctrl+R/ Cmd+R -&gt; refresh</span>）</span></span></li>
<li><span><span>作为Google性能审核的强大自动化工具，Lighthouse已整合到Devtools中。</span><span>因此，您将知道根据糟糕的审核来如何改进您的网站。</span></span></li>
</ul>
<p>&nbsp;</p>
<h3><span><a href="https://ready.mobi/" rel="nofollow" target="_blank">12. MobiReady</a></span></h3>
<p><span>尽管MobiReady是一种新的测试工具，但它已被证明是最有效的免费网站速度测试工具之一，不仅适用于开发人员，设计人员，也适用于营销人员评估移动设备上的网站性能。</span></p>
<p><span>MobiReady的特别之处在于它将根据</span><em>W3C标准Google PageSpeed Insights</em><span>和</span><em>Yahoo YSlow</em><span><span>进行测试</span><span>。</span></span></p>
<p><img alt="mobiready测试网站速度" class="aligncenter size-full wp-image-6049" height="841" src="http://www.360magento.com/media/wysiwyg/blog_195/mobiready-test-website-speed.png" width="1300" /><span>|&nbsp;</span><br /><span>怎么运行的？</span></p>
<ul>
<li><span>MobiReady在4种不同类型的设备（台式机，高端手机，中端手机和低端手机）上实施4项测试，以检查您的网站在同一时间的表现。</span></li>
<li><span>它利用Chrome来下载网页的所有资源并检查尺寸。</span></li>
<li><span>总体而言，MobiReady为我们提供了遵循行业准则的相对准确的分数。</span></li>
</ul>
<p><img alt="mobiready测试网站速度结果" class="aligncenter size-full wp-image-6095" height="1708" src="http://www.360magento.com/media/wysiwyg/blog_195/mobiready-test-website-speed-result-1.png" width="1300" /></p>
<div class="panel panel-default">
<div class="panel-collapse collapse in" id="collapseThree">
<div class="panel-body panel-body-no-border">
<div class="panel panel-default">
<div class="panel-collapse collapse in" id="collapseFive">
<div class="panel-body panel-body-no-border"><span>要根据MobiReady测试增强您的Magento商店，您必须点击每个测试来查看其详细信息以及解决方案。</span></div>
<div class="panel-body panel-body-no-border"></div>
</div>
</div>
</div>
</div>
</div>
<p>&nbsp;</p>
<h3><span><a href="https://varvy.com/pagespeed/" rel="nofollow" target="_blank">13. Varvy</a></span></h3>
<p><span><span>Varvy是电子商务网站最强大的一站式免费网站速度测试工具之一，可以检查您的速度，移动功能和搜索引擎优化（基于Google网站管理员指南）。</span><span>在进行详细分析后，Varvy将为优化您的网站性能提供大量方便的提示和指导。</span></span></p>
<p><span>更具体地说，测试结果包括摘要，页面资源图，CSS传递，Javascript使用率，速度问题，...</span><br /><img alt="varvy测试网站速度" class="aligncenter size-full wp-image-6040" height="670" src="http://www.360magento.com/media/wysiwyg/blog_195/varvy-test-website-speed.png" width="1300" /><br /><img alt="varvy工具测试网站速度" class="aligncenter size-full wp-image-6041" height="1215" src="http://www.360magento.com/media/wysiwyg/blog_195/varvy-tool-test-website-speed.png" width="1300" /></p>
<p>&nbsp;</p>
<h3><span><a href="https://performance.sucuri.net/" rel="nofollow" target="_blank">14.&nbsp;</a></span><a href="https://performance.sucuri.net/" rel="nofollow" target="_blank">Sucuri Load Time Tester</a></h3>
<h3></h3>
<p><span><span>Sucuri Load Time Tester工具提供了一种简单而快速的方式来评估您的网站在全球不同国家的表现。</span><span>在检查每个区域的总时间（根据连接时间和第一字节的时间）后，Sucuri将分析并给您一个全球绩效等级（A到F）。</span></span></p>
<p><span>更具体地说，这个测试有助于确定连接到您的网站以及您的网页完全加载需要多长时间。</span></p>
<p><img alt="sucuri加载时间测试仪" class="aligncenter size-full wp-image-6044" height="381" src="http://www.360magento.com/media/wysiwyg/blog_195/sucuri-load-time-tester.png" width="1300" /><br /><img alt="sucuri加载时间测试结果" class="aligncenter size-full wp-image-6045" height="581" src="http://www.360magento.com/media/wysiwyg/blog_195/sucuri-load-time-tester-results.png" width="1300" /></p>
<h3><span><a href="https://testmysite.thinkwithgoogle.com/" rel="nofollow" target="_blank">15.</a></span><a href="https://testmysite.thinkwithgoogle.com/" rel="nofollow" target="_blank">Think With Google</a>&nbsp;- 移动端友好测试&nbsp;</h3>
<h3></h3>
<p><span>Think With Google工具将帮助您了解您的网站是否适合移动设备，以及向您提供有用的增强建议。</span></p>
<p><img alt="goodle移动友好测试" class="aligncenter size-full wp-image-6058" height="878" src="http://www.360magento.com/media/wysiwyg/blog_195/goodle-mobile-friendly-test.png" width="1300" /></p>
<p><span>此工具可让您将免费报告发送至您的电子邮件，或者只需点击即可将信息转发给您的网站管理员或开发人员。</span></p>
<p><span><span>此外，Think With Google不仅可以分析您的Magento网站，还可以与同行业的其他网站进行比较。</span><span>从那里，你会知道你如何来尝试克服你的竞争对手。</span></span></p>
<p><img alt="goodle移动友好的测试结果" class="aligncenter size-full wp-image-6099" height="1853" src="http://www.360magento.com/media/wysiwyg/blog_195/goodle-mobile-friendly-test-results-1.png" width="1294" /></p>
<p>&nbsp;</p>
<h3><span><a href="https://www.dareboost.com/" rel="nofollow" target="_blank">16. Dareboost</a></span></h3>
<p><span><span>强烈推荐的另一个有用的免费网站速度测试工具是Dareboost。</span><span>像Varvy一样，Dareboost是一款全面的工具，可以分析您的网站速度，性能监控和搜索引擎优化。</span></span></p>
<p><img alt="dareboost免费工具来测试网站的性能" class="aligncenter size-full wp-image-6060" height="557" src="http://www.360magento.com/media/wysiwyg/blog_195/dareboost-free-tool-to-test-website-performance.png" width="1300" /></p>
<p><span>这个测试工具将分析各种数据点（最多80个），例如：请求数量，可访问性，jQuery，缓存策略，浏览器渲染......</span></p>
<p><span><span>与列表中的其他工具相比，Dareboost的安全报告非常特殊。</span><span>它会显示您的网站是否缺少安全政策标头和SSL证书，或者您的网站是否遭受了点击劫持攻击等等。</span></span><br /><img alt="dareboost免费工具来测试网站的性能结果" class="aligncenter size-full wp-image-6061" height="908" src="http://www.360magento.com/media/wysiwyg/blog_195/dareboost-free-tool-to-test-website-performance-results.png" width="1300" /></p>
<p><span>查看Dareboost报告，您可以快速发现您的Magento网站存在的问题并提出改进建议。</span></p>
<p><span>此外，它还允许您每月进行测试并获得5个网站报告。</span></p>
<p>&nbsp;</p>
<h3><span><a href="http://www.webpagetest.org/" rel="nofollow" target="_blank">17. WebPageTest</a></span></h3>
<p><span>由Google开发和支持的WebPageTest是一个了不起的开源工具，允许您使用浏览器（Chrome和Internet Explorer）在全球范围内的一个或多个地点实施免费速度测试。</span></p>
<p><span>通过使用WebPageTest，您可以进行一些独特的测试，例如内容拦截，多步骤交易，连接速度或视频捕捉......几乎所有网站上的所有内容。</span></p>
<p><span>更重要的是，您可以同时对3个网站进行测试，以便将您的网站与竞争对手的网站进行比较。</span></p>
<p><img alt="webpagetest免费测试工具" class="aligncenter size-full wp-image-6055" height="609" src="http://www.360magento.com/media/wysiwyg/blog_195/webpagetest-free-testing-tool-1.png" width="1300" /><br /><img alt="webpagetest免费测试工具结果" class="aligncenter size-full wp-image-6066" height="847" src="http://www.360magento.com/media/wysiwyg/blog_195/webpagetest-free-testing-tool-result.png" width="1300" /></p>
<p>&nbsp;</p>
<h3><span><a href="http://www.bitcatcha.com/" rel="nofollow" target="_blank">18. Bitcatcha</a></span></h3>
<p><span>由于Bitcatcha，您的Magento网站将在8个地点（USx2，伦敦，新加坡，圣保罗，班加罗尔，悉尼和日本）进行测试。</span></p>
<p><span>一旦测试完成，您将获得每个地区的具体时间，性能等级以及如何提高您网站性能的建议。</span></p>
<p><span>此外，由于Bitcatcha提供的可用链接，您可以轻松分享测试结果。</span></p>
<p>&nbsp;</p>
<p><img alt="bitcatcha网站速度测试工具" class="aligncenter size-full wp-image-6032" height="629" src="http://www.360magento.com/media/wysiwyg/blog_195/bitcatcha-website-speed-testing-tool.png" width="1300" /></p>
<p><img alt="bitcatcha网站速度测试" class="aligncenter size-full wp-image-6033" height="718" src="http://www.360magento.com/media/wysiwyg/blog_195/bitcatcha-website-speed-test.png" width="1300" /></p>
<p>&nbsp;</p>
<h3><span><a href="https://github.com/devbridge/Performance" rel="nofollow" target="_blank">19. PerfTool</a></span></h3>
<p><span><span>PerfTool是测试你的Magento网站速度的另一个开源工具，托管在Github上。</span><span>它提供了大量有关您的网站的有用信息，并以易于理解的方式显示结果。</span></span></p>
<p><span>为了提供详细的报告，PefTool收集3个可信数据源，包括DevPerf，PageSpeed Insights和W3CJS。</span></p>
<p><span><span>您的电子商务网站报告中有超过200个绩效指标。</span><span>只需输入您的网站的网址，让PerfTool完成剩下的工作。</span></span></p>
<p><img alt="perftool-网络性能速度测试" class="aligncenter size-full wp-image-6067" height="1364" src="http://www.360magento.com/media/wysiwyg/blog_195/perftool-web-performance-speed-test.png" width="2103" /></p>
<p>&nbsp;</p>
<h3><span><a href="http://www.monitis.com/" rel="nofollow" target="_blank">20. Monitis</a></span></h3>
<p><span><span>最后一个你不应该忽视的网站速度测试工具是Monitis。</span><span>这个工具很简单，但可以生成快速和可靠的结果。</span></span></p>
<p><span>您的Magento网站将从3个不同的地点进行检查，即美国，欧洲和亚太地区。</span></p>
<p><span>最后但并非最不重要的是，它允许您通过电子邮件，社交媒体或直接信息即时分享测试结果。</span></p>
<p><img alt="monitis web速度测试工具" class="aligncenter size-full wp-image-6031" height="511" src="http://www.360magento.com/media/wysiwyg/blog_195/monitis-web-speed-test-tool.png" width="1300" /></p>
<p>&nbsp;</p>
<h2><span>总结</span></h2>
<p><span><span>如果您希望加速您的网站，首先，花时间找一个可靠的网站速度测试工具来评估您当前的表现，找出哪些需要改进以及如何去做。</span><span>此外，市场上还有很多可用的免费网站速度测试工具，所以不需要你付费。</span><span>希望你在这篇文章中提到的工具能找到一个合适的工具来测试你的网站。</span></span></p>
<p><span><span>此外，在注意到您的问题后，如果您没有足够的知识和专业知识来改进网站，我们可以提供帮助。</span><span>在Magento界拥有6年以上的经验，我们知道如何让任何Magento电子商务网站发挥最佳效果。</span><span>通过发送您的请求到</span></span><a href="mailto:sales@360mageno.com">sales@360magento.com</a>&nbsp;或网站下方的联系方式<span><span>以获得免费咨询，</span><span>与我们联系</span><span>。</span></span></p>]]></description>
      <pubDate>Mon, 04 Jun 2018 01:48:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[2018年Magento电子商务网站20大免费网站速度测试工具（第1部分）]]></title>
      <link>https://www.360magento.com/blog/website-speed-test/</link>
      <description><![CDATA[<p><span><span>对于所有Magento电子商务网站，网站速度在客户体验和销售转化中起着至关重要的作用。</span><span>我们在前面的博客中提到了很多简单的方法来提高您的网站速度。</span></span></p>
<p><span>但是，在知道如何更好更快地创建网站之前，您应该测试当前的性能。</span></p>
<p><span><span>在这个博客中，我们将向您提供20个免费网站速度测试工具的列表，您可以使用它们检查Magento电子商务网站的性能。</span><span>让我们开始吧！</span></span></p>
<h2><span>所有Magento电子商务网站都应该知道</span>20个推荐的免费网站速度测试工具...</h2>
<h3><a href="https://developers.google.com/speed/pagespeed/insights/" rel="nofollow" target="_blank">1. Google Pagespeed Insights</a></h3>
<p><span><span>8年前，谷歌宣布网站页面速度将成为搜索引擎优化排名的重要因素。</span><span>同时，他们推出了Google PageSpeed Insights，一款功能强大的免费网站速度测试工具，可测量移动设备和桌面设备的网站性能，然后提出改进网站的具体方法。</span></span></p>
<p><img alt="谷歌pagespeed的见解" height="465" src="http://www.360magento.com/media/wysiwyg/blog_194/google-pagespeed-insights.png" width="1300" /><span>一旦您提交了需要测试的网站的URL，Google就会同时运行2个分析：</span></p>
<ul>
<li><span><span>第一个将检查上述内容的加载时间。</span><span>换句话说，它衡量从用户请求新页面到浏览器呈现上述内容的那一刻为止所用的时间。</span></span></li>
<li><span>第二个将测量提交网站的整体加载速度，从开始到页面完全呈现时。</span></li>
</ul>
<p><img alt="谷歌pagespeed洞察测试" class="aligncenter size-full wp-image-6035" height="764" src="http://www.360magento.com/media/wysiwyg/blog_194/google-pagespeed-insights-testing.png" width="1300" /></p>
<p><span>正如你所看到的，得分在0-100分的范围内。</span></p>
<p><span><span>分数越高，您的网站的优化效果就越好。</span><span>如果您的分数高于85，恭喜，您的网站表现非常好。</span></span><br /><img alt="谷歌pagespeed洞察测试" class="aligncenter size-full wp-image-6036" height="769" src="http://www.360magento.com/media/wysiwyg/blog_194/google-pagespeed-insights-test.png" width="1300" /></p>
<p><span>与桌面报告相比，移动报告添加了一个名为&ldquo;用户体验&rdquo;的新类别，检查按钮和链接的大小，字体大小等。</span></p>
<p><span>您可能知道，Google PageSpeed Insights一直在不断改进，因此随着新规则和更好的分析，分数将随着时间而改变。</span></p>
<h3><a href="https://gtmetrix.com/" rel="nofollow" target="_blank">2. GTmetrix</a></h3>
<p><span>GTmetrix是另一种流行且易于使用的网站速度测试工具。</span><br /><span>一旦输入您的网站URL，此分析工具将立即扫描该网站，并在几分钟后提供您想要了解的网站性能的所有信息。</span></p>
<p><img alt="gtmetrix网站速度测试" class="aligncenter size-full wp-image-6037" height="492" src="http://www.360magento.com/media/wysiwyg/blog_194/gtmetrix-website-speed-test.png" width="1300" /><br /><span>在结果页面上，GTmetrix在顶部显示摘要，列出您的总体性能分数（PageSpeed＆YSlow分数），满载时间，总页面大小和请求总数。</span></p>
<p><span><span>尤其是，由于该工具在瀑布视图中显示了您的请求列表，因此您可以轻松识别您的站点中当前存在的问题。</span><span>此外，该瀑布图允许下载以进行更深入的分析。</span></span></p>
<p><span>此外，与谷歌PageSpeed Insights类似，GTmetrix测试还提出了一些可能的解决方案，以加快您的Magento电子商务网站。</span></p>
<p><img alt="gtmetrix网站速度测试" class="aligncenter size-full wp-image-6038" height="723" src="http://www.360magento.com/media/wysiwyg/blog_194/gtmetrix-website-speed-testing.png" width="1300" /></p>
<p><span>关于GTmextrix，您可能会感兴趣的还有更多：</span></p>
<p><span>您可以创建一个免费帐户并保存多达20个速度测试，这有助于比较不同浏览器（Chrome / Firefox），位置，连接类型（有线/拨号）等的测试。</span></p>
<h3><a href="https://tools.pingdom.com/" rel="nofollow" target="_blank">3. Pingdom</a></h3>
<p><span>很多人认为Pingdom是近年来领先的免费网站速度测试工具。</span></p>
<p><span>要进行测试，您必须输入URL并选择四个可用位置之一，包括美国（德克萨斯州和加利福尼亚州），澳大利亚和瑞典。</span></p>
<p><span>检查完您的网站后，Pingdom将显示一个摘要，其中包含总体性能等级，总载入时间，页面大小，请求数量以及网站速度与其他网站的比较。</span></p>
<p><span>与PageSpeed Insights一样，Pingdom会将您的Magento电子商务网站的性能评分为100。</span></p>
<p><img alt="pingdom网站速度免费测试" class="aligncenter size-full wp-image-6053" height="557" src="http://www.360magento.com/media/wysiwyg/blog_194/pingdom-website-speed-test-free.png" width="1300" /><br /><span>欲了解更多详情，您必须滚动到性能见解，这些见解表明每个元素的得分，并推荐具体的解决方案来增强您的网站性能。</span><br /><img alt="pingdom网站速度测试免费结果" class="aligncenter size-full wp-image-6063" height="776" src="http://www.360magento.com/media/wysiwyg/blog_194/pingdom-website-speed-test-free-results.png" width="1300" /></p>
<p><span>此外，值得注意的是，随着时间的推移，您可以跟踪您的网站性能，因为所有速度测试都将存储在Pingdom库中。</span></p>
<h3><a href="http://pagelocity.com/" rel="nofollow" target="_blank">4. Pagelocity</a></h3>
<p><span>Pagelocity也是当今最流行的免费网站速度测试工具之一。</span></p>
<p><span>与前三种工具不同，Pagelocity不仅提供关于您的页面速度的见解，还提供关于您的页面SEO（源文件大小，文本大小，文本到HTML比率，URL长度）和代码的信息。</span></p>
<p><span>每个测试方面的最高分数是100。</span></p>
<p>另一个有趣的是，资源视图提供了关于哪些资产正在构成总页面权重以进行适当调整的信息。</p>
<p><img alt="pagelocity网站性能测试" class="aligncenter size-full wp-image-6046" height="563" src="http://www.360magento.com/media/wysiwyg/blog_194/pagelocity-website-performance-test.png" width="1300" /><br /><img alt="pagelocity网站性能测试" class="aligncenter size-full wp-image-6047" height="2018" src="http://www.360magento.com/media/wysiwyg/blog_194/pagelocity-website-performance-testing.png" width="1285" /></p>
<h3><span><a href="https://www.dotcom-tools.com/website-speed-test.aspx" rel="nofollow" target="_blank">5. Dotcom工具</a></span></h3>
<p><span><span>下一个有用的免费网站速度测试工具，我们想为您的Magento电子商务网站建议是Dotcom-Tools。</span><span>它能够同时在全球24个不同地点测试网站的性能。</span><span>因此，获得最终结果需要相当长的时间。</span><span>之后，它将显示平均加载时间，页面大小以及来自这些测试位置的错误数量。</span></span></p>
<p><span>此外，您可以选择特定的浏览器进行测试，例如：Chrome，Firefox，Internet Explorer，和选择一个移动浏览器，例如：Android，iOS，Windows Phone，Blackberry等。</span></p>
<p><span>经过快速检查后，您可以通过瀑布分解了解您的网站性能。</span></p>
<p><img alt="dotcom-tools免费查看网站" class="aligncenter size-full wp-image-6062" height="795" src="http://www.360magento.com/media/wysiwyg/blog_194/dotcom-tools-free-check-website.png" width="1300" /></p>
<p><img alt="dotcom-tools免费查看网站结果" class="aligncenter size-full wp-image-6078" height="745" src="http://www.360magento.com/media/wysiwyg/blog_194/dotcom-tools-free-check-website-results.png" width="1300" /></p>
<h3><span><a href="http://yslow.org/" rel="nofollow" target="_blank">6. YSlow</a></span></h3>
<p><span>与此列表中的其他网站速度测试工具不同，YSlow是一款开源工具，可帮助您根据23雅虎的高性能网站规则评估您的网站速度。</span></p>
<p><span>此外，该工具还需要快速安装，作为浏览器的附件。</span></p>
<p><img alt="yslow测试网站速度" class="aligncenter size-full wp-image-6064" height="721" src="http://www.360magento.com/media/wysiwyg/blog_194/yslow-test-website-speed.png" width="1063" /><br /><span>YSlow将在返回结果之前分三步进行操作：</span></p>
<ul>
<li><span>第1步：抓取DOM以查找您网站中的所有组件（例如：image，script)</span></li>
<li><span>步骤2：收集有关这些组件的大小的信息（例如：gzip，过期头文件）YSlow需要</span></li>
<li><span>第3步：为每条规则以及整体规则提供分数。</span></li>
</ul>
<p><span><span>在使用YSlow测试您的网站表现后，您将获得每个区域的特定等级（从A到F得分）。</span><span>从这一点上，很容易知道哪些领域需要您关注并改进您的网站。</span></span></p>
<p><img alt="yslow测试速度结果" class="aligncenter size-full wp-image-6065" height="787" src="http://www.360magento.com/media/wysiwyg/blog_194/yslow-test-speed-results.png" width="689" /></p>
<h3><span><a href="https://loadimpact.com/" rel="nofollow" target="_blank">7.</a></span><a href="https://loadimpact.com/" rel="nofollow" target="_blank">Load Impact</a></h3>
<h3></h3>
<p><span><span>Load Impact是另一款测试网站速度的免费工具。</span><span>特别的是，该工具将同时从10个检查点生成负载，并且您甚至可以根据要求添加更多区域。</span></span></p>
<p><img alt="负载影响测试网站速度" class="aligncenter size-full wp-image-6048" height="474" src="http://www.360magento.com/media/wysiwyg/blog_194/load-impact-testing-website-speed.png" width="1300" /></p>
<p><span>处理完成后，Load Impact将显示一个信息图，显示当有更多用户访问您的Magento电子商务网站时，您的加载时间的波动。</span></p>
<p><span>为了确保您的测试网站能够满足全球客户的需求，该工具将虚拟用户从多个地点发送到您的网站。</span></p>
<p><span>更重要的是，Load Impact根据带宽使用量，请求数量和每秒请求数量显示了令人惊叹的统计数据。</span><br /><img alt="负载影响测试网站速度结果" class="aligncenter size-full wp-image-6052" height="813" src="http://www.360magento.com/media/wysiwyg/blog_194/load-impact-testing-website-speed-results.png" width="1300" /></p>
<p><span>此外，<span>Load Impact&nbsp;</span>为您提供5个免费网站性能测试和每月报告。</span></p>
<h3><span><a href="https://www.uptrends.com/tools/website-speed-test" rel="nofollow" target="_blank">8.</a></span><a href="https://www.uptrends.com/tools/website-speed-test" rel="nofollow" target="_blank">Uptrends</a></h3>
<h3></h3>
<p><span>Uptrends是您的Magento电子商务网站的另一个便捷的免费网站速度测试，使您能够在全球35个地点进行测试 - 旨在确保您的网站能够快速加载来自世界各地的速度。</span></p>
<p><span><span>就分析而言，Uptrends在瀑布或域中呈现丰富多彩的结果。</span><span>因此，您可以诊断您网站的麻烦问题并快速处理。</span></span></p>
<p><img alt="上升趋势免费网站测试工具" class="aligncenter size-full wp-image-6056" height="544" src="http://www.360magento.com/media/wysiwyg/blog_194/uptrends-free-website-testing-tool.png" width="1300" /></p>
<p><img alt="上升趋势免费网站测试工具结果" class="aligncenter size-full wp-image-6057" height="767" src="http://www.360magento.com/media/wysiwyg/blog_194/uptrends-free-website-testing-tool-results.png" width="1300" /></p>
<h3><span><a href="https://tools.geekflare.com/" rel="nofollow" target="_blank">9.</a></span><a href="https://tools.geekflare.com/" rel="nofollow" target="_blank">Geek Flare</a></h3>
<h3></h3>
<p><span>与以前的一些网站速度测试工具一样，Geek Flare可以让您从一系列不同地点的Magento电子商务网站的性能中立即查看，无论使用哪种设备。</span></p>
<p><span>点击测试按钮后，您将获得第一个字节的时间（TTFB），满载时间，页面大小，请求数量，按类型的请求计数，响应代码和域等的结果。</span></p>
<p><img alt="怪胎flare免费检查网站性能" class="aligncenter size-full wp-image-6069" height="607" src="http://www.360magento.com/media/wysiwyg/blog_194/geek-flare-free-check-website-performance.png" width="1300" /><img alt="怪胎耀斑免费检查网站的性能结果" class="aligncenter size-full wp-image-6070" height="624" src="http://www.360magento.com/media/wysiwyg/blog_194/geek-flare-free-check-website-performance-result.png" width="1300" /></p>
<h3><span><a href="http://yellowlab.tools/" rel="nofollow" target="_blank">10.</a></span><a href="http://yellowlab.tools/" rel="nofollow" target="_blank">Yellow Lab Tools</a></h3>
<h3></h3>
<p><span>与列表中的其他工具相比，Yellow Lab Tools似乎对某些人来说很陌生，但对于网站性能评估来说，它确实是一个不错的选择。</span></p>
<p><span>更具体地说，该工具提供了大量有用的信息和一些独特的功能，例如在页面加载和其他代码验证问题期间查看JavaScript与DOM的交互。</span></p>
<p><span>JavaScript时间轴将向您展示DOM在页面加载时如何精确交互。</span></p>
<p><img alt="黄色实验室工具网站速度" class="aligncenter size-full wp-image-6042" height="586" src="http://www.360magento.com/media/wysiwyg/blog_194/yellow-lab-tools-website-speed.png" width="1300" /></p>
<p><img alt="黄色实验室工具网站速度测试" class="aligncenter size-full wp-image-6043" height="857" src="http://www.360magento.com/media/wysiwyg/blog_194/yellow-lab-tools-website-speed-test.png" width="1300" /></p>]]></description>
      <pubDate>Sun, 03 Jun 2018 13:52:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[50种方法立即提升您的Magento网站性能]]></title>
      <link>https://www.360magento.com/blog/improve-magento-website-performance/</link>
      <description><![CDATA[<p><a href="http://www.360magento.com/blog/improve-magento-website-performance/" title="Magento网站性能提升">Magento网站的性能</a><span><span>对于每个电子商务企业的成功都至关重要。</span><span>如果您的当前网站未进行优化，您的客户很有可能会在网站加载时离开。</span><span>提高网站性能意味着您正在为访问者创造更好的购物体验，因此我们来执行以下方法：</span></span></p>
<h2><span>MAGENTO网站性能增强 - 快速配置</span></h2>
<p><span>1.启用cron和日志清理</span></p>
<p><span>2.启用</span><em>Use Flat Catalog Category和 Use&nbsp;</em><em>Flat Calalog Product</em><span><br /></span></p>
<p><span>3.打开Magento的内置缓存</span></p>
<p><span>4.启用</span><em>合并Javascript文件&nbsp;</em><span>并</span><em>合并CSS文件</em><span>以减少HTTP请求的数量</span></p>
<p><span>5.卸载你不需要的所有扩展</span></p>
<p><span>6.为类别和产品使用规范链接Meta标签</span></p>
<p><span>7.产品URL不要使用类别路径</span></p>
<p><span>8.删除类别URL后缀中的.html</span></p>
<p><span>9.限制类别页面上的产品数量</span></p>
<h2><span>MAGENTO网站性能增强 - 应用程序级别修复</span></h2>
<p><span>推迟解析Javascript</span></p>
<p><span>11.避免AlphaImageLoader过滤器</span></p>
<p><span>12.避免URL重定向</span></p>
<p><span>13.使用外部Javascript和CSS</span></p>
<p><span>14.避免使用CSS表达式</span></p>
<p><span>15.减少DOM元素的数量</span></p>
<p><span>16.利用浏览器缓存</span></p>
<p><span>17.删除重复的Javascript和CSS</span></p>
<p><span>18.缩小Javascript和CSS</span></p>
<p><span>19.启用gzip压缩组件</span></p>
<p><span>20.将CSS放在文档头部的顶部</span></p>
<p><span>21.使用CSS精灵组合图像</span></p>
<p><span>22.优化图像</span></p>
<p><span>23.优化样式和脚本的顺序</span></p>
<p><span>24.避免不好的请求</span></p>
<p><span>25.摆脱静态资源中的查询字符串</span></p>
<p><span>26.避免使用CSS @import</span></p>
<p><span>27.指定</span><em>Vary：Accept-Encoding</em><span>标头</span></p>
<p><span>28.从一致的URL提供资源</span></p>
<p><span>29.指定一个缓存验证器</span></p>
<p><span>30.避免在元标记中设置字符</span></p>
<p><span>31.使Ajax可缓存</span></p>
<p><span>32.倾向于异步资源</span></p>
<p><span>33.把Javascript放在底部</span></p>
<p><span>34.使用内容分发网络（CDN）</span></p>
<p><span>35.减少DNS查找</span></p>
<p><span>36.避免HTTP 404 - 未找到错误</span></p>
<p><span>37.启用gzip压缩</span></p>
<p><span>38.使favicon小而且可缓存</span></p>
<p><span>39.减小cookie的大小</span></p>
<h2><span>MAGENTO网站性能增强 - 配置级别修复</span></h2>
<p><span>40.优化cookie的大小</span></p>
<p><span>41.禁用Magento日志</span></p>
<p><span>42.清理Magento数据库日志</span></p>
<p><span>43.为产品设置唯一的名称</span></p>
<h2><span>MAGENTO网站性能增强 - 服务器级别修复</span></h2>
<p><span>44.使用<span>Varnish</span>缓存</span></p>
<p><span>45.使用Redis</span></p>
<p><span>46.使用专用服务器</span></p>
<p><span>47.使用最新的PHP版本</span></p>
<p><span>48.使用高性能SSD驱动</span></p>
<p><span>49.使用RAM 2GB以上，加上双核CPU</span></p>
<p><span>50.使用单独的Web和数据库服务器</span></p>
<p><span>正如你所看到的，为了保持和增强</span><a href="http://www.360magento.com/" rel="noopener noreferrer" title="Magento网站性能提升">Magento网站的性能</a><span><span>，我们必须做很多事情</span><span>。</span><span>因此，如果您没有足够的时间或技术技能，最好找一个可靠的Magento服务商来提供帮助。</span><span>凭借6年以上的Magento经验，</span></span><span>360Magento电子商务解决方案</span><span>可以帮助您在最短的时间内以合理的价格优化您的Magento网站性能。</span><em><span><a href="https://www.tigren.com/our-services/magento-performance-optimization/" rel="noopener noreferrer" target="_blank"><br /></a></span></em></p>]]></description>
      <pubDate>Mon, 28 May 2018 02:38:15 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Adobe将收购Magento]]></title>
      <link>https://www.360magento.com/blog/adobe-to-acquire-magento/</link>
      <description><![CDATA[<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;"><img alt="Adobe将收购magento" src="http://www.360magento.com/media/wysiwyg/adobe-magento_blog.jpg" title="Adobe将收购magento" /></p>
<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;">据美国财经网站MarketWatch报道，Adobe（NASDAQ:ADBE）周一宣布，该公司将以16.8亿美元的价格收购电商公司Magento Commerce，从而为该公司旗下平台补充一个至关重要的组成部分。</p>
<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;">这项并购交易意味着，Adobe将与客户关系管理（CRM）软件服务提供商Salesforce.com（NSYE:CRM）等公司展开一场&ldquo;肉搏战&rdquo;。Adobe的数字体验执行副总裁布莱德&middot;兰切尔（Brad Rencher）在周一召开的一次电话会议上说道，根据市场研究公司作出的估测，该交易代表着一个130亿美元左右的营收机会。</p>
<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;">在此之前，Magento就已经是Adobe的合作伙伴，该公司在2015年被收购，当时包括Permira、Sterling Partners、Longview Asset Management和Innotrac Corp.在内的一个投资者团体以9.25亿美元的价格从电商公司eBay（NASDAQ:EBAY）手中收购了Magento。同年11月份，Permira获得了Magento的全部股权。</p>
<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;">Magento的客户包括佳能和Rosetta Stone（NYSE:RST）等，另外还有与Adobe重叠的一些客户，如可口可乐（NYSE:KO）和雀巢等。据Permira称，Magento的总商品额（GMV）高达1500亿美元以上。</p>
<p class="text" style="margin: 0px 0px 28px; padding: 0px; word-wrap: break-word; color: #000000; font-family: 'Microsoft Yahei', Helvetica, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; text-indent: 2em;">根据交易协议，这项并购交易将在第三季度中完成。Adobe称，在交易完成之后，Magento首席执行官马克&middot;拉维尔（Mark Lavelle）将继续领导该公司的大约700名员工，届时Magento将会成为Adobe旗下数字体验业务的一部分。</p>]]></description>
      <pubDate>Wed, 23 May 2018 07:55:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在30天内将Magento 1迁移到Magento 2 ?]]></title>
      <link>https://www.360magento.com/blog/migrate-magento-1-to-magento-2/</link>
      <description><![CDATA[<p><span>毫无疑问，将Magento 1迁移到Magento 2有很多原因，特别是当Magento发布了最新的惊人版本</span>--Magento 2.2.4时<span><span>。</span><span>与Magento 1相比，Magento 2绝对能够带来更好的设计和性能。</span></span></p>
<p><span><span>如果我们回到几年前，由于其不稳定性，很多人都不敢升级到Magento 2。</span><span>Magento 2的第一个版本中有很多bug。但现在，当Magento似乎将所有努力都用于创新，改进和增强Magento 2功能时，情况就不同了。</span></span></p>
<p><span>此外，您应该考虑尽快从Magento 1迁移到Magento 2，因为Magento可能会在不久的将来停止对Magento 1提供支持。</span><span><span><br /></span></span></p>
<p><span><span>除此之外，Magento 2迁移是一个复杂的过程，需要您的时间，金钱和努力。</span><span>对于Magento开发者，他们可能知道它有多复杂;&nbsp;</span><span>因此这篇博客文章并非针对他们，而是Magento店主，他们将把Magento 1迁移到Magento 2.换言之，在今天发布的文章中，我们将向Magento商人展示如何在最佳的时间段内平稳，循序渐进地进行Magento迁移。</span></span></p>
<h2><span>Magento 2迁移前要知道的重要事项</span></h2>
<p><img alt="Magento1迁移到Magento2" height="628" src="http://www.360magento.com/media/wysiwyg/magento-2-migration.png" title="Magento1迁移到Magento2" width="1216" /><br /><span>许多人认为将Magento 1迁移到Magento 2的过程</span><em>与</em><span><span>更新到最新版本的Magento 1&nbsp;</span><em><span>相似</span></em><span>。</span></span></p>
<p><span>但是，这是完全</span><em>错误的</em><span>！</span></p>
<p><span>更具体地说，Magento迁移意味着您将不得不从头开始构建Magento 2上的新网站，仅是从旧网站迁移数据。</span></p>
<p><span><span>您无法继续使用当前的Magento 1主题，扩展和代码。</span><span>我们将在下一部分详细介绍。</span><span>现在，让我们深入Magento 2迁移过程！</span></span></p>
<h2><span>30天将MAGENTO 2移植到MAGENTO 1 ...</span></h2>
<p><span><span>根据我们的经验，平均完成Magento迁移过程需要4-5周（大约30个工作日）。</span><span>但是，如果您的站点需要大量自定义功能和主题自定义以及大量数据迁移，则升级时间会更长。</span><span>我们来看看迁移中会涉及什么：</span></span></p>
<p><a href="#preparation"><span>7天：查看旧网站并准备即将进行的迁移&lt;准备&gt;</span></a></p>
<p><a href="#theme"><span>5天：主题迁移</span></a></p>
<p><a href="#data"><span>5天：数据迁移</span></a></p>
<p><a href="#extension"><span>3天：扩展迁移</span></a></p>
<p><a href="#code"><span>5天：自定义代码</span></a></p>
<p><a href="#configuration"><span>2天：设置并配置新站点&lt;配置&gt;</span></a></p>
<p><a href="#testing"><span><span><span>3天：测试，修复错误并上线！</span><span>&lt;测试&gt;</span></span></span></a></p>
<div id="preparation">
<h3><span>1.准备</span></h3>
</div>
<p><img alt="准备magento 2迁移" height="768" src="http://www.360magento.com/media/wysiwyg/prepare-for-magento-2-migration.png" width="1024" /></p>
<p><span><span>在开始Magento迁移过程之前，请查看现有的Magento 1商店，并确定哪些是您真正需要的，并且需要迁移到新的网站。</span><span>例如，尽管您的网站可能包含巨大的数据库资产，但您需要迁移的内容仅包括产品，类别，客户和订单。</span><span>此外，就扩展而言，只需保留您认为必要的内容并删除冗余内容即可。</span></span></p>
<p><span>之后，强烈建议您为Magento 1网站进行彻底备份，保留所有文件，文件夹和数据库以处理不良情况。</span></p>
<p><span>此外，我们建议您为Magento 1和2商店使用相同的托管服务器（可选）。</span></p>
<div id="theme">
<h3><span>2.主题迁移</span></h3>
</div>
<p><img alt="magento 2主题迁移" height="768" src="http://www.360magento.com/media/wysiwyg/magento-2-theme-migration.png" width="1024" /></p>
<p><span><span>正如我们之前提到的，将主题和模板从Magento 1移至Magento 2新网站是不可能的。</span><span>有几个解决方案：</span></span></p>
<ul>
<li><span>第一种解决方案：</span><span><span>为Magento 2购买现成的主题以应用到您的新网站。在Magento市场,Themeforest,Magego等知名主题市场</span><span>有数百种有吸引力的设计可供您进行选择......</span></span></li>
</ul>
<p><span><span>优点：您将为您的新网站设计有很多选择，节省您的主题设计和编码时间，并显著节省您的预算。</span><span>它仅花费你从100-200美元就可以得到一个精心设计的Magento 2响应主题。</span></span></p>
<p><span><span>缺点：其他Magento电子商务商店也可以购买主题，并且与您的店面外观相同。</span><span>要处理此问题，您可以自定义主题以匹配您的品牌形象。</span><span>主题定制的成本很大程度上取决于您想要定制的程度以及您与哪个Magento开发人员/设计师合作。</span></span></p>
<ul>
<li><span>第二种解决方案：</span><span><span>查找并使用免费下载的Magento 2主题。Google搜索Magento 2 free theme可以找到很多结果。</span><span><br /></span></span></li>
</ul>
<p><span>优点：此解决方案的明显优势是您无需花费一分钱就可以得到一个新颖的外观。</span></p>
<p><span><span>缺点：与第一种解决方案相比，选择的Magento主题数量只有十分之一甚至更少。</span><span>此外，这些免费主题和模板的质量不能保证。</span><span>他们的大部分功能都非常有限。</span><span>因此，您在应用到新网站之前应仔细检查。</span></span></p>
<ul>
<li><span>第三种解决方案：</span><span><span>从头开始创建一个新的网站设计。</span><span>对于这个选项，你可以找一个Magento开发商，或者只是一个有Magento经验的网站设计师根据你的需求进行设计。</span></span></li>
</ul>
<p><span>优点：获得满足您所有需求和要求的独特网站设计。</span></p>
<p><span><span>缺点：您必须投入大量资金才能部署此解决方案。</span><span>此外，完成PSD和前端编程设计可能需要1-2个月的时间。</span></span></p>
<ul>
<li><span>第四种解决方案：</span><span><span>克隆你的Magento 1商店。</span><span>如果你仍然想保持原有商店设计，你可以考虑克隆它，为你的Magento 2商店创造相同的外观界面。</span></span></li>
</ul>
<p><span>优点：保持所有购物者当前熟悉的Magento网站设计。</span></p>
<p><span><span>缺点：网站克隆的时间取决于当前设计的复杂程度。</span><span>但是，克隆一个网站，一般来说，也将花费大量的时间（平均至少1个月）。</span><span><br /></span></span></p>
<ul>
<li><span>第5种解决方案：</span><span>克隆您感兴趣的任何网站，并为您的新Magento 2网站创建类似的界面外观。</span></li>
</ul>
<p><span>优点：创建一个与您最喜欢的类似的新Magento 2网站设计，并为您的买家带来新鲜感。</span></p>
<p><span>缺点：像第四种解决方案一样，这种方法会花费您的时间和成本。</span></p>
<h4><span>Magento主题迁移的最佳解决方案是什么？</span></h4>
<p><span><span>尽管为您解决Magento主题迁移问题引入了许多解决方案，但我们强烈推荐第一种解决方案。</span><span>总的来说，利用现成的Magento 2主题将花费最少的时间（寻找适当的主题），金钱（拥有主题）和努力（用于安装和定制它）。</span><span>我们的大部分中小型客户现在都选择此方案。</span></span></p>
<p><span>此外，在新的Magento 2网站上部署主题的总时间（包括安装，配置和次要定制）平均为4-5天。</span></p>
<div id="data">
<h3><span>3.数据迁移</span></h3>
</div>
<p><img alt="magento数据迁移" height="768" src="http://www.360magento.com/media/wysiwyg/magento-data-migration.png" width="1024" /><span><span>Magento数据迁移是将您的所有数据（包括产品，类别，客户，订单，推荐信，评论......）传输到新的Magento 2站点的过程。</span><span>诚然，这是Magento 2升级过程中最关键的阶段，要求您具备强大的知识和经验来进行迁移。</span><span>否则，一个小错误可能会导致严重的数据丢失而无法恢复。</span></span></p>
<p><span><span>要将您的数据库资产从Magento 1移至Magento 2，我们可以使用</span><span>由Magento提供</span><span>的便捷的</span></span><span><a href="https://devdocs.magento.com/guides/v2.2/migration/migration-tool.html" title="Magento2数据迁移工具" target="_blank">Magento 2数据迁移工具</a></span><span><span>。</span><span>该工具将使用map文件将数据转换到您的Magento 2商店。</span><span>更具体地说，它将验证您的Magento 1和2数据库结构之间的一致性，跟踪数据传输进度，创建日志，然后运行数据验证测试。</span></span></p>
<p><img alt="magento 2数据迁移工具" height="742" src="http://www.360magento.com/media/wysiwyg/magento-2-data-migration-tool.png" width="1264" /><br /><span><span>要执行数据迁移，首先您必须通过composer安装数据迁移工具。</span><span>请记住下载适用于您的Magento 2版本的正确版本的工具。</span><span>例如，如果您在</span></span>Magento 2.2.4<span><span>上构建新网站</span><span>，则必须安装具有相同版本（2.2.4）的数据迁移工具。</span><span>其次，您需要将配置设置从M1迁移到M2，包括商店，网站，系统配置（运输，付款，税收）等。</span><span>第三，是时候迁移数据库中的主要数据了。</span></span></p>
<p><span>除此之外，根据您的产品，订单和客户的现有数量，需要3到5天才能将数据从Magento 1迁移到Magento 2。</span></p>
<div id="extension">
<h3><span>4.扩展迁移</span></h3>
</div>
<p><img alt="magento扩展迁移" height="768" src="http://www.360magento.com/media/wysiwyg/magento-extension-migration.png" width="1024" /><br /><span><span>与主题一样，您不再可以在Magento 2商店中使用Magento 1扩展列表。</span><span>你需要做的是找到提供相同功能Magento 2版本的模块和插件迁移到新站点。</span><span>但是，并非所有Magento 1的扩展都有针对Magento 2开发的。在这种情况下，您可以联系多个Magento扩展提供商，要求他们为您的商店开发自定义模块。</span></span></p>
<p><span>对于某些扩展，我们还需要从M2中迁移M1的数据，例如奖励积分和商店积分。</span></p>
<p><span>平均而言，每个插件迁移需要3-4个小时，包括安装，配置和可能的冲突解决。</span></p>
<p><span>因此，我们建议您选择并&ldquo;迁移&rdquo;到新网站的必要Magento扩展程序，以节省您的时间，金钱和精力。</span></p>
<div id="code">
<h3><span>5.自定义代码（自定义）</span></h3>
</div>
<p><img alt="magento迁移中的自定义代码" height="768" src="http://www.360magento.com/media/wysiwyg/custom-code-in-magento-migration.png" width="1024" /><span><span>幸运的是，大多数Magento 1自定义代码与Magento 2兼容，因此您可以使用多个Magento代码迁移工具重写或迁移代码。</span><span>我们经常使用</span><span>Magento&nbsp;</span><span>的</span></span><a href="https://github.com/magento/code-migration">Code Migration Toolkit</a><span>，使事情变得更简单。</span></p>
<p><span>此外，值得注意的是，M1和M2的结构有几点不同，您需要仔细检查代码以确保它在新店中运行良好。</span></p>
<div id="configuration">
<h3><span>6.配置</span></h3>
</div>
<p><img alt="从magento 1迁移到magento 2进程" height="768" src="http://www.360magento.com/media/wysiwyg/migrate-from-magento-1-to-magento-2-process.png" width="1024" /><br /><span><span>在主题，数据和扩展迁移之后，您已经完成了Magento 2迁移过程的80％。</span><span>现在，您必须在新的Magento 2网站上完成配置，包括语言，货币，税收，电子邮件模板设置等。</span></span></p>
<p><span><span>此外，搜索引擎优化在以后提高网站访问量方面起着重要作用。</span><span>在Magento 2中，它允许您创建适合搜索引擎优化的URL，编辑元标题/描述/标签/关键字，添加图像替代，控制网站索引以及与Google服务（Analytics / Search Console / Adwords）集成。</span><span>因此，不要忘记利用所有这些有价值的功能。</span></span></p>
<div id="testing">
<h3><span>7.测试</span></h3>
</div>
<p><img alt="magento 2迁移和升级" height="768" src="http://www.360magento.com/media/wysiwyg/magento-2-migration-and-upgrade.png" width="1024" /><br /><span><span>Magento迁移过程的最后一个基本阶段是测试。</span><span>您必须彻底检查并测试整个网站，确保所有内容都按照原站运行。</span><span>以下是在Magento升级后测试商店时使用的建议清单：</span></span><br /><span style="text-decoration: underline;"></span></p>
<h4><span>前端测试：</span></h4>
<p><span>店面外观</span></p>
<ul>
<li><span>主页</span></li>
<li><span>CMS页面</span></li>
<li><span>页面内容</span></li>
<li><span>横幅滑块</span></li>
<li><span>页眉和页脚链接</span></li>
</ul>
<p><span>产品列表</span></p>
<ul>
<li><span>类别和子类别</span></li>
<li><span>产品网格/列表模式</span></li>
<li><span>分层导航菜单</span></li>
<li><span>产品分类</span></li>
<li><span>产品添加到购物车</span></li>
<li><span>面包屑</span></li>
<li><span>产品页面</span></li>
</ul>
<p><span>产品页面</span></p>
<ul>
<li><span>产品加入购物车/愿望清单/比较清单</span></li>
<li><span>产品图片和视频</span></li>
<li><span>产品数量</span></li>
<li><span>产品价格</span></li>
<li><span>产品描述</span></li>
<li><span>产品评分和评论</span></li>
</ul>
<p><span>购物车</span></p>
<ul>
<li><span>产品添加到购物车</span></li>
<li><span>数量变化</span></li>
<li><span>产品删除</span></li>
<li><span>折扣应用</span></li>
<li><span>运费和税务计算</span></li>
<li><span>小计和总价</span></li>
</ul>
<p><span>结帐页面</span></p>
<ul>
<li><span>来宾结帐</span></li>
<li><span>帐单和运输</span></li>
<li><span>运输和付款方式</span></li>
</ul>
<p><span>客户账户和信息</span></p>
<ul>
<li><span>客户登录和注册</span></li>
<li><span>忘记密码</span></li>
<li><span>客户帐户页面</span></li>
</ul>
<p><span>电子邮件</span></p>
<ul>
<li><span>注册确认</span></li>
<li><span>重设密码</span></li>
<li><span>订单确认</span></li>
<li><span>联系我们提交</span></li>
<li><span>通讯订阅</span></li>
</ul>
<p>&nbsp;</p>
<h4><span>后端测试：</span></h4>
<p><span>产品目录</span></p>
<ul>
<li><span>产品配置</span></li>
<li><span>类别配置</span></li>
<li><span>属性管理</span></li>
<li><span>评论管理</span></li>
<li><span>Sitemap生成</span></li>
</ul>
<p><span>销售</span></p>
<ul>
<li><span>订单创建</span></li>
<li><span>发票提交</span></li>
<li><span>装运提交</span></li>
<li><span>贷项凭证创建</span></li>
</ul>
<p><span>顾客</span></p>
<ul>
<li><span>用户管理</span></li>
<li><span>客户群体创建</span></li>
</ul>
<p><span>促销</span></p>
<ul>
<li><span>目录价格规则</span></li>
<li><span>购物车价格规则</span></li>
</ul>
<p>&nbsp;</p>
<h2><span>将MAGENTO 1迁移到MAGENTO 2的成本如何？</span></h2>
<p><img alt="magento 1到magento 2的迁移成本" height="768" src="http://www.360magento.com/media/wysiwyg/magento-1-to-magento-2-migration-cost.png" width="1024" /><br /><span><span>Magento 1到Magento 2的迁移成本可能很高，但它值得。</span><span>根据您预期网站的复杂程度，价格可能会或高或低。</span><span>例如，就Magento主题迁移而言，尤其是，您必须花费100-200美元购买现成的主题，或者高达1,000-2,000美元购买独特的设计或克隆旧网站。</span><span>此外，您希望迁移的扩展程序越多，您必须支付的金额也越多。</span></span></p>
<p>如果您不是自己将Magento 1迁移到Magento 2，而是请<a href="http://www.360magento.com/" title="Magento开发服务商" target="_blank">Magento服务商</a>提供的Magento迁移服务，那么您的项目成本也将大大取决于Magento开发者的工时费。例如，美国以及沿海城市的Magento开发公司每个工作小时会收取75-150美元的费用，但您如果选择内的<a href="http://www.360magento.com/" title="Magento开发公司" target="_blank">Magento公司</a>只要一半甚至更少的费用（每工作小时20-50美元）。这个巨大的价格差距仅仅是由于地区劳动力成本的巨大差异。</p>
<h3>360Magento的Magento迁移服务</h3>
<p><span><span>凭借6年以上的Magento开发经验，我们能够以非常合理的价格提供流畅高质量的迁移过程。</span><span>现在就</span></span><a href="http://www.360magento.com/contacts/">联系我们</a><span>，获取Magento 2迁移项目的免费快速报价和咨询！</span><br /><img alt="magento迁移" height="1025" src="http://www.360magento.com/media/wysiwyg/magento-migration.jpg" width="1920" /></p>
<h2><span>总结</span></h2>
<p><span><span>从现在发生的情况来看，Magento 2是&ldquo;现在&rdquo;和&ldquo;未来&rdquo;，而Magento 1已经过时并且远远落后。</span><span>如果您想为您的网站做到最好，请考虑立即实施Magento 2迁移。</span><span>大多数竞争对手可能已经将他们的网站升级到Magento 2。</span></span></p>]]></description>
      <pubDate>Tue, 15 May 2018 11:03:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[选择专业Magento开发者/开发公司的10条准则]]></title>
      <link>https://www.360magento.com/blog/find-magento-develpoer/</link>
      <description><![CDATA[<p>Magento于2008年3月31日发布，已成为全球领先的电子商务平台。 因此，越来越多的电子商务公司需要Magento开发人员来开发新网站或支持其现有网站。</p>
<p>虽然有大量的Magento开发商和Magento开发人员可供选择，但是要找到在Magento开发方面拥有丰富的专业知识和经验，并且提供合理价格的合适合作伙伴还是很难的。</p>
<p><img alt="magento开发公司" src="http://www.360magento.com/media/wysiwyg/bdmg.png" title="magento开发公司" /></p>
<p>假设你要为你的项目寻找Magento开发人员/开发公司，你会怎么做？ 你会在在Google或百度上搜索并从几万个结果中选择一个可靠的结果吗？</p>
<p>事实上，60-70％的公司会这样。 这并非不是一种好的方法，但如果你没有你想要的Magento程序员的选择特定标准，太多的选择最后可能会感到困惑。 因此，为了让事情变得简单，我们为您提供高效率寻找高质量Magento开发人员和开发商的10条基本准则。我们愉快的阅读下面的内容吧。</p>
<h2>1.明确你的需求和Magento开发人员必须需具备的能力。</h2>
<p>首先，你在寻找Magento开发人员和开发服务商之前一定要非常的清楚自己想要什么。关於这点，不妨来自问几个问题：</p>
<p>你是需要这个Magento开发者来帮助你修复一个严重的bug或者处理一些持续存在的严重问题？</p>
<p>您是否想要Magento开发人员开发自定义功能/从头开始构建网站/将网站迁移到Magento 2 /继续未完成的项目？</p>
<p>你需要得到不断的支持，或者只是在紧急情况下才需要？</p>
<p>你期望你的任务/项目多久完成？</p>
<p>你更喜欢与Magento开发者自由职业者还是Magento开发商合作？</p>
<p>您的预算是多少？</p>
<p><img alt="聘请magento开发人员" src="https://www.tigren.com/wp-content/uploads/2018/04/hire-magento-developers-1.jpg" /></p>
<p>当您回答完完上述的问题，寻找合适的Magento开发人员这件事你已经做好了一半。</p>
<p>例如，如果您需要获得帮助来解决网站中的几个主要但不是紧急的错误，您可以与一些Magento自由职业者开发人员合作。 相反，如果您的网站有一些需要尽快解决的关键问题，我们强烈建议您找Magento开发公司获取专业的Magento支持服务。</p>
<p>另外，如果您需要得到持续不断的支持以确保您网站的高性能，建议您与知名的具有完善Magento解决方案的开发公司合作。</p>
<p>此外，根据您的项目大小，您需要考虑是聘请专门的Magento开发人员还是整个Magento开发团队。 原因在于，从头开发新的Magento网站等大型项目工作量大，通常需要多位Magento程序员，您应该考虑雇用一个团队来保证您的项目质量并提高开发效率节约时间成本。</p>
<p>决定谁能成你的合作对象的另一个因素是你的预算。 如，若钱对您来说不是大问题，您可以自由选择任何Magento开发人员或 Magento开发公司来合作。 但如果您的预算是中等偏低，您应该与内陆Magento开发公司合作（例如：武汉，成都，南京等）而非沿海城市的Magento电子商务公司。 通过这种方式，您可以在高质量完成工作的同时节省预算。</p>
<p>&nbsp;</p>
<h2>2.检验Magento开发人员的专业知识和经验</h2>
<p>在明确定义您的期望之后，您现在可以开始在百度或其他搜索引擎上进行搜索，并参照我们的建议标准来寻找专业的Magento开发人员。</p>
<p>总的来说，当你想聘请Magento程序员时，专业和经验似乎是最基本的考量因素。</p>
<p>无论聘用Magento开发人员还是Magento开发公司，您都要选择至少拥有2年以上Magento经验的人一起完成你的项目。凭借一系列高级功能和大规模定制，Magento为其开发人员创造了真正的挑战，特别是初学者。</p>
<p><img alt="magento开发商招聘" src="https://www.tigren.com/wp-content/uploads/2018/04/magento-developers-for-hire.jpg" /></p>
<p>那么，如何检查Magento开发者的经验？ 这很简单。</p>
<p>首先，直接询问他们。 他们从事Magento开发多久了，期间参与了多少个Magento开发项目，他们不得不面对的最严峻的Magento开发问题以及他们的解决方案。</p>
<p>其次，请他们给您的项目提建议。 Magento专业开发公司将能够根据他们的经验为您提供合理的建议。 例如，当你想开发一个复杂的功能时，一个有经验的Magento程序员可以帮助你分析这个功能的哪些部分是Magento默认的，哪些部分需要定制，然后给你一个最佳的解决方案。</p>
<p>此外，当选择Magento开发人员进行大型项目时，建议您了解他们使用版本控制工具的经验。 一般Magento专业开发公司在使用某些版本控制系统（如GIT,SVN）方面拥有丰富的经验。</p>
<p>&nbsp;</p>
<h2>3.检查Magento开发人员的开发案例</h2>
<p>说的多不如做得好，因此不要只听他们说了什么，更要看他们之前做的案例！</p>
<p><img alt="magento网站设计" src="https://www.tigren.com/wp-content/uploads/2018/04/magento-website-design-1.png" /></p>
<p>通过看他们以前的案例，检查他们开发的Magento网站，能评估他们是否能够满足您的要求。可以从前端设计和功能效果两方面入手，我们在同行网站中发现由他们大多数Magento开发项目都使用现成的主题和模板，因此您不需要过多地检查设计，而是专注于功能效果。 例如，您可以查看他们帮客户做了哪些额外功能，网站的速度，结账过程等。</p>
<p>对于Magento网站开发公司，他们经常在自己的网站上展示他们的案例，以便您快速了解。</p>
<p>&nbsp;</p>
<h2>4.找到真实的见证和反馈</h2>
<p>我们想要建议您的下一步是询问您想聘请的Magento开发人员/开发公司的以前客户的真实反馈。 有时候，一个好的案例不能告诉你整个故事。 例如，虽然最终的网站设计是完美的，但程序却无法按时交付。</p>
<p><img alt="magento电子商务审查" src="https://www.tigren.com/wp-content/uploads/2018/04/magento-ecommerce-review-1.jpg" /></p>
<p>&nbsp;要获得以前客户的联系人，您可以直接询问Magento程序员或访问案例上的网站以获取信息。 之后，您可以通过电子邮件或致电这些客户咨询用后的体验从中获得参考。 以下是您可以询问过去客户的一些有效问题：</p>
<p>他们聘请Magento开发人员/公司的项目/服务是什么？</p>
<p>他们为什么选择这个开发商？</p>
<p>项目管理如何安排的，效果如何？</p>
<p>他们觉得这项服务最令人印象深刻/令人失望的是什么？</p>
<p>开发人员是否按时按预算交付了您的项目？ 是否会产生额外费用？</p>
<p>他们有哪些地方可以改进？</p>
<p>确保您聘用的Magento开发公司为其前客户提供高质量的工作，这对聘用者来说是至关重要的。</p>
<p>&nbsp;</p>
<h2>5.询问后期开发支持和维护</h2>
<p align="left">提供项目后的支持和维护至关重要，尤其是当您聘请Magento开发人员开发大型Magento电子商务网站时。&nbsp;例如，在用户验收测试（UAT）之后，您无法找到开发站点中的所有错误，但这些错误发生在站点上线后。&nbsp;在这种情况下，最好与最初的开发人员一起找出原因并解决问题，而不是找到另一位程序员。<br /> <br /> 在360Magento，我们在客户网站上线后（Magento网站开发项目）提供3个月免费支持，以帮助他们避免及时解决任何可能的问题。&nbsp;因此，我们始终能得到我们所有客户的100％满意。&nbsp;经过3个月的免费支持，如果客户希望得到我们的进一步帮助，他们可以考虑使用我们的Magento年度支持服务。</p>
<p align="left">&nbsp;</p>
<h2>6.在寻找Magento开发者之前策划出项目的开发过程</h2>
<p align="left">您可能知道，Magento项目中应用的开发流程和方法将决定它是否成功。 有很多东西可以使Magento开发过程成为可能，但这里有一些您需要关注的主要问题。</p>
<p align="left">首先，Magento开发公司必须为您提供一个详细的开发计划。 在这个计划中，它必须清楚地告诉你他们将在你的网站上做些什么，分成几个主要任务和多个子任务（次要任务）。 此外，每项任务必须有具体的完成时间。 例如，在360Magento，我们经常为每个项目制定详细的时间安排和时间表，包括一些特定的阶段，例如规划/准备，网站设计和网站开发（产品，客户帐户，管理员配置，发货， 付款，搜索引擎优化，数据集成，扩展实现，...），测试和UAT，以及启动。</p>
<p align="left"><img alt="magento开发过程" src="https://www.tigren.com/wp-content/uploads/2018/04/magento-development-process.png" /></p>
<p align="left">此外，大多数开发人员将在他们的开发服务器上部署您的网站，并且只有在您满意产品时才将网站移动到您的服务器。 问题是你必须问他们是否会让你访问他们的服务器。 否则，您很难跟踪和控制开发进度，并及时提出改进意见。</p>
<p align="left">您需要确保的另一件事是，您想合作的Magento开发公司是否有专门的测试人员在向您提供网站之前检查所有功能。 另一方面，要清楚在发现网站上的任何问题时如何报告。</p>
<p align="left">&nbsp;</p>
<h2>7.评估Magento开发人员的沟通技巧</h2>
<p align="left">通常沟通问题是被许多人忽视的，但其实这很重要，尤其是在面对面会议几乎不可能的情况下外包Magento开发项目。 如果您要进行外地Magento开发，我们就必要具备能跟合作伙伴沟通的任何一种方式。 例如，你必须检查他们是否可以使用音频和视频会议，聊天工具如Skype，QQ或任何特殊的应用程序共享工具。</p>
<p align="left">此外，虽然英语现在变得越来越流行，但语言可能成为障碍。 因此，确保您选择的Magento开发人员有一定程度的英语流利度。</p>
<p align="left">&nbsp;</p>
<h2>8.在预算和Magento开发者期望酬劳之间取得平衡</h2>
<p align="left">在美国，英国或澳大利亚，只需点击几下，您就可以轻松找到很多的Magento开发公司。 如果你想让这些公司来完成你的Magento网站项目，你就不得不做出巨大的投资。 他们中的大多数会否定预算低于10k的开发项目，并且最愿意接受大型项目（从4万美元到10万美元）。 因此，如果您有能力聘请当地公司，将Magento项目外包可能是一个理想的选择。</p>
<p align="left">此外，如果您合作一家专业的Magento开发公司，虽然您在工时费上花费较多，但您只需要花费一半甚至更低的成本来完成低价程序员的工作。</p>
<p align="left">&nbsp;</p>
<h2>9.确定开发人员专业程度</h2>
<p align="left">一个常见的情况是，虽然该公司想建立一个Magento网站，但他们只是寻找一般的&ldquo;网站设计和开发公司&rdquo;。 因此，他们可以找到多家关于网站开发为名的公司，但是这些公司都没有专门从事Magento。</p>
<p align="left">你知道吗？ 一家专注于Shopify的大型电子商务开发公司仍然可以帮助您建立一家Magento商店，但他们跟&ldquo;真正的&rdquo;Magento开发公司没法比的。</p>
<p align="left">因此，除了网站开发商的声誉外，您还应该了解他们的重点平台和开发技能。</p>
<h2>10.询问Magento认证（可选）</h2>
<p align="left">现在，Magento为其开发人员和合作伙伴提供了多项认证，如Magento认证解决方案专家，Magento认证专业开发人员，Magento前端开发人员以及Magento认证开发人员和开发人员。</p>
<p align="left">如果Magento开发人员或Magento网页设计和开发公司可以展示他们的认证，那将是一个优势。 但是，我们将此步骤设置为可选，因为您不需要严重依赖它。 在某些情况下，如果你遇到一个认证的Magento开发者并且手头有很多认证，不要急于与他签署合同。 原因是这些认证可能通过作弊获得。</p>
<p align="left">此外，如果您的预算有限，并选择与Magento外包公司合作，即使他们在Magento拥有5-6年的经验，他们中的大多数也不能提供认证。 为什么？ 对于那些程序员来说，加入Magento认证考试的费用和时间都很浪费。 此外，他们已经完成了大量令人惊叹的网站可以向您展示，这些将比这些证书更有价值。</p>
<p align="left">&nbsp;</p>
<h2>总结</h2>
<p align="left">要寻找到一个可以满足您的所有需求并且接受您的预算的Magento开发人员/开发公司不是一件容易的事情。 但是，如果您遵循我们的建议，那么肯定会花费更少的精力为您的项目找到一个出色的合作者。</p>
<p align="left">凭借5年以上的经验，360Magento已经成为中国口碑最好的Magento开发公司品牌。 与一些代理机构不同，我们只专注于使用Magento构建的项目，并为客户提供最佳解决方案。 现在，我们提供广泛的Magento周边服务，从<a href="http://www.360magento.com/">Magento网站开发</a>，<a href="http://www.360magento.com/magento-service/magento-design.html/" title="Magento网站设计策划">Magento网站设计</a>，Magento技术支持，<a href="http://www.360magento.com/magento-service/magento-extensions-custom.html" title="Magento插件开发">Magento扩展开发</a>，<a href="http://www.360magento.com/magento-service/magento-mobile.html" title="Magento移动应用app开发">Magento移动应用app开发</a>，<a href="http://www.360magento.com/magento-service/magento-migration.html" title="magento迁移">Magento迁移</a>到Magento优化。 现在就联系我们，为您的项目免费获得报价和咨询！</p>
<p align="left"></p>]]></description>
      <pubDate>Sun, 29 Apr 2018 13:39:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento开发人员必掌握的SEO技术技巧]]></title>
      <link>https://www.360magento.com/blog/seo-tips/</link>
      <description><![CDATA[<p><img alt="Technical SEO Tips" class="aligncenter size-full wp-image-13158" height="395" src="https://www.interactone.com/wp-content/uploads/2018/03/shutterstock_226628683.jpg" width="640" /></p>
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_1">
<div class="et_pb_text_inner">
<p><span><span><span>在万维网初期，建立网站的想法和标准还处于起步阶段（甚至是萌芽状态），HTML使用的合法性以及在搜索引擎中寻找网站也超出了理解的范围。</span><span>随着HTML开发和元素（即&ldquo;标签&rdquo;）的创建，网页结构变得更加标准化，搜索引擎处理交付高质量网站到桌面的方式也在不断发展。</span><span>开发人员，设计师，内容创建者和搜索引擎都知道如何以及为什么应该构建结构的方式，最终开始成为真正的科学和艺术。</span></span></span></p>
<p><span><span><span>曾几何时，搜索引擎只是寻找&ldquo;关键字&rdquo;来决定你的网页对搜索者是否重要;&nbsp;</span><span>然后考虑了内容和页面上有多少文字（因为如果有人正在为一个主题撰写5页的文章，那么他们的网页必须真的有关于该主题的大量信息并且非常有用，对吗？ ），然后快速进入今天的谷歌化世界，我们有非常智能的搜索引擎，这些搜索引擎由非常复杂的人工智能算法提供支持，一切考虑从关键字到内容长度，以及所有这些关键字和内容是否与文章有关，以及网页内容的结构以及整个网站的结构。</span></span></span></p>
<p><span>这一切都可以回溯到开发人员这个重要的位置，因为他们是那些真正建立起信息丰富而美丽的网站的人，这些网站将为您正在搜索精确主题提供引人注目和有用的网页。</span></p>
<h2><span>来</span>自Magento开发人员的八项SEO技术技巧</h2>
<h3><span>1.页面结构</span></h3>
<p><span><span><span>一个网页有三个主要部分：头部，主体和页脚。</span><span>头部（HTML元素&lt;head&gt;）包含指令其他元素，用于告诉加载页面（您的浏览器）的页面结构，构建页面所需的资源（调用CSS和JavaScript组件）以及在元数据元素&lt;title&gt;，&lt;meta name =&ldquo;keywords&rdquo;&gt;和&lt;meta name =&ldquo;description&rdquo;&gt;中找到的描述您（或网页抓取工具）正在查看的页面的基本信息。</span></span></span></p>
<p><span><span><span>页面的主体（元素&lt;body&gt;）包含页面的主要内容。</span><span>这是内容区，所有这些标题和响亮的段落信息都是为​​了您的阅读享受而制定的。</span><span>本节的结构和重点也非常重要，因为有一种处理人和机器人阅读器（即搜索漫游器）内容的特定方法。</span><span>这篇文章稍后会详细介绍。</span></span></span></p>
<h3><span>2.元数据</span></h3>
<p><span><span><span>正如其标签和属性所暗示的，这些部分提供了页面的主要标题以及简短描述（通常用于搜索引擎）以及帮助将搜索引擎定位到页面的所有关键字。</span><span>这些部分可能是最容易创建的，也是最容易出错的搜索引擎优化。</span><span>事实上，由于滥用关键字meta，现代搜索引擎常常忽略它，但将考虑一些，所以只要设置正确，它仍然有用。</span></span></span></p>
<p>拥有一个正确的关键词仅仅意味着只提供与页面相关的关键词，而且这些信息应该保持在最低限度，因为页面的目标对象不应该超过几个字。另外，要记住，这是相对于页面的，而不是整个网站！</p>
<p>标题和描述元应包含关键词为好，但就像关键词部分本身，他们应该简洁和集中。如果太短了，它们就不能提供有效信息。太长了，它们会分散注意力，容易失去焦点。这些元素看似简单，可能太简单了，对于页面的初始&ldquo;快照&rdquo;，它们是非常重要的。把它们看作是将被搜索引擎索引的&ldquo;名片&rdquo;。</p>
<h3><span>3. HTML标题</span></h3>
<p><span><span><span>这部分似乎困扰了许多网络开发人员和内容创作者的角色，因为这些标题的真实意图经常被误解。</span><span>大多数曾经创建或改变网页的人很快就知道，在页面上放置文本时选择&lt;h1&gt;或&lt;h2&gt;或&lt;h3&gt;标签意味着改变字体的大小，以及粗体（或不粗体）的大小。</span><span>这是一种简单易用的网页设计，因为当需要大胆突出的页面上放置任何内容时，您不必选择字体大小和粗体（取决于设计平台，实际使用的字体）。</span><span>这种快速而肮脏的设计的缺点在于，您可能会在整个页面上放置不正确或多次的标题迭代，甚至没有意识到它，这对读者来说可能看起来很好，</span></span></span></p>
<p><strong><em>所以这里有个秘密</em></strong><span><span><span>：想想你的网页（和整体网站）的结构，比如一本书的内容部分。</span><span>您需要一个干净整洁的标题和小标题列表，以准确，合理地组织您的所有信息。</span></span></span></p>
<p><span><span><span>标题（即标题标签）的重要程度从1到6进行编号。</span><span>您网页的主标题（您文章的&ldquo;标题&rdquo;）应位于&lt;h1&gt;元素内。</span><span>页面上的后续标题应该用下一级重要性来表示：&lt;h2&gt;，&lt;h3&gt;，&lt;h4&gt;等等。</span></span></span><strong><em>除非</em></strong><span><span><span>声明一个全新的节，</span></span><strong><em><span>否则</span></em></strong><span><span>在页面上永远不应该有另一个&lt;h1&gt;&nbsp;</span></span></span><span><span><span>与之前的&lt;h1&gt;具有相同的重要性。</span><span>由于大多数网页几乎不会做到这一点，它实际上不应该存在。</span></span></span></p>
<p><em>&ldquo;......但是如果我想在我的页面中间添加一个非常大而粗体的字体呢？&rdquo;</em></p>
<p><span><span><span>那么，说实话，你没有。</span><span>为什么？</span><span>因为搜索引擎也会将粗体文本视为重要的内容，因为您已尽力使其突出。</span><span>这会引起某些文本突出显示的重要性内容的细微差别。</span><span>不过，这里不要太疯狂，因为这也是一种被大量滥用的旧技术，就像汤一样，太多的好香料可能会破坏一锅好汤。</span></span></span></p>
<p><span>这里给你一个学习者的图片：</span></p>
</div>
</div>
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_2">
<div class="et_pb_text_inner">
<p><img alt="技术SEO技巧" class="aligncenter size-full wp-image-13156" height="323" src="https://www.interactone.com/wp-content/uploads/2018/03/2018-03-28_1525.png" width="338" /></p>
</div>
</div>
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_3">
<div class="et_pb_text_inner">
<p><span>在上面的图片中，您可以看到页面中甚至有多个部分，其中导航菜单和侧栏可能存在于正文的上方或旁边，但是主体的&lt;h1&gt;标题是</span><span>页面</span><strong><em>的</em></strong><span><span><span>主要标题。</span><span>小标题标出主标题下面的每个主要部分，等等。</span><span>作为一个提示，页脚部分不一定需要标题标签，因为这些标签通常只是链接到其他页面，但是如果在这些标题下还有简短的描述（因为某些设计模板提供的框允许缩短内容描述），那么坚持格式是有帮助的。</span></span></span></p>
<h3><span>4.图像的&ldquo;Alt&rdquo;和&ldquo;Title&rdquo;属性</span></h3>
<p><span><span><span>图像上的这些属性至多被滥用（或使用不当），最坏的情况完全被忽视。</span><span>这些对您的搜索引擎优化不仅有帮助，而且对于越来越重要的领域是强制性的</span></span></span><span>。</span></p>
<p><span>&ldquo;alt&rdquo;和&ldquo;title&rdquo;属性可用于所有图像，旨在提供&ldquo;爬虫&rdquo;无法从图像本身收集到的额外信息（因为漫游器无法看见图像）。</span></p>
<p><span>&lt;img src=&rdquo;images/happycat.jpg&rdquo; alt=&rdquo;A happy cat, drinking some milk from a dish.&rdquo; title=&rdquo;Happy cat drinking milk.&rdquo; /&gt;</span></p>
<p><span><span><span>此图像元素示例显示如何正确使用图像的&ldquo;alt&rdquo;和&ldquo;title&rdquo;属性。</span><span>图像文件名本身不仅帮助搜索引擎找出图像可能涉及的内容以及它与它所在的页面是否相关，而且&ldquo;alt&rdquo;属性有助于提供图像的简明描述，而&ldquo;标题&rdquo;属性提供了更加直接和简洁的内容。</span><span>这两个属性都可帮助残疾人士使用&ldquo;<span>web reader</span>&rdquo;查看网页，以便查找这些属性并将页面上的图像描述给最终用户，否则这些用户可能无法清楚地看到图像或难以辨别图像是什么。</span><span>同样，添加这些属性不仅可以帮助网络爬虫确定您的页面及其提供有价值的信息，还表明你花时间去编辑更好页面可以被搜索引擎索引和完全消化，以及所有的最终用户可能会发现你的页面是一个有价值的信息来源，</span></span></span></p>
<h3><span>5.站点地图</span></h3>
<p><span><span><span>站点地图是为网页抓取工具和搜索引擎提供网站&ldquo;地图&rdquo;的文件。</span><span>他们可以告诉搜索引擎您网站上的哪些网页是最重要的，因此首先要抓取什么，以及其他元数据，例如网页上次更新时间，以及何时需要重新索引。</span></span></span></p>
<p><span><span><span>当启动一个没有大量外部链接指向的新网站时，包含网站地图就显得尤为重要，因为网络爬虫在单次访问中花费有限的时间来抓取网站。</span><span>通过提供站点地图，网络爬虫将充分利用来自其中一个外部链接的每次访问，首先抓取优先页面并忽略自上次访问以来尚未更新的页面。</span></span></span></p>
<h3><span>6.网络分析</span></h3>
<p><span><span><span>网络开发人员为他们构建的任何网站设置网站分析，并让适当的个人访问分析仪表板很重要。</span><span>检查用户在查找您的网站时搜索的关键词以及它们如何点击它们可以帮助为搜索引擎和用户剪裁内容。</span></span></span></p>
<h3><span>7. 404错误</span></h3>
<p><span><span><span>网站质量对于高搜索排名非常重要，并且当网站向网页抓取工具编制索引错误时质量受到很大影响。</span><span>一个网站的404页面未找到错误越多，它就越糟糕。</span><span>使用Google的Search Console或网站分析仪表板查找错误，并确保及时删除死链接。</span><span>如果外部链接为您的网站产生大量流量，但是对于死链接或不正确格式的网址，请考虑设置重定向至其打算访问的网页。</span></span></span></p>
<h3><span>8.页面加载时间</span></h3>
<p><span><span><span>跳出率，因为网页加载时间越长，用户在仅查看一个网页后离开网站的几率就会大幅增加，。</span><span>根据谷歌的说法，从一秒到两秒的加载时间增加了两秒，使跳出率增加了32％，而从一秒增加到五秒则增加了90％。</span><span>Web开发人员可以通过优化图像文件大小和压缩CSS和JavaScript文件来减少页面大小。</span></span></span></p>
<p><span><span><span>开发人员的专业知识对于正确的搜索引擎优化网站至关重要。</span><span>如果您认为您的Magento网站需要技术审查，请</span></span></span><a href="http://www.360magento.com/contacts/">联系我们</a><span>以了解更多关于</span><span><span><span>我们提供</span></span><span><span>的</span></span></span><a href="http://www.360magento.com/">SEO服务的信息</a><span>。</span></p>
</div>
</div>]]></description>
      <pubDate>Wed, 11 Apr 2018 02:23:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[关于Magento 2 应用PWA的论述]]></title>
      <link>https://www.360magento.com/blog/m2-pwa/</link>
      <description><![CDATA[<p><strong>什么是PWA?</strong></p>
<p>PWA全称是Progressive Web App，翻译过来即&ldquo;渐进式Web应用程序&rdquo;，我更愿意叫渐进式增强web app,是google在2015年提出，16年6月开始推广的项目。PWA的目的是使web应用通过渐进增强的方式来更接近原生app的体验及功能。</p>
<p></p>
<p><strong>PWA有哪些特点?</strong></p>
<p><strong>1.添加到手机主屏</strong></p>
<p>用户首次用浏览器浏览网站,会提示添加应用到主屏幕,你的手机屏幕上就会出现一个应用图标，这就跟app一样，有app图标和标题,外形上无差别。并且无须在应用商店下载，也不用更新，通过后台可实时更新变更内容。通过图标启动可看设置启动画面。</p>
<p></p>
<p><strong>2.推送通知</strong></p>
<p><span>即使浏览器未打开Magento 2网站上的任何页面，通知也会发送给客户，就像其他app推送通知一样</span></p>
<p></p>
<p><strong>3.在离线模式下仍然可以访问</strong></p>
<p><span>用户在没有网络的情况下，只要是以前浏览过的页面在离线状态下仍可浏览</span></p>
<p></p>
<p><strong>4.速度秒开</strong></p>
<p><span>pwa会将已经浏览过的页面缓存到用户手机本地（当然这个是可以设置缓存的具体页面），这样就享受火箭般的速度。</span></p>
<p>以上4点其实就是原生app所具备的有点，而pwa具备了web应用和原生app的有点，不仅有原生app应用的良好用户体验，还具有web应用的搜索引擎友好性。一句话，既能像app一样用又能在搜索引擎上排名。</p>
<p></p>
<p>复制一下网络上的：</p>
<p>大家都知道Native app体验确实很好，下载到手机上之后入口也方便。它也有一些缺点:</p>
<ul>
<li>开发成本高(ios和安卓)</li>
<li>软件上线需要审核</li>
<li>版本更新需要将新版本上传到不同的应用商店</li>
<li>想使用一个app就必须去下载才能使用，即使是偶尔需要使用一下下</li>
</ul>
<p>而web网页开发成本低，网站更新时上传最新的资源到服务器即可，用手机带的浏览器打开就可以使用。但是出了体验上比Native app还是差一些，还有一些明显的缺点</p>
<ul>
<li>手机桌面入口不够便捷，想要进入一个页面必须要记住它的url或者加入书签</li>
<li>没网络就没响应，不具备离线能力</li>
<li>不像APP一样能进行消息推送</li>
</ul>
<p>复制粘贴结束。</p>
<p>最后说明几点，</p>
<p>1.PWA还是web应用程序，基于浏览器。</p>
<p>2.以上说的pwa特点目前能够完全在安卓手机上使用，而ios目前不支持添加到主屏和消息推送功能。但我相信在强大的压力下，ios也不得不进行妥协。</p>
<p>3.Magento与google合作，计划在magento2.2.4版本加入pwa，这是一个设置接口插件。</p>
<p>如果想要网站页面能有更好的用户体验还是在于设计与编程。响应式流行了几年，但界面的友好性不如app，如果你想做一款如APP界面体验的移动端PWA网站,请<a href="http://www.360magento.com/contacts/">联系我们</a></p>
<p></p>
<p></p>]]></description>
      <pubDate>Mon, 02 Apr 2018 11:06:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么Magento仍然是2018年的电商巨头？]]></title>
      <link>https://www.360magento.com/blog/why-m-2018/</link>
      <description><![CDATA[<p class="graf graf--p graf-after--h3"><span>首先，我们要问个问题：这些著名的电子商务品牌有什么共同之处？</span></p>
<ol>
<li>Samsung</li>
<li>Ford</li>
<li>Olympus</li>
<li>Nike</li>
<li>Coca Cola</li>
<li>Christian Louboutin</li>
<li>Lenovo</li>
<li>Warby Parker</li>
<li>Rebecca Minkoff</li>
<li>Nestle Nespresso</li>
<li>Fox Connect</li>
<li>Vizio</li>
</ol>
<p class="graf graf--p graf-after--p" id="706a"><img alt="magento品牌" class="aligncenter size-full wp-image-5854" height="720" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-brands.png" width="1280" /><br /><span></span></p>
<p class="graf graf--p graf-after--p"><span>你有答案吗？</span></p>
<p class="graf graf--p graf-after--p"><span>是的，他们都在使用Magento - 现今最流行的电子商务平台！</span></p>
<p class="graf graf--p graf-after--p"><span>不仅这些著名品牌，有</span><em>超过25万</em><span>电子商务品牌，大小规模，选择Magento作为他们的电子商务网站平台。</span></p>
<p class="graf graf--p graf-after--p"><span>为什么？</span></p>
<p class="graf graf--p graf-after--p"><span><span>Magento无疑是易于应用的，因为它配备了大量专用于电子商务的有用默认功能。</span><span>此外，还有一个大型的Magento社区，这意味着当您的网站出现问题时，您可以轻松获得支持。</span></span></p>
<p class="graf graf--p graf-after--p"><span>尽管越来越多的电子商务平台出现（例如：Shopify，BigCommerce，Volution，3Dcart，...），但预计Magento仍将在2018年取得领先。</span></p>
<p class="graf graf--p graf-after--p"><em>以下是Magento如此独特以及电子商务行业最受欢迎的一些原因：</em></p>
<h2 class="graf graf--h3 graf-after--p" id="ba7b"><span>Magento专为电子商务而设计</span></h2>
<p class="graf graf--p graf-after--p" id="5f8f"><span><span>Magento向我们提供全面的电子商务解决方案，不仅为客户提供良好的体验，还为开发人员和商店管理员提供了绝佳的体验。</span><span>在过去的几年中，从Magento 1到Magento 2，我们都看到了一个功能丰富的电子商务平台，预装了所有基础工具，用于构建完美的电子商务商店。</span></span></p>
<p><img alt="magento电子商务" class="aligncenter size-full wp-image-5852" height="1090" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-ecommerce.jpg" width="1920" /></p>
<h2 class="graf graf--h3 graf-after--p" id="1359"><span>Magento是一个开源的电子商务平台</span></h2>
<p class="graf graf--p graf-after--h3" id="26c0"><span><span>你可能知道，Magento是开源的，这意味着它是一个结合了PHP和其他开源工具的免费平台。</span><span>因此，Magento已经比竞争对手有了巨大的优势。</span></span></p>
<p class="graf graf--p graf-after--h3"><span>此外，由于开源，Magento具有很强的适应性，并且易于定制以满足各种项目需求。</span></p>
<p class="graf graf--p graf-after--p" id="835c"><span>更重要的是，该平台可为商店带来强大的性能和最大的安全性。</span></p>
<p><img alt="magento开源电子商务平台" class="aligncenter size-full wp-image-5858" height="208" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-open-source-e-commerce-platform.png" width="648" /></p>
<h2 class="graf graf--h3 graf-after--p" id="c8dc"><span>Magento是快速和可扩展的</span></h2>
<p class="graf graf--p graf-after--h3"><span>如果您希望网页加载速度很快，那么没有电子商务平台可以比Magento做得更好。</span></p>
<p class="graf graf--p graf-after--p" id="2390"><span>由于高端缓存技术，您的Magento商店将显著加速。</span></p>
<p class="graf graf--p graf-after--p" id="006c"><span><span>有些人认为Magento只适合大中型企业，但事实并非如此。</span><span>该平台适用于所有中小型企业，因为它非常灵活，并且在业务变得巨大时能够与您的业务共同发展。</span><span>您可能会对其性能，稳定性和可靠性感到惊讶。</span></span></p>
<p><img alt="magento快速页面加载" class="aligncenter size-full wp-image-5853" height="623" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-fast-page-load.jpg" width="1540" /></p>
<h2 class="graf graf--h3 graf-after--p" id="e30f"><span>Magento默认响应式</span></h2>
<p class="graf graf--p graf-after--h3" id="aa68"><span>Magento整合了HTML5，使您的商店能够很好地展现在任何客户的设备上，从台式机，笔记本电脑，平板电脑到智能手机。</span></p>
<p><img alt="magento反应" class="aligncenter size-full wp-image-5849" height="550" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-responsive.png" width="1903" /></p>
<h2 class="graf graf--h3 graf-after--p" id="35a0"><span>大量的Magento扩展</span></h2>
<p class="graf graf--p graf-after--p" id="460e"><span><span>所有关注Magento的用户关键之一是巨大的Magento扩展和模块市场。</span><span>很容易找到并安装Magento插件来增强商店功能。</span></span></p>
<p><img alt="magento扩展" class="aligncenter size-full wp-image-5850" height="551" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-extensions.png" width="1904" /></p>
<h2 class="graf graf--h3 graf-after--p" id="7b4e"><span>允许多个商店</span></h2>
<p class="graf graf--p graf-after--h3" id="ff17"><span><span>尽管大多数电子商务平台只允许您每个帐户只有一家商店，但Magento可让您通过一个后端/管理面板进行设置管理多家商店。</span><span>因此，您可以同时控制所有商店的库存，订单，帐单和客户信息。</span></span></p>
<p class="graf graf--p graf-after--p" id="57f1"><span>此外，由于每个商店可能有不同的主题，您可以为每个商店分配一个子域。</span></p>
<p><img alt="magento多个商店" class="aligncenter size-full wp-image-5851" height="250" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-multiple-stores.jpg" width="410" /></p>
<h2 class="graf graf--h3 graf-after--p" id="9cf8"><span>易与第三方集成</span></h2>
<p class="graf graf--p graf-after--h3" id="b0b7"><span>Magento允许无限集成第三方组件，因此有助于大幅缩短开发和部署时间。</span></p>
<p class="graf graf--p graf-after--p" id="05d0"><span><span>此外，由于Magento中的可扩展API，您可以无任何障碍地连接到任何应用程序或插件。</span><span>无论是追踪工具，支付网关还是运输或分析工具，您需要做的只是找到扩展并将其安装到您的Magento商店中。</span></span></p>
<p><img alt="Magento的-API的集成" class="aligncenter size-full wp-image-5848" height="326" src="https://www.tigren.com/wp-content/uploads/2018/03/Magento-API-Integration.jpg" width="848" /></p>
<h2 class="graf graf--h3 graf-after--p" id="29ac"><span>对主机没有限制</span></h2>
<p class="graf graf--p graf-after--h3" id="7ea9"><span><span>与Shopify或Volusion平台不同，Magento可让您自由选择喜欢的托管服务。</span><span>因此，您将能够选择符合您的要求和预算的最佳托管解决方案。</span><span>此外，如果您想迁移现有商店，则无论何时何地都可以，都没有限制。</span></span></p>
<p><img alt="magento托管" class="aligncenter size-full wp-image-5846" height="490" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-hosting.jpg" width="1200" /></p>
<h2 class="graf graf--h3 graf-after--p" id="bbfd"><span>Magento社区令人难以置信</span></h2>
<p class="graf graf--p graf-after--p" id="2a90"><span>由于Magento是一个流行的开源电子商务平台，已经建立了一个巨大的Magento社区，包括开发人员，代理商，店主，设计师，商业顾问，解决方案提供商和全球最终用户。</span></p>
<p><img alt="magento论坛" class="aligncenter size-full wp-image-5857" height="937" src="https://www.tigren.com/wp-content/uploads/2018/03/magento-forum.png" width="1031" /></p>
<h2 class="graf graf--h3 graf-after--p" id="9f2a"><span>结论</span></h2>
<p><span><span>正如你所看到的，Magento为我们提供了广泛的功能，以创建完美的电子商务商店。</span><span>这个平台不仅在2018年，而且在未来几年仍将是无与伦比的电子商务巨头。</span></span></p>
<p><span><span>但值得注意的是，它需要开发人员具有一定的专业开发知识才能实现有效的Magento网站。</span><span>因此，您必须更加努力地选择可靠的Magento开发公司来与之合作。</span></span></p>
<p><span><span>凭借</span><span>在Magento电子商务</span></span><span>方面6年以上的经验</span><span><span>，360Magento能够帮助您</span></span><span><span>建立</span><span><span>出色的</span></span><span>Magento商店</span><span>。</span><span>现在就</span></span><a href="http://www.360magento.com/contacts/"><span>联系我们</span></a><span>，为您的项目获取免费报价。</span></p>]]></description>
      <pubDate>Thu, 29 Mar 2018 02:58:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2开源版(社区版)和商业版(企业版)的区别比较]]></title>
      <link>https://www.360magento.com/blog/ce-vs-ee/</link>
      <description><![CDATA[<div class="et_pb_column et_pb_column_4_4  et_pb_column_0">
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_1">
<h2><span>我们一直听到客户这样的问题：</span></h2>
<p><em>&ldquo;社区版（CE）和企业版（EE）有什么区别？&rdquo;</em></p>
<p><em>&ldquo;Magento2与1有什么关系？&rdquo;</em></p>
<p><em>&ldquo;我需要哪一个？&rdquo;</em></p>
<p><span>一旦我们通过他们的第一组问题来谈论他们，接下来的问题就是：</span></p>
<p><em>&ldquo;使用CE和EE创建Magento2网站各自的成本是多少？&rdquo;</em></p>
<p><em>&ldquo;'我为什么要选择付费版本而不是免费版本呢？&rdquo; &nbsp;</em></p>
<p><em>&ldquo;如果我在CE上使用扩展，可以在EE上使用吗？&rdquo;</em></p>
<p><span><span><span>如果不深入了解您的业务，很难在短时间内回答这些问题。</span><span>每个商家都是独一无二的，每个商家都有一套独特的需求，但我们可以详细介绍CE和EE之间的一些关键区别，因此商家在与我们或其他开发人员进行深入通话之前，可以更好地了解从哪里开始。</span></span></span></p>
</div>
</div>
<div class=" et_pb_row et_pb_row_1">
<div class="et_pb_column et_pb_column_4_4  et_pb_column_1">
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_2">
<h3><span>Magento 1 vs Magento 2</span></h3>
<p><span><span>我们详细介绍了M1与M2的区别，以及为什么M2如此强大并值得升级。阅读关于<a href="http://www.360magento.com/blog/m1-m2/" title="magento1和magento2的区别" target="_blank">这里</a></span><span><span>。</span><span>不过，下面是一张备忘单，比较了Magento 2&nbsp;</span></span></span><strong>在</strong><span><span><span>CE和EE上</span></span><span><span>对Magento 1的主要优势</span></span></span><span>。</span></p>
</div>
<div class="et_pb_module et_pb_toggle et_pb_toggle_open  et_pb_toggle_0 et_pb_toggle_item">
<h5 class="et_pb_toggle_title"><span>新的Magento 2（</span>包括Magento 2 CE和EE）功能优化</h5>
<div class="et_pb_toggle_content clearfix">
<table style="width: 849px;">
<tbody>
<tr>
<td><strong><span><span>功能</span></span></strong></td>
<td><strong><span><span>M2社区版（CE）</span></span></strong></td>
<td><strong><span><span>M2企业版（EE）</span></span></strong></td>
</tr>
<tr>
<td><span><span><span>搜索引擎优化</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>现场管理</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>目录管理</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>目录浏览</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>产品浏览</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>结帐，付款和运送</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>订单管理</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>客户账户</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>客户服务</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>国际支持</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>分析和报告</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>移动商务</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>本机设备应用程序</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>营销，促销和转换工具</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_3">
<h3><span>Magento 2的新扩展程序</span></h3>
<p><span><span><span>当Magento 2推出时，Magento也改变了商家访问扩展的方式。</span><span>商家可以访问</span></span></span><a href="https://marketplace.magento.com/">Magento Marketplace</a><span><span><span>以访问数百个扩展。</span><span>扩展分为以下几类：会计与金融，市场营销，内容与定制，客户支持，付款与安全，报告与分析，销售，运输与配送以及网站优化。 &nbsp;</span></span></span></p>
<p><span><span><span>许多扩展是免费的，但有些可能需要花费数百甚至数千美金。最</span><span>重要是要考虑质量，可靠性和可用性的扩展支持。</span><span>市场的好处是，所有的扩展都通过扩展质量程序进行了审查和测试。</span></span></span></p>
</div>
</div>
</div>
<div class=" et_pb_row et_pb_row_2">
<div class="et_pb_column et_pb_column_4_4  et_pb_column_2">
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_4">
<h2><span>Magento2社区企业版可以提供什么。</span></h2>
<p><span><span><span>站在商家的角度考虑，我们推荐Magento 2企业版而不是Magento 1企业版。</span><span>在Magento 1中，商家购买EE的兴趣不大。</span><span>社区没有足够的额外功能让企业值得投资。</span><span>值得注意的是，我们看到CE上的许多商家利用扩展来获得EE的力量而没有价格标签。</span><span>这对一些人有效，但管理和维护一个健康的网站可能会很棘手。</span><span>那些M1扩展网站可能会造成一些昂贵且耗时问题。</span></span></span></p>
<p><span><span><span>但是，Magento 2 Enterprise并非如此。</span><span>Magento2企业版包含了最新的和许多令人兴奋的开箱即用功能 - 不需要复杂的扩展！</span></span></span></p>
</div>
<div class="et_pb_module et_pb_toggle et_pb_toggle_open  et_pb_toggle_1 et_pb_toggle_item">
<h5 class="et_pb_toggle_title"><span>Magento 2 EE功能与CE版本</span></h5>
<div class="et_pb_toggle_content clearfix">
<table>
<tbody>
<tr>
<td><strong><span><span>功能</span></span></strong></td>
<td><strong><span><span>M2社区版（CE）</span></span></strong></td>
<td><strong><span><span>M2企业版（EE）</span></span></strong></td>
</tr>
<tr>
<td><span><span><span>客户细分，有针对性的促销和销售</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>基于动态规则的产品关系</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>持久购物</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>自动电子邮件营销提醒</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>私人销售</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>礼品登记</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>赠送选项</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>奖励积分</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>商店积分</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>多个愿望清单</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>由SKU添加到购物车</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>退货管理授权（RMA）</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>内容管理系统</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>计划导入/导出功能</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>备份和回滚</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>内容的分段，合并和回滚</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>客户属性管理</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>网站和商店级别的管理员权限角色</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>价格和促销权限</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>记录管理员操作</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>每个客户组的类别查看和购买权限（限制目录访问）</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>订单归档</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>Solr搜索</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>全页面缓存</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>优化索引</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>可配置的订单追踪小工具</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>支持备用媒体存储 - CDN和数据库</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>PA-DSS认证/支付桥梁</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
<tr>
<td><span><span><span>强大的数据加密，散列和密钥管理</span></span></span></td>
<td><span><span><span>没有</span></span></span></td>
<td><span><span><span>是</span></span></span></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_5"><span><span><span>除了上面详细介绍的M2 EE功能之外，商户还可以全天候获得技术支持。</span><span>这包括专注于帮助您从Magento商店获得最佳效果的专门客户经理。</span></span></span></div>
</div>
</div>
<div class=" et_pb_row et_pb_row_3">
<div class="et_pb_column et_pb_column_4_4  et_pb_column_3">
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_6">
<h2><span>Magento2企业版费用及价格如何计算？</span></h2>
<p><span>Community Edition是Magento的免费版本 - 使用该平台不需要额外费用。</span></p>
<p><span>企业版是Magento的付费选项 - 总费用因商家收入而异。</span></p>
<div class="fusion-table table-1">
<table style="width: 100%;">
<tbody>
<tr>
<td width="156"><strong>收入(美元)</strong></td>
<td width="172"><strong>授权费用(每年) (美元)</strong></td>
<td width="139"><strong>百分比</strong></td>
</tr>
<tr>
<td width="156">0 &ndash; 100万</td>
<td width="172">22K</td>
<td width="139">min&nbsp; 2.2%</td>
</tr>
<tr>
<td width="156">1百万 &ndash; 5百万</td>
<td width="172">32K</td>
<td width="139">3.2% &ndash; 0.64%</td>
</tr>
<tr>
<td width="156">5百万 &ndash; 1千万</td>
<td width="172">49K</td>
<td width="139">0.98% &ndash; 0.49%</td>
</tr>
<tr>
<td width="156">1千万 &ndash; 2.5万</td>
<td width="172">75K</td>
<td width="139">0.75% &ndash; 0.3%</td>
</tr>
</tbody>
</table>
</div>
<p><span>特别是EE，</span><span><span><span>商店的商品销售总额（GMV）越高，年费就越高。</span><span>考虑到这一点，大商人通常认为EE的好处值得投资。</span><span>较小的商户通常首先利用免费的社区版，直到他们可以增加销售额，以证明企业的投资。</span></span></span></p>
<p><span><span><span>但是，考虑到CE与EE之间的关系，重要的是还要计算投资扩展的成本。</span><span>不仅要考虑扩展的总体成本，还要考虑安装，设置和配置所需的时间，其中包括确保所有扩展都能很好地协同工作。</span><span>随着时间的推移，更新和维护扩展也要不断的花费。</span></span></span></p>
<p><span><span><span>虽然从CE和一些扩展开始可能更经济，但重要的是要考虑长期的商业计划。</span><span>如果在接下来的几年中，需要安装数十个扩展才能获得所需的完整功能，那么从一开始就投入EE可能是值得的。</span></span></span></p>
</div>
</div>
</div>
<div class=" et_pb_row et_pb_row_4">
<div class="et_pb_column et_pb_column_1_2  et_pb_column_4">
<div class="et_pb_text et_pb_module et_pb_bg_layout_light et_pb_text_align_left  et_pb_text_7">
<h3><span>什么版本的Magento最适合你？</span></h3>
<p><span><span><span>M2 EE和CE的简要概述是为了在早期阶段帮助商家研究和规划。</span><span>我们非常乐意与商家交谈，了解他们的未来个人需求和目标。</span><span>特别是当他们正在考虑重大的M2升级或像企业一样的投资时。</span><span>我们希望帮助确保商家做出他们感到有信心的决定，并且不会后悔。</span><span>Magento是一个明智的商业投资，如果做得适当，可以带来极大的回报。</span></span></span></p>
<p><span><a href="http://www.360magento.com/contacts/"><span><span>联系我们</span></span></a><span><span>&nbsp;&nbsp;以获取更多关于Magento 2 CE和EE的信息，我们将安排时间回答您的所有问题。</span></span></span></p>
</div>
</div>
</div>]]></description>
      <pubDate>Tue, 20 Mar 2018 13:16:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2认证考试已准备就绪]]></title>
      <link>https://www.360magento.com/blog/m2-cert-ready/</link>
      <description><![CDATA[<p>期待已久，Magento2认证专业开发人员考试已经启动。自2016年我们开始第一个magento2项目时，我们就一直等待这个认证考试。所有的客户都希望自己的项目能与magento认证开发人员合作，<span>它为他们提供了可持续性和高质量的感觉。2011年的时候我们公司参与首批Magento认证考试并斩获5位认证开发人员，在他们的带领下，公司声誉及项目质量得到了极大的提高。此外Magento2的认证考试启动，我们将依靠magento认证考试来简化我们的招聘过程。</span></p>
<p><span>Magento 2认证专业开发人员考试是一种主要基于场景的考试，旨在验证在以下领域对Magento 2进行定制所需的技能和知识：UI修改，数据库更改，管理员修改，结帐流程定制，订单管理集成和定制，目录结构和功能的变化。</span><span>这门考试适用于对Magento 2开发概念和经验（推荐1.5年）有深入理解的Magento 2开发人员，可以实现自定义和定制Magento 2。</span></p>
<p></p>
<h4><span>关于考试</span></h4>
<ul>
<li><span>60多项选择项目</span></li>
<li><span>90分钟完成考试</span></li>
<li><span>基于Magento开源（2.2）和Magento Commerce（2.2），适用于那些使用过任何版本的Magento 2。</span></li>
</ul>
<p></p>
<p><span>Magento U已经分享了</span><a href="https://u.magento.com/free-study-guide" title="Magento 2认证专业开发考试学习指南" target="_blank"><span><span>Magento 2认证专业开发考试学习指南</span></span><span class="fa fa-external-link"></span></a></p>
<p><span><span>对于前端开发人员来说，要通过Magento 2 Certified Frontend-Developer考试，你必须等到5月份。</span><span>所以你有一些时间来提高你的技能来实现这个吸引人的徽章。</span></span></p>
<p><span>如此纯粹的指导，购买考试券（260美金），找到一个考试中心，注册参加考试并为自己挑战;）</span></p>
<p><span>PS：你最多可以重试4次这个考试。</span></p>
<p></p>]]></description>
      <pubDate>Mon, 19 Mar 2018 13:11:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为什么要升级到Magento2?]]></title>
      <link>https://www.360magento.com/blog/why-m2/</link>
      <description><![CDATA[<p>1.Magento 1官方将支持到2018年12月。当Magento停止支持Magento 1的过程时，他们将停止发布重要的安全补丁，因此所有安全风险将成为您的责任</p>
<p>2.维护和增强Magento 1商店的成本将在一段时间内增加</p>
<p>3.2016年已停止为Magento 1平台开发新功能</p>
<p>4.与Magento 1相比，Magento 2具有更好的安全性</p>
<p>5.Magento 1基于旧版本的PHP（5.6或更低），而Magento 2支持PHP 7，充分发挥其性能优势。正确的配置和正确的基础架构设置将使Magento 2上的网上商店性能比Magento 1好得多</p>
<p>6.Magento 2的结账速度快了38％，能够比Magento 1的订单多出117％的订单</p>
<p>7.Magento 2内置了全页面缓存和Varnish 4 支持</p>
<p>8.Magento2的后台管理界面人性化，它允许甚至不懂技术的用户处理Web商店管理</p>
<p>9.通过Magento 2管理面板产品创建工作流程更简单</p>
<p>10.主题响应式和移动设备支持是Magento 2的核心</p>
<p>11.Magento 2具有广泛的响应和搜索引擎优化友好的主题和综合视频</p>
<p>12.更方便用户使用Magento 2.结账步骤更少 -顾客完成结账的机会更多</p>
<p>13.Magento 2支持更多支付选项和网关</p>
<h2>这一举措 - 顺利还是痛苦？</h2>
<p>magento官方发布了一个<a href="http://devdocs.magento.com/guides/v2.2/migration/bk-migration-guide.html" rel="nofollow">迁移工具</a>，可以帮你平滑的迁移数据（商店设置，产品，客户，订单，促销规则......）</p>
<p>但是，正如那里清楚地指出的那样，主题和代码自定义（包括第三方扩展）将不可转移，这意味着它们需要在Magento 2上重做。</p>
<p>因此，需要在前端界面和功能开发方面进行额外投资。在我看来，这应该被视为一件好事，因为：</p>
<ol>
<li>它可以给你一些新的想法，让你重新思考你的整个业务</li>
<li>你将能够摆脱一些遗留代码</li>
<li>您可以提高网站的整体可用性</li>
</ol>
<p>让我们面对现实 - 如果您的商店有50多个扩展程序（根据我们近期的一些经验，甚至比这还多），Magento 2可能成为一个救生员，因为它可以让您重新思考和希望以更好的方式重做。带给客户一个崭新的更好用户体验的商店。</p>
<p>如果您需要任何帮助为您的业务计划下一步，请告诉我们。</p>
<h2>我应该什么时候升级到MAGENTO 2？</h2>
<p>这很大程度上取决于您当前的网站和当前的状况 - 底线是，如果您的网站运行良好（顺利运行，订单很多...），并且您使用的版本不是非常过时（任何在CE1.8 和EE1.13之前的版本会被认为相当过时），但并不急于求成，您可以（也应该）开始探索Magento 2，请求您的解决方案合作伙伴结合您自己的想法并开始制定一些基本计划。</p>
<p>如果您使用的是旧版本的软件，甚至是较新的版本，但出现严重的性能问题，并且最重要的是您已经安装了多个第三方扩展程序，现在将是计划进行升级的好时机。</p>
<p>如果您需要认真做一些事情来显著提高商店的性能，那么您绝对应该启动Magento 2升级计划。</p>
<h2>谁在使用Magento 2？</h2>
<p>ninewest.co.uk Shop.landroverusa.com Shop.jaguarusa.com shopworld.seat.de Shop.jazzercise.com Rogersandhollands.com Scufgaming.com Oliversweeney.com Sassandbide.com Pumpunderwear.com Stoneandstrand.com Danarebeccadesigns.com Eberjey.com Shop.dilmahusa.com H2oplus.com alcatelonetouch.us Thehundreds.com Shoei-helmets.com Kingsouq.com graze.com</p>]]></description>
      <pubDate>Thu, 15 Mar 2018 08:55:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2有哪些优势？magento1和magento2有哪些区别不同？]]></title>
      <link>https://www.360magento.com/blog/m1-m2/</link>
      <description><![CDATA[<p>2016年整个圈子都在讨论一个热门话题magento2，我们也完成了比较性能测试并总结了评测结果 - Magento 2与Magento 1相比的优缺点。老实说，在那一刻，我们对结果感到失望，因为所有得出的数字不支持最新版本。但现在，magento已升级到2.2.3,其表现结果是令我们满意的，我们强烈建议考虑迁移到Magento 2。</p>
<h2>性能提升</h2>
<p>页面加载时间减少超过50％。它对那些经常在你的商店浏览购买的顾客有很好的体验。人们对页面加载时间变得越来越敏感，因此Magento 2的性能改进可以让访问者留在网站上。 如果一个电子商务网站每天赚10万美元，1秒的页面延迟可能会让你每年损失250万美元的销售额。- Kissmetrics 此外，它使您的电子商务商店对搜索引擎更具吸引力。</p>
<h2>用户友好方式</h2>
<p>改进了Magento 2后端管理UX界面。如果您熟悉Magento 1.x管理，您将会对新的界面视图感到满意。这个新的管理面板具有用户友好的界面，使管理过程直观清晰和简单。 - 响应式和触摸友好的导航 - 简单的产品创建工作流程 - 拖放布局编辑 - 4倍的产品导入能力</p>
<h2>新购物者体验特性</h2>
<p>实现高度个性化的购物体验是Magento 2平台的主要目标之一。它采用新的响应式设计参考主题，客户购物车中的产品图像以及更多种类的付款方式成功实施。</p>
<h2>简化结账</h2>
<p>以最少的步骤和所需的信息优化结账流程，让您的客户购买更快更轻松。</p>
<h2>灵活的架构</h2>
<p>下一代架构为您的网上商店提供了前所未有的灵活性。因为它具有模块化的代码库，所以很容易定制您的电子商务系统。它节省了上线时间并优化了部署流程。 更快地连接，操作和扩展任何主题或扩展。更广泛和高效的API将关注这些。</p>
<h2>时髦技术</h2>
<ol>
<li>PHP 7</li>
<li>Varnish(全页面缓存可实现更快的开箱即用性能)</li>
<li>Redis</li>
<li>现代JS堆栈</li>
<li>RabbitMQ</li>
<li>Solr</li>
<li>PHPUnit</li>
<li>Composer (用于管理依赖)</li>
</ol>
<h2>框架改进</h2>
<p>主要代码重构，以摆脱系统中的所有混乱 - 主要数据网格增强 - 现在可以为Magento应用程序启用/禁用模块 - 兼容HHVM和PHP 7</p>
<h2>高质量扩展</h2>
<p>Magento将Magento Connect重新整合到只提供高质量扩展的新Magento Marketplace中，因为要成为这个新的magento模块商店的开发公司，所有第三方解决方案都必须通过5级质量检查。</p>
<h2>平台季度更新</h2>
<p>每3个月Magento 2发布社区版和企业版的新功能</p>
<p><a href="http://www.360magento.com" title="magento2定制开发">Magento2定制开发</a>认准老品牌开发商360Magento</p>]]></description>
      <pubDate>Thu, 15 Mar 2018 04:03:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento首席执行官说，“每一个企业战略都是数字战略”]]></title>
      <link>https://www.360magento.com/blog/digital01/</link>
      <description><![CDATA[<p><span class="author vcard hidden"><span class="fn"></span></span><span class="updated hidden"></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">据电子商务平台Magento首席执行官Mark Lavelle称，如果有任何组织没有受到数字化转型的影响，那么很少有公司会这样做。</span><span style="vertical-align: inherit;">他认为，数字化转型现在是每个人都面临的问题，组织采取的良好做法是遵循成功模式。</span></span></p>
<div class="vw-post-content clearfix">
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">正在发生的</span></span>数字转型现正在影响每一个行业，&rdquo;<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavelle</span></span>上周在悉尼举行的澳大利亚Magento Live 2018活动中表示。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;这是因为<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">现在</span></span>吸引和留住客户是数字行为。</span><span style="vertical-align: inherit;">我们把时间花在银幕上，社交媒体上，你的品牌必须超越的各个地方。&ldquo;</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavelle还指出节省成本和效率的重大收益，特别是对于B2B企业。</span><span style="vertical-align: inherit;">最终，这意味着数字化转型已成为每个组织的一个问题，成功意味着适应性<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">更</span></span>强，以客户为中心的业务。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavelle表示，Magento电子商务平台每年处理大约1,550亿美元的商品总量，显示出数字化转型的广泛影响和需求。</span></span></p>
<h3><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">按照收入</span></span></h3>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">根据引用IDC研究的Lavell的说法，公司正在迎头赶上，他们认为全球2000强企业中超过半数认为其收入依赖于数字体验。</span></span></p>
<img alt="" class=" wp-image-34662" height="348" src="https://images.which-50.com/wp-content/uploads/2016/11/Magento-Mark_Lavelle-COLOR-1.jpg" width="219" /><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Magento首席执行官Mark Lavelle</span></span>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;世界上大多数大的企业都认为这是他们收入的增长点。</span><span style="vertical-align: inherit;">所以，[它]远离实验阶段[它]是非常真实的。</span><span style="vertical-align: inherit;">每个企业都意识到，他们的企业战略实际上是一种数字战略，他们首先得从头开始。&ldquo;</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavell说，数字化的焦点正在被买家的期望&ldquo;推向顶峰&rdquo;。</span><span style="vertical-align: inherit;">消费者现在拥有前所未有的信息，包括价格和库存透明度。</span><span style="vertical-align: inherit;">&ldquo;他们希望<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">作为品牌</span></span>能够全天候<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">365</span></span>天与您进行互动。&rdquo;</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavell还提到&ldquo;亚马逊效应&rdquo;，供应和交付链已经完善到&ldquo;事情可以立即完成&rdquo;的地步。</span><span style="vertical-align: inherit;">根据Lavell的说法，尽管这在B2C交易中最容易看到，但它对于B2B买家来说日益重要。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">消费者期望值的提高意味着组织必须&ldquo;不断前进&rdquo;并愿意尝试。</span><span style="vertical-align: inherit;">&ldquo;你必须弄清楚你的客户下一步想要什么，他们将采用什么新的创新。</span><span style="vertical-align: inherit;">因为他们将快速采用它们。&ldquo;</span></span></p>
<h3><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">成功模式</span></span></h3>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Magento产品的本质意味着Lavell亲眼目睹数字化转型。</span><span style="vertical-align: inherit;">他说随着时间的推移，他注意到了某些模式和数字转换的真相。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;一旦组织对这四件事情感到满意，那就是当我们看到真正的数字化转变发生时，&rdquo;<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavell</span></span>说。</span></span></p>
<p><strong><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">1.大胆品牌</span></span></strong></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;你必须有一个能够切入的品牌，&rdquo;<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavell</span></span>解释道。</span><span style="vertical-align: inherit;">虽然在数字时代之前这是真的，但是这个要求变得越来越重要，据Lavell说。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;你走进一个组织，你可以判断整个品牌是否将转向数字化转型，或者这只是一个侧面项目。&rdquo;</span></span></p>
<p><strong><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">2.首先拥抱数字</span></span></strong></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">Lavell</span></span></span></span>说，真正的转型是文化，它意味着打破孤岛，必须从顶端来。</span><span style="vertical-align: inherit;">Lavelle表示，这是一项重要的事业，为其中之一就是公司丛生存到快速发展。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;你可能必须改变你组织的方式，以便进行完整的数字化转型。</span><span style="vertical-align: inherit;">当我们看到公司接受它时，它很快就会成为一种竞争优势。&ldquo;</span></span></p>
<p><strong><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">3.增加业务灵活性。</span></span></strong></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&ldquo;你不会购买某些技术或平台期望它保持相同的方式。</span><span style="vertical-align: inherit;">这是一个错误。</span><span style="vertical-align: inherit;">这就是我们10-15年前做事情的方式，&ldquo;拉维尔说。</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">根据lavelle的说法，当今的趋势意味着选择灵活和可扩展技术至关重要。</span><span style="vertical-align: inherit;">在Magento，他们称之为&ldquo;拥有玻璃&rdquo; - 参考客户的互动主要在屏幕上出现。</span><span style="vertical-align: inherit;">根据拉维尔的说法，灵活性意味着他们可以通过各种渠道满足客户的需求，包括那些尚不明显的渠道。</span></span></p>
<p><strong><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">4.通过独创性创新</span></span></strong></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">拉维尔说，最终的数字化转型事实是&ldquo;人为因素&rdquo;。</span><span style="vertical-align: inherit;">拉维尔说，企业迫切需要创新和创造力。</span><span style="vertical-align: inherit;">&ldquo;我们发现，这些开放式的创新方法往往会使大企业通过这些类型的变革。&rdquo;</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">他说，虽然公司通常没有这种内部人力资源，但Magento开发商提供解决方案的社区平台是一个很好的选择。比如360Magento专注Magento开发长达10年，其技术实力和信誉值得信赖。</span></span></p>
</div>]]></description>
      <pubDate>Wed, 14 Mar 2018 02:54:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[发现最新的Magento Imagine 2018发言人]]></title>
      <link>https://www.360magento.com/blog/imagine2018/</link>
      <description><![CDATA[<div class="row-fluid">
<h1><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">发现最新的Imagine 2018发言人</span></span></h1>
</div>
<div class="row-fluid">
<div class="span12">
<p class="blog-date"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">&nbsp;</span></span></p>
</div>
</div>
<div class="row-fluid">
<div class="span7">
<div class="field-name-field-blog-tags field-label-inline"></div>
</div>
<div class="span5">
<div class="share-buttons"><!-- ShareThis Button BEGIN --> <span class="st_facebook_custom"> <span class="fa-stack fa-lg"> <em class="fa fa-circle fa-stack-2x"></em> <em class="fa fa-facebook fa-stack-1x"></em> </span> </span> <span class="st_twitter_custom"> <span class="fa-stack fa-lg"> <em class="fa fa-circle fa-stack-2x"></em> <em class="fa fa-twitter fa-stack-1x"></em> </span> </span> <span class="st_linkedin_custom"> <span class="fa-stack fa-lg"> <em class="fa fa-circle fa-stack-2x"></em> <em class="fa fa-linkedin fa-stack-1x"></em> </span> </span> <span class="st_googleplus_custom"> <span class="fa-stack fa-lg"> <em class="fa fa-circle fa-stack-2x"></em> <em class="fa fa-google-plus fa-stack-1x"></em> </span> </span> <span class="st_email_custom"> <span class="fa-stack fa-lg"> <em class="fa fa-circle fa-stack-2x"></em> <em class="fa fa-envelope fa-stack-1x"></em> </span> </span> <!-- ShareThis Button END --></div>
</div>
</div>
<div class="row-fluid">
<div class="span12 article-image">
<div class="video-wrapper">
<div class="field field-name-field-video field-type-video-embed-field field-label-hidden">
<div class="field-items">
<div class="field-item even">
<div class="embedded-video">
<div class="player">
<script src="//fast.wistia.com/embed/medias/2jgzrbtay1.jsonp" type="text/javascript"></script>
<script src="//fast.wistia.com/assets/external/E-v1.js" type="text/javascript"></script>
<div class="wistia_responsive_padding wistia_embed" style="padding: 56.25% 0 0 0; position: relative;">
<div class="wistia_responsive_wrapper" style="height: 100%; left: 0; position: absolute; top: 0; width: 100%;">
<div class="wistia_embed wistia_async_2jgzrbtay1 videoFoam=true wistia_embed_initialized" id="wistia-2jgzrbtay1-1" style="height: 433px; width: 770px;">
<div class="w-chrome" id="wistia_chrome_29" style="display: inline-block; height: 433px; margin: 0px; padding: 0px; position: relative; vertical-align: top; width: 770px; zoom: 1; outline: none; overflow: hidden; box-sizing: content-box;">
<div id="wistia_grid_35_wrapper" style="display: block; width: 770px; height: 433px;">
<div id="wistia_grid_35_above" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
<div id="wistia_grid_35_main" style="width: 770px; left: 0px; height: 433px; margin-top: 0px;">
<div id="wistia_grid_35_behind"></div>
<div id="wistia_grid_35_center" style="width: 100%; height: 100%;">
<div class="w-video-wrapper w-css-reset" style="height: 100%; position: absolute; top: 0px; width: 100%; background-color: #000000;"><video id="wistia_simple_video_69" width="320" height="240" style="background: transparent; display: block; height: 100%; position: static; visibility: visible; width: 100%; object-fit: fill;" crossorigin="anonymous" poster="https://fast.wistia.com/assets/images/blank.gif" src="blob:https://magento.com/f6407030-9d87-496e-9683-e60661f54159" controlslist="nodownload" playsinline="" preload="metadata" type="video/m3u8" x-webkit-airplay="allow"></video></div>
<div class="w-ui-container" style="height: 100%; left: 0px; position: absolute; top: 0px; width: 100%;">
<style type="text/css"><!--
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset{font-size:14px;}
#wistia_chrome_29 #wistia_grid_35_wrapper div.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper span.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper ul.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper li.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper label.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper button.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper img.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper a.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper svg.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper p.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper a.w-css-reset{border:0;}
#wistia_chrome_29 #wistia_grid_35_wrapper p.w-css-reset{margin:1.4em 0;}
#wistia_chrome_29 #wistia_grid_35_wrapper a.w-css-reset{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper span.w-css-reset{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper svg.w-css-reset{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper ul.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper ol.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper li.w-css-reset{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper ul:before.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper ol:before.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper li:before.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper ul:after.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper ol:after.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper li:after.w-css-reset{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper label.w-css-reset{background-attachment:scroll;background-color:transparent;background-image:none;background-position:0 0;background-repeat:no-repeat;background-size:100% 100%;float:none;outline:none}
#wistia_chrome_29 #wistia_grid_35_wrapper button.w-css-reset{background-attachment:scroll;background-color:transparent;background-image:none;background-position:0 0;background-repeat:no-repeat;background-size:100% 100%;border:0;border-radius:0;outline:none;position:static}
#wistia_chrome_29 #wistia_grid_35_wrapper img.w-css-reset{border:0;display:inline-block;vertical-align:top;border-radius:0;outline:none;position:static}
      #wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree {font-size:14px;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree div{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree span{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ul{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree li{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree label{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree button{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree img{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree a{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree svg{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree p{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree a{border:0;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree p{margin:1.4em 0;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree a{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree span{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree svg{display:inline;}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ul{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ol{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree li{box-sizing:inherit;box-shadow:none;color:inherit;display:block;float:none;font:inherit;font-family:inherit;font-style:normal;font-weight:normal;font-size:inherit;letter-spacing:0;line-height:inherit;margin:0;max-height:none;max-width:none;min-height:none;min-width:none;padding:0;position:static;text-decoration:none;text-transform:none;text-shadow:none;transition:none;word-wrap:normal;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;-webkit-font-smoothing:antialiased;list-style-type:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ul:before{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ol:before{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree li:before{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ul:after{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree ol:after{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree li:after{display:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree label{background-attachment:scroll;background-color:transparent;background-image:none;background-position:0 0;background-repeat:no-repeat;background-size:100% 100%;float:none;outline:none}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree button{background-attachment:scroll;background-color:transparent;background-image:none;background-position:0 0;background-repeat:no-repeat;background-size:100% 100%;border:0;border-radius:0;outline:none;position:static}
#wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-tree img{border:0;display:inline-block;vertical-align:top;border-radius:0;outline:none;position:static}
      #wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-max-width-none-important{max-width:none!important}
      #wistia_chrome_29 #wistia_grid_35_wrapper .w-css-reset-button-important{border-radius:0!important;color:#fff!important;}
--></style>
<div class="w-vulcan-v2 w-css-reset" id="w-vulcan-v2-34" style="box-sizing: border-box; cursor: default; height: 100%; left: 0px; position: absolute; visibility: visible; top: 0px; width: 100%;">
<div class="w-vulcan--background w-css-reset" style="height: 100%; left: 0px; position: absolute; top: 0px; width: 100%;">
<div class="w-css-reset" style="pointer-events: auto;" data-handle="statusBar"></div>
<div class="w-css-reset" style="pointer-events: auto;" data-handle="thumbnail"><img alt="视频缩略图" class="w-css-reset" src="https://embedwistia-a.akamaihd.net/deliveries/aae13a4c189da94604c47bfe36536131261e2177.jpg?image_crop_resized=960x540" style="border-width: 0px; border-style: solid; border-color: #000000; box-sizing: content-box; height: 433px; left: 0px; top: 0px; width: 770px; display: none; visibility: hidden;" /></div>
</div>
<div class="w-vulcan-overlays-table w-css-reset" style="display: table; pointer-events: none; position: absolute; width: 100%;">
<div class="w-vulcan-overlays--left w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 0px;">
<div class="w-css-reset" style="height: 399px;"></div>
</div>
<div class="w-vulcan-overlays--center w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 100%;">
<div class="w-css-reset" style="height: 399px;">
<div class="w-css-reset" style="pointer-events: auto;" data-handle="bigPlayButton">
<div class="w-bpb-wrapper w-css-reset w-css-reset-tree" style="display: none; left: 50%; position: absolute; top: 50%; transform: translate(-50%, -50%);"></div>
</div>
<div class="w-css-reset" style="pointer-events: auto;" data-handle="clickForSoundButton">
<div class="w-css-reset w-css-reset-tree" style="display: none; height: 100%; left: 0px; pointer-events: none; position: absolute; top: 0px; width: 100%;">
<style><!--
@keyframes VOLUME_SMALL_WAVE_FLASH {
          0% { opacity: 0; }
         33% { opacity: 1; }
         66% { opacity: 1; }
        100% { opacity: 0; }
      }

      @keyframes VOLUME_LARGE_WAVE_FLASH {
          0% { opacity: 0; }
         33% { opacity: 1; }
         66% { opacity: 1; }
        100% { opacity: 0; }
      }

      .volume__small-wave {
        animation: VOLUME_SMALL_WAVE_FLASH 2s infinite;
        opacity: 0;
      }

      .volume__large-wave {
        animation: VOLUME_LARGE_WAVE_FLASH 2s infinite .3s;
        opacity: 0;
      }
--></style>
<div style="color: white; display: inline; font-family: WistiaPlayerOverpass, Helvetica, sans-serif; font-size: 13px; margin-left: -4px; width: 36%;">Click for sound<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">点击声音</span></span></div>
</div>
</div>
<div class="w-css-reset" style="pointer-events: auto;" data-handle="loadingIndicator">
<div style="display: none; height: 80px; width: 125px;">
<div style="height: 80px; left: 50%; position: absolute; top: 50%; transform: translate(-50%, -50%); width: 125px;">
<style type="text/css"><!--
#wistia_loading_svg_98 path {
        stroke-width: 2px;
        stroke-dasharray: 36.299235026041664, 72.59847005208333;
        -webkit-animation: wistia_dash 1s infinite linear forwards;
      }
      @-webkit-keyframes wistia_dash {
        from { stroke-dashoffset: 108.897705078125; }
        to { stroke-dashoffset: 0; }
      }
--></style>
</div>
</div>
</div>
<div class="w-css-reset" style="pointer-events: auto;" data-handle="playPauseNotifier">
<div class="w-play-pause-notifier" style="height: 72px; left: 50%; pointer-events: none; position: absolute; opacity: 0; top: 50%; transform: translate(-33%, -50%) scale(1.5); width: 60px; transition: opacity 0.6s, transform 0.6s;"></div>
</div>
</div>
</div>
<div class="w-vulcan-overlays--right w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 0px;">
<div class="w-css-reset" style="height: 399px;"></div>
</div>
</div>
<div class="w-bottom-bar w-css-reset" style="bottom: 0px; border-collapse: collapse; display: none; height: 34px; left: 0px; opacity: 0; pointer-events: none; position: absolute; table-layout: auto; transition: opacity 0.2s; width: 100%;">
<div class="w-bottom-bar-upper w-css-reset" style="display: none;">
<div class="w-css-reset" style="height: 100%; pointer-events: auto;" data-handle="upperPlaybar">
<div class="w-playbar-wrapper w-css-reset w-css-reset-tree" style="cursor: pointer; height: 100%; outline: none; position: relative;">
<div style="display: block; height: 100%; overflow: hidden; pointer-events: none; position: relative; width: 770px;"></div>
<div class="w-storyboard-anchor" style="height: 0px; left: 0px; position: absolute; top: 0px; width: 100%;">
<div class="w-storyboard" style="bottom: 24px; display: none; height: 84.6144px; left: 0px; overflow: hidden; pointer-events: none; position: absolute; width: 149.76px;"><img class="w-css-reset-max-width-none-important" src="https://embedwistia-a.akamaihd.net/deliveries/4c8e9b321e2973d82df8a78607762a5cd280f194.bin" style="height: 1438.44px; left: 0px; position: absolute; top: 0px; vertical-align: top; width: 1497.6px;" />
<div class="w-storyboard-time" style="background: rgba(0, 0, 0, 0.5); bottom: 0px; color: #ffffff; font-family: WistiaPlayerOverpassNumbers, Helvetica, sans-serif; font-size: 13px; height: 30px; left: 0px; line-height: 34px; position: absolute; text-align: center; width: 100%;">0:00<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:00</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:00</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:00</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:00</span></span></div>
</div>
</div>
<div class="w-playbar__hoverMarker" style="background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.12) 100%); display: none; height: 100%; left: -36px; pointer-events: none; position: absolute; top: 0px; width: 36px;"></div>
<div class="w-playbar__focus-border" style="border: 2px solid #ffffff; display: none; height: 100%; left: 0px; pointer-events: none; position: absolute; top: 0px; width: 100%;"></div>
</div>
</div>
</div>
<div class="w-bottom-bar-lower w-css-reset">
<div class="w-bottom-bar-left w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 0px;">
<div class="w-bottom-bar-left-inner w-css-reset" style="height: 34px; position: relative; white-space: nowrap;">
<div class="w-css-reset" style="display: inline-block; vertical-align: top; pointer-events: auto;" data-handle="smallPlayButton">
<div class="w-vulcan-button-wrapper w-css-reset" style="display: inline-block; height: 34px; position: relative; vertical-align: top; width: 50px;">
<div class="w-vulcan-icon-wrapper" style="box-sizing: border-box; height: 100%;" data-handle="smallPlayButton"></div>
</div>
</div>
</div>
</div>
<div class="w-bottom-bar-middle w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 100%;">
<div class="w-bottom-bar-middle-inner w-css-reset" style="height: 34px; position: relative; white-space: nowrap;">
<div class="w-css-reset" style="height: 100%; pointer-events: auto;" data-handle="lowerPlaybar">
<div class="w-playbar-wrapper w-css-reset w-css-reset-tree" style="cursor: pointer; height: 100%; outline: none; position: relative;">
<div style="display: block; height: 100%; overflow: hidden; pointer-events: none; position: relative; width: 600px;"></div>
<div class="w-storyboard-anchor" style="height: 0px; left: 0px; position: absolute; top: 0px; width: 100%;">
<div class="w-storyboard" style="bottom: 24px; display: none; height: 84.6144px; left: 139.636px; overflow: hidden; pointer-events: none; position: absolute; width: 149.76px;"><img class="w-css-reset-max-width-none-important" src="https://embedwistia-a.akamaihd.net/deliveries/4c8e9b321e2973d82df8a78607762a5cd280f194.bin" style="height: 1438.44px; left: -1347.84px; position: absolute; top: -423.072px; vertical-align: top; width: 1497.6px;" />
<div class="w-storyboard-time" style="background: rgba(0, 0, 0, 0.5); bottom: 0px; color: #ffffff; font-family: WistiaPlayerOverpassNumbers, Helvetica, sans-serif; font-size: 13px; height: 30px; left: 0px; line-height: 34px; position: absolute; text-align: center; width: 100%;">0:30<span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:32</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">0:27</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">1:17</span></span><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">1:17</span></span></div>
</div>
</div>
<div class="w-playbar__hoverMarker" style="background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.12) 100%); display: none; height: 100%; left: 178.516px; pointer-events: none; position: absolute; top: 0px; width: 36px;"></div>
<div class="w-playbar__focus-border" style="border: 2px solid #ffffff; display: none; height: 100%; left: 0px; pointer-events: none; position: absolute; top: 0px; width: 100%;"></div>
</div>
</div>
</div>
</div>
<div class="w-bottom-bar-right w-css-reset" style="display: table-cell; vertical-align: top; position: relative; width: 0px;">
<div class="w-bottom-bar-right-inner w-css-reset" style="height: 34px; position: relative; white-space: nowrap;">
<div class="w-css-reset" style="display: inline-block; vertical-align: top; pointer-events: auto;" data-handle="volumeButton">
<div class="w-vulcan-button-wrapper w-css-reset" style="display: inline-block; height: 34px; position: relative; vertical-align: top; width: 40px;">
<div class="w-vulcan-icon-wrapper" style="box-sizing: border-box; height: 100%;" data-handle="volumeButton"></div>
</div>
</div>
<div class="w-css-reset" style="display: inline-block; vertical-align: top; pointer-events: auto;" data-handle="settingsButton">
<div class="w-vulcan-button-wrapper w-css-reset" style="display: inline-block; height: 34px; position: relative; vertical-align: top; width: 40px;">
<div class="w-vulcan-icon-wrapper" style="box-sizing: border-box; height: 100%;" data-handle="settingsButton"></div>
</div>
</div>
<div class="w-css-reset" style="display: inline-block; vertical-align: top; pointer-events: auto;" data-handle="fullscreenButton">
<div class="w-vulcan-button-wrapper w-css-reset" style="display: inline-block; height: 34px; position: relative; vertical-align: top; width: 40px;">
<div class="w-vulcan-icon-wrapper" style="box-sizing: border-box; height: 100%;" data-handle="fullscreenButton"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-foreground w-css-reset" style="height: 100%; left: 0px; pointer-events: none; position: absolute; top: 0px; width: 100%;">
<div class="w-css-reset" style="pointer-events: auto;" data-handle="contextMenu"></div>
<div class="w-css-reset" style="pointer-events: auto;" data-handle="loadingHourglass"></div>
</div>
<div class="w-focus-border" style="border: 2px solid #ffffff; box-sizing: border-box; display: none; height: 100%; left: 0px; pointer-events: none; position: absolute; top: 0px; width: 100%;"></div>
</div>
</div>
</div>
<div id="wistia_grid_35_front"></div>
<div id="wistia_grid_35_top_inside">
<div id="wistia_grid_35_top" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
</div>
<div id="wistia_grid_35_bottom_inside">
<div id="wistia_grid_35_bottom" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
</div>
<div id="wistia_grid_35_left_inside">
<div id="wistia_grid_35_left" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
</div>
<div id="wistia_grid_35_right_inside">
<div id="wistia_grid_35_right" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
</div>
</div>
<div id="wistia_grid_35_below" style="height: 0px; font-size: 0px; line-height: 0px;"></div>
<style type="text/css"><!--
#wistia_grid_35_wrapper{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;font-family:Arial,sans-serif;font-size:14px;height:100%;position:relative;text-align:left;width:100%;}
#wistia_grid_35_wrapper *{-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}
#wistia_grid_35_above{position:relative;}
#wistia_grid_35_main{display:block;height:100%;position:relative;}
#wistia_grid_35_behind{height:100%;left:0;position:absolute;top:0;width:100%;}
#wistia_grid_35_center{height:100%;overflow:hidden;position:relative;width:100%;}
#wistia_grid_35_front{display:none;height:100%;left:0;position:absolute;top:0;width:100%;}
#wistia_grid_35_top_inside{position:absolute;left:0;top:0;width:100%;}
#wistia_grid_35_top{width:100%;position:absolute;bottom:0;left:0;}
#wistia_grid_35_bottom_inside{position:absolute;left:0;bottom:0;width:100%;}
#wistia_grid_35_bottom{width:100%;position:absolute;top:0;left:0;}
#wistia_grid_35_left_inside{height:100%;position:absolute;left:0;top:0;}
#wistia_grid_35_left{height:100%;position:absolute;right:0;top:0;}
#wistia_grid_35_right_inside{height:100%;right:0;position:absolute;top:0;}
#wistia_grid_35_right{height:100%;left:0;position:absolute;top:0;}
#wistia_grid_35_below{position:relative;}
--></style>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="field field-name-body field-type-text-with-summary field-label-hidden">
<div class="field-items">
<div class="field-item even">
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">看看一些精彩的主题演讲和分组会议发言人以及品牌，在这个新的视频卷轴中分享他们在Imagine 2018上的成功故事。&nbsp;</span></span></p>
<p><span style="vertical-align: inherit;"><span style="vertical-align: inherit;"><span>Imagine 2018</span>是Magento专家和创新者最大的聚会，将于4月23 - 25日在拉斯维加斯举行。</span><span style="vertical-align: inherit;">此活动是与3000多名商业专家和创新者联系的绝佳机会。</span><span style="vertical-align: inherit;">加入我们。</span></span><a href="https://imagine.magento.com/" target="_blank"><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">立即注册</span></span></a><span style="vertical-align: inherit;"><span style="vertical-align: inherit;">。</span></span></p>
<p><img alt="" src="https://static.magento.com/sites/default/files/images/8822_baked_by_melissa_announcement_social_images_blog_cta_r2_v1.jpg" style="width: 770px; height: 216px;" /></p>
</div>
</div>
</div>
</div>
</div>]]></description>
      <pubDate>Tue, 13 Mar 2018 02:49:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[论magento1和magento2的速度性能优化问题]]></title>
      <link>https://www.360magento.com/blog/magento-speed-up/</link>
      <description><![CDATA[<p>magento从2007年发展至今，也经历了十余年的磨练，如今也迎来了magento的换代产品magento2,无论从安全性，稳定性还是速度，其实都已经做的很好了。但现如今还有客户说magento速度很慢，那这类客户肯定是道听途说，自己根本就还没有搭建一个magento网站，网上说magento慢的帖子那都是10年左右的老帖子了。</p>
<p>当然了，无论是magento 1还是magento 2,它可扩展性，灵活性，系统安全性和可靠性方面处于领先地位,但是所有Magento的高级功能和特性都是以拥有大量文件和大型数据库为代价的，也正因此，从理论上来说要比其他平台速度相对慢点，微不足道的。也可以从以下方面做一些优化。</p>
<p>一、服务器的选择</p>
<p>迈向优化Magento性能的第一步应该是找到一个适合的好的Magento服务器，magento对服务器的要求一向很高，所以我建议选择独立云服务器，服务器内部优化配置自己掌控，当然这也需要专业的技术做支撑。如果有成本的限制，比如刚创业的小商家，可以找一家可靠的共享托管服务器，针对magento优化的共享服务器。我可以推荐一家专门针对magento优化的服务器托管商<a href="https://www.siteground.com/go/host-features" title="SiteGround链接地址" target="_blank">SiteGround</a>。推荐选择GoGeek套餐。这样后期如果做的好可以升级独立云服务器，节省成本。</p>
<p></p>
<p>二、数据库服务器</p>
<p>大部分网站直接把网站程序服务器和数据库服务器共用，当然这在数据量小，请求量少的情况下还是可行的，一旦数据量和数据请求量上去了，那网站的速度是非常慢的。如果遇到这种情况，我的建议是直接上RDS，不懂的可以搜索RDS,可以称之为云数据库。前不久接手了一个二手项目，用的是magento2.1.5,我还记得3月份开发的一个2.1.5版本的项目，那个痛苦啊简直不敢想象，无论是线上还是本地刷新一个页面比蜗牛还慢，而接手的这个项目竟然秒开，原来一看配置是用了RDS，这就是花了钱的区别啊。当然现在的magento1.9和magento2.1.6以上版本都还是非常快的。</p>
<p></p>
<p>三、CDN加速</p>
<p>我们打开浏览器按"F12"选择"Network",然后运行网站，我们会看到加载这个网站的静态文件所需的时间（比如：图片，js，css），插一句，如果有的图片加载时间过长，可以用工具适当压缩图片。当然，无论你的网站有大型图片还是居多的css和js文件，都可以通过cdn来加载，这意味着你的图片和css，js文件将从另外一台服务器上加载，并且可以在加载页面时防止服务器上出现不必要的压力。从而提高加载速度。</p>
<p></p>
<p>以上三点都是需要Money，当然这些Money花的是值得的，而且是物美价廉。下面我简单介绍下通过magento后台设置来进一步优化速度。</p>
<p></p>
<p>1.进入到<em>System &gt; Configuration &gt; Catalog &gt; FrontEnd，在 &lsquo;Use Flat Catalog Category&rsquo; 和 &lsquo;Use Flat Catalog Product&rsquo;.选择<em>&ldquo;Yes&rdquo;。</em></em>我解释下，magento数据库采用EAV模型，说简单点就是要想查询一个数据，得从好几个表里面联合查询才能得到你想要的数据，而上面设置后，那么我们的程序在加载分类和产品相关的数据时就直接单表查询，单表查询和多表查询哪个速度快就不用我说了吧。</p>
<p>2.禁用日志记录，&nbsp;进入到System -&gt; Configuration -&gt; Advanced -&gt; Developer -&gt; Log Settings&nbsp;来禁用</p>
<p>3.另一个重要的步骤是定期清理cron和日志。进入到<em>System &gt; Configuration &gt; Advanced &gt; System -&gt; Log Cleaning</em>，在这里你应该启用日志清理，并设置尽可能最小的时间。</p>
<p>4.&nbsp;合并css和js文件，进入到<em>System &gt; Configuration &gt; Developer进行设置</em>.合并意味着减少请求，从而提升速度。在此提醒，如果是经过二次开发的网站谨慎操作，合并之后可能会出现问题，我建议在具有丰富经验的magento开发人员的指导下进行。</p>
<p>5.运行预编译，进入到&nbsp;<em>System &gt; Tools &gt; Compilation，</em>运行预编译，这将提升网站加载速度高达50%以上。但因为一些用户操作不当导致网站无法访问，我之前写过一篇文章，<a href="http://www.360magento.com/blog/error-compilation/" title="解决magento开启Compilation预编译网站无法访问" target="_blank">解决magento开启Compilation预编译网站无法访问</a></p>
<p>6.最后一步就是开启缓存,进入到System &gt; Cache Management</p>
<p></p>
<p>以上六点为magento 1的后台操作指导，magento2方法一样，只是路径不同，我就不再赘述。magento2更多的时候需要去运行命令,这就需要更专业的人士啦。magento2对技术的要求性还是很高的。另外magento 2如果切换到生产环境模式速度也是非常快的。在网站的根目录下再行如下命令:</p>
<pre><code>php bin/magento deploy:mode:set production<br /></code></pre>
<p><br />最后补充一点，能花钱解决的就花钱解决，自己去折腾肯定是浪费时间的，最后还解决不好，时间就是金钱，找专业的人做专业的事才是最划算的</p>]]></description>
      <pubDate>Thu, 25 Jan 2018 10:42:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 2.2软件的更新版本现已推出]]></title>
      <link>https://www.360magento.com/blog/magento22-updated/</link>
      <description><![CDATA[<table border="0" cellpadding="0" cellspacing="0" class="table100 mktoContainer" id="emailContainer">
<tbody>
<tr>
<td class="mktEditable" id="bodyCopy2"><span><span>Magento 2.2已经达到了另一个重要的里程碑，这要归功于几个小时的测试和您的大量投入。</span><span>随着Magento 2.2发布的更新版本，几乎所有的主要问题已经解决，代码现在稳定，并准备好开始提交您的扩展到市场。</span><span>我们也对您的反馈感兴趣，请继续提交您在未来几周内发现的任何问题。&nbsp;</span></span><br /><br /><span><span>接下来的步骤，我们鼓励您：&nbsp;</span></span><br /><br />
<table border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td valign="top">&bull;</td>
<td><strong>查看Magento 2.2发布信息。</strong><span><span>&nbsp;Magento 2.2&nbsp;&nbsp;</span></span><a href="http://email2.magento.com/x0G0000x2N90XqG0Qs5hwDF" id="" target="_blank">快速入门网站</a><span><span>&nbsp;&nbsp;包括发行说明，文档，向后不兼容的更改列表，以及更多帮助您准备发布。&nbsp;</span></span></td>
</tr>
<tr>
<td valign="top">&bull;</td>
<td><strong>下载该软件的更新版本。</strong><span><span>&nbsp;Magento开源（以前的社区版）软件可用于</span></span><a href="http://email2.magento.com/kG0RX0q00xh02GsFw90O50D" id="" target="_blank">GitHub上的</a><span><span>所有开发者&nbsp;</span><span>。</span><span>解决方案，技术和托管合作伙伴可以通过签署</span></span><a href="http://email2.magento.com/iSxG0qG9hPX00s000wF2D05" id="" target="_blank">在线协议</a><span><span>&nbsp;&nbsp;并提供GitHub帐户信息</span><span>来访问私人存储库中的Magento Commerce（以前的企业版）软件&nbsp;&nbsp;</span><span>。</span><span>查看我们以前的&nbsp;&nbsp;</span></span><a href="http://email2.magento.com/a0200X09FG0w00TDQGqx5hs" id="" target="_blank">论坛帖子</a><span><span>&nbsp;&nbsp;，了解更多关于这个过程</span></span></td>
</tr>
<tr>
<td valign="top"><span><span>&bull;</span></span></td>
<td><strong>测试版本。</strong><span><span>&nbsp;请继续测试此最新版本，并在2017年8月21日之前通过GitHub提交任何问题。在该日期之后提交的问题很可能会在GA发布后得到解决。</span><span>请注意，技术支持不适用于预发布软件。</span><span>如果在网站上线之前计划/完成对GA的升级，开发人员可能会根据预发布代码启动客户构建。</span></span></td>
</tr>
<tr>
<td valign="top">&bull;</td>
<td><strong>测试并提交您的Marketplace扩展。</strong><span><span>&nbsp;从今天开始，我们鼓励您提交已通过新版本测试的扩展程序。</span><span>要在GA中及时列出您的扩展，我们建议您将更新限制在composer.json和module.xml文件中。</span><span>这将允许您的扩展程序通过加快的审查过程。</span><span>有关</span><span>&nbsp;该过程的更多信息，</span><span>请参阅我们最新的关于</span></span><a href="http://email2.magento.com/XsX0hUG0q000Dx5wF029GR0" id="" target="_blank">更新Magento 2.2的扩展和主题的</a><span><span>博客文章&nbsp;&nbsp;</span><span>。</span></span></td>
</tr>
</tbody>
</table>
<br /><span><span>再次感谢您的支持和反馈。</span><span>请务必定期检查，因为我们将继续每周更新代码。&nbsp;</span></span><br /><br /><span><span>最好的问候，&nbsp;&nbsp;</span></span><br /><span><span>Magento团队</span></span></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>]]></description>
      <pubDate>Tue, 15 Aug 2017 14:39:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2定制布局示例]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-practice/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>本文将一步一步演示如何进行布局的定制任务。也就是说，将演示如何改变Magento页面头部中顾客账户链接的布局。</p>
<h2>移动顾客账户链接</h2>
<p>在Orange主题中，OrangeCo想要把头部链接转换成下拉菜单，Magento Luma主题中完成的方式是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_customizing_layout1.png" width="610px" /></div>
<p>要实现该效果，需要将头部链接用一个容器包住并在列表前添加一个箭头。</p>
<p>默认的头部链接看起来是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_customizing_layout2.png" width="425px" /></div>
<p>需要变成这样：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_customizing_layout3.png" width="455px" /></div>
<h3>步骤1：定义块</h3>
<p>OrangeCo应用了Luma主题。使用<a href="http://www.360magento.com/blog/magento2-locate-files/">《Magento2定位模板，布局和样式》</a>中的方法。找到显示头部链接的块被定义在：</p>
<p><code>&lt;Magento_Customer_module_dir&gt;/view/frontend/layout/default.xml:</code></p>
<pre><code>...
&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;referenceBlock name="top.links"&gt;
            &lt;block class="Magento\Customer\Block\Account\Link" name="my-account-link"&gt;
                &lt;arguments&gt;
                    &lt;argument name="label" xsi:type="string" translate="true"&gt;My Account&lt;/argument&gt;
                &lt;/arguments&gt;
            &lt;/block&gt;
            &lt;block class="Magento\Customer\Block\Account\RegisterLink" name="register-link"&gt;
                &lt;arguments&gt;
                    &lt;argument name="label" xsi:type="string" translate="true"&gt;Register&lt;/argument&gt;
                &lt;/arguments&gt;
            &lt;/block&gt;
            &lt;block class="Magento\Customer\Block\Account\AuthorizationLink" name="authorization-link" template="account/link/authorization.phtml"/&gt;
        &lt;/referenceBlock&gt;
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<h3>步骤2：定义模板</h3>
<p>与上一步定义布局的同样方法相同，OrangeCo定义用来重新排列链接的模板：</p>
<p><code>&lt;Magento_Customer_module_dir&gt;/view/frontend/templates/account/customer.phtml</code></p>
<pre><code>&lt;?php if($this-&gt;customerLoggedIn()): ?&gt;
    &lt;li class="customer welcome customer-welcome"&gt;
        &lt;span class="customer name" data-mage-init='{"dropdown":{}}' data-toggle="dropdown"&gt;
            &lt;span&gt;&lt;?php echo $this-&gt;getCustomerName(); ?&gt;&lt;/span&gt;
            &lt;button type="button" class="action switch"&gt;&lt;span&gt;&lt;?php echo __('Change')?&gt;&lt;/span&gt;&lt;/button&gt;
        &lt;/span&gt;
        &lt;?php if($this-&gt;getChildHtml()):?&gt;
        &lt;div class="customer menu customer-menu" data-target="dropdown"&gt;
            &lt;?php echo $this-&gt;getChildHtml();?&gt;
        &lt;/div&gt;
        &lt;?php endif; ?&gt;
    &lt;/li&gt;
&lt;?php endif; ?&gt;
</code></pre>
<h3>步骤3：扩展base布局来增加一个块</h3>
<p>OrangeCo需要在容器<code>header.panel</code>中新建一个名为<code>header.links</code>的块用来移动链接。由于链接可以在不同模型中被添加，最好是在<code>Magento_Theme</code>模型的页面配置<code>default.xml</code>中添加这个块。</p>
<p>所以下面的扩展布局被添加在Orange主题中：</p>
<p><code>app/design/frontend/OrangeCo/orange/Magento_Theme/layout/default.xml</code></p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;referenceContainer name="header.panel"&gt;
            &lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;
                &lt;arguments&gt;
                    &lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;
                &lt;/arguments&gt;
            &lt;/block&gt;
        &lt;/referenceContainer&gt;
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<h3>步骤4：移动链接</h3>
<p>要移动链接到<code>header.links</code>块，OrangeCo添加一个扩展布局：</p>
<p><code>app/design/frontend/OrangeCo/orange/Magento_Customer/layout/default.xml</code></p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
        &lt;body&gt;
            &lt;referenceBlock name="header.links"&gt;
                &lt;block class="Magento\Customer\Block\Account\Customer" name="customer" template="account/customer.phtml" before="-"/&gt;
                &lt;block class="Magento\Customer\Block\Account\AuthorizationLink" name="authorization-link-login" template="account/link/authorization.phtml"/&gt;
            &lt;/referenceBlock&gt;
            &lt;move element="register-link" destination="header.links"/&gt;
            &lt;move element="top.links" destination="customer"/&gt;
            &lt;move element="authorization-link" destination="top.links" after="-"/&gt;
        &lt;/body&gt;
    &lt;/page&gt;
</code></pre>
<p>现在，顾客链接看起来如下：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_customizing_layout4.png" width="784px" /></div>
<p>最后是添加样式：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_customizing_layout5.png" width="784px" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 27 Feb 2016 15:20:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2通用布局定制任务]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-tasks/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>这篇文章描述了下面这些典型布局定制任务：</p>
<ul>
<li><a href="#set-page-layout">设置页面布局</a></li>
<li><a href="#include-static-resources"> 在&lt;head&gt;里加载静态资源（JavaScript, CSS, fonts）</a></li>
<li><a href="#remove-static-resources"> 移除&lt;head&gt;中的静态资源（JavaScript, CSS, fonts）</a></li>
<li><a href="#create-container">创建一个容器</a></li>
<li><a href="#reference-container">引用一个容器</a></li>
<li><a href="#create-block">创建一个块</a></li>
<li><a href="#block-sets-template">使用块来设置模板</a></li>
<li><a href="#modify-block-arguments">修改块参数</a></li>
<li><a href="#reference-block">引用一个块</a></li>
<li><a href="#methods-set-properties">使用块对象方法来设置块性能</a></li>
<li><a href="#rearrange-elements">元素重新排序</a></li>
<li><a href="#remove-elements">移除元素</a></li>
<li><a href="#replace-elements">替换元素</a></li>
</ul>
<p>提示：为保证你定制内容的稳定性和安全性，避免在升级中被删除。请不要改变Magento的模型和主题布局。要定制布局可以在你的自定义主题中扩展和重写主题文件。</p>
<h2 id="set-page-layout">设置页面布局</h2>
<p>特定页面的布局在页面配置文件中被定义，在根<code>&lt;page&gt;</code>结点的layout属性中。</p>
<p>例如：将Advanced Search页面的布局由一列布局改为带左侧栏的两列布局：<code>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_CatalogSearch/layout/catalogsearch_advanced_index.xml</code></p>
<pre><code>&lt;page layout="2columns-left" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
...
&lt;/page&gt;
</code></pre>
<h2 id="include-static-resources">在&lt;head&gt;里加载静态资源（JavaScript, CSS, fonts）</h2>
<p>JavaScript, CSS和其它静态资产在页面配置文件的<code>&lt;head&gt;</code>区域被添加，默认地<code>&lt;head&gt;</code>在<code>app/code/Magento/Theme/view/frontend/layout/default_head_blocks.xml</code>中被定义。建议在你自定义的主题中扩展该文件来加载JavaScript, CSS和其它静态资产。下面的文件包含了一些你必须添加的文件的示例：</p>
<p><code>&lt;theme_dir&gt;/Magento_Theme/layout/default_head_blocks.xml</code></p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;head&gt;
        &lt;!-- Add local resources --&gt;
    	&lt;css src="css/my-styles.css"/&gt;
    
        &lt;!-- The following two ways to add local JavaScript files are equal --&gt;
        &lt;script src="Magento_Catalog::js/sample1.js"/&gt;
        &lt;link src="js/sample.js"/&gt;
		
    	&lt;!-- Add external resources --&gt;
	    &lt;css src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css" src_type="url" /&gt;
        &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js" src_type="url" /&gt;
        &lt;link src="http://fonts.googleapis.com/css?family=Montserrat" src_type="url" /&gt; 
    &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<p>要添加外部资源时，必须要指明<code>src_type="url"</code>参数。</p>
<p>你可以使用<code>&lt;link src="js/sample.js"/&gt;或<code>&lt;script src="js/sample.js"/&gt;指令来添加本地存储的JavaScript文件到你的主题。</code></code></p>
<p>指定资源的路径必须是以下中的一个：</p>
<ul>
<li>&lt;theme_dir&gt;/web</li>
<li>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web</li>
</ul>
<h3>添加条件注释</h3>
<p>条件注释意味着针对Internet Explorer给出特殊的指令。你可以给特定版本的Internet Explorer添加CSS文件。以下是一个示例：</p>
<pre><code>&lt;head&gt;
        &lt;css src="css/ie-9.css" ie_condition="IE 9" /&gt;
    &lt;/head&gt;
&lt;/page&gt;
</code></pre>
<p>这样就能在生成的HTML中增加一个IE条件注释，如下：</p>
<pre><code>&lt;!--[if IE 9]&gt;
&lt;link rel="stylesheet" type="text/css" media="all" href="&lt;your_store_web_address&gt;/pub/static/frontend/OrangeCo/orange/en_US/css/ie-9.css" /&gt;
&lt;![endif]--&gt;
</code></pre>
<p>上面例子中的<code>orange</code>是被OrangeCo创建的自定义主题。</p>
<h2 id="remove-static-resources">移除&lt;head&gt;中的静态资源（JavaScript, CSS, fonts）</h2>
<p>要移除页面&lt;head&gt;中的静态资源，按照下面的扩展文件做些类似的修改即可：</p>
<p><code>app/design/frontend/&lt;Vendor&gt;/&lt;theme&gt;/Magento_Theme/layout/default_head_blocks.xml</code></p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
   &lt;head&gt;
        &lt;!-- Remove local resources --&gt;
        &lt;remove src="css/styles-m.css" /&gt;
        &lt;remove src="my-js.js"/&gt;
        &lt;remove src="Magento_Catalog::js/compare.js" /&gt;
								
	&lt;!-- Remove external resources --&gt;
        &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"/&gt;
        &lt;remove src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"/&gt;
        &lt;remove src="http://fonts.googleapis.com/css?family=Montserrat" /&gt; 
   &lt;/head&gt;
</code></pre>
<p>注意，如果在初始文件中静态块带有模型路径（例如：<code>Magento_Catalog::js/sample.js</code>），那么在移除时也应指明模型路径。</p>
<h2 id="create-container">创建一个容器</h2>
<p>使用下面的例子来创建（声明）一个容器</p>
<p><code>&lt;container name="some.container" as="someContainer" label="Some Container" htmlTag="div" htmlClass="some-container" /&gt;</code></p>
<h2 id="reference-container">引用一个容器</h2>
<p>要更新一个容器，使用<code>&lt;referenceContainer&gt;</code>指令。</p>
<p>示例：添加链接到页面头部面板</p>
<pre><code>&lt;referenceContainer name="header.panel"&gt;
        &lt;block class="Magento\Framework\View\Element\Html\Links" name="header.links"&gt;
            &lt;arguments&gt;
                &lt;argument name="css_class" xsi:type="string"&gt;header links
            &lt;/arguments&gt;
        &lt;/block&gt;
&lt;/referenceContainer&gt;
</code></pre>
<h2 id="create-block">创建一个块</h2>
<p>块的创建（声明）使用<code>&lt;block&gt;</code>指令。</p>
<p>示例：增加一个产品SKU信息的块</p>
<pre><code>&lt;block class="Magento\Catalog\Block\Product\View\Description" name="product.info.sku" template="product/view/attribute.phtml" after="product.info.type"&gt;
    &lt;arguments&gt;
        &lt;argument name="at_call" xsi:type="string"&gt;getSku&lt;/argument&gt;
        &lt;argument name="at_code" xsi:type="string"&gt;sku&lt;/argument&gt;
        &lt;argument name="css_class" xsi:type="string"&gt;sku&lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/block&gt;
</code></pre>
<h2 id="reference-block">引用一个块</h2>
<p>要更新一个块，使用<code>&lt;referenceBlock&gt;</code>指令。</p>
<p>示例：向<code>logo</code>块传送图片</p>
<pre><code>&lt;referenceBlock name="logo"&gt;
        &lt;arguments&gt;
            &lt;argument name="logo_file" xsi:type="string"&gt;images/logo.png&lt;/argument&gt;
        &lt;/arguments&gt;
&lt;/referenceBlock&gt;
</code></pre>
<h2 id="block-sets-template">使用块来设置模板</h2>
<p>要设置模板的块，使用<code>&lt;argument&gt;</code>指令来传递。</p>
<p>示例：改变page模板的title块</p>
<pre><code>&lt;referenceBlock name="page.main.title"&gt;
        &lt;arguments&gt;
            &lt;argument name="template" xsi:type="string"&gt;Namespace_Module::title_new.phtml&lt;/argument&gt;
        &lt;/arguments&gt;
 &lt;/referenceBlock&gt;
</code></pre>
<p>模型的路径被指明关系到模型的<code>view/&lt;area&gt;/templates/</code>目录。<code>&lt;area&gt;</code>对应布局文件被使用的地方。</p>
<h2 id="modify-block-arguments">修改块参数</h2>
<p>要修改块参数，使用<code>&lt;referenceBlock&gt;</code>指令</p>
<p>示例：改变已存在块中的参数并添加一个新参数。</p>
<p>初始块声明：</p>
<pre><code>...
&lt;block class="Namespace_Module_Block_Type" name="block.example"&gt;
    &lt;arguments&gt;
        &lt;argument name="label" xsi:type="string"&gt;Block Label&lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/block&gt;
...
</code></pre>
<p>扩展布局：</p>
<pre><code>...
&lt;referenceBlock name="block.example"&gt;
    &lt;arguments&gt;
        &lt;!-- Modified block argument --&gt;
        &lt;argument name="label" xsi:type="string"&gt;New Block Label&lt;/argument&gt;
        &lt;!- Newly added block argument --&gt;
        &lt;argument name="custom_label" xsi:type="string"&gt;Custom Block Label&lt;/argument&gt;
    &lt;/arguments&gt;
&lt;/referenceBlock&gt; 
...
</code></pre>
<h2 id="methods-set-properties">使用块对象方法来设置块性能</h2>
<p>有两种方式访问块对象方法：</p>
<ul>
<li>对<code>&lt;block&gt;</code>或<code>&lt;referenceBlock&gt;</code>使用&lt;argument&gt;指令</li>
<li>使用&lt;action&gt;指令。不推荐使用该方法，不过可以用来调用未被重构，不能用<code>&lt;argument&gt;</code>的方法。</li>
</ul>
<p>示例1：使用<code>&lt;argument&gt;</code>为产品页面设置CSS类并添加一个属性</p>
<p>扩展布局：</p>
<pre><code>&lt;referenceBlock name="page.main.title"&gt;
		&lt;arguments&gt;
		    &lt;argument name="css_class" xsi:type="string"&gt;product&lt;/argument&gt;
		    &lt;argument name="add_base_attribute" xsi:type="string"&gt;itemprop="name"&lt;/argument&gt;
		&lt;/arguments&gt;
	&lt;/referenceBlock&gt;
</code></pre>
<p>示例2：使用<code>&lt;action&gt;</code>设置页面标题</p>
<p>扩展布局：</p>
<pre><code>...
	&lt;referenceBlock name="page.main.title"&gt;
	    &lt;action method="setPageTitle"&gt;
	        &lt;argument translate="true" name="title" xsi:type="string"&gt;Catalog Advanced Search&lt;/argument&gt;
	    &lt;/action&gt;
	&lt;/referenceBlock&gt;
	...
</code></pre>
<h2 id="rearrange-elements">元素重新排序</h2>
<p>在布局文件中你可以改变页面中元素的顺序，使用下面的方法即可实现：</p>
<ul>
<li><code>&lt;move&gt;</code>指令：允许改变元素的顺序和父亲。</li>
<li><code>&lt;block&gt;</code>的<code>before</code>和<code>after</code>属性：允许改变有同一父亲的元素的顺序。</li>
</ul>
<p><code>&lt;move&gt;</code>使用示例：将产品页面中的stock availability和SKU块放在产品价格旁边。</p>
<p>在Magento Blank主题中这些元素的位置如下：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization before" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_layout_customization1.png" width="840px" /></div>
<p>让我们将产品库存和SKU块放到产品价格块的后面，将review块从product-info-price容器中移出。要实现这些，在<code>app/design/frontend/OrangeCo/orange/Magento_Catalog/layout/</code>目录下添加<code>catalog_product_view.xml</code>。</p>
<pre><code>&lt;page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;move element="product.info.stock.sku" destination="product.info.price" after="product.price.final"/&gt;
        &lt;move element="product.info.review" destination="product.info.main" before="product.info.price"/&gt;
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p>这将使得产品页面看起来像这样：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 layout customization after" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_layout_customization2.png" width="840px" /></div>
<h2 id="remove-elements">移除元素</h2>
<p>使用<code>&lt;referenceBlock&gt;</code>和<code>&lt;referenceContainer&gt;</code>的<code>remove</code>属性可移除元素。</p>
<p>示例：移除店铺页面中的Compare Products侧边栏</p>
<p>这个块在<code>app/code/Magento/Catalog/view/frontend/layout/default.xml</code>中被声明：</p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
...
        &lt;referenceContainer name="sidebar.additional"&gt;
            &lt;block class="Magento\Catalog\Block\Product\Compare\Sidebar" name="catalog.compare.sidebar" template="product/compare/sidebar.phtml"/&gt;
        &lt;/referenceContainer&gt;
...
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p>要移除这个块，你需要在你的主题中扩展<code>default.xml</code>：</p>
<p><code>&lt;theme_dir&gt;/Magento_Catalog/layout/default.xml</code></p>
<p>在这个文件中，引用已被添加了<code>remove</code>属性的元素：</p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
...
        &lt;referenceBlock name="catalog.compare.sidebar" remove="true" /&gt;
...
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<h2 id="replace-elements">替换元素</h2>
<p>要替换元素，你可以移除它然后添加一个新的。</p>
<h3>相关文章：</h3>
<ul>
<li><a href="http://www.360magento.com/blog/magento2-xml-instructions/">Magento2布局指令</a></li>
<li><a href="http://www.360magento.com/blog/magento2-layout-extend/">Magento2如何扩展一个布局</a></li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 25 Feb 2016 08:16:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何更新Magento插件]]></title>
      <link>https://www.360magento.com/blog/magento-update-modules/</link>
      <description><![CDATA[<p>要确认Magento插件的更新，首先你需要登录到后台。然后进入<strong>System -&gt; Magento Connect -&gt; Magento Connect Manager</strong>。在Extensions标签中点击<strong>Check for Upgrades</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento update modules" src="http://7xjryy.com1.z0.glb.clouddn.com/update-modules-1.jpg" width="auto" /></div>
<p>Magento连接管理器会自动连接到服务器并检查可用的升级。如果你的插件中有已发布的升级版，它们的背景色会被标记为黄色，你可以将升级应用到你的插件。注意！在升级前对你的Magento网上商店进行备份是十分重要的。在<strong>Action</strong>的下拉列表里你可以选择想要升级到的版本。然后点击<strong>Commit Changes</strong>进行升级。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento after update modules" src="http://7xjryy.com1.z0.glb.clouddn.com/update-modules-2.jpg" width="auto" /></div>
<p>你所选择的升级包将被自动下载并应用。</p>
<p>插件升级完成后你可以通过Refresh按钮来刷新页面。然后检测插件的状态，你会发现升级后的插件的黄色背景色消失了。Installed列中也会变为你刚才所安装的版本。</p>
<p>现在你可以点击Return to Admin，检查你的插件是否有新的可用配置。当然，也要确认你的网上商店工作正常，没有错误。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 19 Feb 2016 13:56:25 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2布局的覆盖]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-override/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>并不是所有的自定义布局都能通过扩展现有布局来实现。如果自定义的量很大时，可以覆盖所需的布局文件。这就意味着你在主题中新建的布局文件将被用来代替默认的主题布局文件。</p>
<p>在这篇文章中，页面布局，页面配置和通用布局被称为布局文件，它们的覆盖是一样的。</p>
<p>这类覆盖了默认或父主题的布局文件被称为覆盖布局文件。</p>
<h2>关于自定义覆盖布局的例子</h2>
<ul>
<li>抑制方法调用（如果块里有取消原始调用的方法，覆盖就没有必要了。这种情况下，你可以通过在取消方法调用的位置添加布局文件来自定义布局。）</li>
<li>修改方法参数</li>
<li>使用<code>remove</code>属性取消块/容器的输出</li>
<li>为块和容器设置XML属性</li>
<li>移除块参数</li>
<li>修改并抑制句柄包容</li>
<li>移除所有句柄指令，通过声明一个空句柄覆盖布局文件</li>
</ul>
<h2>如何覆盖一个布局</h2>
<h3>覆盖base布局</h3>
<p>在如下位置放置一个同名的布局文件：</p>
<pre><code>&lt;theme_dir&gt;
  |__/&lt;Namespace_Module&gt;
    |__/layout
      |__/override
         |__/base
           |--&lt;layout1&gt;.xml
           |--&lt;layout2&gt;.xml
</code></pre>
<p>这些文件覆盖如下布局：</p>
<ul>
<li><code>&lt;module_dir&gt;/view/frontend/layout/&lt;layout1&gt;.xml</code></li>
<li><code>&lt;module_dir&gt;/view/frontend/layout/&lt;layout2&gt;.xml</code></li>
</ul>
<h3>覆盖主题布局</h3>
<p>在如下位置放置一个同名的布局文件：</p>
<pre><code>&lt;theme_dir&gt;
  |__/&lt;Namespace_Module&gt;
    |__/layout
      |__/override
         |__/theme
            |__/&lt;Parent_Vendor&gt;
               |__/&lt;parent_theme&gt;
                  |--&lt;layout1&gt;.xml
                  |--&lt;layout2&gt;.xml
</code></pre>
<p>这些文件覆盖如下布局：</p>
<ul>
<li><code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout1&gt;.xml</code></li>
<li><code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/&lt;layout1&gt;.xml</code></li>
</ul>
<p>注意：要覆盖页面布局文件时将文件名'layout'替换为'page_layout'</p>
<h2>自定义错误</h2>
<p>虽然布局覆盖机制提供了极大的定制灵活性，它也可以进行逻辑相关的改变。我们强烈建议你不要做以下修改：</p>
<ul>
<li>更改块名或别名。块的名字不应该被修改，块的别名也应该与父元素中的保持一致。</li>
<li>更改句柄继承。例如，你不应该修改页面类型的父句柄。</li>
</ul>
<h3>相关文章</h3>
<ul>
<li><a href="http://www.360magento.com/blog/layout-extend/">Magento2如何扩展一个布局</a></li>
<li><a href="http://www.360magento.com/blog/magento2-theme-create/">创建magento2主题</a></li>
<li><a href="http://www.360magento.com/blog/magento2-xml-instructions/">Magento2布局指令</a></li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 16 Feb 2016 14:09:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何安装Magento模型/插件]]></title>
      <link>https://www.360magento.com/blog/magento_connect/</link>
      <description><![CDATA[<p>Magento具有内置的为线上店铺安装附加模型的功能。基本上，你所需要的就是插件的key以及点击几下。在这篇教程中，我们将详细解释如何通过Magento Connet为Magento安装附加的模型/插件。另外，我们也将说明如何升级已有的模型/插件。首先，你需要进入Magento的管理员区域。然后进入 <strong>System -&gt; Magento Connect -&gt; Magento Connect Manager。</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento connet" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-1.jpg" width="auto" /></div>
<p>Magento Connect Manager页面打开后你将被要求再次提供管理凭据。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento connet admin" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-2.jpg" width="auto" /></div>
<p>登录后你将看到两个区域：<strong>Extensions</strong>和<strong>Settings</strong>。建议首先在Settings区域验证被选择的设置。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento connet setting" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-3.jpg" width="auto" /></div>
<p>在<strong>Setting</strong>区域，有几个选项你可以按需配置。当然，前提是你知道你正在做什么。保持默认值是安全的。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento connet setting state" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-4.jpg" width="auto" /></div>
<p>Preferred State选项控制你安装的插件状态。有三个状态：稳定，测试和阿尔法。针对在线网站推荐选择稳定版。设置为测试/阿尔法能让你检查插件是否为最新版本，但是一般不推荐测试版插件，尤其是阿尔法状态的插件可能有bug并可能破坏你线上网店的功能。在插件下载和升级前做备份是非常重要的。这样的话，在下载安装插件后发生冲突的情况下，你可以运行备份进行恢复。做好备份后你就可以进入Magento Connect Manager-&gt; Extensions标签，点击Magento Connect链接。</p>
<p>这将为Magento Connect打开一个新的窗口并让你浏览可用的插件。这里有搜索功能，而且模型分为几类。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento available extensions" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-5.jpg" width="auto" /></div>
<p>这里有各种插件，有些是免费的。不论哪种情况都需要注册来获取插件key。指令是根据特定的插件。当你选择一个插件，点击<strong>Install Now</strong>按钮并选择相匹配的Magento Connect版本（Magento1.5以上选择版本2.0，其它保持1.0）。阅读插件许可协议，勾选"I agree to the extension license agreement"。最后点击<strong>Get Extension Key</strong>按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento extensions version" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-6.jpg" width="auto" /></div>
<p>你将获取插件的key。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento extensions key" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-7.jpg" width="auto" /></div>
<p>这就是你需要复制并粘贴到你Magento Connect区域的key。然后点击<strong>Install</strong>按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento extensions install" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-8.jpg" width="auto" /></div>
<p>新的插件会自动下载和安装。如果安装过程出现问题，将会显示相关信息，以便你知道如何去解决它。插件安装完成后，成功安装界面将会出现：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento extensions install success" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-connect-9.jpg" width="auto" /></div>
<p>插件安装完成后返回Magento后台并按需调整设置是很重要的。当然也要确保你网上店铺有正确的功能并不存在错误。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 09 Feb 2016 14:44:44 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2如何扩展一个布局]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-extend/</link>
      <description><![CDATA[<h2>创建一个布局扩展文件</h2>
<p>在Magento系统中扩展布局你只需要创建一个包含修改内容的扩展布局文件，而不是复制大量的页面布局或页面配置代码并修改你想要改变的部分。</p>
<p>要添加一个扩展页面配置或通用布局文件：</p>
<p>将布局文件放在如下位置：</p>
<pre><code>&lt;theme_dir&gt;
 |__/&lt;Namespace&gt;_&lt;Module&gt;
   |__/layout
     |--&lt;layout1&gt;.xml
     |--&lt;layout2&gt;.xml
</code></pre>
<p>例如，自定义<code>&lt;Magento_Catalog_module_dir&gt;/view/frontend/layout/catalog_product_view.xml</code>布局，你需要在你自定义的主题中添加一个同样名字的布局，就像这样：<code>&lt;theme_dir&gt;/Magento_Catalog/layout/catalog_product_view.xml</code></p>
<p>要添加一个扩展页面布局文件：</p>
<p>将文件放在如下位置：</p>
<pre><code>&lt;theme_dir&gt;
 |__/&lt;Namespace&gt;_&lt;Module&gt;
   |__/page_layout
     |--&lt;layout1&gt;.xml
     |--&lt;layout2&gt;.xml
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 18 Jan 2016 14:14:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2布局文件类型]]></title>
      <link>https://www.360magento.com/blog/magento2-layout-types/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>对于一个特定的页面，其布局主要被两个重要的布局组件定义：页面布局文件和页面配置文件。</p>
<p>一个页面布局文件定义页面线框，例如，一列布局。技术页面布局是.xml文件，定义html页面<code>&lt;body&gt;</code>区域内的结构。页面布局功能只是容器。所有的页面布局声明应在页面布局声明文件中声明。</p>
<p>页面配置也是一个.xml文件。它定义详细的结构（页面头部，底部等），内容和页面元信息，包括使用的页面布局。页面配置功能包括主元素和块（尤其是类和容器）。</p>
<p>我们还区分了第三类布局文件，通用布局。它们是定义内容和HTML页面组成中<code>&lt;body&gt;</code>区域详细结构的.xml文件。这些文件用于返回Ajax请求，电子邮件，HTML片段等页面。</p>
<p>本文给出了每种布局文件类型的详细描述。</p>
<h2>页面布局</h2>
<p>页面布局声明页面区域内的线框，如一列布局或者两列布局。</p>
<p>允许的布局指令：</p>
<ul>
<li>&lt;container&gt;</li>
<li>&lt;referenceContainer&gt;</li>
<li>&lt;move&gt;</li>
<li>&lt;update&gt;</li>
</ul>
<p>页面布局示例：</p>
<p><code>&lt;Magento_Theme_module_dir&gt;/view/frontend/page_layout/2columns-left.xml</code></p>
<pre><code>&lt;layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_layout.xsd"&gt;
    &lt;update handle="1column"/&gt;
    &lt;referenceContainer name="columns"&gt;
        &lt;container name="div.sidebar.main" htmlTag="div" htmlClass="sidebar sidebar-main" after="main"&gt;
            &lt;container name="sidebar.main" as="sidebar_main" label="Sidebar Main"/&gt;
        &lt;/container&gt;
        &lt;container name="div.sidebar.additional" htmlTag="div" htmlClass="sidebar sidebar-additional" after="div.sidebar.main"&gt;
            &lt;container name="sidebar.additional" as="sidebar_additional" label="Sidebar Additional"/&gt;
       &lt;/container&gt;
    &lt;/referenceContainer&gt;
&lt;/layout&gt;
</code></pre>
<h3>页面布局文件常规位置</h3>
<p>常规页面布局位置如下：</p>
<ul>
<li>Module page layouts（模型页面布局）：<code>&lt;module_dir&gt;/view/frontend/page_layout</code></li>
<li>Theme page layouts:（主题页面布局）：<code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/page_layout</code></li>
</ul>
<h3>页面布局声明</h3>
<p>要能够使用一个布局为实际的页面进行渲染，你需要在<code>layouts.xml</code>中声明它。</p>
<p>常规布局声明文件可能位于下面位置之一：</p>
<ul>
<li>Module layout declarations（模型布局声明）：<code>&lt;module_dir&gt;/view/frontend/layouts.xml</code></li>
<li>Theme layout declaration（主题布局声明）：<code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layouts.xml</code></li>
</ul>
<p>使用<code>&lt;layout&gt;&lt;/layout&gt;</code>指令声明布局文件，如下指定：</p>
<ul>
<li><code>&lt;layout id="layout_file_name"&gt;</code>例如，<code>2columns-left.xml</code>页面布局如下声明：<code>&lt;layout id = "2columns-left"/&gt;</code></li>
<li><code>&lt;label translate="true|false"&gt;{Label_used_in_Admin}&lt;/label&gt;</code></li>
</ul>
<p>页面布局声明文件示例：</p>
<p><code>&lt;Magento_Theme_module_dir&gt;/view/frontend/layouts.xml</code></p>
<pre><code>&lt;page_layouts xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/PageLayout/etc/layouts.xsd"&gt;
    &lt;layout id="1column"&gt;
        &lt;label translate="true"&gt;1 column
    &lt;/layout&gt;
    &lt;layout id="2columns-left"&gt;
        &lt;label translate="true"&gt;2 columns with left bar
    &lt;/layout&gt;
    &lt;layout id="2columns-right"&gt;
        &lt;label translate="true"&gt;2 columns with right bar
    &lt;/layout&gt;
    &lt;layout id="3columns"&gt;
        &lt;label translate="true"&gt;3 columns
   &lt;/layout&gt;
&lt;/page_layouts&gt;
</code></pre>
<h2>页面配置</h2>
<p>页面配置在一个页面布局文件中定义添加到线框的内容。一个页面配置也包含页面元信息和<code>&lt;head&gt;</code>内容。</p>
<h3>页面配置文件常规位置</h3>
<p>常规页面配置文件位于下面位置：</p>
<ul>
<li>Module page configurations（模型页面配置）： <code>&lt;module_dir&gt;/view/frontend/layout</code></li>
<li>Theme page configurations（主题页面配置）： <code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout</code></li>
</ul>
<h3>页面配置结构和允许的布局指令</h3>
<p>下表描述了页面配置文件的指令。要查看通用布局指令请看<a href="http://www.360magento.com/blog/magento2-xml-instructions/ target=">《Magento2布局指令》</a></p>
<table>
<tbody>
<tr><th>Element</th><th colspan="1">Attributes</th><th colspan="1">Parent of</th><th>Description</th></tr>
<tr>
<td><code><span>&lt;page&gt;&lt;/page&gt;</span></code></td>
<td colspan="1">
<ul>
<li><code>layout = {layout}</code></li>
<li><code>xsi:noNamespaceSchemaLocation ="{path_to_schema}"</code></li>
</ul>
</td>
<td colspan="1">
<ul>
<li><code>&lt;html&gt;</code></li>
<li><code>&lt;head&gt;</code></li>
<li><code>&lt;body&gt;</code></li>
<li><code>&lt;update&gt;</code></li>
</ul>
</td>
<td>Mandatory root element.</td>
</tr>
<tr>
<td colspan="1"><code>&lt;html&gt;&lt;/html&gt;</code></td>
<td colspan="1">
<p>none</p>
</td>
<td colspan="1">
<ul>
<li><code>&lt;attribute&gt;</code></li>
</ul>
</td>
<td colspan="1"><span>Mandatory element.</span></td>
</tr>
<tr>
<td colspan="1"><code>&lt;head&gt;&lt;/head&gt;</code></td>
<td colspan="1">none</td>
<td colspan="1">
<ul>
<li><code>&lt;title&gt;</code></li>
<li><code>&lt;meta&gt;</code></li>
<li><code>&lt;link&gt;</code></li>
<li><code>&lt;css&gt;</code></li>
<li><code>&lt;script&gt;</code></li>
</ul>
</td>
<td colspan="1">&nbsp;</td>
</tr>
<tr>
<td colspan="1"><code>&lt;body&gt;&lt;/body&gt;</code></td>
<td colspan="1">none</td>
<td colspan="1">
<ul>
<li><code>&lt;block&gt;</code></li>
<li><code>&lt;container&gt;</code></li>
<li><code>&lt;move&gt;</code></li>
<li><code>&lt;attribute&gt;</code></li>
<li><code>&lt;referenceBlock&gt;</code></li>
<li><code>&lt;referenceContainer&gt;</code></li>
<li><code>&lt;action&gt;</code></li>
</ul>
</td>
<td colspan="1">&nbsp;</td>
</tr>
<tr>
<td colspan="1"><code>&lt;attribute&gt;</code></td>
<td colspan="1">
<ul>
<li><code>name = {arbitrary_name}</code></li>
<li><code>value = {arbitrary_value}</code></li>
</ul>
</td>
<td colspan="1">&nbsp;</td>
<td colspan="1">
<p>Specified for <code>&lt;html&gt;</code>, rendered like following:</p>
<p><code>&lt;html name="value'&gt;</code></p>
</td>
</tr>
<tr>
<td colspan="1">
<p><code>&lt;title&gt;</code></p>
</td>
<td colspan="1">none</td>
<td colspan="1">none</td>
<td colspan="1">Page title</td>
</tr>
<tr>
<td colspan="1">
<p><code>&lt;meta&gt;</code></p>
</td>
<td colspan="1">
<ul>
<li><span><code>content</code></span></li>
<li><span><code>charset</code></span></li>
<li><span><code>http-equiv</code></span></li>
<li><span><code>name</code></span></li>
<li><span><code>scheme</code></span></li>
</ul>
</td>
<td colspan="1"><span>none</span></td>
<td colspan="1">&nbsp;</td>
</tr>
<tr>
<td colspan="1">
<p><code>&lt;link&gt;</code></p>
</td>
<td colspan="1">
<ul>
<li><span><code>src</code></span></li>
<li><span><code>defer</code></span></li>
<li><span><code>ie_condition</code></span></li>
<li><span><code>charset</code></span></li>
<li><span><code>hreflang</code></span></li>
<li><span><code>media</code></span></li>
<li><span><code>rel</code></span></li>
<li><span><code>rev</code></span></li>
<li><span><code>sizes</code></span></li>
<li><span><code>target</code></span></li>
<li><span><code>type</code></span></li>
</ul>
</td>
<td colspan="1"><span>none</span></td>
<td colspan="1">&nbsp;</td>
</tr>
<tr>
<td colspan="1"><span><code>&lt;css&gt;</code></span></td>
<td colspan="1">
<ul>
<li><span><code>src</code></span></li>
<li><span><code>defer</code></span></li>
<li><span><code>ie_condition</code></span></li>
<li><span><code>charset</code></span></li>
<li><span><code>hreflang</code></span></li>
<li><span><code>media</code></span></li>
<li><span><code>rel</code></span></li>
<li><span><code>rev</code></span></li>
<li><span><code>sizes</code></span></li>
<li><span><code>target</code></span></li>
<li><span><code>type</code></span></li>
</ul>
</td>
<td colspan="1"><span>none</span></td>
<td colspan="1">&nbsp;</td>
</tr>
<tr>
<td colspan="1">
<p><code>&lt;script&gt;</code></p>
</td>
<td colspan="1">
<ul>
<li><span><code>src</code></span></li>
<li><span><code>defer</code></span></li>
<li><span><code>ie_condition</code></span></li>
<li><span><code>async</code></span></li>
<li><span><code>charset</code></span></li>
<li><span><code>type</code></span></li>
</ul>
</td>
<td colspan="1"><span>none</span></td>
<td colspan="1">&nbsp;</td>
</tr>
</tbody>
</table>
<h2>通用布局</h2>
<p>通用布局定义HTML页面<code>&lt;body&gt;</code>区域内的内容和详细结构。</p>
<h3>通用布局文件常规位置</h3>
<p>常规通用布局文件位于以下位置：</p>
<ul>
<li>Module generic layouts（模型通用布局）：<code>&lt;module_dir&gt;/view/frontend/layout</code></li>
<li>Theme generic layouts（主题通用布局）：<code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout</code></li>
</ul>
<h3>通用布局结构和允许的布局指令</h3>
<p>下表描述了页面配置文件的指令。要查看通用布局指令请看<a href="http://www.360magento.com/blog/magento2-xml-instructions/ target=">《Magento2布局指令》</a></p>
<table>
<tbody>
<tr><th>Element</th><th colspan="1">Attributes</th><th colspan="1">Parent of</th><th>Description</th></tr>
<tr>
<td><code> &lt;layout&gt;&lt;/layout&gt; </code></td>
<td colspan="1">
<ul>
<li><code> xsi:noNamespaceSchemaLocation="{path_to_schema}" </code></li>
</ul>
</td>
<td colspan="1">
<ul>
<li><code>&lt;container&gt;</code></li>
<li><code>&lt;update&gt;</code></li>
</ul>
</td>
<td>Mandatory root element.</td>
</tr>
<tr>
<td><code> &lt;update&gt; </code></td>
<td colspan="1">
<ul>
<li><code>handle="{name_of_handle_to_include}"</code></li>
</ul>
</td>
<td colspan="1">none</td>
<td>&nbsp;</td>
</tr>
<tr>
<td colspan="1"><code>&lt;container&gt;</code></td>
<td colspan="1">
<ul>
<li><code>name="root"</code></li>
<li>For complete list of attributes, see <a href="http://www.360magento.com/blog/magento2-xml-instructions/ 

target=">Layout instructions</a></li>
</ul>
</td>
<td colspan="1">
<ul>
<li><code>&lt;block&gt;</code></li>
<li><code>&lt;container&gt;</code></li>
<li><code>&lt;referenceBlock&gt;</code></li>
<li><code>&lt;referenceContainer&gt;</code></li>
</ul>
</td>
<td colspan="1">Mandatory element</td>
</tr>
</tbody>
</table>
<p>通用布局示例：</p>
<pre><code>&lt;layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/layout_generic.xsd"&gt;
    &lt;update handle="formkey"/&gt;
    &lt;update handle="adminhtml_googleshopping_types_block"/&gt;
    &lt;container name="root"&gt;
        &lt;block class="Magento\Backend\Block\Widget\Grid\Container" name="googleshopping.types.container" template="Magento_Backend::widget/grid/container/empty.phtml"/&gt;
    &lt;/container&gt;
&lt;/layout&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 08 Jan 2016 15:21:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento主题安装]]></title>
      <link>https://www.360magento.com/blog/magento_themes_install/</link>
      <description><![CDATA[<p>当你选好一个主题，进入它的详细页，点击<strong>Install Now</strong>，选择<strong>Magento Connect</strong>版本（Magento1.5以上选择2.0版本，其它的保持默认的1.0），同意扩展协议并点击<strong>Get Extension Key</strong>按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento theme extension key" src="http://7xjryy.com1.z0.glb.clouddn.com/install_magento_theme1.jpg" width="auto" /></div>
<p>扩展密钥将会呈现出来，所以你可以选择和复制它。然后，打开Magento后台，进入<strong>System -&gt; Magento Connect -&gt; Magento Connect Manager</strong>。再次输入管理员登录信息并在<strong>Paste extension key to install</strong>区域粘贴密钥。最后点击Install按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento theme install" src="http://7xjryy.com1.z0.glb.clouddn.com/install_magento_theme2.jpg" width="auto" /></div>
<p>安装完成后返回后台，进入<strong>System -&gt; Configuration -&gt; Design -&gt; Themes</strong>。在<strong>Default</strong>区域输入主题名并点击<strong>Save Config</strong>按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento theme change" src="http://7xjryy.com1.z0.glb.clouddn.com/install_magento_theme3.jpg" width="auto" /></div>
<p>前台页面也许没能正确地加载。原因可能是新主题的首页布局列数。你可以在<strong>CMS -&gt; Pages</strong>中解决这个问题。一个是两列，其它的都是一列。通过点击它们的status禁用第一个和启用第二个。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento cms page" src="http://7xjryy.com1.z0.glb.clouddn.com/install_magento_theme4.jpg" width="auto" /></div>
<p>现在前端页面就正确地显示新的主题了。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento new theme" src="http://7xjryy.com1.z0.glb.clouddn.com/install_magento_theme5.jpg" width="auto" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 04 Jan 2016 15:59:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento谷歌分析设置]]></title>
      <link>https://www.360magento.com/blog/magento_google_analytics/</link>
      <description><![CDATA[<p>谷歌分析是谷歌的一项免费服务，它可以让网站的拥有者和管理员监控他们网站的流量和转化率。Magento支持两种类型的跟踪：</p>
<ul>
<li>页面视图跟踪：列出访客的链接起源，即访客是从哪个链接进入你的店铺的。</li>
<li>电子商务跟踪：列出达成交易的客户极其购买的商品。</li>
</ul>
<p>首先，你需要在http://www.google.com/analytics/sign_up.html注册。你将收到一个谷歌分析帐号。把它记下来，因为你会在Magento设置时需要它。</p>
<p>现在，你需要在你的店铺里配置谷歌分析。登录你的Magento后台，进入<strong>System -&gt; Configuration -&gt; Sales -&gt; Google API</strong>，展开<strong>Google Analytics</strong>区域。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento google analytics.jpg" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_google_analytics.jpg" width="auto" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 31 Dec 2015 15:05:57 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2布局指令]]></title>
      <link>https://www.360magento.com/blog/magento2-xml-instructions/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>改变布局是Magento中自定义页面布局的两种方式之一（第二种方式是改变模板文件）。改变页面线框，修改页面布局文件；所有其它自定义的设置在页面配置或通过布局文件来执行。</p>
<p>使用布局指令来：</p>
<ul>
<li>移动页面元素到另一个父元素</li>
<li>添加内容</li>
<li>删除页面元素</li>
</ul>
<p>对于所有类型的布局文件来说基础指令集是相同的。这篇文章描述这些基本指令；至于如何在特定布局文件类型中使用的细节，请参阅下一篇文章。</p>
<h2>常用布局指令</h2>
<p>使用下面的布局指令来自定义你的布局：</p>
<ul>
<li><code>&lt;block&gt;</code></li>
<li><code>&lt;container&gt;</code></li>
<li><code>before</code>和<code>after</code>属性</li>
<li><code>&lt;action&gt;</code></li>
<li><code>&lt;referenceBlock&gt;</code>和<code>&lt;referenceContainer&gt;</code></li>
<li><code>&lt;move&gt;</code></li>
<li><code>&lt;update&gt;</code></li>
<li><code>&lt;argument&gt;</code></li>
</ul>
<h3>&lt;block&gt;</h3>
<p>定义一个块</p>
<p>详细信息：块是页面输出呈现出不同内容的单元-一片信息，一个用户界面元素-任何客户视觉上可见的东西。块使用模板来生成HTML。模块的例子有：分类列表，迷你购物车，产品标签和产品列表。</p>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>class（类）</td>
<td>生成特定块的类名，这个类对应一个实际输出的块。</td>
<td>类名</td>
<td>是的</td>
</tr>
<tr class="odd">
<td>name（名字）</td>
<td>用于处理分配到该属性的块，在每个生成的页面中名字必须是唯一的。 如果没有指定就会自动以 <code>ANONYMOUS_<em>n</em></code>的格式分配一个名字</td>
<td>0-9, A-Z, a-z, 下划线 (_), 点(.),破折号(-)。必须以字母开头。区分大小写。</td>
<td>否</td>
</tr>
<tr class="even">
<td>before(在&hellip;&hellip;之前）</td>
<td>用于块的位置。在相同父元素下，出于一个元素之前。在这个值中元素的名字或别名是指定的。使用破折号(-)将元素放在其他 元素之前。详细信息请看<a href="#fedg_xml-instrux_before-after">before和after属性</a></td>
<td>可能值:元素名或破折号(-)</td>
<td>否</td>
</tr>
<tr class="odd">
<td>after（在&hellip;&hellip;之后）</td>
<td>用于块的位置。在相同父元素下，出于一个元素之后。在这个值中元素的名字或别名是指定的。使用破折号(-)将元素放在其他 元素之后。详细信息请看<a href="#fedg_xml-instrux_before-after">before和after属性</a></td>
<td>可能值:元素名或破折号(-)</td>
<td>否</td>
</tr>
<tr class="even">
<td>模板</td>
<td>模板用来呈现该属性分配的块的功能。</td>
<td>模板文件名</td>
<td>否</td>
</tr>
<tr class="odd">
<td>as（别名）</td>
<td>作为父元素范围内的标识</td>
<td>0-9，A-Z，a-z，下划线(_)，点(.)，破折号(-)。区分大小写。</td>
<td>否</td>
</tr>
<tr class="odd">
<td>cacheable（可缓存）</td>
<td>定义块元素是否可缓存。这可以用于卡发目的并为页面动态元素提供服务</td>
<td><code>true（真）</code>或<code>false（假）</code></td>
<td>否</td>
</tr>
</tbody>
</table>
<p>要传递参数，使用<a href="#argument"><code>&lt;argument&gt;&lt;/argument&gt;</code></a>指令。</p>
<h3>&lt;container&gt;</h3>
<p>用于支持其它元素（如块和容器）的没有内容的结构。</p>
<p>详细信息：在视图输出生成时容器渲染子元素。它可以为空或包含一组<code>&lt;container&gt;</code>和<code>&lt;block&gt;</code> 元素。</p>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>名字</td>
<td>用于处理分配到该属性的容器，在每个生成的页面中名字必须是唯一的。</td>
<td>0-9, A-Z, a-z, 下划线 (_), 点(.),破折号(-)。必须以字母开头。区分大小写。</td>
<td>是</td>
</tr>
<tr class="odd">
<td>标签</td>
<td>用于在浏览器展示的任意名字</td>
<td>任何</td>
<td>否</td>
</tr>
<tr class="even">
<td>before</td>
<td>用于块的位置。在相同父元素下，出于一个元素之前。在这个值中元素的名字或别名是指定的。使用破折号(-)将元素放在其他 元素之前。详细信息请看<a href="#fedg_xml-instrux_before-after">before和after属性</a></td>
<td>可能值:元素名或破折号(-)</td>
<td>否</td>
</tr>
<tr class="odd">
<td>after（在&hellip;&hellip;之后）</td>
<td>用于块的位置。在相同父元素下，出于一个元素之后。在这个值中元素的名字或别名是指定的。使用破折号(-)将元素放在其他 元素之后。详细信息请看<a href="#fedg_xml-instrux_before-after">before和after属性</a></td>
<td>可能值:元素名或破折号(-)</td>
<td>否</td>
</tr>
<tr class="odd">
<td>as（别名）</td>
<td>作为父元素范围内的标识</td>
<td>0-9，A-Z，a-z，下划线(_)，点(.)，破折号(-)。区分大小写。</td>
<td>no</td>
</tr>
<tr class="odd">
<td>output</td>
<td>定义是否输出根元素。如果指定元素将被添加到输出列表。（如果没有指定，父元素渲染他的子元素）</td>
<td>除<code>toHtml</code>外的任何值。推荐值为<code>1</code>。</td>
<td>否</td>
</tr>
<tr class="even">
<td>htmlTag（html标签）</td>
<td>输出参数。如果指定，输出被抱进指定的Html标签中</td>
<td>&nbsp;</td>
<td>任何可用的html5标签</td>
<td>否</td>
</tr>
<tr class="odd">
<td>htmlId</td>
<td>输出参数。如果指定，参数值被添加到包着的元素。如果没有包着的元素，该属性就没有效果。</td>
<td>任何可用的html5标签<code>&lt;id&gt;</code>值。</td>
<td>否</td>
</tr>
<tr class="even">
<td>htmlClass（html类）</td>
<td>输出参数。如果指定，参数值被添加到包着的元素。如果没有包着的元素，该属性就没有效果。</td>
<td>任何可用的html5标签<code>&lt;class&gt;</code> 值。</td>
<td>否</td>
</tr>
</tbody>
</table>
<p>布局中使用的示例：</p>
<pre><code>...
&lt;container name="div.sidebar.additional" htmlTag="div" htmlClass="sidebar sidebar-additional" after="div.sidebar.main"&gt;
    &lt;container name="sidebar.additional" as="sidebar_additional" label="Sidebar Additional"/&gt;
&lt;/container&gt;
...
</code></pre>
<p>这将在页面布局中新加一行</p>
<h2 id="fedg_xml-instrux_before-after">before和after属性</h2>
<p>为帮助你按特定的顺序排列元素以满足设计，搜索引擎优化，实用或其它要求，Magento提供了<code>before</code>和<code>after</code>布局属性。</p>
<p>这些可选属性可被用在布局XML文件中，在公用的父元素中控制顺序。下面的表格给出你使用<code>before</code>和<code>after</code>属性后的结果。第一张表使用一个块作为定位元素。</p>
<table>
<tbody>
<tr><th>属性</th><th>值</th><th>描述</th></tr>
<tr class="even">
<td>before</td>
<td>破折号(-)</td>
<td>在父节点中显示在其它元素之前。</td>
</tr>
<tr class="odd">
<td>before</td>
<td>元素名字</td>
<td>块在该名字的元素之前显示。</td>
</tr>
<tr class="even">
<td>before</td>
<td>空值或元素名不存在</td>
<td>使用值<code>after</code>。如果值为空或者元素名不存在则被视为未被定位。</td>
</tr>
<tr class="even">
<td>after</td>
<td>破折号(-)</td>
<td>在父节点中显示在其它元素之后。</td>
</tr>
<tr class="odd">
<td>after</td>
<td>元素名字</td>
<td>块在该名字的元素之后显示。</td>
</tr>
<tr class="even">
<td>after</td>
<td>空值或元素名不存在</td>
<td>使用值<code>before</code>。如果值为空或者元素名不存在则被视为未被定位。</td>
</tr>
</tbody>
</table>
<h3>示例：</h3>
<table>
<tbody>
<tr><th>情况</th><th>结果</th></tr>
<tr class="even">
<td><code>before</code>和<code>after</code>属性都存在</td>
<td><code>after</code>优先。</td>
</tr>
<tr class="odd">
<td>Both <code>before</code> and <code>after</code>属性都不存在或为空</td>
<td>元素被视为未定位。其它元素按指定位置定位。未被定位的元素随机出现在与其它元素定位不冲突的位置。</td>
</tr>
<tr class="even">
<td>几个元素属性值<code>before</code> or <code>after</code>被设置为破折号(-)</td>
<td>所有元素显示在顶部 (或底部，属性为after时)，但该组顺序未被定义。</td>
</tr>
<tr class="odd">
<td>The <code>before</code>或<code>after</code>属性值中的元素不位于与该元素不在同一父节点中</td>
<td>元素处在一个随机位置但不与正确的元素位置冲突</td>
</tr>
</tbody>
</table>
<h3>&lt;action&gt;</h3>
<p><code>&lt;action&gt;</code>指令已被废弃。如果方法生成允许，使用<code>&lt;argument&gt;</code>来访问<code>&lt;block&gt;</code>或<code>&lt;referenceBlock&gt;</code>的公共API。</p>
<p>调用块API的公共方法：</p>
<p>详细信息：在块的生成过程中设置某个方法的执行。<code>&lt;action&gt;</code>结点必须位于块的结点范围。</p>
<p>示例：</p>
<pre><code>
&lt;block class="Magento\Module\Block\Class" name="block"&gt;
    &lt;action method="setText"&gt;
        &lt;argument name="text" translate="true" xsi:type="string"&gt;Text&lt;/argument&gt;
    &lt;/action&gt;
    &lt;action method="setEnabled"&gt;
        &lt;argument name="enabled" xsi:type="boolean"&gt;true&lt;/argument&gt;
    &lt;/action&gt;
&lt;/block&gt;
</code></pre>
<p><code>&lt;action&gt;</code>子节点被翻译成块的方法参数。子节点的名称是任意的。如果<code>&lt;action&gt;</code>下有多个同名的子节点，那么这些子节点会作为数组被传递。</p>
<p>在上面的例子中<code>&lt;arg1&gt;</code>的值作为和<code>&lt;arg2&gt;</code>的值组成的<code>array('one', 'two')</code>中的第一个参数被传递。所有可用的方法取决于块的实现。</p>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>method</td>
<td>块的公用方法类名，在块的生成过程中被调用。</td>
<td>块方法名</td>
<td>是</td>
</tr>
</tbody>
</table>
<p>要传递参数，使用<a href="#argument"><code>&lt;argument&gt;&lt;/argument&gt;</code></a>指令。</p>
<h3>&lt;referenceBlock&gt;和&lt;referenceContainer&gt;</h3>
<p>使用<code>&lt;referenceBlock&gt;</code>和<code>&lt;referenceContainer&gt;</code>来更新对应的<code>&lt;block&gt;</code>或<code>&lt;container&gt;</code>。例如，你如果使用<code>&lt;referenceBlock name="right"&gt;</code>，那么你指向的目标块就是<code>&lt;block name="right"&gt;</code>。</p>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>remove（移除）</td>
<td>允许移除或取消元素的输出，如果一个容器被移除，其子元素也被去除。</td>
<td>真/假</td>
<td>否</td>
</tr>
<tr class="even">
<td>display（显示）</td>
<td>允许禁用特定块或容器及其孩子的渲染(都是通过引用直接设置)。块/容器及它们的孩子各自的PHP对象仍然被生产并可供操作 。</td>
<td>真/假</td>
<td>否</td>
</tr>
</tbody>
</table>
<p><code>remove</code>属性是可选的，默认值为false。在你的布局中设置<code>remove</code>属性值为false来取消块或容器的输出。例如：</p>
<pre><code>&lt;referenceBlock name="block.name" remove="true" /&gt;</code></pre>
<p><code>display</code>属性是可选的，默认值为true。你可以在你的布局中重写这个值。当remove属性为true时，display属性被忽略。例如：</p>
<pre><code>&lt;referenceContainer name="container.name" display="false" /&gt;</code></pre>
<h3>&lt;ltmove&gt;</h3>
<p>设定声明的块或元素以特定的顺序作为另一个元素的子元素。</p>
<p>示例：</p>
<pre><code>&lt;move element="name.of.an.element" destination="name.of.destination.element" as="new_alias" after="name.of.element.after" before="name.of.element.before"/&gt;
</code></pre>
<ul>
<li>如果被移动的元素未被定义，则<code>&lt;move&gt;</code>被跳过。</li>
<li>如果<code>as</code>属性没有被定义，使用现有的元素别名。如果值不可用则用那么值来代替。</li>
<li>在布局生成过程中<code>&lt;move&gt;</code>指令在<code>&lt;remove&gt;</code>指令之前执行。这意味着任何元素移动到预定位置后都将被移除。</li>
</ul>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>element（元素）</td>
<td>要移动的元素的名称。</td>
<td>元素名</td>
<td>是</td>
</tr>
<tr class="odd">
<td>destination（目的地）</td>
<td>目标父元素的名称</td>
<td>元素名</td>
<td>是</td>
</tr>
<tr class="even">
<td>as（别名）</td>
<td>元素在新位置的别名。</td>
<td>0-9，A-Z，a-z，下划线(_)，点(.)，破折号(-)。区分大小写。</td>
<td>否</td>
</tr>
<tr class="odd">
<td>after | before</td>
<td>指定元素相对同级元素的位置。使用破折号（-）时元素在其它元素之后或之前。如果省略该值则元素在其它同级元素之后。</td>
<td>元素名</td>
<td>否</td>
</tr>
</tbody>
</table>
<h3>&lt;update&gt;</h3>
<p>包含一个特定的布局文件，如下使用：</p>
<pre><code>&lt;update handle="{name_of_handle_to_include}"/&gt;</code></pre>
<p>指定的句柄被包括并递归执行。</p>
<h3 id="argument">&lt;argument&gt;</h3>
<p>用于传递参数。</p>
<table>
<tbody>
<tr><th>属性</th><th>描述</th><th>值</th><th>必须性</th></tr>
<tr class="even">
<td>名称</td>
<td>参数名</td>
<td>唯一</td>
<td>是</td>
</tr>
<tr class="odd">
<td>xsi:type</td>
<td>参数类型</td>
<td>string|boolean|object|number|null|array</td>
<td>是</td>
</tr>
<tr class="even">
<td>translate</td>
<td>&nbsp;</td>
<td>真|假</td>
<td>否</td>
</tr>
</tbody>
</table>
<p>要传递多个参数时，使用下面的指令：</p>
<pre><code>&lt;arguments&gt;
   &lt;argument&gt;&lt;/argument&gt;
   &lt;argument&gt;&lt;/argument&gt;
   ...
&lt;/arguments&gt;
</code></pre>
<p>传递的参数为数组时，使用下面的指令：</p>
<pre><code>&lt;argument&gt;
   &lt;item&gt;&lt;/item&gt;
   &lt;item&gt;&lt;/item&gt;
   ...
&lt;/argument&gt;
</code></pre>
<p>在布局中设置的参数值可以在模块中使用<code>get{ArgumentName}()</code>和<code>has{ArgumentName}()</code>方法调用。无论是否有值被设置，最终返回一个布尔值。从<code>name</code>属性获取<code>{ArgumentName}</code>的方法是：获取<code>&lt;argument name="some_string"&gt;</code>值的方法名是<code>getSomeString()</code>。例如：在<code>app/code/Magento/Theme/view/frontend/layout/default.xml</code>布局文件中设置<code>css_class</code>的值：</p>
<pre><code>...
&lt;arguments&gt;
    &lt;argument name="css_class" xsi:type="string"&gt;header links&lt;/argument&gt;
&lt;/arguments&gt;
...
</code></pre>
<p>在<code>app/code/Magento/Theme/view/frontend/templates/html/title.phtml</code>文件中使用<code>css_class</code>的值：</p>
<pre><code>...
$cssClass = $this-&gt;getCssClass() ? ' ' . $this-&gt;getCssClass() : '';
...
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 30 Dec 2015 16:53:01 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento通讯管理]]></title>
      <link>https://www.360magento.com/blog/magento_newsletter/</link>
      <description><![CDATA[<p>告诉你的客户最新促销和折扣活动是很重要的。Magento通讯功能允许店铺管理员给订阅客户发送这些信息。 首先你需要开启客户同意接收订阅，该功能可以在Magento后台<strong>System-&gt; Configuration-&gt; Customers-&gt; Newsletter</strong>区域被打开。展开<strong>Subscription Options</strong>区域，修改<strong>Need to Confirm</strong>值为<strong>Yes</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="enable magento newsletter" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_newsletter1.jpg" width="auto" /></div>
<p>客户可以退订新闻。管理员可以通过下拉列表菜单定义退订电子邮件的发件人和模板。对于成功订阅和确认邮件发送者和模板也可以进行同样的操作。你可以使用同一个，也可以根据自己需求自定义它们。点击保存以确认修改。</p>
<p>下一步，你应该设置通讯模板。进入后台<strong>Newsletter -&gt; Newsletter Templates -&gt; Add New Template</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento new newsletter template" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_newsletter2.jpg" width="auto" /></div>
<p>输入模板名，邮件将被送达的对象，发送者姓名和邮箱以及通讯模板内容。填写完毕后可点击<strong>Preview Template</strong>进行预览，点击<strong>Save Template</strong>按钮保存模板。模板将被添加到对应的列表，你将能够编辑它。</p>
<p>当你计划发送信息给很多收件人时，你应该把列表分成小部分。你可以通过后台<strong>Newsletter -&gt; Newsletter Templates-&gt; Action -&gt; Queue Newsletter</strong>来配置和管理这个功能。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magentoqueue newsletter" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_newsletter3.jpg" width="auto" /></div>
<p>在<strong>Queue Date Start</strong>区域填写邮件发送的时间。这些信息将小批量地离开电子邮件服务器。确认其它选项，准备好后点击<strong>Save Newsletter</strong>按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento newsletter queue information" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_newsletter4.jpg" width="auto" /></div>
<p>你可以找到不同的通讯报道。在后台<strong>Newsletter-&gt; Newsletter Queue</strong>你可以监视通讯队列的进展。你可以在后台Newsletter -&gt; Newsletter Subscribers查看订阅邮件的客户列表。你可以手动取消它们。后台<strong>Newsletter-&gt; Newsletter Problem Reports</strong>区域显示在通讯发送过程中出现的错误，你可以采取必要的步骤来解决它们。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 29 Dec 2015 16:04:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento客户管理]]></title>
      <link>https://www.360magento.com/blog/magento_customer_manager/</link>
      <description><![CDATA[<p>新客户可以通过首页<strong>My Account</strong>或者下单过程来注册到你的网站。他们应该点击<strong>Create an Account</strong>按钮并填写详细信息：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento customer create" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_customer_manager1.jpg" width="auto" /></div>
<p>你可以通过后台Customers区域来创建新客户或者管理已有客户：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento customer manager" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_customer_manager2.jpg" width="auto" /></div>
<p>点击<strong>Edit</strong>按钮可改变客户详细信息。你可以改变所有的客户详细信息，包括用户名和密码，地址，监控订单，购物车，收藏产品，产品评价和标签，订阅的管理。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento customer edit" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_customer_manager3.jpg" width="auto" /></div>
<p>你可以通过后台<strong>Customers-&gt;Customer Groups</strong>来创建和管理客户组：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento customer group manager" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_customer_manager4.jpg" width="auto" /></div>
<p>你可以从后台<strong>Customers-&gt;Online Customers</strong>来观察在线的用户。你将要发送个客户的订阅信息在后台<strong>Newsletter</strong>处被撰写和管理。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento newsletter" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_customer_manager5.jpg" width="auto" /></div>
<p>你可以创建模板，管理订阅信息邮件传出的队列，订阅发送对象和问题报告的检查。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 28 Dec 2015 15:23:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2定位模板，布局和样式]]></title>
      <link>https://www.360magento.com/blog/magento2-locate-files/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>当你创建一个Magento主题时，你可能需要为默认主题和模型视图文件创建重写文件。那么在此之前，你必须决定Magento使用的是哪个模板，布局和样式文件。本文就描述如何做到这一点。</p>
<h2>定位模板</h2>
<p>要定位特定部分对应的前端或后台模块，你可以使用Magento内置的模板提示。</p>
<p>开启模板提示：</p>
<ol>
<li>点击<strong>Stores &gt; Configuration &gt; ADVANCED &gt; Developer</strong>。</li>
<li>在左上角的<strong>Scope</strong>下拉列表里选择你想要开启模板提示的视图。</li>
<li>在<strong>Debug</strong>标签里，设置<strong>Template Path Hints for storefront</strong>为<strong>Yes</strong>。要开启后台通道提示，设置<strong>Template Path Hints for Admin</strong>为<strong>Yes</strong>。</li>
<li>保存更改，点击右上角的<strong>Save Config</strong>。</li>
</ol>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 templates path hint" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-locate-files1.png" width="860px" /></div>
<p>现在，你已经开启了模板提示，刷新你想要修改的页面，查看模板文件路径或者模板提示显示的文件。</p>
<p>例如，开启模板提示后的产品详细页看起来是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 category page hint" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-locate-files2.png" width="860px" /></div>
<p>在本示例中，迷你购物车页面元素被定义在<code>&lt;Magento_Checkout_module_dir&gt;/view/frontend/templates/cart/minicart.phtml</code>模板。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 mini cart page" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-locate-files3.png" width="860px" /></div>
<p>（模板名称在元素上面）</p>
<p>开启模板提示的后台Customer页面看起来是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 admin template hints" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-locate-files4.png" width="860px" /></div>
<p>另外，你可以在文件系统中通过搜索系统生成的标题，CSS类名，块标题，标签或链接文字来找到对应的模块。例如，使用一个浏览器调试工具，你可以看到迷你购物车块的css类是<code>minicart-wrapper</code>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 minicart block css" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-locate-files5.png" width="860px" /></div>
<p>在app目录下搜索&ldquo;minicart-wrapper&rdquo;，得到的<code>.phtml</code>文件是<code>app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml</code>。由于不推荐修改默认文件，如果你想要修改这个模板就需要添加重写文件。重写模板的细节将会在后面的《自定义主题模板》中讲解。</p>
<h2>定位布局</h2>
<p>和模板一样，布局被存储在每个模型基础文件中。根据你感兴趣的元素位于哪个模板的模型，你可以轻松地定位布局文件。要定位模板，你可以使用模板提示或者在app目录下使用文本搜索。</p>
<p>在你决定模型以后，你可以在下面的位置中搜索布局：</p>
<ol>
<li><code>&lt;current_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/</code></li>
<li><code>&lt;parent_theme(s)_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/layout/</code></li>
<li><code>&lt;module_dir&gt;/frontend/layout/</code></li>
<li><code>&lt;module_dir&gt;/view/base/layout/</code></li>
</ol>
<p>这里没有直接的算法来发现准确的布局文件，但是大部分情况下，布局文件名是自我描述性的。你也可以搜索它们提到的对应模块。</p>
<p>示例：</p>
<p>比方说，当Blank主题被Magento应用为店铺视图时，你要定位在前端显示迷你购物车的布局文件。</p>
<p>使用模板提示我们发现对应的模板是<code>app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml</code>，由路径我们发现它是属于<code>Magento_Checkout</code>模型的。</p>
<p>让我们根据回退计划来寻找布局：</p>
<ol>
<li>检查<code>app/design/frontend/Magento/blank/Magento_Checkout/layout</code>，在这个目录中搜索模板名称&ldquo;minicart.phtml&rdquo;。没有找到相匹配的文件，所以我们进行回退级别的下一级，父主题布局。</li>
<li>在主题配置文件<code>theme.xml</code>中我们可以找到父主题的信息，父主题的名字在<code>&lt;parent&gt;&lt;/parent&gt;</code>节点指定。在<code>app/design/frontend/Magento/blank/theme.xml</code>中没有<code>&lt;parent&gt;节点，这意味着Blank主题没有父主题。所以我们该搜索回退等级的下一级：模型布局。</code></li>
<li>Magento_Checkout布局位于<code>app/code/Magento/Checkout/view/frontend/layout/</code>。在这个目录中搜索&ldquo;<code>minicart.phtml</code>&rdquo;，我们找到了要寻找的布局<code>app/code/Magento/Checkout/view/frontend/layout/default.xml</code>。</li>
</ol>
<p>在定位了必要的布局文件，你可以在你的主题文件夹中创建对应名字的主题来重写或者扩展主题的内容。</p>
<h2>定位样式</h2>
<p>要定位一个被应用到特定元素的CSS规则，找到包含这个元素页面的模板。或者你可以使用浏览器调试工具来定位类名。找到类名之后，在主题和模型样式目录中使用文本搜索来定位要找的<code>.less</code>或<code>.css</code>文件。根据下面的回退计划来搜索：</p>
<ol>
<li>主题样式 <code>&lt;current_theme_dir&gt;/web/css/</code></li>
<li>模型主题样式 <code>&lt;current_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web/css/</code></li>
<li>父主题样式 <code>&lt;parent_theme_dir&gt;/web/css/</code></li>
<li>前端模型样式 <code>&lt;module_dir&gt;/view/frontend/web/css/</code></li>
<li>base模型样式 <code>&lt;module_dir&gt;/view/base/web/css/</code></li>
</ol>
<p>示例：</p>
<p>当Blank主题被Magento应用为店铺视图时，让我们找出用于前端显示迷你购物车的CSS类。 在迷你购物车模板<code>app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml</code>中最高级的元素有<code>minicart-wrapper</code>类。所以，我们根据回退计划搜索&ldquo;<code>minicart-wrapper</code>&rdquo;。</p>
<ol>
<li>在<code>app/design/frontend/Magento/blank/web/css</code>搜索，返回无结果。</li>
<li>搜索<code>app/design/frontend/Magento/blank/Magento_Checkout/web/css</code>。&ldquo;<code>minicart-wrapper</code>&rdquo;样式被定义在<code>app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less</code>。</li>
</ol>
<p>在确定定义类的<code>.css</code>或<code>.less</code>文件后，你可以在你自定义的<code>.css</code>或<code>.less</code>中重写默认的类。详细的信息会在后面的CSS文章中讲解。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 27 Dec 2015 13:02:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2主题继承]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-inherit/</link>
      <description><![CDATA[<h2>本章内容</h2>
<p>主题继承使你可以轻松地扩展主题和减少维护工作。你可以使用现有的主题作为定制开发的基础，或者细微的店面设计更新，像节假日装饰。你可以添加重写和扩展文件，而不是复制原主题文件做修改。</p>
<p>主题继承的级别是不限定的。</p>
<p>主题继承是基于回退机制（保证如果一个视图文件没有在当前主题中被找到，系统就会在祖先主题，模型视图文件或者库中搜索）。 回退的顺序与静态文件（CSS，JavaScript，字体和图像），其它类型主题文件略有不同。本文描述每种主题文件的回退并提供如何重写祖先主题和模型设计的概念。</p>
<p>有关开发主题组件的全面信息，请参阅Magento2教程的后续章节。</p>
<h2>设置一个父主题</h2>
<p>一个父主题在子主题的<code>theme.xml</code>声明文件中被指明。</p>
<p>例如：OrangeCo的Orange主题继承自Magento的Blank主题。继承被声明在<code>app/design/frontend/OrangeCo/orange/theme.xml</code>，代码如下：</p>
<pre><code>&lt;theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd"&gt;
     &lt;title&gt;Orange&lt;/title&gt;
     &lt;parent&gt;Magento/blank&lt;/parent&gt; 
     &lt;media&gt;
         &lt;preview_image&gt;media/preview.jpg&lt;/preview_image&gt; 
     &lt;/media&gt;
&lt;/theme&gt;
</code></pre>
<p>父主题和子主题可以属于不同的供应商。例如，你自定义的主题可以继承Magento的Blank主题。</p>
<h2>重写静态资产</h2>
<p>静态资产，或静态视图文件，是样式，JavaScript，图像和字体。</p>
<p>要自定义父主题、模型视图或库文件里的视图文件，你可以通过添加一个相同名字的文件到相关位置来重写它们。特定的目录（系统在回退过程中搜索的地方）取决于模型内容是否对文件已知。下面是对两种情况的描述：</p>
<p>如果模型内容没有为文件做定义：</p>
<ol>
<li>当前主题静态文件：<code>&lt;theme_dir&gt;/web/</code></li>
<li>祖先静态文件，递归，直到到达一个没有父类的主题：<code>&lt;parent_theme_dir&gt;/web/</code></li>
<li>库静态视图文件：<code>lib/web/</code></li>
</ol>
<p>如果模型内容为文件做了定义：</p>
<ol>
<li>当前主题模型静态文件：<code>&lt;ttheme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web/</code>. 例如：<code>app/design/frontend/OrangeCorp/orange/Magento_Catalog/web/</code></li>
<li>祖先静态文件，递归，直到到达一个没有父类的主题：<code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/web/</code></li>
<li>前端模型静态视图文件：<code>&lt;module_dir&gt;/view/frontend/web/</code></li>
<li>base区域模型静态视图文件：<code>&lt;module_dir&gt;/view/base/web/</code></li>
</ol>
<p>示例：</p>
<p>一家名为OrangeCo的公司有一个名为Orange的主题。主题文件位于：<code>app/design/frontend/OrangeCo/orange</code>。Orange继承自Magento的Blank主题。</p>
<p>让我们想像一下，OrangeCo需要添加一些冬季假期装饰。所以它创建以一个继承自Orange的新主题<code>orange_winter</code>，位于<code>app/design/frontend/OrangeCo/orange_winter</code>。在Orange主题中底部背景图位于<code>app/design/frontend/OrangeCo/orange/web/images/background.jpg</code>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 theme background1" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-theme-inherit1.jpg" width="auto" /></div>
<p>OrangeCo希望它被替换成一个节日的背景。于是一个有同样名字的新的背景图被放在<code>app/design/frontend/OrangeCo/orange_winter/web/images/background.jpg</code></p>
<p>当Orange Winter主题被应用，新的节日图片就会重写Orange主题中的图片，那么前台效果就是这样：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 theme background2" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-theme-inherit2.jpg" width="auto" /></div>
<h2>重写模板</h2>
<p>模板的回退计划如下（模型内容对它们来说是已知的）：</p>
<ol>
<li>当前主题模块：<code>&lt;theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/templates</code></li>
<li>祖先主题模块，递归，直到到达一个没有父类的主题：<code>&lt;parent_theme_dir&gt;/&lt;Namespace&gt;_&lt;Module&gt;/templates</code></li>
<li>模型模板： <code>&lt;module_dir&gt;/view/frontend/templates</code></li>
</ol>
<p>所以如果你需要自定义一个特定的模板，你需要创建一个同样名字的模板放在主题模型文件<code>../templates/&lt;path_to_template&gt;</code> 目录下。其中，<code>&lt;path_to_template&gt;</code>是原始模板的路径。</p>
<p>例如：你想要重写<code>&lt;Magento_Catalog_module_dir&gt;/view/frontend/templates/category/widget/link/link_block.phtml</code>，那么<code>&lt;path_to_template&gt;</code>就是<code>category/widget/link/</code>。</p>
<p>示例：在默认情况下，根据模型文件，迷你购物车中的产品是在Checkout按钮之下的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 theme minicart1" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-theme-inherit3.png" width="auto" /></div>
<p>顺序是在<code>&lt;Magento_Checkout_module_dir&gt;/view/frontend/templates/cart/minicart.phtml</code>模型文件中被定义的。Blank主题没有重写这个模板。OrangeCo希望他们的产品展示在Go to Checkout按钮之前。他们需要在Orange主题文件夹内为对应的模型添加一个重写模板：<code>app/design/frontend/OrangeCo/orange/Magento_Checkout/templates/cart/minicart.phtml</code>。注意，主题<code>templates</code>目录中的模块路径与模型相对应。改变顺序之后，OrangeCo的购物车看起来是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 theme minicart2" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-theme-inherit4.png" width="auto" /></div>
<p>你可以在之后的文章中找到详细的代码和其它任务。</p>
<h2>扩展布局</h2>
<p>布局进程机制不涉及回退。系统按下面的顺序收集主题文件：</p>
<ol>
<li>当前主题布局：<code>&lt;theme_dir&gt;/&lt;Vendor&gt;_&lt;Module&gt;/layout/</code></li>
<li>祖先主题布局，递归，直到到达一个没有父类的主题：<code>&lt;parent_theme_dir&gt;/&lt;Vendor&gt;_&lt;Module&gt;/layout/</code></li>
<li>前端区域的模型主题：<code>&lt;module_dir&gt;/view/frontend/layout/</code></li>
<li>Base区域的模型主题：<code>&lt;module_dir&gt;/view/base/layout/</code></li>
</ol>
<p>与模板、图片不同，主题不仅能被重写还能被扩展。推荐的自定义布局是通过创建主题扩展布局文件来扩展它。 要添加一个扩展布局文件：把你自定义的布局文件放在：<code>&lt;theme_dir&gt;/&lt;Vendor&gt;_&lt;Module&gt;/layout/</code>目录下。</p>
<p>例如：</p>
<p>OrangeCo决定移除<code>&lt;Magento_Theme_module_dir&gt;/view/frontend/layout/default.xml</code>中定义的底部&ldquo;Report bugs&rdquo;链接。要实现它，他们添加了一个扩展主题文件在<code>app/design/frontend/OrangeCo/orange/Magento_Theme/layout/default.xml</code>。</p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;remove name="report.bugs"/&gt;
   &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p>更多关于主题扩展的知识将会在《扩展主题》中提到。</p>
<h3>重写布局</h3>
<p>虽然不推荐重写布局，但这也是特定自定义任务的一种解决方式。要重写祖先主题的布局文件：</p>
<ul>
<li>创建同样名字的布局文件到<code>&lt;theme_dir&gt;/&lt;Vendor&gt;_&lt;Module&gt;/layout/override/theme/&lt;Vendor&gt;/&lt;ancestor_theme&gt;</code>目录下</li>
</ul>
<p>要重写模型布局文件（base布局）</p>
<ul>
<li>创建同样名字的布局文件到<code>&lt;theme_dir&gt;/&lt;Vendor&gt;_&lt;Module&gt;/layout/override/base</code></li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 25 Dec 2015 15:57:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为Magento2主题配置图片性能]]></title>
      <link>https://www.360magento.com/blog/magento2-images-properties/</link>
      <description><![CDATA[<h2>为Magento2主题配置图片性能</h2>
<p>Magento2中用于前台的产品图片性能都被存储在<code>view.xml</code>配置文件中。本文提供所有的可用性能细节及配置方法。</p>
<h2>在view.xml中配置图片性能</h2>
<p><code>view.xml</code>通常位于主题的：</p>
<pre><code>&lt;theme_dir&gt;/etc/view.xml</code></pre>
<p>例如，<code>view.xml</code>在Magento Blank主题中的位置是：</p>
<pre><code>app/design/frontend/Magento/blank/etc/view.xml</code></pre>
<p>在<code>view.xml</code>中，图片性能被配置在<code>&lt;images module="Magento_Catalog"&gt;</code>元素内：</p>
<pre><code>&lt;images module="Magento_Catalog"&gt;
...
&lt;images/&gt;
</code></pre>
<p>每种被图片性能配置的类型图片是通过<code>&lt;image&gt;</code>元素的<code>id</code>和<code>type</code>属性定义的：</p>
<pre><code>&lt;images module="Magento_Catalog"&gt;
	&lt;image id="unique_image_id" type="image_type"&gt;
	...
	&lt;/image&gt;
&lt;images/&gt;
</code></pre>
<p>下面的表格描述属性的详情：</p>
<table>
<tbody>
<tr><th>属性</th><th>类型</th><th>描述</th></tr>
<tr>
<td><code> id（标识） </code></td>
<td>string（字符串）</td>
<td>
<p>图片标识，主题中是唯一的</p>
<p>可以是任何值，但在Magento主题中<code>ID</code>是有意义的并描述图像的位置。</p>
<p>例如，购物车中的交叉销售产品图片&lt;code&gt;ID是<code>cart_cross_sell_products</code>.</p>
<p><code>ID</code>被用在<code>.phtml</code>模版来给特定网页特定位置的图片定义类型和性能。</p>
</td>
</tr>
<tr>
<td><code> type（类型） </code></td>
<td>string（字符串）</td>
<td>通过指定的&lt;code&gt;ID来定义图片的类型。允许值为：
<ul>
<li><code>image</code> - 对应Magento2后台中的Base Image</li>
<li><code>small_image</code> - 对应Magento2后台中的Small Image</li>
<li><code>swatch_image</code> - 对应Magento2后台中的Swatch Image</li>
<li><code>swatch_thumb</code> - 对应Magento2后台中的Swatch Image</li>
<li><code>thumbnail</code> - 对应Magento2后台中的Thumbnail Image</li>
</ul>
下面的图片说明了Magento2后台中的各种图片角色:<br /> <img class="attachment-full wp-post-image" alt="magento2 cache" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_image_roles.png" width="232px" /></td>
</tr>
</tbody>
</table>
<p>图片性能通过对应的元素而被定义，例如：</p>
<pre><code>&lt;images module="Magento_Catalog"&gt;
    &lt;image id="unique_image_id" type="image"&gt;
        &lt;width&gt;100&lt;/width&gt; &lt;!-- Image width in px --&gt; 
        &lt;height&gt;100&lt;/height&gt; &lt;!-- Image height in px --&gt;
    &lt;/image&gt;
&lt;/images&gt;
</code></pre>
<p>下面表格是所有可配置性能的列表：</p>
<table>
<tbody>
<tr><th>元素</th><th>属性值类型</th><th>描述</th><th>属性值必须性</th></tr>
<tr>
<td><code> width</code></td>
<td>整型</td>
<td>以像素为单位的图像宽度。</td>
<td>可选填</td>
</tr>
<tr>
<td><code> height</code></td>
<td>整型</td>
<td>以像素为单位的图像高度。</td>
<td>可选填</td>
</tr>
<tr>
<td><code> constrain</code></td>
<td>布尔型</td>
<td>如果被设置为<code>true</code>时，当图像小于配置值时不会扩大。默认值为：<code>true</code>。</td>
<td>可选填</td>
</tr>
<tr>
<td><code> aspect_ratio</code></td>
<td>布尔型</td>
<td>如果被设置为<code>true</code>，图片比例不会改变即使配置中需求。默认值为：<code>true</code>.</td>
<td>可选填</td>
</tr>
<tr>
<td><code> frame</code></td>
<td>布尔型</td>
<td>如果被设置为<code>true</code>, 图片不被裁剪。默认值为：<code>true</code>。只有当<code>aspect_ratio</code>被设置为 <code>true</code>时才可被应用。</td>
<td>可选填</td>
</tr>
<tr>
<td><code> 透明度 </code></td>
<td>布尔型</td>
<td>如果被设置为<code>true</code>，图片的透明背景被保存。如果设置为<code>false</code>，图片背景为白色（默认的)。你可以使用 <code>background</code>字段来设置背景色。默认值为：<code>true</code>。</td>
<td>可选填</td>
</tr>
<tr>
<td><code> 背景 </code></td>
<td>数组</td>
<td>图片的背景色。如果<code>transparency</code>被设置为<code>true</code>时，不被应用到透明背景图。</td>
<td>可选填</td>
</tr>
</tbody>
</table>
<h3>目录图片大小调整命令</h3>
<p>Magento_Catalog模型提供调整所有产品图片的Magento CLI命令。调整后的图片被存储在<code>/pub/media/catalog/product/cache</code>目录下。</p>
<p>catalog:images:resize命令没有选项和参数。</p>
<p>基本语法：<code>bin/magento catalog:images:resize</code></p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 21 Dec 2015 14:36:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento2后台应用和配置一个主题]]></title>
      <link>https://www.360magento.com/blog/theme-apply-configure/</link>
      <description><![CDATA[<h2>在Magento2后台应用和配置一个主题</h2>
<p>本文描述如何将一个主题应用到你的商店，禁用缓存和添加一个与主题无关的logo。</p>
<h2>禁用系统缓存</h2>
<p>当Magento系统缓存开启时，你必须每次都清理缓存来查看你的设计给前端带来的改变。为了避免这种情况，在更改设计的同时禁用某些系统缓存。你需要要这么做：</p>
<ol>
<li>后台进入<strong> System &gt; Tools &gt; Cache Management</strong>。</li>
<li>选择Layouts, Blocks HTML output, View files fallback, View files pre-processing and Page Cache cache types。</li>
<li>在<strong>Action</strong>选项中选择<strong>Disable</strong>并点击<strong>Submit</strong>。选择的缓存类型会显示成红色的DISABLED。</li>
</ol>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 cache" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2_cache.png" width="840px" /></div>
<p>如果你第二次应用一个主题，你可能需要手动清除<code>pub/static/frontend/&lt;Vendor&gt;/&lt;theme&gt;</code>目录。这个目录存储已发布的静态文件。</p>
<h2>应用一个主题</h2>
<p>在将你的主题添加到文件系统以后，你可以将它应用到你的店铺。去应用一个主题：</p>
<ol>
<li>进入后台<strong> CONTENT &gt; Design &gt; Themes</strong> 。确认你的主题在主题列表里。</li>
<li>进入<strong> Stores &gt; Configuration &gt; Design</strong> 。</li>
<li>在Scope下拉框里选择你主题想要应用的店视图。</li>
<li>在<strong> Design Theme</strong> 标签的<strong> Design Theme</strong> 下拉框里选择你最新创建的主题。</li>
<li>点击<strong> Save Config</strong> 。</li>
<li>查看效果，重载前端页面。</li>
</ol>
<p>如果在你的Magento后台面板中缓存是可用的，那么你必须清理缓存来查看效果。你可能还需要手动清理<code>pub/static/frontend</code>文件夹中已发布的静态文件。</p>
<h2>添加一个设计例外</h2>
<p>你可以为特定的用户代理设置指定的主题，而不用创建一个独立的店铺视图。要添加设计例外：</p>
<ol>
<li>进入后台<strong> CONTENT &gt; Design &gt; Themes</strong> 。确认你的主题在主题列表里。</li>
<li>进入<strong> Stores &gt; Configuration &gt; Design</strong> 。</li>
<li>在<strong> Scope下</strong> 拉框里选择你主题想要应用的店视图。</li>
<li>点击<strong> Design Theme</strong> 标签<strong> User-Agent Exceptions</strong> 旁的<strong> Add</strong> 。</li>
<li>在<strong> Search String</strong> 框里指明用户代理使用普通字符串或常规异常（PCRE)。在<strong> Design Theme</strong> 下拉列表里选择与代理匹配的主题。</li>
<li>点击<strong>Save Config</strong>。</li>
</ol>
<p>如果在你的Magento后台面板中缓存是可用的，那么你必须清理缓存来查看效果。</p>
<h2>添加一个与主题无关的logo</h2>
<p>你可能想要设置一个永久性的店铺logo，不论应用哪个主题它都会显示在店铺前端。要添加一个与主题无关的永久性logo</p>
<ol>
<li>进入后台<strong>Stores &gt; Configuration &gt; Design</strong>。</li>
<li>在<strong>Scope</strong>下拉框里选择你主题想要应用的店视图。</li>
<li>在<strong>Design</strong>的<strong>General</strong>区域展开<strong>Header</strong>标签。</li>
<li>在<strong>Logo Image</strong>处选择在文件系统中存储的logo图片。</li>
<li>上传文件。</li>
<li>点击<strong>Save Config</strong>。</li>
</ol>
<p>你在这里添加的logo被存储在<code>/pub/media/logo/default/</code>目录下。</p>
<p>如果在你的Magento后台面板中缓存是可用的，那么你必须清理缓存来查看效果。</p>
<p>要删除永久性logo，只需到相同位置，点击右侧的Delete即可。</p>
<h2>清除缓存</h2>
<p>如果在你的Magento后台面板中缓存是可用的，那么在你应用主题，添加主题例外，添加logo以及执行其他任务后都需要清理缓存。会有一条系统信息提醒你，无效的缓存类型应该被刷新。</p>
<ol>
<li>点击<strong>System &gt; Cache Management</strong>。</li>
<li>清除无效的缓存类型。</li>
</ol>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 19 Dec 2015 14:38:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2主题结构]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-structure/</link>
      <description><![CDATA[<h2>Magento2主题结构</h2>
<p>店面的主题通常位于<code>app/design/frontend/&lt;Vendor&gt;（供应商）/</code>之下。虽然在技术上它们可以放在其它目录。例如Magento2的内置主题在<code>vendor/magento/theme-frontend-&lt;theme_code&gt;</code>之下，这是因为Magento2的实例是从Composer部署的。</p>
<p>每个主题必须存储在单独的目录：</p>
<pre><code>app/design/frontend/&lt;Vendor&gt;/
├── &lt;theme1&gt;
├── &lt;theme2&gt;/
├── &lt;theme3&gt;
├--...
</code></pre>
<h2>主题组件</h2>
<p>Magento的主题目录结构通常是这样的：</p>
<pre><code>&lt;theme_dir&gt;/
├── &lt;Vendor&gt;_&lt;Module&gt;/ 
│	├── web/
│	│	├── css/
│	│	│	├── source/
│	├── layout/
│	│	├── override/
│	├── templates/
├── etc/
├── i18n/ 
├── media/
├── web/
│	├── css/
│	│	├── source/ 
│	├── fonts/
│	├── images/
│	├── js/
├── composer.json 
├── registration.php 
├── theme.xml 
</code></pre>
<p>让我们仔细看看每一个特定的子目录。</p>
<table>
<tbody>
<tr><th>目录</th><th colspan="1">必须性</th><th>描述</th></tr>
<tr>
<td colspan="1"><code> /&lt;Vendor&gt;_&lt;Module&gt; </code></td>
<td colspan="1">非必须</td>
<td colspan="1">指定模型的样式，布局和模板.</td>
</tr>
<tr>
<td colspan="1"><code>/&lt;Vendor&gt;_&lt;Module&gt;/web/css/source</code></td>
<td colspan="1">非必须</td>
<td colspan="1">指定模型的样式（.css或.less）。一般模型样式在<code>module.less</code>中，挂件（widgets）的样式在 <code>widgets.less</code>中。</td>
</tr>
<tr>
<td colspan="1"><code>/&lt;Vendor&gt;_&lt;Module&gt;/layout</code></td>
<td colspan="1">非必须</td>
<td colspan="1">扩展默认模型或父主题的布局文件</td>
</tr>
<tr>
<td colspan="1"><code>/&lt;Vendor&gt;_&lt;Module&gt;/layout/override/base</code></td>
<td colspan="1">非必须</td>
<td colspan="1">重写默认模型布局的布局文件</td>
</tr>
<tr>
<td colspan="1"><code>/&lt;Vendor&gt;_&lt;Module&gt;/layout/override/&lt;parent_theme&gt;</code></td>
<td colspan="1">非必须</td>
<td colspan="1">重写父主题中模型布局的布局文件</td>
</tr>
<tr>
<td colspan="1"><code>/&lt;Vendor&gt;_&lt;Module&gt;/templates</code></td>
<td colspan="1">非必须</td>
<td colspan="1">该目录包含重写默认模型模版或父主题模版的主题模板。自定义模版也在该目录下。</td>
</tr>
<tr>
<td colspan="1"><code> /etc/view.xml </code></td>
<td colspan="1">对单个主题必须, 若有父主题则为非必须</td>
<td colspan="1">该文件包含店铺前端产品图片和缩略图的配置。</td>
</tr>
<tr>
<td colspan="1">/<code>i18n</code></td>
<td colspan="1">非必须</td>
<td colspan="1">带有翻译的.csv文件</td>
</tr>
<tr>
<td colspan="1"><code>/media</code></td>
<td colspan="1">必须</td>
<td colspan="1">该目录包含一个主题预览(你主题的一张截图)。</td>
</tr>
<tr>
<td colspan="1"><code>/web</code></td>
<td colspan="1">非必须</td>
<td colspan="1">可被前端直接读取的静态文件</td>
</tr>
<tr>
<td colspan="1"><code>/web/css/source</code></td>
<td colspan="1">非必须</td>
<td colspan="1">该目录包含主题<code>less</code>配置文件（从Magento UI库里调用全局文件），和<code>theme.less</code>（重 写默认变量值）</td>
</tr>
<tr>
<td colspan="1"><code>/web/css/source/lib</code></td>
<td colspan="1">非必须</td>
<td colspan="1">重写UI库的视图文件存储在<code>lib/web/css/source/lib</code></td>
</tr>
<tr>
<td colspan="1"><code>/web/fonts</code></td>
<td colspan="1">非必须</td>
<td colspan="1">主题字体。</td>
</tr>
<tr>
<td colspan="1"><code>/web/images</code></td>
<td colspan="1">非必须</td>
<td colspan="1">主题中使用的图片。</td>
</tr>
<tr>
<td colspan="1"><code>/web/js</code></td>
<td colspan="1">非必须</td>
<td colspan="1">主题JavaScript文件。</td>
</tr>
<tr>
<td colspan="1"><code> /composer.json </code></td>
<td colspan="1">非必须</td>
<td colspan="1">描述主题依赖关系和一些元信息。如果你的主题是composer包的话，就在这里。</td>
</tr>
<tr>
<td colspan="1"><code>/registration.php</code></td>
<td colspan="1">必须</td>
<td colspan="1">将你的主题注册到系统。</td>
</tr>
<tr>
<td colspan="1"><code>/theme.xml</code></td>
<td colspan="1">必须</td>
<td colspan="1">由于该文件声明一个主题作为系统部件，所以它是强制性的。它包含基本元信息，如主题名和父主题名（主题继承自已有主题）。该文件让Magento识别你的主题。</td>
</tr>
</tbody>
</table>
<h2>主题文件</h2>
<p>除了配置文件和主题的元数据文件，所有主题文件分为以下两类：</p>
<ul>
<li>静态视图文件</li>
<li>动态视图文件</li>
</ul>
<h3>静态视图文件</h3>
<p>一组是由服务器返回到浏览器，不进行任何处理的主题文件，被称为一个主题的静态文件。</p>
<p>静态文件可以位于一个主题目录如下：</p>
<pre><code>&lt;theme_dir&gt;/
├── media/
├── web
│	├── css/ (except the "source" sub-directory)
│	├── fonts/
│	├── images/
│	├── js/
</code></pre>
<p>静态文件和其他主题文件之间的主要区别是，静态文件出现在网页作为引用的文件，而其它主题文件参加页面生成，但并未明确地被引用。</p>
<p>静态视图的文件可以通过从店面的直接链接进行访问，以此与公共主题文件区分开。</p>
<h3>动态视图文件</h3>
<p>被服务器处理或执行用来返回结果给客户的视图文件。它们是： .less 文件，模板（templates），布局（layouts）。 动态视图文件在一个主题目录中的位置，如下所示：</p>
<pre><code>&lt;theme_dir&gt;/
├── Magento_&lt;module&gt;/ 
│	├── web/
│	│	├── css/
│	│	│	├── source/
│	├── layout/
│	│	├── override/
│	├── templates/
├── web/
│	├── css/
│	│	├── source/
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 18 Dec 2015 14:05:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[创建magento2主题]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-create/</link>
      <description><![CDATA[<h2>创建一个主题</h2>
<p>本文讨论如何创建一个主题，怎么为主题添加一个logo，如何定义图片尺寸。</p>
<h3>文章内容</h3>
<ul>
<li><a href="#create-theme-directory">创建一个主题目录</a></li>
<li><a href="#declare-your-theme">声明你的主题</a></li>
<li><a href="#make-theme-composer">为你的主题写一个Composer包（可选）</a></li>
<li><a href="#add-registration">添加registration.php</a></li>
<li><a href="#configure-images">配置图片</a></li>
<li><a href="#create-static-directories">创建静态文件目录</a></li>
<li><a href="#theme-directory-structure">当前你主题的目录结构</a></li>
<li><a href="#declaring-theme-logo">声明主题logo</a></li>
</ul>
<h2 id="create-theme-directory">创建一个主题目录</h2>
<p>为你的主题创建目录：</p>
<p>1.进入<code>/app/design/frontend.</code></p>
<p>2.根据你供应商的名字创建一个新的目录<code>/app/design/frontend/</code></p>
<p>3.在vendor目录下，根据你的主题创建一个目录</p>
<pre><code>/app/design/frontend/
├── &lt;Vendor&gt;/
│   │   ├──...&lt;theme&gt;/
│   │   │   ├── ...
│   │   │   ├── ...
</code></pre>
<p>文件夹名称通常匹配主题代码的命名：供应商认可的任何字幕数字字符集。该公约仅仅是一个建议，并未阻止以另一种方式命名。</p>
<h2 id="declare-your-theme">声明你的主题</h2>
<p>在创建了主题目录以后，你必须创建包含至少主题名和父主题名（如果主题继承自一个主题）的<code>theme.xml</code>。你也可以指定主题预览图的存储位置。</p>
<p>1.添加或者拷贝已有的<code>theme.xml</code>到你的主题目录<code>app/design/frontend//</code>下。</p>
<p>2.用下面的示例来配置<code>theme.xml</code>：</p>
<pre><code>&lt;theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/theme.xsd"&gt;
     &lt;title&gt;New theme &lt;!-- your theme's name --&gt;
     &lt;parent&gt;Magento/blank&lt;/parent&gt; &lt;!-- the parent theme, in case your theme inherits from an existing theme --&gt;
     &lt;media&gt;
         &lt;preview_image&gt;media/preview.jpg&lt;/preview_image&gt; &lt;!-- the path to your theme's preview image --&gt;
     &lt;/media&gt;
 &lt;/theme&gt;
</code></pre>
<h2 id="make-theme-composer">为你的主题写一个Composer包（可选）</h2>
<p>Magento默认的主题被创建为Composer包。要把你的主题写成一个包，添加一个<code>composer.json</code>文件到主题目录下并在包服务器上注册这个包。默认的公共包装服务器https://packagist.org/。</p>
<pre><code>composer.json</code></pre>
<p>提供主题相关信息。下面是一个主题code&gt;composer.json的示例：</p>
<pre><code>
{
    "name": "magento/theme-frontend-luma",
    "description": "N/A",
    "require": {
        "php": "~5.5.0|~5.6.0|~7.0.0",
        "magento/theme-frontend-blank": "100.0.*",
        "magento/framework": "100.0.*"
    },
    "type": "magento2-theme",
    "version": "100.0.1",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "autoload": {
        "files": [
            "registration.php"
        ]
    }
}
</code></pre>
<h2 id="add-registration">添加registration.php</h2>
<p>要在系统中注册你的主题，你需要用下面的内容在你的主题目录下创建一个<code>registration.php</code>：</p>
<pre><code>&lt;?php
/**
* Copyright &copy; 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::THEME,
    'frontend/&lt;Vendor&gt;/&lt;theme&gt;',
    __DIR__
);
</code></pre>
<p>这里的<code></code>是你供应商的名字，<code>theme</code>是你主题的名字。你可以查看Luma主题的registration.php文件。</p>
<h2 id="configure-images">配置图片</h2>
<p>产品图片大小和其它店铺前端性能在<code>view.xml</code>里被配置。它需要一个主题，但是否有父主题都可。 如果你主题里的产品图片与父主题不同，或者你的主题没有继承任何主题，用下面的步骤添加一个<code>view.xml</code></p>
<p>1.以可以创建文件夹权限的用户（通常情况下，是Magento的文件系统的所有者）登录到Magento服务器中。</p>
<p>2.在你的主题目录下创建etc文件夹</p>
<p>3.从已有主题中拷贝view.xml文件（例如，从Blank主题）到你主题的etc文件夹中。</p>
<p>4.在view.xml中配置所有店铺前端产品图片尺寸。例如，你可以指定分类网格视图产品图片为250x250像素，相应的配置会是这样：</p>
<pre><code>...
    &lt;image id="category_page_grid" type="small_image"&gt;
        &lt;width&gt;250&lt;/width&gt;
        &lt;height&gt;250&lt;/height&gt;
    &lt;/image&gt;
...
</code></pre>
<h2 id="create-static-directories">创建静态文件目录</h2>
<p>你的主题将包含几种静态文件：样式，字体，JavaScript和图片。每种类型的图片都被存储在<code>web</code>目录下的独立子目录中：</p>
<pre><code>app/design/&lt;area&gt;/&lt;Vendor&gt;/&lt;theme&gt;/
├── web/
│ ├── css/
│ │ ├── source/ 
│ ├── fonts/
│ ├── images/
│ ├── js/
</code></pre>
<h2 id="theme-directory-structure">当前你主题的目录结构</h2>
<p>当前，你的主题目录看起来是这样的：</p>
<pre><code>app/design/frontend/&lt;Vendor&gt;/
├── /
│   ├── etc/
│   │   ├── view.xml
│   ├── web/
│   │   ├── images
│   │   │   ├── logo.svg
│   ├── theme.xml
│   ├── composer.json
</code></pre>
<h2>主题logo</h2>
<p>在Magento2中，默认的logo名字和格式是<code>logo.svg</code>。当你把一个<code>logo.svg</code>放在常规位置（<code>&lt;theme_dir&gt;/web/images</code>目录）中，它就会被自动识别为主题logo。主题被应用时就会出现在店铺页面的头部。</p>
<p>在你自定义的主题中，你可以使用不同名字和格式的logo，但是你可能需要声明它。</p>
<p>是否需要声明取决于你的主题是否有父主题以及它的logo图片。可能是下面的情况：</p>
<ul>
<li>你的主题没有父主题：
<ul>
<li>如果你的logo图片名字和格式是默认的，<code>logo.svg</code>，那么就不需要声明它。</li>
<li>如果你的logo图片名字和格式不是默认的就需要声明它。</li>
</ul>
</li>
<li>不的主题有父主题
<ul>
<li>如果你的主题logo图片名字和格式与父主题的logo一样，那么就不需要声明它。</li>
<li>如果你的logo图片有不同的名字和格式就需要声明它。</li>
</ul>
</li>
</ul>
<h2 id="declaring-theme-logo">声明主题图片</h2>
<p>要声明一个主题logo，需要添加一个扩展的<code>&lt;theme_dir&gt;/Magento_Theme/layout/default.xml</code>布局。</p>
<p>例如，如果你的logo文件是<code>my_logo.png</code>，尺寸为300x300像素，你可以如下声明它：</p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"&gt;
    &lt;body&gt;
        &lt;referenceBlock name="logo"&gt;
            &lt;arguments&gt;
                &lt;argument name="logo_file" xsi:type="string"&gt;images/my_logo.png&lt;/argument&gt;
                &lt;argument name="logo_img_width" xsi:type="number"&gt;300&lt;/argument&gt; 
                &lt;argument name="logo_img_height" xsi:type="number"&gt;300&lt;/argument&gt;
            &lt;/arguments&gt;
        &lt;/referenceBlock&gt;
    &lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p>声明logo尺寸是可选的。更多关于主题的布局，会在之后的文章中详细讲解。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Dec 2015 13:44:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento订单创建和管理]]></title>
      <link>https://www.360magento.com/blog/magento_orders/</link>
      <description><![CDATA[<h1>如何配置Magento订单选项</h1>
<p>要修改Magento订单选项（结账设置，邮寄设置，支付方式等等）你需要进入后台-&gt;System-&gt;Configuration。我们要设置的选项在左侧菜单栏的Sales区域。让我们简短地看下这些选项：</p>
<ul>
<li><strong>Sales（销售）</strong>-通过这个选项你可以配置支付总额的排序，是否允许再次下单，为PDF和HTML打印输出（发票和装箱单的设计）设置logo，设置最小订单金额和礼物信息。</li>
<li><strong>Sales Email（销售电子邮件）</strong>-在这里你可以为订单，发票，运输和信用备忘录配置不同的邮箱。更多相关信息你可以在下面的Magento订单邮件部分中到。</li>
<li><strong>PDF Print-outs（PDF打印）</strong>-这个选项允许你设置是否在发票，装运和信用备忘录的头部显示订单ID。</li>
<li><strong>Tax（税）</strong>-这里你可以设置不同的税选项-税类，计算设置，税务显示设置和固定产品税。</li>
<li><strong>Checkout（结账）</strong>-这个重要的选线允许你配置你的结账设置，购物车和侧边栏，支付失败的邮件。</li>
<li><strong>Shipping Settings（运输设置）</strong>-这里你可以设置你的运输来源和选项。</li>
<li><strong>Shipping Method（运输方式）</strong>-顾名思义，在这里你可以配置你的运输方式；可用的运输方式有：扁平率，表率，免费送货，UPS，USPS，联邦快递。</li>
<li><strong>Google API（谷歌API）</strong>-这里你可以为Magento配置谷歌服务-谷歌分析和谷歌结账。</li>
<li><strong>Paypal（贝宝）</strong>-这个选项允许你为店铺配置贝宝。</li>
<li><strong>Payment Method（支付方式）</strong>-最重要的选项，这里你应该配置你将接受的支付方式。</li>
<li><strong>Payment Services（支付服务）</strong>-这里只有一个选项来配置-3D信用卡安全验证 - 这是作为一个额外的安全层，用于网上信用交易的基于XML的协议。</li>
<li><strong>Moneybookers </strong>-在你的店铺中为Moneybookers配置一个独立的区域。</li>
</ul>
<h1>如何管理订单邮件</h1>
<p>正如在Magento订单选项中提到的，Magento有一个非常棒的内置的电子邮件功能。这个邮件功能被称作销售电子邮件，允许你管理订单邮件。在配置你的电子邮件之前，你也许需要添加一个新的电子邮件模版。你可以进入后台System -&gt; Transactional Emails来实现。现在，让我们仔细看看每个Sales Email（销售电子邮件）选项：</p>
<ul>
<li><strong>Order and Order Comments（订单和评论）</strong>-在这里你可以启用/禁用包含订单和评论信息的客户电子邮件通知。在这里，你可以设置新的订单提交邮件发送者，新的订单确认模版（针对已注册的用户），新的订单确认模版（针对访客用户）。你还可以设置邮件接收订单电子邮件的副本，并选择如何复制邮件发 - 作为密件抄送或作为一个单独的电子邮件。</li>
<li><strong>Invoice and Invoice Comments（发票及发票评论）</strong>-这里可以启用/禁用包含发票和发票评论的客户电子邮件通知。其他选项与Order相同。</li>
<li><strong>Shipment and Shipment Comments （发货和发货评论）</strong>-这里可以启用/禁用包含发货和发货评论的客户电子邮件通知。其他选项与Order相同。</li>
<li><strong>Credit Memo and Credit Memo Comments（贷项通知单和贷项通知单评论）</strong>-这里可以启用/禁用包含贷项通知单和贷项通知单评论的客户电子邮件通知。其他选项与Order相同。</li>
</ul>
<h1>如何在Magento中下订单</h1>
<p>下订单包含几个简单的步骤。以添加产品到购物车开始，然后进行结账，选择结帐方式，填写一些账单和发货信息，选择付款方式，然后下订单。整个流程表现为：</p>
<pre><code>Add to Cart -&gt; Process Checkout (Billing/Shipping/Payment) -&gt; Place Order</code></pre>
<p>一旦订单被下达，它会显示在Magento后台的Sales -&gt; Orders中。</p>
<h1>在Magento中如何管理订单</h1>
<p>当客户成功完成订购过程中，您将收到有关新订单的邮件通知。您可以在后台Sales -&gt; Orders中查看所有的订单。在上一部分中，我们下了订单，让我们点击它，看看它的样子。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Sales Order" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_sales_order_1.jpg" width="auto" /></div>
<p>你会在屏幕的右上角发现几个橙色按钮。这些都是你可以对订单进行的操作：</p>
<ul>
<li><strong>Edit（编辑）</strong>-该操作会取消当前订单并创建一个有同样细节的订单供你编辑和再次提交。</li>
<li><strong>Cancel（取消）</strong>-取消订单。</li>
<li><strong>Send Email（发送邮件）</strong>-重新发送订单电子邮件给客户。</li>
<li><strong>Hold（挂起）</strong>-将订单挂起，在其它时间进行处理。处理前需（Unhold）恢复。</li>
<li><strong>Invoice（发票）</strong>-你需要点击（Submit Invoice）提交发票来创建它。这将使得订单状态从待定变为进行中。</li>
<li><strong>Credit Memo（贷项通知单）</strong>- 只会在发票创建后出现。允许你创建一个线下退款的订单。</li>
<li><strong>Ship（发货）</strong>-订单管理的最后一步，这是产品的实际交付。你需要点击Submit Shipment（提交发货）来完成订单。它使得订单状态从进行中变为完成。</li>
<li><strong>Reorder（再次下单）</strong>-允许你再次提交订单。</li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Dec 2015 14:26:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento产品价格管理]]></title>
      <link>https://www.360magento.com/blog/magento_price/</link>
      <description><![CDATA[<p>Magento为你的产品价格提供了很多选项。你可以设置特价，定时促销等等。要编辑你的产品价格，首先登录你的Magento后台，然后进入<strong>Catalog-&gt;Manage Products</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento manage product" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_1.jpg" width="auto" /></div>
<p>现在定位你要修改价格的产品上，点击它边上的Edit链接。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento product edit" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_2.jpg" width="auto" /></div>
<p>这里你将看到许多用来修改产品的选项。在左侧菜单选择Prices标签。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento product price" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_3.jpg" width="auto" /></div>
<p>在这里你可以修改产品的价格，下面是一些比较重要选项的说明：</p>
<ul>
<li><strong>Price</strong>（价格）：你要出售产品的价格，必填项，最重要的信息</li>
<li><strong>Cost</strong>（成本）：你购买产品的价格</li>
<li><strong>Tier Price</strong>（阶梯价格）：可根据购买数量设定折扣</li>
<li><strong>Special Price</strong>（特价）：可设置特价及特价的起止事件，此选项不受购买数量的限制</li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 14 Dec 2015 10:50:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento社区版本下载]]></title>
      <link>https://www.360magento.com/blog/magento-community-download/</link>
      <description><![CDATA[<h2>最新最全magento社区版下载链接<a href="http://blog.magego.com/magento-download/" target="_blank">http://blog.magego.com/magento-download/</a></h2>
<h2>magento 社区版2.x下载列表</h2>
<ul>
<li><a href="http://www.360magento.com/magento-community/Magento-CE-2.0.0-2015-11-17-05-53-58.tar.gz">magento 社区版 2.0.0 下载</a></li>
<li><a href="http://www.360magento.com/magento-community/Magento-CE-2.0.0+Samples-2015-11-17-06-24-03.tar.gz">magento 社区版 2.0.0 + 示例数据 下载</a></li>
<li><a href="http://www.360magento.com/magento-community/Composer-Setup.exe">Composer 下载</a></li>
</ul>
<h2>magento 社区版1.x下载列表</h2>
<ul>
<li><a href="http://www.360magento.com/magento-community/magento-1.9.2.2-2015-10-27-03-14-30.zip">magento community ver 1.9.2.2 下载</a></li>
<li><a href="http://www.360magento.com/magento-community/magento-1.9.1.1-2015-04-30-12-49-08.zip">magento community ver 1.9.1.1 下载</a></li>
<li><a href="http://www.360magento.com/magento-community/magento-1.8.1.0-2015-02-10-10-06-27.zip">magento community ver 1.8.1.0 下载</a></li>
<li><a href="http://www.360magento.com/magento-community/magento-1.7.0.2-2015-02-11-09-59-20.zip">magento community ver 1.7.0.2 下载</a></li>
</ul>]]></description>
      <pubDate>Mon, 30 Nov 2015 08:52:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 2.0发布及介绍]]></title>
      <link>https://www.360magento.com/blog/magento-2-launched/</link>
      <description><![CDATA[<p>magento官方于2015年11月17日宣布他们的下一代开源电子商务平台magento 2.0正式发布上市。新的平台让品牌商，零售商和企业可以跨越B2C，B2B行业来快速且经济高效的参与全渠道的购物体验。magento 2.0还提供了增强的性能和扩展性，新的功能更能提高转化率和和业务灵活性，以及生产率的提高。magento 2.0还是建立在开源的基础上，并提供无与伦比的灵活性和创新的空间。</p>
<p>magento基于magento 2.0推出了出了两个版本：magento 2.0企业版 和 magento 2.0社区版，当然还是一样企业版还是每年要收费的。</p>
<h2>开放、灵活的体系结构</h2>
<p>magento 2.0是是下一代平台，全新的架构体系。拥有无与伦比的灵活性，是你的商业眼界和思想能够得以实现。magento 2.0采用模块化的代码库，使自定义更为容易，更快速的推向市场。更强大的部署灵活性使其能够运行在公有云和私有云的环境中。更广泛和更有效的API允许您与任何第三方解决方案连接和操作，主体化的功能使得网站建设随新的产品线或者地域的变化比以往更容易。广泛的turnkey扩展还能够快速、经济的增强你的网店</p>
<h2>吸引人的购物体验</h2>
<p>无论通过任何设备都可以创建一个吸引人的、无缝的和个性化的客户体验是magento 2.0的核心。全新的响应式的参考主题，可以快速的创建一个支持在任何时间、任何地点都可以销售的站点。并且你可以通过集成视频更逼真的方式分享你的产品。全新的结账通过最大限度的减少支付步骤和所需的信息是的更容易定制和进一步提高转化率。您也可以提供一键创建账户来保存未来采购的客户档案。</p>
<h2>增强业务得灵活性和效率</h2>
<p>magento电子商务正在革新商人的体验，使您能够更有效地运作和处理快速增长、不扩大你的团队。新的管理面板的设计提供了一个简化，消费者一样的界面，节省了管理每天的日常任务并且直观的看到新的团队成员学习时的时间。他对触摸屏也是非常有好的，所以无论你去哪儿你都可以更新和跟踪销售订单。改进的业务工具，使您能够不断优化您的操作来推动增长。你现在可以通过后台管理面板轻松的自定义和保存商店视图。创建新的产品也比较快，通过一步步的产品创建向导工具并且产品导入功能比以前快四倍</p>
<h2>企业级可扩展性和性能</h2>
<p>magento平台已经增压，提供更快的超过50%的页面加载时间，在目录页和结账页上有明显体现。以帮助您的客户和提高转换率。它预先集成了 Apache Varnish来缓存页面内容。 Magento企业版2.0还提供了企业级的可扩展性和高可用性与多个从数据库关键子系统独立的主数据库</p>
<h2>安全支付</h2>
<p>此外，magento本身自带的可用PayPal, Braintree, and Authorize.net的支付网关。Magento企业版2.0还集成WorldPay和CyberSource支付网关。所有版本提供更好的安全性和追求PCI合规性的最简单的级别，根据所选择的付款方式</p>
<h2>易于维护和升级</h2>
<p>最后，这个现代化的，模块化的架构降低了复杂性和维护网站的成本。他的升级也很简单，因为他是开源的，这意味着你可以将创新性的功能整合进去。通过magento电商平台来实现每季更高的销售和更高的效率。</p>
<p>&nbsp;</p>
<p><a href="http://www.360magento.com/blog/magento-community-download/">下载magento 2.0</a></p>]]></description>
      <pubDate>Wed, 18 Nov 2015 11:31:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento创建、修改分类]]></title>
      <link>https://www.360magento.com/blog/magento_category/</link>
      <description><![CDATA[<h1>如何在Magento中创建分类</h1>
<p>要为产品创建一个分类，你需要进入Magento后台Catalog &gt; Manage Categories。在左侧你将看到已有的分类（如果有的话），在此之上你可以看到两个按钮Add Root Category（添加主分类）和Add Subcategory（添加子分类）。由于我们装了Magento数据，所以有几个分类。让我们通过选择主分类，再通过点击 Add Subcategory来创建新的子分类吧。</p>
<p>你应该填写它的名字，描述，添加一幅图片，一些有利于搜索引擎优化的Meta数据，设置它为Active来使它显示在前台并且将它包含在导航菜单中。</p>
<p>最后一个URL关键字，如果设置了就将用来链接到这个分类。这对于SEO来说非常有用，链接中考虑使用一些关键词。如果分类被称为PC，那么你可以考虑在这个区域填上"personal-computers" 。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento catalog General Information" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_category_1.jpg" width="auto" /></div>
<p>上图是分类的General Information Settings（一般设置），另外还有3个标签你可以设置：</p>
<p><strong>Display Settings</strong>（显示设置）：这里你可以设置显示的模式，它的CMS块和产品排列选项。</p>
<p><strong>Custom Design</strong>（自定义设计）：这里你可以选择分类的设计，它的布局。</p>
<p><strong>Category Products</strong>（分类产品）：这个标签允许你将已有的产品添加到分类中。</p>
<p>当你设置完成后点击Save按钮来创建它。</p>
<h1>如何在Magento中添加分类图片</h1>
<p>添加Magento分类图片很简单。进入Magento后台Catalog &gt; Manage Categories，选择你要添加图片的分类，选择General Information 标签，点击Image边上的Browse 按钮。选择你要添加的图片，点击Save Category保存。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento catalog Image" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_category_2.jpg" width="auto" /></div>
<h1>如何在Magento中列出所有可用的分类</h1>
<p>如果你想要查看Magento中分类的列表，进入Magento后台Catalog &gt; Manage Categories，在左侧分类菜单中点击Expand All即可。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento catalog list" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_category_3.jpg" width="auto" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 14 Nov 2015 16:04:49 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento2对商家的意味着什么？]]></title>
      <link>https://www.360magento.com/blog/magento2-to-merchants/</link>
      <description><![CDATA[<p>Magento开发团队已经公布了Magento2 Develop版本，里面包含完整的代码和架构。所有的Magento开发者都能深入了解Magento2了。那么，这对于商家来说意味着什么呢？</p>
<h2>什么是Magento2？</h2>
<p>你肯定知道Magento 1.x。Magento2是对之前的一个重构。大部分的代码已经以一种避免问题的方式重写。特别是，插件冲突，性能，代码质量和当前技术的更新。Magento2承诺满足商家更强大的功能需求。它的变化和提升是建立在过去5年客户的反馈之上的。</p>
<h2>Magento2历程-这一路，它如何走来</h2>
<p>Magento2的发布使得Magento2团队刚刚达到了一座新的里程碑。这意味着架构和代码更加稳定，更多新的功能，稳定性和错误修正。然而商家完全不会受此影响。如今开放的商家测试版大家可以看看，相信2016年你将看到在线网站。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Export Success" src="http://7xjryy.com1.z0.glb.clouddn.com/magento2-to-merchants.png" width="auto" /></div>
<h2>它怎么影响我的Magento店铺？</h2>
<p>Magento将继续支持Magento 1.x产品至2018年并停止对当前版本增加新功能。你的商店也许在2015年不受影响。如果在2015年不升级到magento2，那么在2016或者2017年就要计划了。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 03 Nov 2015 15:59:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento产品数量]]></title>
      <link>https://www.360magento.com/blog/magento-quantity/</link>
      <description><![CDATA[<p>Magento提供了一种简单又强大的方式来让你管理产品数量。那么我们该如何做呢？首先，登录Magento后台，进入<strong>Catalog -&gt; Manage Products</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Manage Products" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-quantity-1.jpg" width="auto" /></div>
<p>在下面的页面中，你将看到Magento商店中已有的所有产品。找到你想要修改数量的产品，点击它的<strong>Edit</strong>链接。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Products Edit" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-quantity-2.jpg" width="auto" /></div>
<p>之后你将进入产品页面，点击左侧菜单中的<strong>Inventory</strong> 。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Products Inventory" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-quantity-3.jpg" width="auto" /></div>
<p>现在，定位到<strong>Qty</strong>区域，加上你想要修改的产品数量。最后点击Save按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Products Qty" src="http://7xjryy.com1.z0.glb.clouddn.com/magento-quantity-4.jpg" width="auto" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 03 Nov 2015 15:50:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento由Permira基金支持成为独立公司]]></title>
      <link>https://www.360magento.com/blog/magento-independent/</link>
      <description><![CDATA[<p>The Permira Funds&rsquo; Investment in Leading Worldwide Commerce Platform to Fuel Global Expansion and Product Innovation</p>
<p>CAMPBELL, Calif. &mdash; (Nov. 2, 2015) &mdash; Magento Commerce, the leading provider of open omnichannel innovation, announced today that it has launched as an independent company, backed by the Permira funds. The launch marks the close of the acquisition of Magento Commerce Technologies by companies owned by the Permira funds from eBay, Inc. Mark Lavelle, formerly senior vice president at eBay Enterprise, will lead the company as its new CEO.</p>
<p>&ldquo;Magento is at the forefront of a tremendous market opportunity. As an independent company, with the full support and global resources of the Permira funds, we are poised to accelerate our leadership as innovators, creating products that drive exceptional experiences across every stage of the commerce lifecycle,&rdquo; said Mark Lavelle, CEO of Magento Commerce. &ldquo;During our time as a division of eBay, Inc., we grew revenue fivefold, made significant investments in our core platform and added innovative mobile and omnichannel products. Now, we will build on this momentum--continuing to innovate with speed and at scale while we put renewed focus on expanding our market leadership with stronger emphasis on our global network of system integrators, technology partners and developer community.&rdquo;</p>
<p>&ldquo;We are excited to support Mark and his outstanding team as they build on Magento&rsquo;s product leadership and rich ecosystem,&rdquo; said Phil Guinand, Principal at Permira. &ldquo;Given the Permira funds&rsquo; experience backing some of the world&rsquo;s leading brands and retailers, we know first-hand how Magento provides these companies with distinct advantages over their competitors in terms of owning the customer experience, future-proofing their business by leveraging the power of an open architecture, and achieving superior ROI from their omnichannel investments. As the importance of the digital commerce experience expands over the next decade we believe Magento will continue to be the partner of choice for the world&rsquo;s leading brands and retailers.&rdquo;</p>
<p>The flagship open-source Magento platform is already the worldwide leader in eCommerce, powering more than 240,000 sites globally and supporting over $50 billion in gross merchandise volume annually. Magento is the dominant platform to the Internet Retailer Top 1000, and the Internet Retailer B2B 300, counting more than double the number of retailers using the platform to the next closest competitor, as well as to the Internet Retailer Hot 100 which represents retailers who deliver the most innovative and best new ideas in commerce. Additionally, Forrester Research recently cited Magento as a Strong Performer &ldquo;blending strong strategy with a maturing product" among the eight most significant B2B commerce suite vendors in its industry benchmark report, &ldquo;The Forrester Wave&trade;: B2B Commerce Suites, Q2 2015.&rdquo; Magento was also cited as a Challenger in the 2014 Gartner Magic Quadrant for Digital Commerce.</p>
<p>Emerging as an independent company, Magento Commerce boasts a strong portfolio of open-source and cloud-based omnichannel solutions designed to disrupt the legacy technologies that have siloed the consumer experience between digital and physical:</p>
<ul>
<li><strong>Magento Community Edition</strong> is a modular and customizable eCommerce platform that ideally suits the needs of small businesses, and provides core commerce capabilities that can be extended though a wealth of extensions on the Magento Marketplace.</li>
<li>The <strong>Magento Enterprise Edition</strong> is a high performance, scalable eCommerce solution for fast-growing and large businesses. Magento Enterprise Edition provides a rich, robust feature set that can be tailored in order to accelerate business growth across digital and physical channels.</li>
<li><strong>Magento Commerce Order Management</strong> is a product suite at the core of retail distribution, connecting supply and demand side channels, gathering information from each and facilitating the choices for each individual order. Whether integrated with Magento Enterprise Edition or stand-alone, this modular, cloud-based suite of software, tools, and services, is designed to manage your orders, inventory and fulfillment.</li>
<li><strong>Magento Retail Commerce</strong> is a product suite designed to provide a more engaging and relevant experience within the retail environment. Magento's Point-of-Service gives store associates a mobile platform to deliver on all of a customer's in store needs, from commerce to clienteling. Magento Retail Commerce blurs the line between online and &ldquo;offline&rdquo; in a way the world has never seen before.</li>
<li>The <strong>Magento Marketplace</strong> is the largest commerce application marketplace. The Marketplace provides merchants with a curated user experience for easy discovery of high quality products and services, while providing developers with a vibrant Magento community and the tools and marketing resources to monetize their application business.</li>
</ul>
<h2>About Magento Commerce</h2>
<p>Trusted by more than 240,000 businesses worldwide, Magento Commerce is the leading provider of open omnichannel innovation to retailers, brands and branded manufacturers across retail B2C and B2B industries. In addition to its flagship open source eCommerce platform, Magento Commerce boasts a strong portfolio of cloud-based omnichannel solutions empowering merchants to successfully integrate digital and physical shopping experiences. With over $50B in gross merchandise volume transacted on the platform annually, Magento Commerce is the dominant provider to the Internet Retailer Top 1000, counting more than double the clients to the next closest competitor, and to the Internet Retailer Hot 100. Magento Commerce is supported by a vast global network of solution and technology partners, a highly active global developer community and the largest eCommerce marketplace for extensions available for download on the Magento Marketplace. More information can be found at <a title="Magento" href="www.magento.com" rel="nofollow">www.magento.com</a>.</p>
<h2>About Permira</h2>
<p>Permira is a global investment firm that finds and backs successful businesses with ambition. Founded in 1985, the firm advises funds with a total committed capital of approximately $28 billion. The Permira funds make long-term investments in companies with the objective of transforming their performance and driving sustainable growth. In the past 30 years, the Permira funds have made over 200 private equity investments in five key sectors: Consumer, Financial Services, Healthcare, Industrials and Technology. Permira employs over 200 people in 14 offices across North America, Europe, the Middle East and Asia. For more information visit: <a title="Permira" href="www.permira.com" rel="nofollow">www.permira.com</a>.</p>
<p>Permira established itself in North America in 2002 and today has offices in New York and Menlo Park. The Permira funds have a long track record of successfully investing in technology companies around the world including Informatica, Magento Commerce, eBay Marketing Solutions, NDS, Genesys, Ancestry.com, TeamViewer, Renaissance Learning, Metalogix, LegalZoom.com, and Teraco. Since 1997, over 33% of the Permira funds' investments have been in the core sector of Technology.</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 03 Nov 2015 02:59:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在不同的商店获取被重写后的产品网址]]></title>
      <link>https://www.360magento.com/blog/magento-rewritten-url/</link>
      <description><![CDATA[<p>在之前一篇在不同店铺获取产品网址的文章中，有人指出，如果当你想要获取的产品已经被重写那么将很麻烦。我想到一个返回被重写产品网址的方法。你将需要添加一个店铺的基本网址来返回一个完整网址的值。</p>
<p>要注意的是：这个方法只有在设置了网址关键字(URL key)属性集范围的店视图(store view)才有效。这意味着一件商品在不同店视图中的网址是不一样的。例如：一个产品在英文店铺中的网址关键字(URL key)是'nokia-blue'，在德文店铺中的网址关键字(URL key)是'nokia blau'。这将作用于你正在编辑产品的重写。如果你决定在网址重写中添加一个你自己的网址重写，也许你有一个很好的理由，但是我们不会被这种情况覆盖。</p>
<p>这次我不会去创建和注册一个模块。让我们以加入这个方法到你的模块助手中开始。</p>
<p><strong>app/code/community/Alwayly/Rewrites/Helper/Data.php</strong></p>
<pre><code>&lt;?php
class Alwayly_Rewrites_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function rewrittenProductUrl($productId, $categoryId, $storeId)
    {
        $coreUrl = Mage::getModel('core/url_rewrite');
        $idPath = sprintf('product/%d', $productId);
        if ($categoryId) {
            $idPath = sprintf('%s/%d', $idPath, $categoryId);
        }
        $coreUrl-&gt;setStoreId($storeId);
        $coreUrl-&gt;loadByIdPath($idPath);
 
        return $coreUrl-&gt;getRequestPath();
    }
}
?&gt;
</code></pre>
<p>现在我们将做一个小的试演。如你所见，这个方法中接收productId, $categoryId 和 $storeId作为参数。要了解网址（URLS）在被重写前是什么样的，我们一起看下我们数据库中<strong>core_url_rewrite</strong>的这张表。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="core_url_rewrite表" src="http://7xjryy.com1.z0.glb.clouddn.com/rewritten-product-url-1.png" width="auto" /></div>
<p>一个不在任何类别中产品的id_path表现形式为<strong>product/productId</strong>，如果它属于任意的类别，它将表现为<strong>product/productId/categoryId</strong>。</p>
<p>让我们回到我们的方法。我们将用Magento注册表中的数据创建一个id_path的结构体。在我们寻找重写前我们需要为模型用setStoreId()设置店铺的Id。在这之后，我们将用<strong>loadByIdPath()</strong>读取我们重写了的地址列。现在剩下的就是获取一个请求通道，也就是产品网址中重写的部分。我们将用Magento中的<strong>core/url_rewrite</strong>模型来实现这些。</p>
<p>一个例子是，指向你正在寻找的同一产品的语言切换器，但在不同的店视图中。只需将下面的代码放入你的languages.phtml文件。<strong>app/design/base/default/template/page/html/switch/languages.phtml</strong></p>
<pre><code>&lt;?php if(count($this-&gt;getStores())&gt;1): ?&gt;
    &lt;?php
    $helper = Mage::helper('inchoo_rewrites');
    $prod = Mage::registry('current_product');
    $categ = Mage::registry('current_category');
    $categId = $categ ? $categ-&gt;getId() : null;
 
    ?&gt;
    &lt;div class="form-language"&gt;
        &lt;label for="select-language"&gt;&lt;?php echo $this-&gt;__('Your Language:') ?&gt;&lt;/label&gt;
        &lt;select id="select-language" title="&lt;?php echo $this-&gt;__('Your Language') ?&gt;" onchange="window.location.href=this.value"&gt;
            &lt;?php foreach ($this-&gt;getStores() as $_lang): ?&gt;
                &lt;?php $_selected = ($_lang-&gt;getId() == $this-&gt;getCurrentStoreId()) ? ' selected="selected"' : '' ?&gt;
                &lt;option value="&lt;?php
                    if($prod) {
                        echo $_lang-&gt;getBaseUrl() . $helper-&gt;rewrittenProductUrl($prod-&gt;getId(), $categId, $_lang-&gt;getId()) . '?___store=' . $_lang-&gt;getCode();
                    }else{
                        echo $_lang-&gt;getCurrentUrl(false);
                    }
                ?&gt;"&lt;?php echo $_selected ?&gt;&gt;&lt;?php echo $this-&gt;escapeHtml($_lang-&gt;getName()) ?&gt;&lt;/option&gt;
            &lt;?php endforeach; ?&gt;
        &lt;/select&gt;
    &lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>你的语言切换器源码应该有些像这样（只要你的产品至少在一个店铺中有不同的网址）</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="language switcher" src="http://7xjryy.com1.z0.glb.clouddn.com/rewritten-product-url-2.png" width="auto" /></div>
<p>希望这将对你们掌握多店铺中网址重写的概念有所帮助。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 02 Nov 2015 15:38:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中导入产品]]></title>
      <link>https://www.360magento.com/blog/magento-import-products/</link>
      <description><![CDATA[<p>在Magento中以手动的方式添加大量产品是很不方便的。一件一件地添加产品会消耗很长的时间，特别是当你有成百上千的产品。这种情况，你就需要一种自动的方式添加所有的产品到你的Magento店铺。按照下面的步骤就能成功导入。</p>
<p>首先，从Magento后台进入<strong>Catalog -&gt; Manage Categories</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Manage Categories" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-1.jpg" width="auto" /></div>
<p>填写如下的内容来创建所有你需要的分类：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Categories Information" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-2.jpg" width="auto" /></div>
<p>填写所有的信息以后，点击Save Catagory按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Save Catagory" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-3.jpg" width="auto" /></div>
<p>注意，记下新创建的分类的id。最好以文本的形式，如下：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Catagory id" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-4.jpg" width="auto" /></div>
<p>如果需要，你还可以通过<strong>Catalog -&gt;Attributes -&gt;Manage Attributes -&gt; Add new Attribute</strong>.创建产品的额外属性。当然，在创建简单产品的时候你也可以创建属性。什么时候创建由你决定。</p>
<p>下一步是在Magento中手动添加一个产品。之后用来导出作为大量数据导入的模版。确保已经创建了所有需要的属性，是否删除已有的商品。当你创建并保存一个新产品以后，它将出现在Magento店铺的产品列表里。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento product list" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-5.jpg" width="auto" /></div>
<p>现在导出作为样本的模版。在Magento后台<strong>System -&gt; Import/Export -&gt; Dataflow - Profiles -&gt; Export All Products</strong>。在<strong>Profile Information -&gt; Store</strong>选择你刚才创建产品所在的店铺。在<strong>Data Transfer</strong>下拉菜单选择<strong>Local/Remote Server</strong>。在<strong>Data Format</strong>这栏选择<strong>CSV/ Tab Separated</strong>，点击<strong>Save</strong>按钮。接着再次点击<strong>export all products</strong>，点击<strong>Run Profile in Popup</strong>按钮。</p>
<p>在你的项目的<strong>var/export/</strong>文件夹里将有一个名为<strong>export_all_products.csv</strong>的文件。导出成功的界面看起来是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Export Success" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-6.jpg" width="auto" /></div>
<p>使用FTP将文件下载到本地。文件里每一列对应你要定义产品的属性。用电子表格程序打开它，添加你要导入的产品。确保复制/粘贴属性到对应的列。记得添加上分类的id。</p>
<p>完成这些之后，返回Magento后台，进入<strong>System -&gt; Import/Export -&gt; Dataflow - Profiles -&gt; Import All Products</strong>。之后选择<strong>Upload</strong>，上传要导入的.csv文件。上传完以后再次点击<strong>Import All Products</strong>，之后<strong>Run Profile</strong>，从下拉框选择你刚才上传的文件，点击<strong>Run Profile in Popup</strong>按钮。一个导入状态的窗口就弹出了。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Import process" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-7.jpg" width="auto" /></div>
<p>导入成功后会有提示信息。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Import Success" src="http://7xjryy.com1.z0.glb.clouddn.com/import-products-8.jpg" width="auto" /></div>
<p>现在，你可以到后台产品页面查看导入的产品了。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 02 Nov 2015 13:08:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[更新购物车中的可配置产品]]></title>
      <link>https://www.360magento.com/blog/updating-cart-configurable/</link>
      <description><![CDATA[<p>假设我们的购物车中有Magento可配置产品，我们想要修改它的选项但又不愿意删除或者重新添加它，那么怎么办呢？其实，按照下面的步骤，实现起来还是很简单的。</p>
<p>首先，打开你主题文件夹下的<strong>template/checkout/cart/item/default.phtml</strong>,找到下面的代码：</p>
<pre><code>&lt;?php if ($_options = $this-&gt;getOptionList()):?&gt;
</code></pre>
<p>在这行代码下面添加：</p>
<pre><code>&lt; ?php
if($this-&gt;getProduct()-&gt;isConfigurable()){
$_product = Mage::getModel('catalog/product')-&gt;load($this-&gt;getProduct()-&gt;getId());
Mage::getBlockSingleton('catalog/product_view_type_configurable')-&gt;unsetData();
$_configurable = Mage::getBlockSingleton('catalog/product_view_type_configurable')-&gt;setData('product', $_product);
$_cdata = json_decode($_configurable-&gt;getJsonConfig());
$_current = array();
foreach((array)$this-&gt;getOptionList() as $_option) {
$_current[$_option['label']]=$_option['value'];
}
foreach($_cdata-&gt;attributes as $attribute) {
?&gt;
&lt;strong&gt;&lt; ?php echo $attribute-&gt;label; ?&gt;&lt;/strong&gt;
&lt;select style="width:150px;" name="cart[&lt;?php echo $_item-&gt;getId() ?&gt;][option][&lt; ?php echo $attribute-&gt;id ?&gt;]"&gt;
&lt; ?php
foreach($attribute-&gt;options as $option) {
?&gt;
&lt;option &lt;?php echo ($_current[$attribute-&gt;label]==$option-&gt;label) ? ' selected' : '' ?&gt; value="&lt; ?php echo $option-&gt;id ?&gt;"&gt;&lt; ?php echo $option-&gt;label ?&gt; &lt; ?php echo $this-&gt;helper('checkout')-&gt;formatPrice($option-&gt;price+$_item-&gt;getProduct()-&gt;getPrice()) ?&gt;&lt;/option&gt;
&lt; ?php
}
?&gt;
&lt;/select&gt;
&lt; ?php
}
} else {
// THIS IS PLACE WHERE EXISTING CODE from [*] goes
}
?&gt;</code></pre>
<p>现在你已经完成了模板，你可以以你喜欢的方式来装饰它。下一步，你需要在local下创建你的&ldquo;Model&rdquo;和&ldquo;etc&rdquo;。etc中的config.xml代码是：</p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;config&gt;
&lt;frontend&gt;
&lt;events&gt;
&lt;checkout_cart_update_items_before&gt;
&lt;observers&gt;
&lt;your_firm_module_name_event&gt;
&lt;type&gt;singleton&lt;/type&gt;
&lt;class&gt;YOUR_FIRM_MODULE_NAME_Model_Card&lt;/class&gt;
&lt;method&gt;update&lt;/method&gt;
&lt;/your_firm_module_name_event&gt;
&lt;/observers&gt;
&lt;/checkout_cart_update_items_before&gt;
&lt;/events&gt;
&lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>&ldquo;Model&rdquo;中的Card.php代码为：</p>
<pre><code>&lt; ?php
 
class YOUR_FIRM_MODULE_NAME_Model_Card
{
public function update($e)
{
$_this = $e-&gt;cart;
$data = $e-&gt;info;
 
foreach ($data as $itemId =&gt; $itemInfo) {
$item = $_this-&gt;getQuote()-&gt;getItemById($itemId);
 
if (!$item) continue;
if (!isset($itemInfo['option']) or empty($itemInfo['option'])) continue;
 
foreach ($item-&gt;getOptions() as $option){
 
if($option-&gt;getCode()=='info_buyRequest'){
 
$unserialized = unserialize($option-&gt;getValue());
$unserialized['super_attribute'] = $itemInfo['option'];
$option-&gt;setValue(serialize($itemInfo['option']));
 
}elseif ($option-&gt;getCode()=='attributes'){
$option-&gt;setValue(serialize($itemInfo['option']));
}
 
}
$item-&gt;save();
}
}
 
}
?&gt;
</code></pre>
<p>最后在app/etc中用下面的代码创建YOUR_FIRM_MODULE_NAME.xml。</p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;config&gt;
&lt;modules&gt;
&lt;your_firm_module_name&gt;
&lt;codepool&gt;local&lt;/codepool&gt;
&lt;active&gt;true&lt;/active&gt;
&lt;/your_firm_module_name&gt;
&lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 01 Nov 2015 11:16:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 创建、修改CMS]]></title>
      <link>https://www.360magento.com/blog/magento_home_design/</link>
      <description><![CDATA[<p>为了管理网站页面，你需要进入后台CMS区域。点击Pages链接进入页面修改。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento CMS" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_home_design1.jpg" width="auto" /></div>
<p>通过点击页面，你就可以修改它。修改页面将展开下面这样的窗口：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Page" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_home_design2.jpg" width="auto" /></div>
<p>你可以按你的喜好来进行修改。Static block是另一种非常有用的选项。例如，你可以编辑页面底部包含链接的footer块：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Static Block" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_home_design3.jpg" width="auto" /></div>
<p>Polls区域允许你创建和修改投票：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Poll" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_home_design4.jpg" width="auto" /></div>
<p>事实上，Magento集成了一个功能齐全的CMS系统。你可以添加不同的元素到你的网站里。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 01 Nov 2015 11:10:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento2中创建主题（第二部分）]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-2/</link>
      <description><![CDATA[<h2>2.配置和创建主题文件夹</h2>
<p>&middot;按<strong>app/design/&lt;area&gt;/&lt;vendorName&gt;/&lt;newTheme&gt;/</strong>的结构在design文件夹下创建主题文件夹</p>
<p>例如：<strong>/app/design/frontend/Magento/magestore</strong></p>
<h3>声明主题</h3>
<p>在刚创建的magestore主题文件夹里创建theme.xml文件。声明信息包括：主题，版本，父类主题（如果是继承主题）</p>
<pre><code>&lt;theme xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Config/etc/theme.xsd"&gt;
&lt;title&gt;Alwaylystore Theme&lt;/title&gt;
&lt;media&gt;
&lt;preview_image&gt;media/preview.jpg&lt;/preview_image&gt;
&lt;/media&gt;
&lt;/theme&gt;
</code></pre>
<p>为新主题创建一张图片：magestore.png，它的文件位置是：<strong>/app/design/frontend/Magento/magestore/media/theme/preview/magestore.png</strong>。如果路径不对会找不到图片的。</p>
<h3>在主题文件夹里创建composer.json文件</h3>
<pre><code>{
    "name": "magento/theme-frontend-blank",
    "description": "N/A",
    "require": {
        "php": "~5.4.11|~5.5.0",
        "magento/framework": "0.42.0-beta1",
        "magento/magento-composer-installer": "*"
    },
    "type": "magento2-theme",
    "version": "0.42.0-beta1",
    "license": [
        "OSL-3.0",
        "AFL-3.0"
    ],
    "extra": {
        "map": [
            [
                "*",
                "frontend/Magento/blank"
            ]
        ]
    }
}
</code></pre>
<p>在后台，进入<strong> Content &gt; Design &gt; Themes</strong>，可以看到新主题；</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2新主题" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-1.png" width="1000px" /></div>
<h3>配置图片（可选）</h3>
<p>在view.xml中，图片的尺寸将被配置。在新主题中新的文件夹被创建在<strong> app/design/&lt;area&gt;/&lt;vendorName&gt;/&lt;newTheme&gt;/etc/</strong></p>
<p>例如： <strong> /app/design/frontend/Magento/magestore/etc/</strong></p>
<p>把默认主题中的view.xml文件拷贝到&lt;etc&gt;文件夹中</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2etc" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-2.png" width="auto" /></div>
<p>在view.xml中配置前端显示设置。例如，设置图片的尺寸到120px</p>
<pre><code>&lt;var name="new_products_content_widget_grid:type"&gt;small_image&lt;/var&gt;
&lt;var name="new_products_content_widget_grid:width"&gt;120&lt;/var&gt;
&lt;var name="new_products_content_widget_grid:ratio"&gt;1&lt;/var&gt;
&lt;var name="new_products_content_widget_grid:height"&gt;120&lt;/var&gt;
</code></pre>
<h3>创建图片文件夹</h3>
<p>在主题中，创建&lt;web&gt;文件夹，并在&lt;web&gt;文件夹内创建&lt;image&gt;文件夹：</p>
<p><strong>App/design/&lt;area&gt;/&lt;vendorName&gt;/&lt;newTheme&gt;web/images/</strong></p>
<p>例如：<strong> /app/design/frontend/Magento/alwaylystore/web/images/</strong></p>
<h3>为主题添加一个logo图片</h3>
<p>进入app/design/&lt;area&gt;/&lt;vendorName&gt;/&lt;newTheme&gt;web/images/</p>
<p>例如：<strong>/app/design/frontend/Magento/mageystore/web/images/</strong></p>
<p>拷贝名为logo.png的图片到文件夹中。 Magento默认设置logo.gif图片作为logo图片。如果你想要修改，那么拷贝默认主题里的<strong>/Magento_Theme/layout/default.xml</strong>到你的主题中。</p>
<p>例如：/app/design/frontend/Magento/magestore/Magento_Theme/layout/default.xml</p>
<p>添加下面的代码：</p>
<pre><code>&lt;referenceBlock name="logo"&gt;
&lt;arguments&gt;
&lt;argument name="logo_file" xsi:type="string"&gt;images/logo.png&lt;/argument&gt;
&lt;/arguments&gt;
&lt;/referenceBlock&gt;
</code></pre>
<p>现在，我们的文件结构看起来像是这样的：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 default.xml" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-3.png" width="auto" /></div>
<h3>使用创建的主题：</h3>
<p>进入后台<strong>Store &gt; Configuration &gt; Design</strong>在Design Theme里选择我们创建的主题，然后保存。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2使用新主题" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-4.png" width="1000px" /></div>
<p>我们已经创建了一个新主题的文件结构，下面的部分将一步一步地配置你的主题。</p>
<h1>3.基础元素定制</h1>
<h3>定制CSS：</h3>
<p>到<strong>/app/design/frontend/Magento/blank</strong>文件夹中拷贝web/css文件夹</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 web/css" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-5.png" width="auto" /></div>
<p>粘贴到你的主题相应的文件夹中（<strong>/app/design/frontend/Magento/magestore/web</strong>）：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 new web" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-6.png" width="auto" /></div>
<p>到文件夹<strong>/lib/web/css/source/lib</strong>中拷贝lib.css文件到Magestore主题中</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 lib.css" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-7.png" width="auto" /></div>
<p>打开<strong>app/design/frontend/Magento/magestore/web/css/</strong>中的style.less文件，如下编辑代码：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 style.less" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-8.png" width="auto" /></div>
<p>之后，在你的source文件夹里创建mytheme.less。</p>
<p>我们就有了这样的文件路径：<strong>app/design/frontend/Magento/magestore/web/css/source/mytheme.less</strong>,将下面的代码加入到mytheme.less中：</p>
<pre><code>body {
  margin: 0px!important;
  padding: 0px!important;
}
 
.page-wrapper {
  background-color: #333;
}
 
 
.mycustom-class {
  color: red;
}
</code></pre>
<p>删除Var/cache文件夹，刷新你的浏览器，你将看到：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 mytheme修改效果" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-9.png" width="auto" /></div>
<h3>定制模版模块：</h3>
<p>你还可以定制任何模块的html，例如，如果你想定制前端的<strong>Magento_Catalog</strong>模块，到模块的<strong>app/code/Magento/Catalog/view/frontend/</strong>文件夹中，拷贝layout, templages, web文件到你的主题中并放置到和模块一样名字的<strong>Magento_catalog</strong>文件夹中，例如：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 Magento_Catalog" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-10.png" width="auto" /></div>
<p>让我们把&ldquo;Buy this product now&rdquo;加入到&ldquo;Add to Cart&rdquo;之下。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 添加语句到Add to cart下效果" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-11.png" width="auto" /></div>
<p>进入<strong>app/design/frontend/Magento/magestore/Magento_Catalog/templates/product/view/addto.phtml</strong>文件，在第31行的位置，如下编辑：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento2 添加语句到Add to cart下代码" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-2-12.png" width="auto" /></div>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 31 Oct 2015 14:25:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento邮寄方式的设置和修改]]></title>
      <link>https://www.360magento.com/blog/magento_shipping_methods/</link>
      <description><![CDATA[<p>要配置你的Magento邮寄方式，你需要登录后台，然后进入<strong>System -&gt; Configuration -&gt; Sales -&gt;Shipping Methods.</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Shipping Methods" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_shipping_methods_1.jpg" width="auto" /></div>
<p>在开启邮寄方式前你需要完成邮寄方式的设置，在<strong>System -&gt; Configuration -&gt; Sales -&gt; Shipping Settings.</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Shipping Setting" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_shipping_methods_2.jpg" width="auto" /></div>
<p>展开Origin区域。输入产品的发货地址，通常是产品存储的仓库。之后展开Option区域。开启<strong>Allow Shipping to Multiple Addresses</strong>就允许一个订单中的货物发送到多个地址。这是很实用的，比如一个客户买了很多明信片或者钢笔之类的东西，他想要发给不同的地址。你可以在<strong>Maximum Qty Allowed for Shipping to Multiple Addresses</strong>这一栏定义允许邮寄的地址的最大数量。</p>
<p>例如，要开启USPS邮寄方式，你可以进入<strong>System -&gt; Configuration -&gt; Sales -&gt; Shipping Methods</strong>，转到USPS区域：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Shipping USPS" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_shipping_methods_3.jpg" width="auto" /></div>
<p>开启邮寄方式，输入Gateway URL和UserID。下面的选项允许你描述包裹的信息（大小，重量等等&hellip;&hellip;）。然后你可以定义handling fee（手续费），可以是固定值也可以按百分比计算。之后你可以选择运输方式，你也可以配置一个到多少金额免运费的方法。</p>
<p>最后，你可以定义支持运输的国家和运输服务出错时的报错信息。在Sort order选项你应该输入这个运输方法相对其它运输方法的位置。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 31 Oct 2015 14:25:00 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento支付方法的设置和修改]]></title>
      <link>https://www.360magento.com/blog/magento_payment_methods/</link>
      <description><![CDATA[<p>Magento提供不同的支付方法来支持各种支付方式。例如：Paypal,Authorize.net和其它的支付方式。客户也能通过普通信用卡（如Visa，Master Card，American Express等&hellip;&hellip;）来完成支付。</p>
<p>要在Magento中配置你的支付方式，你需要先进入后台，接着<strong>System -&gt; Configuration -&gt; Sales -&gt; Payment Methods</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Payment Methods" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_payment_methods_1.jpg" width="auto" /></div>
<p>在这篇教程里，我们将开启信用卡支付方法。这个方法可以在Saved CC区域配置：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Saved CC" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_payment_methods_2.jpg" width="auto" /></div>
<p>开启方法，输入标题，设置新的订单状态，挑选支持的信用卡，决定是否需要信用卡验证，通过设置允许支付的国家来限定支付的范围。</p>
<p>填写Sort order可调整与其它支付方式的相对位置。好了，你已经为客户开启了这种支付方法。由于所有的支付方法都有不同的配置，我没办法在这里逐个详细说明，只要按照特定页面的说明，它们就应该可以工作。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 30 Oct 2015 12:37:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento2中创建主题（第一部分）]]></title>
      <link>https://www.360magento.com/blog/magento2-theme-1/</link>
      <description><![CDATA[<p>嘿，伙计。你已经积累多少Magento2知识了，有没有想要和大家分享的？我在Magento2中发现了一些有趣的功能。不论你是插件或主题开发人员，你都应该花时间读读这篇文章。因为你将明白更多关于Magento2主题和模版结构的知识。</p>
<p>我把这个教程分成了两个部分。今天的这篇是第一部分，关于主题包中的基础元素。第二部分将展示如何在Magento2中自定义它。</p>
<h2>1、主题包中的基础元素</h2>
<h3>a.Magento2中的主题结构</h3>
<p>Magento2的MVC结构比Magento1中更加明了。Magento2模块将添加View元素到模块文件结构里。以Catalog为例：<strong>app/code/Magento/Catalog/</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Catalog" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-1.png" width="auto" /></div>
<p>注意，View元素和Controller，Model在同一位置。展开View文件夹，你将看到：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Catalog View" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-2.png" width="auto" /></div>
<p>你可以看到，这个结构下有3个元素，他们是从 
<area />
 标签移出来的。 
<area />
 文件结构展开以后包含layout, templates, web。例如，frontend有3个基础文件夹：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento Catalog View frontend web" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-3.png" width="auto" /></div>
<p><strong>Layout（布局）</strong>文件夹包含所有模块的布局文件（类似于Magento 1.x，布局文件包含在主题文件夹的Layout里）。当然，这些布局的代码有不同的结构。我将在后面具体的部分说明。</p>
<p><strong>Template（模板）</strong>文件夹有所有的.phtml文件，和Magento1中一样由php和html代码混合而成，用来渲染成html。</p>
<p>Web文件夹是Magento2中新出现的文件夹，你可以从下图看到它的组成：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="web文件夹结构" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-4.png" width="auto" /></div>
<p>不难看出，它里面包含了CSS，JS和Images文件夹。也就是说，在Magento2中，旧的skin文件夹被划分到每个模块中去了，使得模块更加独立。</p>
<h3>b.Layout</h3>
<p>在Magento2中，每个模块有默认的布局，可以被重写或被另一个布局扩展。</p>
<p>例如：<strong>app/code/Magento/Catalog/view/frontend/layout/default.xml</strong></p>
<p>Magento用特别的句柄来分离布局文件。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="layout" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-5.png" width="auto" /></div>
<p>句柄的声明和之前规则一样catalog_product_view是一个根据模块和控制器动作命名的句柄。定义页面则需要更加具体的声明：<strong>catalog_product_view_type_simple_id_128</strong>。或者我们可以调用其它句柄。这里是关于Catalog模块布局文件位置的示例：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="Magento2 Catalog模块布局文件" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-6.png" width="auto" /></div>
<p>模块中有两种布局，<strong>Base layout</strong>和<strong>Theme layout</strong>。</p>
<p><strong>Base layout</strong>是每个模块默认的布局区域。如果不是你自定义的模块，我们是不建议你直接修改这些文件的。</p>
<p>例如：<strong>app/design/frontend/Magento/blank/Magento_Checkout/layout/</strong></p>
<pre><code>__app/code/&lt;Namespace&gt;/&lt;Module&gt;|__/view|__/&lt;area&gt;|__/layout|&ndash;&lt;layout_file1&gt;.xml|&ndash;&lt;layout_file2&gt;.xml</code></pre>
<p><strong>Theme layouts</strong>是模块的外部主题，允许通过报告主题文件中对应的&lt;Namespace&gt;_&lt;lModule&gt;来定制默认的主题布局。</p>
<p>例如：<strong>app/design/frontend/Magento/blank/Magento_Checkout/layout/</strong></p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="Magento2 Checkout布局" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-7.png" width="auto" /></div>
<p><strong>创建一个布局文件要遵循下面的规则：</strong></p>
<ul>
<li>每个布局文件调用一个句柄，其它被调用；</li>
<li>布局文件的名字就是布局句柄的名字，例如：checkout_cart_index</li>
<li>布局文件在布局文件夹中被调用</li>
</ul>
<p>例如：</p>
<pre><code>&lt;layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
&lt;update handle="page_one_column" /&gt;
   &lt;referenceContainer name="content"&gt;
   &lt;!-- ... --&gt;
   &lt;/referenceContainer&gt;
&lt;/layout&gt;
</code></pre>
<p><strong>下面描述布局文件的读取和处理顺序</strong>：</p>
<ul>
<li>如果布局文件属于不同的模块，那么执行的顺序将是：独立模块，相关模块，然后按字母顺序排列；</li>
<li>如果文件属于同一个模块，那么就按文件名字的字母顺序排列。</li>
</ul>
<p><strong>布局系统执行的步骤</strong></p>
<ul>
<li>读取所有默认布局文件组（base），包括关联的那个；</li>
<li>决定继承和重写文件的顺序；</li>
<li>添加所有被展开的布局，替换掉base中的布局，获取父类布局，替换被子类重写的父类布局。</li>
</ul>
<p>下面是布局进程的模型：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="Magento2布局进程" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-8.png" width="auto" /></div>
<p>由此看以看出，布局文件是由上自下被重写的，父类主题重写模块中的base主题，子主题（一般是我们定义的主题）重写父类。例如：Module_One模块的布局文件layout_2在重写文件夹中的父类主题parent_theme里被声明。因此，系统会用parent_theme &gt; Module_One &gt; override &gt; layout_2.xml替换掉Module_One &gt; layout_2.xml。</p>
<p><strong>布局/块区域：</strong></p>
<p>和magento1一样，它分为基础的布局区域：</p>
<p><strong>Container（容器）</strong>：分配页面元素的区域</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="Magento2容器" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-9.png" width="auto" /></div>
<p><strong>Block（块）</strong>：容器中默认Magento块元素所在的区域</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="Magento2块" src="http://7xjryy.com1.z0.glb.clouddn.com/create-magento2-custom-theme-1-10.png" width="auto" /></div>
<p>下面是一个布局内容示例：</p>
<pre><code>&lt;container name="container.1" label="Container 1"
as="container_1" output="1" htmlTag="div" htmlId="container-1"
htmlClass="container"&gt;
&lt;block class="Magento\Module\Block\Class" name="block.1"&gt;
&lt;container name="child.container" label="Child Container" as="child"&gt;
&lt;block type="Magento\Module\Block\Class" name="block.2"&gt;
&lt;/container&gt;
&lt;block class="Magento\Module\Block\Class" name="block.3"/&gt;
&lt;/container&gt;
&lt;container name="container.2" as="container_2" htmlTag="div"
htmlId="container-2" htmlClass="container"/&gt;
</code></pre>
<h2>c.新语言风格LESS介绍</h2>
<p>在定义主题元素之前，我们需要学习新的语言风格-LESS。在Magento2中这个语言很有趣。由于有一些高级的功能，LESS的添加级别要高于CSS。它被翻译成CSS得益于php中的LESS库。我们仍然允许在源码中添加CSS URL直接使用。</p>
<p>LESS语言的预处理是通过<strong>lib/internal/Magento/Css/PreProcesso</strong>中的库完成的。在LESS文件中的导入方式是：</p>
<p><strong>file.less</strong></p>
<pre><code>@magento_import &ldquo;&lt;some_id&gt;&rdquo;;
@import &ldquo;path/to/dir1/some_file&rdquo;;@import &ldquo;path/to/file/file1.less&rdquo;;@import &ldquo;path/to/file/file2.less&rdquo;;
</code></pre>
<p>想要了解更多关于LESS语言，你可以访问<a href="http://lesscss.org/">http://lesscss.org/</a>或者<a href="http://less.eten.vn/">http://less.eten.vn/</a></p>
<p>默认的LESS库文件结构是：</p>
<p><strong>lib/web/ ├── css/<br /> <br /> │ ├── docs/ (Library documentation)<br /> <br /> │ ├── source/<br /> <br /> │ │ ├── lib/ (Library source files)<br /> <br /> │ │ │ ├── abstract.less<br /> <br /> │ │ │ ├── actions-toolbar.less<br /> <br /> │ │ │ ├── breadcrumbs.less<br /> <br /> │ │ │ ├── buttons.less<br /> <br /> │ │ │ ├── dropdowns.less<br /> <br /> │ │ │ ├── forms.less<br /> <br /> │ │ │ ├── icons.less<br /> <br /> │ │ │ ├── layout.less<br /> <br /> │ │ │ ├── lib.less<br /> <br /> │ │ │ ├── loaders.less<br /> <br /> │ │ │ ├── messages.less<br /> <br /> │ │ │ ├── navigation.less<br /> <br /> │ │ │ ├── pages.less<br /> <br /> │ │ │ ├── popups.less<br /> <br /> │ │ │ ├── rating.less<br /> <br /> │ │ │ ├── resets.less<br /> <br /> │ │ │ ├── responsive.less<br /> <br /> │ │ │ ├── sections.less<br /> <br /> │ │ │ ├── tables.less<br /> <br /> │ │ │ ├── tooltips.less<br /> <br /> │ │ │ ├── typography.less<br /> <br /> │ │ │ ├── utilities.less<br /> <br /> │ │ │ └── variables.less<br /> <br /> │ │ └── theme.less<br /> <br /> │ └── styles.less<br /> <br /> ├── fonts/<br /> <br /> │ └── Blank-Theme-Icons/ (Library custom icons font)<br /> <br /> ├── images/<br /> <br /> │ └── blank-theme-icons.png (Library icons sprite)<br /> <br /> └── jquery/ (Library javascript files)</strong></p>
<h3>&nbsp;</h3>
<h3>d.Mage_page元素</h3>
<p>之前Magento版本中的Mage_page元素被Mangento_Theme模块替代了。</p>
<p>现在，准备好学习下一章了吗？那么开始<a title="如何在Magento2中创建主题（第二部分）" href="https://www.360magento.com/blog/magento2-theme-2/">第二部分</a>吧！</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 30 Oct 2015 12:24:27 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento产品教程]]></title>
      <link>https://www.360magento.com/blog/magento_product/</link>
      <description><![CDATA[<p>在这篇教程中我们将讨论网店中最重要的一个方面--你的产品。一旦你读了这篇教程，你将知道如何添加、管理产品，给产品添加图片和标签。</p>
<h1>1、在Magento中如何添加产品</h1>
<p>进入Magento后台-&gt; Catalog -&gt; Manage Products -&gt; Add Product</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento产品添加" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_1.jpg" height="346" width="609" /></div>
<p>选择产品设置（属性组和产品类型），点击Continue按钮；</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento产品属性组和类型选择" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_2.jpg" height="346" width="609" /></div>
<p>在接下来的页面里，你需要填写产品的相关信息（Name, SKU (Stock Keeping Unit), Weight, Status (Enabled/Disabled), Tax Class等等&hellip;&hellip;）你也可以通过Create New Attribute按钮为产品添加自定义属性。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento产品基本信息" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_3.jpg" height="346" width="609" /></div>
<p>填好以后，点击Save and Continue Edit按钮，在下一个选项卡里你将为产品定价。你也可以添加像Tier Price和Special Price这样的特殊价格。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento产品价格" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_4.jpg" height="346" width="609" /></div>
<p>点击Save and Continue Edit按钮保存产品，如果想让产品在前端显示，请务必设置Inventory为In Stock。</p>
<h1>2、如何为产品添加图片</h1>
<p>在Magento中为产品添加图片是很容易的。在后台-&gt; Catalog -&gt; Manage Products出现的网格中选择你要添加图片的产品，然后在左侧选择Images选项。点击Browse Files按钮，然后选中你要上传的图片，再点击Upload Files上传图片到服务器。最后，选择用点选按钮选择图片出现的位置，点击Save按钮。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento图片上传" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_6.jpg" height="346" width="609" /></div>
<h1>3、如何管理产品属性</h1>
<p>点击Create New Attribute按钮可为产品创建属性</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento添加属性" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_7.jpg" height="346" width="609" /></div>
<p>属性填写完以后点击Save Attribute按钮，在category选项卡里可为产品选择一个分类。最后点击Save按钮保存产品信息。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento产品加入分类" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_8.jpg" height="346" width="609" /></div>
<h1>4、如何管理产品标签</h1>
<p>默认地，Magento允许顾客对产品进行标记。当客户给某个产品标记以后，标签会变为待定状态，只有被批准以后才会显示在产品页面。</p>
<p>让我们给产品添加标签，批准它，然后看它在产品详细页是如何显示的。添加产品标签只需要简单地在Add Your Tags区域填写、提交即可。我们添加"Great"标签，点击Add Tags，之后会出现一条提示信息，说明标签已经被接收。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento标签添加" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_9.jpg" height="346" width="609" /></div>
<p>接着，进入后台-&gt; Catalog -&gt; Tags -&gt; Pending Tags，这里可以看到所有的标签。在我们这种情况下，只有一个出于"Pending"状态下名为"Great"的标签。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento标签列表" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_10.jpg" height="346" width="609" /></div>
<p>点击它，你就会看到下面的界面，在这里将"pending"改为"Approved",点击Save Tag。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento标签状态修改" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_11.jpg" height="346" width="609" /></div>
<p>现在，这个标签就被批准了，其它客户可以在对应产品的详细页看到这个标签了。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 29 Oct 2015 15:57:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在Magento2中创建一个简单的模块]]></title>
      <link>https://www.360magento.com/blog/create-magento2-module/</link>
      <description><![CDATA[<p>本示例中命名空间为：Magento，模块名为：Hello，示例链接为http://localhost/magento20/hello/index/index。</p>
<h1>1、创建<strong>app/code/Magento/Hello/etc/module.xml</strong>文件来声明模块</h1>
<pre><code>&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd"&gt;
   &lt;module name="Magento_Hello" schema_version="0.0.1"/&gt;
&lt;/config&gt;
</code></pre>
<h1>2、创建控制器和动作：</h1>
<p>创建<strong>app/code/Magento/Hello/Controller/Index/Index.php</strong>，其中Index扮演控制器的角色，Index.php是动作。Index.php中执行的方法是execute()。</p>
<pre><code>namespace Magento\Hello\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{
  public function execute()
{
     $this-&gt;_view-&gt;loadLayout();
       $this-&gt;_view-&gt;getLayout()-&gt;initMessages();
    $this-&gt;_view-&gt;renderLayout();
}
}
</code></pre>
<p>创建一个块：<strong>app/code/Magento/Hello/Block/Hello.php</strong></p>
<pre><code>namespace Magento\Hello\Block;
class Hello extends \Magento\Framework\View\Element\Template
{
public function _prepareLayout()
{
    return parent::_prepareLayout();
}
}
</code></pre>
<p>写配置文件<strong>/app/code/Magento/Hello/etc/frontend/routes.xml</strong>。</p>
<p>在Magento2中config.xml 只配置默认&lt;default&gt;标签中的配置值。前端路由的信息会在<strong>Magento/Hello/etc/frontend/routes.xml</strong>中（后台也是类似的）。前端事件会被声明在<strong>Magento/Hello/ect/frontend/events.xml</strong>（后台类似）。我们这里只是一个简单的示例，只在<strong>Magento/Hello/etc/frontend/routes.xml</strong>中声明路由。</p>
<pre><code>&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd"&gt;
&lt;router id="standard"&gt;
    &lt;route id="hello" frontName="hello"&gt;
        &lt;module name="Magento_Hello" /&gt;
    &lt;/route&gt;
&lt;/router&gt;
&lt;/config&gt;</code></pre>
<h1>3、创建前端模板</h1>
<p>这一步中布局的名字很重要，它将被命名在结构后：<strong>router name_controller namer_action name</strong>（路由器名_控制器名_动作名）。</p>
<pre><code>&lt;page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"&gt;
&lt;body&gt;
    &lt;referenceContainer name="content"&gt;
        &lt;block class="Magento\Hello\Block\Hello" name="hello" template="success.phtml"&gt;
        &lt;/block&gt;
    &lt;/referenceContainer&gt;
&lt;/body&gt;
&lt;/page&gt;
</code></pre>
<p>接着，我们创建布局文件中调用的<strong>success.phtml</strong>文件。</p>
<pre><code>&lt;?php echo &lsquo;Successful! This is a simple module in Magento 2.0&prime;; ?&gt;
</code></pre>
<h1>4、打开<strong>app/etc/config.xml</strong>，在&lsquo;module&rsquo;数组里添加元素&lsquo;Magento_Hello&rsquo; =&gt; 1,</h1>
<p>最后访问http://localhost/magento20/hello/index/index，查看结果。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 28 Oct 2015 12:27:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento的安装]]></title>
      <link>https://www.360magento.com/blog/magento-installation/</link>
      <description><![CDATA[<p>1.从官网下载最新的Magento安装包：<a title="magento 下载" href="http://www.magentocommerce.com/download">http://www.magentocommerce.com/download</a>；</p>
<p>2.将下载的安装包放到安装环境下，本地使用wamp或者xamp，在线则需要使用cPanel或者FTP工具；</p>
<p>3.本地进入phpmyadmin（线上则用cPanel的MySQL管理），创建一个数据库和用户，在安装过程中会用到。</p>
<p>4.在浏览器中输入Magento安装包地址就会进入安装步骤，会看到如下界面：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento安装协议" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_installation_1.jpg" height="346" width="609" /></div>
<p>勾选"I agree to the above terms and conditions"，点击Continue按钮；</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento安装语言环境" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_installation_2.jpg" height="346" width="609" /></div>
<p>选择时区和货币类型，点击Continue按钮；</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento安装数据库配置" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_installation_3.jpg" height="346" width="609" /></div>
<p>进入数据库安装页面，输入之前创建的数据库名和用户名，密码，勾选"Skip Base URL validation before next step"选项，点击Continue按钮；</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento安装个人设置" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_installation_4.jpg" height="346" width="609" /></div>
<p>最后进入个人信息和后台登录详情页面，按要求填写信息，点击Continue按钮即可。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento安装数据库成功" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_installation_5.jpg" height="346" width="609" /></div>
<p>安装成功，可点击对应的按钮进入前端或者后台。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 28 Oct 2015 12:13:51 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ 如何重写Magento模型类？]]></title>
      <link>https://www.360magento.com/blog/override_magento_model/</link>
      <description><![CDATA[<p>很多时候当我想要实现新功能，但又不想修改核心类。对于控制器来说，这很简单。从核心文件中拷贝控制器，放到local中同样的位置，然后修改就可以了。但这不适用于模型，那么如何在不修改核心文件的前提下重写Magento模型呢？</p>
<p>幸运的是，这并不难。让我们一起做个插件吧。我们以<strong>app/code/core/Mage/Wishlist/Model/Item.php</strong>中的<strong>Mage_Wishlist_Model_Item</strong>为例。我们想要添加新的功能，所以创建新的模块。<strong>app/code/local/Alwayly/Wishlist/Model/Item.php</strong>。现在将<strong>Mage_Wishlist_Model_Item</strong>重命名为<strong>Alwayly_Wishlist_Model_Item</strong>并在<strong>loadByProductWishlist</strong>方法加入下面一行代码：</p>
<pre><code>var_dump(get_class($this)); exit();
</code></pre>
<p>现在，在<strong>app/etc/modules/</strong>中创建<strong>Alwayly_Wishlist.xml</strong>，代码如下：</p>
<pre><code>&lt; ?xml version="1.0"?&gt;  
&lt;config&gt;  
    &lt;modules&gt;  
        &lt;alwayly_wishlist&gt;  
            &lt;active&gt;true&lt;/active&gt;  
            &lt;codepool&gt;local&lt;/codepool&gt;  
        &lt;/alwayly_wishlist&gt;  
    &lt;/modules&gt;  
&lt;/config&gt; 
</code></pre>
<p>接着用下面的代码创建<strong>app/code/local/Alwayly/Wishlist/etc/Config.xml</strong>：</p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;alwayly_wishlist&gt;
            &lt;version&gt;0.1&lt;/version&gt;
        &lt;/alwayly_wishlist&gt;
    &lt;/modules&gt;
    &lt;global&gt;
       &lt;models&gt;
          &lt;wishlist&gt;
              &lt;rewrite&gt;
                  &lt;item&gt;Alwayly_Wishlist_Model_Item&lt;/item&gt;
              &lt;/rewrite&gt;
          &lt;/wishlist&gt;
       &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 27 Oct 2015 12:19:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[以编程的方式创建Magento并与布局关联]]></title>
      <link>https://www.360magento.com/blog/programatically-blocks-layout/</link>
      <description><![CDATA[<p>想像一下，当你要创建一个简单的视图文件（例如，custom-note.phtml）并在Magento的一些新链接中展示出来。一种方式是创建CMS页面，在CMS页面中调用这个块。但是当你想要让这个块在Magento布局的其它部分，或者说后台CMS修改不了的地方？如果我想在面包屑导航下面添加新的div元素或者新的块，又该如何做？</p>
<p>Magento的理念是在你模块的/Block文件夹下创建块类，/layout文件夹下创建xml布局文件，等等。总之，你要么需要创建Block文件或添加/修改布局文件入口。</p>
<p>一切都确定好了，如果你要在多店铺中开发一个模块，我首要关心的就是将必要模块文件的数量降到最低。下面的代码将让你知道调用Core/Template块到任何Magento布局区域是多么简单。</p>
<p><strong>app/code/local/ActiveCodeline/CustomOutputs/controllers/IndexController.php</strong></p>
<pre><code>public function indexAction()
{
//Get current layout state
$this-&gt;loadLayout();
 
$block = $this-&gt;getLayout()-&gt;createBlock(
'Mage_Core_Block_Template',
'my_block_name_here',
array('template' =&gt; 'activecodeline/developer.phtml')
);
 
$this-&gt;getLayout()-&gt;getBlock('content')-&gt;append($block);
 
//Release layout stream... lol... sounds fancy
$this-&gt;renderLayout();
}
</code></pre>
<p>值得注意的是，当你提交一个无效的块到<strong>-&gt;append()</strong>时，可能什么也不会发生。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 27 Oct 2015 12:14:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento自定义邮件]]></title>
      <link>https://www.360magento.com/blog/magento-custom-emails/</link>
      <description><![CDATA[<p>是否曾想过用Magento内置的电子邮件功能发送邮件？是否想在Magento中做些什么的时候碰壁？好吧，我已经知道答案了。总之，Magento发送邮件被证实只要几个小时跟踪Magento代码。那么，我要创建名为activecodeline_custom_email1.html电子邮件，我想在它运行时传几个变量给它，我要以编程的方式发送电子邮件。</p>
<p>下面就是：</p>
<pre><code>...
/*
 * Loads the html file named 'custom_email_template1.html' from
 * app/locale/en_US/template/email/activecodeline_custom_email1.html
 */ 
$emailTemplate  = Mage::getModel('core/email_template')
						->loadDefault('custom_email_template1');					

//Create an array of variables to assign to template
$emailTemplateVariables = array();
$emailTemplateVariables['myvar1'] = 'Branko';
$emailTemplateVariables['myvar2'] = 'Ajzele';
$emailTemplateVariables['myvar3'] = 'ActiveCodeline';
 
/**
 * The best part :)
 * Opens the activecodeline_custom_email1.html, throws in the variable array 
 * and returns the 'parsed' content that you can use as body of email
 */
$processedTemplate = $emailTemplate->getProcessedTemplate($emailTemplateVariables);
 
/*
 * Or you can send the email directly, 
 * note getProcessedTemplate is called inside send()
 */
$emailTemplate->send('john@someemail.com','John Doe', $emailTemplateVariables);
...
</code></pre>
<p>为了让上面的代码工作，你需要在<strong>config.xml</strong>中添加下面的代码：</p>
<pre><code>...
&lt;global>      
	&lt;template>
		&lt;email>
			&lt;custom_email_template1 module="SampleModule1">
				&lt;label>ActiveCodeline custom email module&lt;/label>
				&lt;file>activecodeline_custom_email1.html&lt;/file>
				&lt;type>html&lt;/type>
			&lt;/custom_email_template1>
		&lt;/email>
	&lt;/template>
&lt;/global>  
...
</code></pre>
<p>不要忘了邮件模版<strong>app/locale/en_US/template/email/activecodeline_custom_email1.html.</strong></p>
<pre><code>&lt;!--@subject ActiveCodeline custom email module @-->
 
&lt;div>
&lt;h1>ActiveCodeline custom email example by Branko Ajzele&lt;/h1>
&lt;p>Hi there {{var myvar1}} {{var myvar2}} from {{var myvar3}}. This is just some example template to test custom email module.&lt;/p>
&lt;/div>
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 26 Oct 2015 12:57:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何用前端模版代码删除Magento产品]]></title>
      <link>https://www.360magento.com/blog/delete-magento-product/</link>
      <description><![CDATA[<p>由于某些原因，你可能需要在视图文件中用自定义代码删除产品。但是你会惊讶的看到 &ldquo;Cannot complete this operation from non-admin area.&rdquo;这样的报错。下面有些小技巧让你实现它。</p>
<p>这里是奏效的代码部分：</p>
<pre><code>$_authors_product = new Mage_Catalog_Model_Product();
	$_authors_product-&gt;load($_item_val_id);
 
	//echo "DELETED... ".$_POST['submit_item4sale_remove_by_entity_id'];
	$_item_val_id = $_POST['submit_item4sale_remove_by_entity_id']; 
	$_item_val_id = (int)str_replace('entity_id_', '', $_item_val_id);
 
	$_authors_product = new Mage_Catalog_Model_Product();
	$_authors_product-&gt;load($_item_val_id);
 
	$_current_customer_id = Mage::getSingleton('customer/session')-&gt;getCustomer()-&gt;getId();
 
	//Allow deletion only if product is from author
	if($_authors_product-&gt;submited_by_author == $_current_customer_id) 
	{
		//var_dump(Mage::registry('isSecureArea'));
 
		Mage::register('isSecureArea', true);
		//$_authors_product-&gt;delete();
		echo 'ALLOWED DELETED OH YEAAAAAA....';
		Mage::unregister('isSecureArea');	
	}
</code></pre>
<p>上面的代码是我最近项目中的一部分，其中最重要的是：</p>
<pre><code>Mage::register('isSecureArea', true);
echo 'ALLOWED DELETED OH YEAAAAAA....';
Mage::unregister('isSecureArea');
</code></pre>
<p>基本的想法是在注册表中写入合适的值Mage::register(&lsquo;isSecureArea&rsquo;, true)，删除产品后移除它。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 26 Oct 2015 12:52:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何获取Magento中所有启用的支付模块]]></title>
      <link>https://www.360magento.com/blog/active-payment-modules/</link>
      <description><![CDATA[<p>下面的代码将获取你所有启用的Magento支付模块。下面的例子返回一个数组，你可以用它在Magento的前后台创建一个下拉框或者别的东西。</p>
<pre><code>class Alwayly_Vendor_Model_Activpayment
{
 
 
	public function getActivPaymentMethods()
	{
	   $payments = Mage::getSingleton('payment/config')-&gt;getActiveMethods();
 
	   $methods = array(array('value'=&gt;'', 'label'=&gt;Mage::helper('adminhtml')-&gt;__('--Please Select--')));
 
	   foreach ($payments as $paymentCode=&gt;$paymentModel) {
            $paymentTitle = Mage::getStoreConfig('payment/'.$paymentCode.'/title');
            $methods[$paymentCode] = array(
                'label'   =&gt; $paymentTitle,
                'value' =&gt; $paymentCode,
            );
        }
 
        return $methods;
 
	} 
 
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 25 Oct 2015 12:31:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[更改Magento后台网格行数]]></title>
      <link>https://www.360magento.com/blog/admin-grid-rows/</link>
      <description><![CDATA[<p>我们从客户那里接到一个需求，让我们更改Magento后台网格显示的行数。现在，这非常简单，我们知道如何做。下面的例子中，我们将使用Magento观测者模型和事件<strong>&ldquo;core_block_abstract_prepare_layout_before&rdquo;</strong>。</p>
<p>首先，给你的文件做好备份。</p>
<p>这是事件的例子，将下面的代码放入到<strong>config.xml</strong>：</p>
<pre><code>&lt;adminhtml&gt;
        &lt;events&gt;            
            &lt;core_block_abstract_prepare_layout_before&gt;
    		&lt;observers&gt;
                    &lt;reward&gt;
                        &lt;class&gt;grid/observer&lt;/class&gt;
                        &lt;method&gt;applyLimitToGrid&lt;/method&gt;
                    &lt;/reward&gt;
                &lt;/observers&gt;
    	    &lt;/core_block_abstract_prepare_layout_before&gt;
        &lt;/events&gt;
&lt;/adminhtml&gt;
</code></pre>
<p>第二步</p>
<p>创建模型类<strong>observer.php</strong></p>
<pre><code>class Alwayly_Grid_Model_Observer
{
 
    public function applyLimitToGrid(Varien_Event_Observer $observer)
    {
    	$block = $observer-&gt;getEvent()-&gt;getBlock();
    	if(($block instanceof Mage_Adminhtml_Block_Widget_Grid) &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; !($block  instanceof Mage_Adminhtml_Block_Dashboard_Grid))
    	$block-&gt;setDefaultLimit(200);
 
    }
 
}
</code></pre>
<p>如果你知道如何创建Magento模块，那么最好将这些代码写入你自己的模块。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 25 Oct 2015 12:28:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为Magento网格中的自定义列添加自定义渲染器]]></title>
      <link>https://www.360magento.com/blog/magento-custom-renderer/</link>
      <description><![CDATA[<p>有时你会需要在Magento的一些网格中添加新列，这是个很简单的任务。但是你可能想按你的方式格式化值或者别的什么。那么写你自己的渲染器就十分有用和简单了。</p>
<p>那么实际情况该如何做呢？让我们看看后台产品列表网格。在<strong>/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Grid.php</strong>文件中被称为<strong>Mage_Adminhtml_Block_Catalog_Product_Grid</strong>的类。在这篇文章中我们不重写这个块，但是让你知道如何做到这一点。用新的数据修改<strong>_prepareCollection()</strong>方法，例如，让我们为一个产品添加短描述。</p>
<pre><code>protected function _prepareCollection()
{
$store = $this-&gt;_getStore();
$collection = Mage::getModel('catalog/product')-&gt;getCollection()
-&gt;addAttributeToSelect('sku')
-&gt;addAttributeToSelect('name')
-&gt;addAttributeToSelect('short_description') // THIS IS WHAT WE HAVE ADDED
-&gt;addAttributeToSelect('attribute_set_id')
-&gt;addAttributeToSelect('type_id')
-&gt;joinField('qty',
'cataloginventory/stock_item',
'qty',
'product_id=entity_id',
'{{table}}.stock_id=1',
'left');
 
if ($store-&gt;getId()) {
//$collection-&gt;setStoreId($store-&gt;getId());
$collection-&gt;addStoreFilter($store);
$collection-&gt;joinAttribute('custom_name', 'catalog_product/name', 'entity_id', null, 'inner', $store-&gt;getId());
$collection-&gt;joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner', $store-&gt;getId());
$collection-&gt;joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner', $store-&gt;getId());
$collection-&gt;joinAttribute('price', 'catalog_product/price', 'entity_id', null, 'left', $store-&gt;getId());
}
else {
$collection-&gt;addAttributeToSelect('price');
$collection-&gt;addAttributeToSelect('status');
$collection-&gt;addAttributeToSelect('visibility');
}
 
$this-&gt;setCollection($collection);
 
parent::_prepareCollection();
$this-&gt;getCollection()-&gt;addWebsiteNamesToResult();
return $this;
}
</code></pre>
<p>现在，让我们把这些添加到一个新的列：</p>
<pre><code>*You will find some more code inside this method, but for readability purposes, I'll just say you need to add code you find 

here at beginning of this method...*/
 
protected function _prepareColumns()
{
$this-&gt;addColumn('Short description',
array(
'header'=&gt; Mage::helper('catalog')-&gt;__('Short description'),
'index' =&gt; 'short_description',
'renderer'  =&gt; 'Mage_Adminhtml_Block_Catalog_Product_Renderer_Red',// THIS IS WHAT THIS POST IS ALL ABOUT
));
 
}
</code></pre>
<p>创建<strong>Mage_Adminhtml_Block_Catalog_Product_Renderer_Red </strong>类，其代码如下</p>
<pre><code>&lt; ?php
class Mage_Adminhtml_Block_Catalog_Product_Renderer_Red extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
 
public function render(Varien_Object $row)
{
$value =  $row-&gt;getData($this-&gt;getColumn()-&gt;getIndex());
return '&lt;span style="color:red;"&gt;'.$value.'';
 
}
 
}
?&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 24 Oct 2015 14:31:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用PHP-ExcelReader类来读取XLS文件到Magento模块]]></title>
      <link>https://www.360magento.com/blog/excelreader-load-xls/</link>
      <description><![CDATA[<p>最近遇上一个不小的问题，我要读取XLS（Microsoft Excel文件）到PHP。在我花了近两个小时在网上搜索以后，我发现了一个开源的&ldquo;PHP-ExcelReader class&rdquo;很不错。它有所有我需要的东西（多表支持，可读取EXCEL 2000和2007的数据），另一方面，Magento不支持XLS。我决定些一个小的方法，这样你就可以在任何Magento的类里执行了。</p>
<p>那么，下面就是代码了：</p>
<pre><code>public function loadXML($path_to_XML)
{
$include_path = dirname(__FILE__);
$path_to_PHP_ExcelReader = $include_path."/read_xls/Excel/reader.php";
 
require_once $path_to_PHP_ExcelReader;
 
// ExcelFile($filename, $encoding);
$data = new Spreadsheet_Excel_Reader();
 
// Set output Encoding.
$data-&gt;setOutputEncoding('utf-8');
/* if you want you can change 'iconv' to mb_convert_encoding:*/
 
$data-&gt;setUTFEncoder('mb');
 
/*
* By default rows &amp; cols indeces start with 1
* For change initial index use:
*/
$index = 0;
 
$data-&gt;setRowColOffset($index);
/* setDefaultFormat - set format for columns with unknown formatting*/
 
$data-&gt;setDefaultFormat('%.2f');
 
/* setColumnFormat - set format for column (apply only to number fields)*/
$data-&gt;setColumnFormat(4, '%.3f');
/*Do the actual reading of file*/
 
$data-&gt;read($path_to_XML);
return $data;
}
</code></pre>
<p>下面是你的Excel文件数据化为PHP数组后可以调用的方法：</p>
<pre><code>$data-&gt;sheets[0]['numRows']
//count rows
 
$data-&gt;sheets[0]['numCols']
//count columns
 
$data-&gt;sheets[0]['cells'][$i][$j]
//data from $i-row $j-column
 
$data-&gt;sheets[0]['cellsInfo'][$i][$j]
//extended info about cell
 
$data-&gt;sheets[0]['cellsInfo'][$i][$j]['type'] = "date" | "number" | "unknown"
//if 'type' == "unknown" - use 'raw' value, because  cell contain value with format '0.00';
$data-&gt;sheets[0]['cellsInfo'][$i][$j]['raw'] = value
//if cell without format
 
$data-&gt;sheets[0]['cellsInfo'][$i][$j]['colspan']
//gets colspan value
 
$data-&gt;sheets[0]['cellsInfo'][$i][$j]['rowspan']
//gets rowspan value
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 24 Oct 2015 14:12:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento核心动作前后调用事件]]></title>
      <link>https://www.360magento.com/blog/before-after-events/</link>
      <description><![CDATA[<p>正如我们所知的，Magento中有些事件被默认地调度。我们可以轻易地挂钩这些事件，但这不是这篇文章的主题。我们要尝试的是在一些Magento控制器的一些动作前后添加自定义事件。</p>
<p>这样，我们就不需要事件被默认调度。当然，有些事件需要多做一点处理（例如，如果你需要一些session的东西，session在动作之后要被清除），但是大部分情况，有一种方法可以从事件中获取我们想要的。</p>
<p>例如，<strong>&ldquo;Mage_Checkout_CartController&rdquo;</strong>中的&ldquo;addAction()&rdquo;方法，我们可以用标准的方式重写这个方法并在重写的类里调度我们的事件。但我们可以做些类似这样的事情。</p>
<p>添加下面的代码到你模块的<strong>config.xml</strong>文件：</p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;dispatcher&gt;
                &lt;class&gt;Alwayly_Dispatcher_Model&lt;/class&gt;
            &lt;/dispatcher&gt;
        &lt;/models&gt;
    &lt;/global&gt;
    &lt;frontend&gt;
        &lt;events&gt;
            &lt;!-- Hooking to Magento's default event "controller_action_predispatch" --&gt;
            &lt;controller_action_predispatch&gt;
                &lt;observers&gt;
                    &lt;controller_action_before&gt;
                        &lt;class&gt;dispatcher/observer&lt;/class&gt;
                        &lt;method&gt;hookToControllerActionPreDispatch&lt;/method&gt;
                    &lt;/controller_action_before&gt;
                &lt;/observers&gt;
            &lt;/controller_action_predispatch&gt;
            &lt;!-- Hooking to Magento's default event "controller_action_postdispatch" --&gt;
            &lt;controller_action_postdispatch&gt;
                &lt;observers&gt;
                    &lt;controller_action_after&gt;
                        &lt;class&gt;dispatcher/observer&lt;/class&gt;
                        &lt;method&gt;hookToControllerActionPostDispatch&lt;/method&gt;
                    &lt;/controller_action_after&gt;
                &lt;/observers&gt;
            &lt;/controller_action_postdispatch&gt;
            &lt;!-- Hooking to our own event "add_to_cart_before" --&gt;
            &lt;add_to_cart_before&gt;
                &lt;observers&gt;
                    &lt;add_to_cart_before&gt;
                        &lt;class&gt;dispatcher/observer&lt;/class&gt;
                        &lt;method&gt;hookToAddToCartBefore&lt;/method&gt;
                    &lt;/add_to_cart_before&gt;
                &lt;/observers&gt;
            &lt;/add_to_cart_before&gt;
            &lt;!-- Hooking to our own event "add_to_cart_after" --&gt;
            &lt;add_to_cart_after&gt;
                &lt;observers&gt;
                    &lt;add_to_cart_after&gt;
                        &lt;class&gt;dispatcher/observer&lt;/class&gt;
                        &lt;method&gt;hookToAddToCartAfter&lt;/method&gt;
                    &lt;/add_to_cart_after&gt;
                &lt;/observers&gt;
            &lt;/add_to_cart_after&gt;
        &lt;/events&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>添加下面的代码到你模块的<strong>Observer.php</strong></p>
<pre><code>class Alwayly_Dispatcher_Model_Observer
{
    //this is hook to Magento's event dispatched before action is run
    public function hookToControllerActionPreDispatch($observer)
    {
        //we compare action name to see if that's action for which we want to add our own event
        if($observer-&gt;getEvent()-&gt;getControllerAction()-&gt;getFullActionName() == 'checkout_cart_add') 
        {
            //We are dispatching our own event before action ADD is run and sending parameters we need
            Mage::dispatchEvent("add_to_cart_before", array('request' =&gt; $observer-&gt;getControllerAction()-&gt;getRequest()));
        }
    }
 
    public function hookToControllerActionPostDispatch($observer)
    {
         //we compare action name to see if that's action for which we want to add our own event 
        if($observer-&gt;getEvent()-&gt;getControllerAction()-&gt;getFullActionName() == 'checkout_cart_add') 
        {
            //We are dispatching our own event before action ADD is run and sending parameters we need
            Mage::dispatchEvent("add_to_cart_after", array('request' =&gt; $observer-&gt;getControllerAction()-&gt;getRequest()));
        }
    }
 
 	public function hookToAddToCartBefore($observer) 
	{   
            //Hooking to our own event
	    $request = $observer-&gt;getEvent()-&gt;getRequest()-&gt;getParams();
            // do something with product
	    Mage::log("Product ".$request['product']." will be added to cart.");
	}
 
	public function hookToAddToCartAfter($observer) 
	{
            //Hooking to our own event
	    $request = $observer-&gt;getEvent()-&gt;getRequest()-&gt;getParams();
            // do something with product
	    Mage::log("Product ".$request['product']." is added to cart.");
	}
}
</code></pre>
<p>最后，我要指出的是：这段代码没有在产品环境中做测试，我们只是添加了两个自定义事件在Magento核心动作的前后，而不必重写这个类。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 23 Oct 2015 11:49:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何扩展Magento核心控制器]]></title>
      <link>https://www.360magento.com/blog/extend-magento-controller/</link>
      <description><![CDATA[<p>今天我将演示如何在不弄乱核心文件本身的前提下编辑Magento核心模块。</p>
<p>我选择Magento Customer模块下的Account控制器作为本文的示例。你要先找出它在Magento核心文件夹里的路径（完整路径是：<strong>app/code/core/Mage/Customer/controllers/AccountController.php</strong>）。</p>
<p>首先创建有类似文件结构的文件：</p>
<p><strong>app/code/local/Alwayly/Coreextended/controllers/Frontend/Customer/AccountController.php</strong>。（当然，你可以把Alwayly替换成你想要的命名空间，Coreextended换成其它模块名，但你需要对其它部分做相应的修改）。</p>
<p>接着创建我们模块的xml文件：app/code/local/Alwayly/Coreextended/etc/config.xml。将下面的代码写入对应的文件中：</p>
<h1>1.AccountController.php:</h1>
<pre><code>&lt; ?php
require_once Mage::getModuleDir('controllers', 'Mage_Customer').DS.'AccountController.php';
//we need to add this one since Magento wont recognize it automatically

class Alwayly_Coreextended_Frontend_Customer_AccountController extends Mage_Customer_AccountController
{//here, you extended the core controller with our public function indexAction()
{
parent::indexAction();
//you can always use default functionality
}

public function myactionAction()
{
//my code
//you can write your own methods / actions
}

public function mymethod()
{
//my code
//you can write your own methods
}

public function loginAction()
{
//finally you can write your code that will rewrite the whole core method
//and you can call for your own methods, as you have full control over core controller
}
}
</code></pre>
<h1>2.config.xml:</h1>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;alwayly_coreextended&gt;
            &lt;version&gt;0.2.0&lt;/version&gt;
        &lt;/alwayly_coreextended&gt;
    &lt;/modules&gt;
    &lt;frontend&gt;
        &lt;routers&gt;
            &lt;customer&gt;
                &lt;args&gt;
                    &lt;modules&gt;
                        &lt;alwayly_coreextended before="Mage_Customer_AccountController"&gt;
                               Alwayly_Coreextended_Frontend_Customer
                        &lt;/alwayly_coreextended&gt;
                    &lt;/modules&gt;
                &lt;/args&gt;
            &lt;/customer&gt;
        &lt;/routers&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<h1>3.Alwayly_Coreextended.xml：</h1>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;!--we need to enable this module as any other if--&gt;
&lt;!--you wish to do it as standalone module extension--&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;alwayly_coreextended&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codepool&gt;local&lt;/codepool&gt;
        &lt;/alwayly_coreextended&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 23 Oct 2015 11:42:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[以编程的方式修改magento核心配置数据]]></title>
      <link>https://www.360magento.com/blog/programmatically-core-config/</link>
      <description><![CDATA[<p>Magento安装完成后一定有一些设置好的核心配置。当你从后台面板更新这些值的时候，数据会被保存到<strong>core_config_data到</strong>这张数据表。这看起来很重要，也是你不会去碰触的，是嘛？在有些情况下，你想要用代码直接修改设置，这篇文章就将演示如何去做。
</p>
<p>假设我们想将<strong>“demo store notice” </strong>(on/off)的值从0改为1。你可以打开你的数据库，进入<strong>“core_config_data“</strong>表，改变这个数据的值，然后保存。好吧，下面就是我要讲的代码，你可以在你代码的任何一位置调用它：</p>
<pre><code>$alwaylySwitch = new Mage_Core_Model_Config();
/*
*turns notice on
*/
$alwaylySwitch ->saveConfig('design/head/demonotice', "1", 'default', 0);
/*
*turns notice off
*/
$alwaylySwitch ->saveConfig('design/head/demonotice', "0", 'default', 0);
</code></pre>
<p>实现这一神奇功能的代码是：</p>
<pre><code>class Mage_Core_Model_Config
{
	.
	.
	.
 
	/**
     * Save config value to DB
     *
     * @param string $path
     * @param string $value
     * @param string $scope
     * @param int $scopeId
     * @return Mage_Core_Store_Config
     */
    public function saveConfig($path, $value, $scope = 'default', $scopeId = 0)
    {
        $resource = $this->getResourceModel();
        $resource->saveConfig(rtrim($path, '/'), $value, $scope, $scopeId);
 
        return $this;
    }
 
	.
	.
	.
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 22 Oct 2015 11:23:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[给Magento PDF发票添加自定义属性]]></title>
      <link>https://www.360magento.com/blog/magentos-invoice-attribute/</link>
      <description><![CDATA[<p>今天我将用短短的几步添加自定义属性到Magento的PDF发票。最近我有个任务是为产品创建一个名称为<strong>&ldquo;alwayly_warehouse_location&rdquo;</strong>的自定义属性，当点击&ldquo;打印&rdquo;（在后台发票区域）事件时输出它。由于发票打印是Magento核心功能，所以我们需要重写它。</p>
<h1>第一步</h1>
<p>在你的Magento项目中创建下面的文件：</p>
<ul>
<li>app/code/local/Alwayly/Invoice/Model/Order/Pdf/Items/Invoice/Default.php</li>
<li>app/code/local/Alwayly/Invoice/Model/Order/Pdf/Invoice.php</li>
<li>app/code/local/Alwayly/Invoice/etc/config.xml</li>
</ul>
<p>这些是用来修改Magento核心功能的。</p>
<h1>第二步</h1>
<p>将下面代码加入到对应的文件中去： <strong>config.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Invoice&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Alwayly_Invoice&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;sales&gt;
                &lt;rewrite&gt;
                    &lt;order_pdf_invoice&gt;Alwayly_Invoice_Model_Order_Pdf_Invoice&lt;/order_pdf_invoice&gt;                &lt;order_pdf_items_invoice_default&gt;Alwayly_Invoice_Model_Order_Pdf_Items_Invoice_Default&lt;/order_pdf_items_invoice_default&gt;
                &lt;/rewrite&gt;
            &lt;/sales&gt;
        &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p><strong>Default.php</strong></p>
<pre><code>&lt;?php
/**
 * Alwayly PDF rewrite for custom attribute
 * Attribute "alwayly_warehouse_location" has to be set manually
 * Original: Sales Order Invoice Pdf default items renderer
 *
 * @category   Alwayly
 * @package    Inhoo_Invoice
 */
 
class Alwayly_Invoice_Model_Order_Pdf_Items_Invoice_Default extends Mage_Sales_Model_Order_Pdf_Items_Invoice_Default
{
    /**
     * Draw item line
	 **/
    public function draw()
    {
        $order  = $this-&gt;getOrder();
        $item   = $this-&gt;getItem();
        $pdf    = $this-&gt;getPdf();
        $page   = $this-&gt;getPage();
        $lines  = array();
 
		//Alwayly - Added custom attribute to PDF, first get it if exists
		$WarehouseLocation = $this-&gt;getWarehouseLocationValue($item);
 
        // draw Product name
        $lines[0] = array(array(
            'text' =&gt; Mage::helper('core/string')-&gt;str_split($item-&gt;getName(), 60, true, true),
            'feed' =&gt; 35,
        ));
 
		//Alwayly - Added custom attribute
		//draw Warehouse Location
        $lines[0][] = array(
            'text'  =&gt; Mage::helper('core/string')-&gt;str_split($WarehouseLocation, 25),
            'feed'  =&gt; 245
        );
 
        // draw SKU
        $lines[0][] = array(
            'text'  =&gt; Mage::helper('core/string')-&gt;str_split($this-&gt;getSku($item), 25),
            'feed'  =&gt; 325
        );
 
        // draw QTY
        $lines[0][] = array(
            'text'  =&gt; $item-&gt;getQty()*1,
            'feed'  =&gt; 435
        );
 
        // draw Price
        $lines[0][] = array(
            'text'  =&gt; $order-&gt;formatPriceTxt($item-&gt;getPrice()),
            'feed'  =&gt; 395,
            'font'  =&gt; 'bold',
            'align' =&gt; 'right'
        );
 
        // draw Tax
        $lines[0][] = array(
            'text'  =&gt; $order-&gt;formatPriceTxt($item-&gt;getTaxAmount()),
            'feed'  =&gt; 495,
            'font'  =&gt; 'bold',
            'align' =&gt; 'right'
        );
 
        // draw Subtotal
        $lines[0][] = array(
            'text'  =&gt; $order-&gt;formatPriceTxt($item-&gt;getRowTotal()),
            'feed'  =&gt; 565,
            'font'  =&gt; 'bold',
            'align' =&gt; 'right'
        );
 
        // custom options
        $options = $this-&gt;getItemOptions();
        if ($options) {
            foreach ($options as $option) {
                // draw options label
                $lines[][] = array(
                    'text' =&gt; Mage::helper('core/string')-&gt;str_split(strip_tags($option['label']), 70, true, true),
                    'font' =&gt; 'italic',
                    'feed' =&gt; 35
                );
 
                if ($option['value']) {
                    $_printValue = isset($option['print_value']) ? $option['print_value'] : strip_tags($option['value']);
                    $values = explode(', ', $_printValue);
                    foreach ($values as $value) {
                        $lines[][] = array(
                            'text' =&gt; Mage::helper('core/string')-&gt;str_split($value, 50, true, true),
                            'feed' =&gt; 40
                        );
                    }
                }
            }
        }
 
        $lineBlock = array(
            'lines'  =&gt; $lines,
            'height' =&gt; 10
        );
 
        $page = $pdf-&gt;drawLineBlocks($page, array($lineBlock), array('table_header' =&gt; true));
        $this-&gt;setPage($page);
 
    }
 
	/*
	 * Return Value of custom attribute
	 * */
	private function getWarehouseLocationValue($item)
	{
		$prod = Mage::getModel('catalog/product')-&gt;load($item-&gt;getProductId());
 
		if(!($return_location = $prod-&gt;getAlwaylyWarehouseLocation()))
			return 'N/A';
		else
			return $return_location;
	}
}
</code></pre>
<p><strong>Invoice.php</strong></p>
<pre><code>&lt;?php
/**
 * Alwayly PDF rewrite for custom attribute
 * * Attribute "alwayly_warehouse_location" has to be set manually
 * Original: Sales Order Invoice PDF model
 *
 * @category   Alwayly
 * @package    Alwayly_Invoice
 */
class Alwayly_Invoice_Model_Order_Pdf_Invoice extends Mage_Sales_Model_Order_Pdf_Invoice
{
	public function getPdf($invoices = array())
    {
        $this-&gt;_beforeGetPdf();
        $this-&gt;_initRenderer('invoice');
 
        $pdf = new Zend_Pdf();
        $this-&gt;_setPdf($pdf);
        $style = new Zend_Pdf_Style();
        $this-&gt;_setFontBold($style, 10);
 
        foreach ($invoices as $invoice) {
            if ($invoice-&gt;getStoreId()) {
                Mage::app()-&gt;getLocale()-&gt;emulate($invoice-&gt;getStoreId());
            }
            $page = $pdf-&gt;newPage(Zend_Pdf_Page::SIZE_A4);
            $pdf-&gt;pages[] = $page;
 
            $order = $invoice-&gt;getOrder();
 
            /* Add image */
            $this-&gt;insertLogo($page, $invoice-&gt;getStore());
 
            /* Add address */
            $this-&gt;insertAddress($page, $invoice-&gt;getStore());
 
            /* Add head */
            $this-&gt;insertOrder($page, $order, Mage::getStoreConfigFlag(self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID, $order-&gt;getStoreId()));
 
            $page-&gt;setFillColor(new Zend_Pdf_Color_GrayScale(1));
            $this-&gt;_setFontRegular($page);
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Invoice # ') . $invoice-&gt;getIncrementId(), 35, 780, 'UTF-8');
 
            /* Add table */
            $page-&gt;setFillColor(new Zend_Pdf_Color_RGB(0.93, 0.92, 0.92));
            $page-&gt;setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
            $page-&gt;setLineWidth(0.5);
 
            $page-&gt;drawRectangle(25, $this-&gt;y, 570, $this-&gt;y -15);
            $this-&gt;y -=10;
 
            /* Add table head */
            $page-&gt;setFillColor(new Zend_Pdf_Color_RGB(0.4, 0.4, 0.4));
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Products'), 35, $this-&gt;y, 'UTF-8');
			//Added for custom attribute "alwayly_warehouse_location"
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Warehouse Location'), 245, $this-&gt;y, 'UTF-8');
			$page-&gt;drawText(Mage::helper('sales')-&gt;__('SKU'), 325, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Price'), 380, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Qty'), 430, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Tax'), 480, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Subtotal'), 535, $this-&gt;y, 'UTF-8');
 
            $this-&gt;y -=15;
 
            $page-&gt;setFillColor(new Zend_Pdf_Color_GrayScale(0));
 
            /* Add body */
            foreach ($invoice-&gt;getAllItems() as $item){
                if ($item-&gt;getOrderItem()-&gt;getParentItem()) {
                    continue;
                }
 
                if ($this-&gt;y &lt; 15) {
                    $page = $this-&gt;newPage(array('table_header' =&gt; true));
                }
 
                /* Draw item */
                $page = $this-&gt;_drawItem($item, $page, $order);
            }
 
            /* Add totals */
            $page = $this-&gt;insertTotals($page, $invoice);
 
            if ($invoice-&gt;getStoreId()) {
                Mage::app()-&gt;getLocale()-&gt;revert();
            }
        }
        $this-&gt;_afterGetPdf();
 
        return $pdf;
    }
 
	public function newPage(array $settings = array())
    {
        /* Add new table head */
        $page = $this-&gt;_getPdf()-&gt;newPage(Zend_Pdf_Page::SIZE_A4);
        $this-&gt;_getPdf()-&gt;pages[] = $page;
        $this-&gt;y = 800;
 
        if (!empty($settings['table_header'])) {
            $this-&gt;_setFontRegular($page);
            $page-&gt;setFillColor(new Zend_Pdf_Color_RGB(0.93, 0.92, 0.92));
            $page-&gt;setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
            $page-&gt;setLineWidth(0.5);
            $page-&gt;drawRectangle(25, $this-&gt;y, 570, $this-&gt;y-15);
            $this-&gt;y -=10;
 
            $page-&gt;setFillColor(new Zend_Pdf_Color_RGB(0.4, 0.4, 0.4));
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Product'), 35, $this-&gt;y, 'UTF-8');
			//Added for custom attribute "alwayly_warehouse_location"
			$page-&gt;drawText(Mage::helper('sales')-&gt;__('Warehouse Location'), 245, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('SKU'), 325, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Price'), 380, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Qty'), 430, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Tax'), 480, $this-&gt;y, 'UTF-8');
            $page-&gt;drawText(Mage::helper('sales')-&gt;__('Subtotal'), 535, $this-&gt;y, 'UTF-8');
 
            $page-&gt;setFillColor(new Zend_Pdf_Color_GrayScale(0));
            $this-&gt;y -=20;
        }
        return $page;
    }
}
</code></pre>
<h1>第三步</h1>
<p>进入后台 <strong>&ldquo;Sales-&gt;Invoices-&gt;(View any of them)-&gt;Print&rdquo;</strong>。下载PDF后可在每个订单物品中看到<strong>&ldquo;Warehouse Location&rdquo;<strong> 。</strong></strong></p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 22 Oct 2015 11:17:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为你的Magento插件创建配置]]></title>
      <link>https://www.360magento.com/blog/magento-extension-configuration/</link>
      <description><![CDATA[<p>今天，我想讲讲初学者如何在Magento配置区域创建一个简单的插件配置。首先，你需要一个插件。如果你是初学者，不知道如果创建你自己的插件，你可以看看网站里的其它文章。但我建议从一个新的插件开始，用于测试&hellip;&hellip;</p>
<p>第一步，添加（或者修改）你的<strong>system.xml</strong>文件：</p>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;config&gt;
    &lt;tabs&gt;
        &lt;alwayly translate="label" module="mymodule"&gt;
            &lt;label&gt;Alwayly Extensions&lt;/label&gt;
            &lt;sort_order&gt;100&lt;/sort_order&gt;
        &lt;/alwayly&gt;
    &lt;/tabs&gt;
    &lt;sections&gt;
        &lt;alwayly translate="label" module="mymodule"&gt;
            &lt;label&gt;Extension Options&lt;/label&gt;
            &lt;tab&gt;alwayly&lt;/tab&gt;
            &lt;sort_order&gt;1000&lt;/sort_order&gt;
            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
 
            &lt;groups&gt;
                &lt;alwayly_group translate="label" module="mymodule"&gt;
                    &lt;label&gt;My Extension Options&lt;/label&gt;
                    &lt;frontend_type&gt;text&lt;/frontend_type&gt;
                    &lt;sort_order&gt;1000&lt;/sort_order&gt;
                    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
                    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
 
                    &lt;fields&gt;
                        &lt;alwayly_input translate="label"&gt;
                            &lt;label&gt;My Input Field: &lt;/label&gt;
                            &lt;comment&gt;My Comment&lt;/comment&gt;
                            &lt;frontend_type&gt;text&lt;/frontend_type&gt;
                            &lt;sort_order&gt;20&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                        &lt;/alwayly_input&gt;
                        &lt;alwayly_select translate="label"&gt;
                            &lt;label&gt;My Dropdown: &lt;/label&gt;
                            &lt;comment&gt;Source model provider Magento's default Yes/No values&lt;/comment&gt;
                            &lt;frontend_type&gt;select&lt;/frontend_type&gt;
                            &lt;sort_order&gt;90&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_yesno&lt;/source_model&gt;
                        &lt;/alwayly_select&gt;
                    &lt;/fields&gt;
                &lt;/alwayly_group&gt;
            &lt;/groups&gt;
        &lt;/alwayly&gt;
    &lt;/sections&gt;
&lt;/config&gt;
</code></pre>
<p>第二步，为了使用Magento配置区域，你需要编辑你的<strong>config.xml</strong>文件并定义模型和助手：</p>
<pre><code>&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Mymodule&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Alwayly_Mymodule&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;mymodule&gt;
                &lt;class&gt;Alwayly_Mymodule_Model&lt;/class&gt;
            &lt;/mymodule&gt;
        &lt;/models&gt;
        &lt;helpers&gt;
            &lt;mymodule&gt;
                &lt;class&gt;Alwayly_Mymodule_Helper&lt;/class&gt;
            &lt;/mymodule&gt;
        &lt;/helpers&gt;
     &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>最后你需要再次编辑插件的config.xml文件，加入 &ldquo;&rdquo;标签：</p>
<pre><code>&lt;adminhtml&gt;
    &lt;acl&gt;
        &lt;resources&gt;
            &lt;all&gt;
                &lt;title&gt;Allow Everything&lt;/title&gt;
            &lt;/all&gt;
            &lt;admin&gt;
                &lt;children&gt;
                    &lt;system&gt;
                        &lt;children&gt;
                            &lt;config&gt;
                                &lt;children&gt;
                                    &lt;alwayly&gt;
                                        &lt;title&gt;Alwayly - All&lt;/title&gt;
                                    &lt;/alwayly&gt;
                                &lt;/children&gt;
                            &lt;/config&gt;
                        &lt;/children&gt;
                    &lt;/system&gt;
                &lt;/children&gt;
            &lt;/admin&gt;
        &lt;/resources&gt;
    &lt;/acl&gt;
&lt;/adminhtml&gt;
</code></pre>
<p>要检索你保存的配置，你应该使用像这样的代码：</p>
<pre><code>Mage::getStoreConfig('alwayly/alwayly_group/alwayly_input',Mage::app()-&gt;getStore());
</code></pre>
<p>或者这样：</p>
<pre><code>Mage::getStoreConfig('alwayly/alwayly_group/alwayly_select',Mage::app()-&gt;getStore());
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 21 Oct 2015 12:15:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中为自定义控制器布局]]></title>
      <link>https://www.360magento.com/blog/layout-magento-controller/</link>
      <description><![CDATA[<p>当你用到Magento中的自定义控制器（不论前台还是后台）时，你可能会使用现有的块和模型，或者需要重写类。但当你想要移动、删除常见块的时候会发生什么呢？你真的能设计你的网页视图而不需要触及层叠样式表（CSS）？</p>
<p>事实上，是的你可以以一种相当简单的方式做到。前提是你知道你控制器的句柄。</p>
<p>要获取你控制器的句柄，你需要一些调试技术。在你控制器的动作里加入下面代码：</p>
<pre><code> Zend_Debug::dump($this-&gt;getLayout()-&gt;getUpdate()-&gt;getHandles());
</code></pre>
<p>它以同样的方式作用于前端和后台。你自定义的动作看起来像这样：</p>
<pre><code>public function indexAction()
{
        $this-&gt;loadLayout();
        $this-&gt;renderLayout();
        Zend_Debug::dump($this-&gt;getLayout()-&gt;getUpdate()-&gt;getHandles());
}
</code></pre>
<p>在你的浏览器输出，你可能会得到这样的结果：</p>
<p>前端控制器：</p>
<pre><code>array(5) {
  [0] =&gt; string(7) "default"
  [1] =&gt; string(13) "STORE_default"
  [2] =&gt; string(29) "THEME_frontend_default_hybrid"
  [3] =&gt; string(29) "alwayly_developers_index_index"
  [4] =&gt; string(19) "customer_logged_out"
}
</code></pre>
<p>后台控制器：</p>
<pre><code>array(4) {
  [0] =&gt; string(7) "default"
  [1] =&gt; string(11) "STORE_admin"
  [2] =&gt; string(30) "THEME_adminhtml_default_inchoo"
  [3] =&gt; string(28) "adminhtml_switch_index_index"
}
</code></pre>
<p>你需要数组中第四项的值。</p>
<p>前端：</p>
<pre><code> [3] =&gt; string(29) "alwayly_developers_index_index"
</code></pre>
<p>后台：</p>
<pre><code> [3] =&gt; string(28) "adminhtml_switch_index_index"
</code></pre>
<p>现在，你了解了句柄之后，我们开始你的布局文件。在你主题的布局文件夹里创建&ldquo;local.xml&rdquo;布局文件。在我简单的例子里，我移除头部和底部，前端和后台。</p>
<p>前端示例：<strong>app/design/frontend/default/default/layout/local.xml</strong></p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;!--
/**
 * Magento
 *
 * @category    Alwayly
 * @package     Alwayly_Developers
 */
--&gt;
&lt;layout&gt;
 
    &lt;alwayly_developers_index_index&gt;
	&lt;remove name="header" /&gt;
    	&lt;remove name="footer" /&gt;
    &lt;/alwayly_developers_index_index&gt;
 
&lt;/layout&gt;
</code></pre>
<p>后台示例:<strong>app/design/adminhtml/default/default/layout/local.xml</strong></p>
<pre><code>&lt; ?xml version="1.0"?&gt;
&lt;!--
/**
 * Magento
 *
 * @category    Alwayly
 * @package     Alwayly_Developers
 */
--&gt;
&lt;layout&gt;
 
    &lt;adminhtml_switch_index_index&gt;
	&lt;remove name="header" /&gt;
    	&lt;remove name="footer" /&gt;
    &lt;/adminhtml_switch_index_index&gt;
 
&lt;/layout&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 21 Oct 2015 12:05:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何扩展Magento订单网格]]></title>
      <link>https://www.360magento.com/blog/extend-order-grid/</link>
      <description><![CDATA[<p>这里是一个小示例来解释如何修改订单网格。订单网格的主类是<strong>&ldquo;Mage_Adminhtml_Block_Sales_Order_Grid&rdquo;</strong>，如果你想添加一些列，你必须重写这个类（块）。</p>
<p>如何重写magento块</p>
<pre><code>&lt;blocks&gt;
    &lt;adminhtml&gt;
        &lt;rewrite&gt;
            &lt;sales_order_grid&gt;Alwayly_Test_Block_Adminhtml_Order_Grid&lt;/sales_order_grid&gt;
        &lt;/rewrite&gt;
    &lt;/adminhtml&gt;
&lt;/blocks&gt;
</code></pre>
<p>如果你调用<strong>&ldquo;adminhtml/sales_order_grid&rdquo;</strong>，你将获取<strong>Alwayly_Test_Block_Adminhtml_Order_Grid</strong>，那么创建<strong>Alwayly_Test_Block_Adminhtml_Order_Grid</strong>吧。下面是我的代码：</p>
<pre><code>&lt; ?php
class Alwayly_Test_Block_Adminhtml_Order_Grid extends Mage_Adminhtml_Block_Widget_Grid
{
     public function __construct()
    {
        parent::__construct();
        $this-&gt;setId('sales_order_grid');
        $this-&gt;setUseAjax(true);
        $this-&gt;setDefaultSort('created_at');
        $this-&gt;setDefaultDir('DESC');
        $this-&gt;setSaveParametersInSession(true);
    }
 
    /**
     * Retrieve collection class
     *
     * @return string
     */
    protected function _getCollectionClass()
    {
        return 'sales/order_grid_collection';
    }
 
    protected function _prepareCollection()
    {
        $collection = Mage::getResourceModel($this-&gt;_getCollectionClass());
 
        //we changed mysql query, we added inner join to order item table
        $collection-&gt;join('sales/order_item', 'order_id=entity_id', array('name'=&gt;'name', 'sku' =&gt;'sku', 'qty_ordered'=&gt;'qty_ordered' ), null,'left');
        $this-&gt;setCollection($collection);
        return parent::_prepareCollection();
    }
 
    protected function _prepareColumns()
    {
 
        $this-&gt;addColumn('real_order_id', array(
            'header'=&gt; Mage::helper('sales')-&gt;__('Order #'),
            'width' =&gt; '80px',
            'type'  =&gt; 'text',
            'index' =&gt; 'increment_id',
        ));
 
        if (!Mage::app()-&gt;isSingleStoreMode()) {
            $this-&gt;addColumn('store_id', array(
                'header'    =&gt; Mage::helper('sales')-&gt;__('Purchased from (store)'),
                'index'     =&gt; 'store_id',
                'type'      =&gt; 'store',
                'store_view'=&gt; true,
                'display_deleted' =&gt; true,
                'filter_index' =&gt; 'main_table.store_id'
            ));
        }
 
        $this-&gt;addColumn('created_at', array(
            'header' =&gt; Mage::helper('sales')-&gt;__('Purchased On'),
            'index' =&gt; 'created_at',
            'type' =&gt; 'datetime',
            'width' =&gt; '100px',
            'filter_index' =&gt; 'main_table.created_at'
        ));
 
        $this-&gt;addColumn('billing_name', array(
            'header' =&gt; Mage::helper('sales')-&gt;__('Bill to Name'),
            'index' =&gt; 'billing_name',
        ));
 
        $this-&gt;addColumn('qty_ordered', array(
            'header'    =&gt; Mage::helper('sales')-&gt;__('Items Ordered'),
            'index'     =&gt; 'qty_ordered',
            'type'      =&gt; 'number',
            'total'     =&gt; 'sum'
        ));
 
        $this-&gt;addColumn('sku', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('SKU'),
            'index'     =&gt; 'sku',
			'type' =&gt; 'text'
        ));
 
        $this-&gt;addColumn('base_grand_total', array(
            'header' =&gt; Mage::helper('sales')-&gt;__('G.T. (Base)'),
            'index' =&gt; 'base_grand_total',
            'type'  =&gt; 'currency',
            'currency' =&gt; 'base_currency_code',
        ));
 
        $this-&gt;addColumn('grand_total', array(
            'header' =&gt; Mage::helper('sales')-&gt;__('G.T. (Purchased)'),
            'index' =&gt; 'grand_total',
            'type'  =&gt; 'currency',
            'currency' =&gt; 'order_currency_code',
        ));
 
        $this-&gt;addColumn('status', array(
            'header' =&gt; Mage::helper('sales')-&gt;__('Status'),
            'index' =&gt; 'status',
            'type'  =&gt; 'options',
            'width' =&gt; '70px',
            'options' =&gt; Mage::getSingleton('sales/order_config')-&gt;getStatuses(),
        ));
 
 
        return $this;
    }
 
    protected function _prepareMassaction()
    {
        $this-&gt;setMassactionIdField('entity_id');
        $this-&gt;getMassactionBlock()-&gt;setFormFieldName('order_ids');
        $this-&gt;getMassactionBlock()-&gt;setUseSelectAll(false);
 
        if (Mage::getSingleton('admin/session')-&gt;isAllowed('sales/order/actions/cancel')) {
            $this-&gt;getMassactionBlock()-&gt;addItem('cancel_order', array(
                 'label'=&gt; Mage::helper('sales')-&gt;__('Cancel'),
                 'url'  =&gt; $this-&gt;getUrl('*/sales_order/massCancel'),
            ));
        }
 
        if (Mage::getSingleton('admin/session')-&gt;isAllowed('sales/order/actions/hold')) {
            $this-&gt;getMassactionBlock()-&gt;addItem('hold_order', array(
                 'label'=&gt; Mage::helper('sales')-&gt;__('Hold'),
                 'url'  =&gt; $this-&gt;getUrl('*/sales_order/massHold'),
            ));
        }
 
        if (Mage::getSingleton('admin/session')-&gt;isAllowed('sales/order/actions/unhold')) {
            $this-&gt;getMassactionBlock()-&gt;addItem('unhold_order', array(
                 'label'=&gt; Mage::helper('sales')-&gt;__('Unhold'),
                 'url'  =&gt; $this-&gt;getUrl('*/sales_order/massUnhold'),
            ));
        }
 
        $this-&gt;getMassactionBlock()-&gt;addItem('pdfinvoices_order', array(
             'label'=&gt; Mage::helper('sales')-&gt;__('Print Invoices'),
             'url'  =&gt; $this-&gt;getUrl('*/sales_order/pdfinvoices'),
        ));
 
        $this-&gt;getMassactionBlock()-&gt;addItem('pdfshipments_order', array(
             'label'=&gt; Mage::helper('sales')-&gt;__('Print Packingslips'),
             'url'  =&gt; $this-&gt;getUrl('*/sales_order/pdfshipments'),
        ));
 
        $this-&gt;getMassactionBlock()-&gt;addItem('pdfcreditmemos_order', array(
             'label'=&gt; Mage::helper('sales')-&gt;__('Print Credit Memos'),
             'url'  =&gt; $this-&gt;getUrl('*/sales_order/pdfcreditmemos'),
        ));
 
        $this-&gt;getMassactionBlock()-&gt;addItem('pdfdocs_order', array(
             'label'=&gt; Mage::helper('sales')-&gt;__('Print All'),
             'url'  =&gt; $this-&gt;getUrl('*/sales_order/pdfdocs'),
        ));
 
        return $this;
    }
 
    public function getRowUrl($row)
    {
        if (Mage::getSingleton('admin/session')-&gt;isAllowed('sales/order/actions/view')) {
            return $this-&gt;getUrl('*/sales_order/view', array('order_id' =&gt; $row-&gt;getId()));
        }
        return false;
    }
    public function getGridUrl()
    {
        return $this-&gt;getUrl('*/*/grid', array('_current'=&gt;true));
    }
}
</code></pre>
<p>如果你想添加一些列，你需要添加下面的代码到<strong> _prepareColumns</strong>方法：</p>
<pre><code>$this-&gt;addColumn('sku', array(
'header'    =&gt; Mage::helper('catalog')-&gt;__('SKU'),
'index'     =&gt; 'sku',
'type' =&gt; 'text'
));
</code></pre>
<p>如你所见，我们修改了<strong>_prepareCollection()</strong>方法。我们改变了SQL语句，连接了第二张数据表。这只是我的例子，你可以根据你的需求来修改SQL语句。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 20 Oct 2015 13:03:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[插入动态菜单到Magento后台]]></title>
      <link>https://www.360magento.com/blog/dynamical-menu/</link>
      <description><![CDATA[<p>最近Magento的一个核心功能（后台管理员菜单需要XML定义）让我觉得沮丧。我想要加一些快速的网站/店铺链接到后台。解决方法是重写Magento的一个后台块，然后连接我的动态菜单（没有XML）。如果你对此感兴趣，那么读下去。</p>
<p>为了让它可升级，我决定做成插件。它值包含2个文件，<strong>config.xml</strong>和一个重写块。</p>
<p>首先，创建<strong>config.xml</strong>，我的是这样的：</p>
<pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_ExtendedMenu&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Alwayly_ExtendedMenu&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;configurable&gt;
                &lt;class&gt;Alwayly_Configurable_Block&lt;/class&gt;
            &lt;/configurable&gt;
            &lt;adminhtml&gt;
                &lt;rewrite&gt;
                    &lt;page_menu&gt;Alwayly_ExtendedMenu_Block_Adminhtml_Menu&lt;/page_menu&gt;
                &lt;/rewrite&gt;
            &lt;/adminhtml&gt;
        &lt;/blocks&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>由于Magento一如既往地解析XML，对我来说理想的解决方法就是在输出菜单前与解析数据挂钩。所以，我之前提到的块是<strong>&ldquo;Mage_Adminhtml_Block_Page_Menu&rdquo;</strong>。我对<strong>getMenuArray</strong>方法比较感兴趣，它是这样的：</p>
<pre><code> /**
     * Retrieve Adminhtml Menu array
     *
     * @return array
     */
    public function getMenuArray()
    {
        return $this-&gt;_buildMenuArray();
    }

</code></pre>
<p>这是最合适的地方来修改Magento核心，我用下面的代码创建了<strong>&ldquo;Alwayly_ExtendedMenu_Block_Adminhtml_Menu&rdquo;：</strong></p>
<pre><code>&lt;?php
class Alwayly_ExtendedMenu_Block_Adminhtml_Menu extends Mage_Adminhtml_Block_Page_Menu
{
	public function getMenuArray()
	{
		//Load standard menu
		$parentArr = parent::getMenuArray();
 
		//Prepare "View Sites" menu
		$parentArr['view_sites'] = array(
			'label' =&gt; 'View Sites',
			'active'=&gt;false ,
			'sort_order'=&gt;0,
			'click' =&gt; 'return false;',
			'url'=&gt;'#',
			'level'=&gt;0,
			'last'=&gt; true,
			'children' =&gt; array()
		);
 
		$app = Mage::app();
 
		$j = 0;
 
		$allWebsites = $app-&gt;getWebsites();
		$totalWebsiteCount = count($allWebsites) - 1;
 
		foreach ($allWebsites as $_eachWebsiteId =&gt; $websiteVal){
			$_storeName = $app-&gt;getWebsite($_eachWebsiteId)-&gt;getName();
			$_websiteUrl = array(
					'label' =&gt; $_storeName,
					'active' =&gt; false ,
					'url' =&gt; '#',
					'click' =&gt; "return false",
					'sort_order' =&gt; $j++ * 10,
					'level' =&gt; 1,
					'children' =&gt; array()
					);
 
			if(count($parentArr['view_sites']['children']) == $totalWebsiteCount){
				$_websiteUrl['last'] = true;
			} else {
				$_websiteUrl['last'] = false;
			}
 
			$parentArr['view_sites']['children'][$j - 1] = $_websiteUrl;
 
			$allStores = $app-&gt;getWebsite($app-&gt;getWebsite($_eachWebsiteId)-&gt;getId())-&gt;getStores();
			$totalCount = count($allStores);
			$i = 0;
			foreach ($allStores as $_eachStoreId =&gt; $val){
				$_websiteId = $app-&gt;getStore($_eachStoreId)-&gt;getWebsiteId();
				if($_websiteId == $j){
					$_storeName = $app-&gt;getStore($_eachStoreId)-&gt;getName();
					$baseUrl = $app-&gt;getStore($_eachStoreId)-&gt;getUrl();
					$_websiteUrl = array(
							'label' =&gt; $_storeName,
							'active' =&gt; false ,
							'click' =&gt; "window.open(this.href, 'Website - ' + this.href); return false;",
							'sort_order' =&gt; $i++ * 10,
							'level' =&gt; 2,
							'url' =&gt; $baseUrl
							);
 
					if(count($parentArr['view_sites']['children'][$j - 1]['children']) + 1 == $totalCount or $totalCount == 0)
						$_websiteUrl['last'] = true;
						else
						$_websiteUrl['last'] = false;
 
					$parentArr['view_sites']['children'][$j - 1]['children'][$i] = $_websiteUrl;
				}
			}
		}
		return $parentArr;
    }
}
</code></pre>
<p>我这里重写了父类方法<strong>&ldquo;getMenuArray()&rdquo;</strong>，我的动态菜单也在结果数组中。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 20 Oct 2015 12:52:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为Magento数量框添加“+”,“-”功能]]></title>
      <link>https://www.360magento.com/blog/magentos-quantity-increment/</link>
      <description><![CDATA[<p>你也许注意到了Magento的数量输入只是普通的输入框，当你想要修改它的值时必须先手动删除现有值，然后输入新的值。今天我将展示添加加号和减号来修改数量。感兴趣的话就继续往下阅读吧。</p>
<p>这是一项非常简单的工作，但又与Magento中的其它东西不一样，它需要些时间（我花了2小时测试）。我所做的就是创建一个连接JavaScript的插件。我动态地创建了div元素并用包含&ldquo;+&rdquo;和&ldquo;-&rdquo;号的段落标签来填充。</p>
<p>负责执行的代码是这样的：</p>
<pre><code>var parentTD;
	var newDiv;
	var navigationDiv;
	var i = 1;
	var currentElement = null;
 
	$$('input.qty').each(function(el){
		parentTD = el.parentNode;
 
		newDiv = document.createElement('div');
		Element.extend(newDiv);
		newDiv.id = i++;
		newDiv.update(parentTD.innerHTML).innerHTML; //set new input inside new div
		parentTD.update().innerHTML; //erase old input
		parentTD.appendChild(newDiv); //show new div
 
		navigationDiv = document.createElement('div');
		Element.extend(navigationDiv);
		navigationDiv.update('&lt;p class="up">+&lt;/p>&lt;p class="dn">-&lt;/p>').innerHTML;
		newDiv.appendChild(navigationDiv);
	});
 
	$$('p.up').each(function(el){
		el.observe('click',function(event){
			currentElement = el.parentNode.previous();
			i = 0; //In case we get in to infinite loop
			while(currentElement.type != 'text' && i &lt; 5){
				currentElement = currentElement.previous();
				i++;
			}
			currentElement.value = parseInt(currentElement.value) + 1;
		});
	});
 
	$$('p.dn').each(function(el){
		el.observe('click',function(event){
			currentElement = el.parentNode.previous();
			i = 0; //In case we get in to infinite loop
			while(currentElement.type != 'text' && i &lt; 5){
				currentElement = currentElement.previous();
				i++;
			}
			if(parseInt(currentElement.value) > 0){
				currentElement.value = parseInt(currentElement.value) - 1;
			}
		});
	});
</code></pre>
<p>为安全起见，请先做好备份。执行之后是没有样式的，但是你可以随时添加一些CSS样式。生成的HTML结构大概是这样的：</p>
<pre><code>&lt;div id="1"&gt;
	&lt;label for="qty"&gt;
		Qty:
	&lt;/label&gt;
	&lt;input name="qty" id="qty" maxlength="12" value="1" title="Qty" class="input-text qty" type="text"&gt;
	&lt;button type="button" title="Add to Cart" class="button btn-cart" onclick="productAddToCartForm.submit(this)"&gt;
		&lt;span&gt;
			&lt;span&gt;
				Add to Cart
			&lt;/span&gt;
		&lt;/span&gt;
	&lt;/button&gt;
	&lt;div&gt;
		&lt;p class="up"&gt;
			+
		&lt;/p&gt;
		&lt;p class="dn"&gt;
			-
		&lt;/p&gt;
	&lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 19 Oct 2015 12:46:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中如何添加新的自定义类别属性]]></title>
      <link>https://www.360magento.com/blog/custom-category-attribute/</link>
      <description><![CDATA[<p>有时候你需要扩展Magento的类别功能。有几种方法你可以达到目的，你可以直接修改和添加数据到表里，但如果你不知道怎么做的话就会浪费时间。这篇文章将演示如何通过sql_setup脚本来给你的Magento店铺添加新的自定义类别属性。</p>
<p>示例Mysql setup脚本是这样的，你需要根据你的需求来修改新属性的配置。</p>
<pre><code>$installer = $this;
$installer-&gt;startSetup();
 
$entityTypeId     = $installer-&gt;getEntityTypeId('catalog_category');
$attributeSetId   = $installer-&gt;getDefaultAttributeSetId($entityTypeId);
$attributeGroupId = $installer-&gt;getDefaultAttributeGroupId($entityTypeId, $attributeSetId);
 
$installer-&gt;addAttribute('catalog_category', 'new_cat_attrb',  array(
    'type'     =&gt; 'int',
    'label'    =&gt; 'New Category Attribute',
    'input'    =&gt; 'text',
    'global'   =&gt; Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
    'visible'           =&gt; true,
    'required'          =&gt; false,
    'user_defined'      =&gt; false,
    'default'           =&gt; 0
));
 
 
$installer-&gt;addAttributeToGroup(
    $entityTypeId,
    $attributeSetId,
    $attributeGroupId,
    'new_cat_attrb',
    '11'					//last Magento's attribute position in General tab is 10
);
 
$attributeId = $installer-&gt;getAttributeId($entityTypeId, 'new_cat_attrb');
 
$installer-&gt;run("
INSERT INTO `{$installer-&gt;getTable('catalog_category_entity_int')}`
(`entity_type_id`, `attribute_id`, `entity_id`, `value`)
    SELECT '{$entityTypeId}', '{$attributeId}', `entity_id`, '1'
        FROM `{$installer-&gt;getTable('catalog_category_entity')}`;
");
 
 
//this will set data of your custom attribute for root category
Mage::getModel('catalog/category')
    -&gt;load(1)
    -&gt;setImportedCatId(0)
    -&gt;setInitialSetupFlag(true)
    -&gt;save();
 
//this will set data of your custom attribute for default category
Mage::getModel('catalog/category')
    -&gt;load(2)
    -&gt;setImportedCatId(0)
    -&gt;setInitialSetupFlag(true)
    -&gt;save();
 
$installer-&gt;endSetup();
</code></pre>
<p>在你模块的<strong>config.xml</strong>中你需要添加下面的代码来使新的类别属性正确安装：</p>
<pre><code>&lt;resources&gt;
	&lt;new_attribute_csv_setup&gt;
	  &lt;setup&gt;
		&lt;module&gt;New_Attribute&lt;/module&gt;
		&lt;class&gt;Mage_Catalog_Model_Resource_Eav_Mysql4_Setup&lt;/class&gt;
	  &lt;/setup&gt;
	  &lt;connection&gt;
		&lt;use&gt;core_setup&lt;/use&gt;
	  &lt;/connection&gt;
	&lt;/new_attribute_setup&gt;
	&lt;new_attribute_setup_write&gt;
	  &lt;connection&gt;
		&lt;use&gt;core_write&lt;/use&gt;
	  &lt;/connection&gt;
	&lt;/new_attribute_setup_write&gt;
	&lt;new_attribute_setup_read&gt;
	  &lt;connection&gt;
		&lt;use&gt;core_read&lt;/use&gt;
	  &lt;/connection&gt;
	&lt;/new_attribute_setup_read&gt;
&lt;/resources&gt;
</code></pre>
<p>注意，这里的类标签必须是<strong> &ldquo;Mage_Catalog_Model_Resource_Eav_Mysql4_Setup&rdquo;</strong>。</p>
<p>正确安装后，进入后台类别中，你可以看到在General Information中出现了"New Category Attribute"。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 19 Oct 2015 12:43:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[分层导航]]></title>
      <link>https://www.360magento.com/blog/magento-layered-navigation/</link>
      <description><![CDATA[<p>最近，有个客户想要让所有&ldquo;筛选器&rdquo;一直显示。例如，当你想要通过颜色筛选器筛选产品时，发现所有的筛选器都在，那么你就可以轻松地按其它条件筛选而不必返回类别页。</p>
<p>分层导航的文件默认在<strong>app/design/frontend/base/default/template/catalog/layer/</strong>下。分层导航的模版文件是<strong>view.phtml</strong>，用来显示筛选器。筛选器状态模版是<strong>state.phtml</strong>，当我们点击一个筛选器时，他响应结果。我们就要编辑<strong>state.phtml</strong>。将这个文件拷贝到你的包或主题中。</p>
<p>这是默认的state.phtml文件：</p>
<pre><code>&lt;?php $_filters = $this-&gt;getActiveFilters() ?&gt;
&lt;?php if(!empty($_filters)): ?&gt;
&lt;div class="currently"&gt;
    &lt;p class="block-subtitle"&gt;&lt;?php echo $this-&gt;__('Currently Shopping by:') ?&gt;&lt;/p&gt;
    &lt;ol&gt;
    &lt;?php foreach ($_filters as $_filter): ?&gt;
        &lt;li&gt;
            &lt;a href="&lt;?php echo $_filter-&gt;getRemoveUrl() ?&gt;" title="&lt;?php echo $this-&gt;__('Remove This Item') ?&gt;" class="btn-remove"&gt;&lt;?php echo $this-&gt;__('Remove This Item') ?&gt;&lt;/a&gt;
            &lt;span class="label"&gt;&lt;?php echo $this-&gt;__($_filter-&gt;getName()) ?&gt;:&lt;/span&gt; &lt;?php echo $this-&gt;stripTags($_filter-&gt;getLabel()) ?&gt;
        &lt;/li&gt;
    &lt;?php endforeach; ?&gt;
    &lt;/ol&gt;
    &lt;div class="actions"&gt;&lt;a href="&lt;?php echo $this-&gt;getClearUrl() ?&gt;"&gt;&lt;?php echo $this-&gt;__('Clear All') ?&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>我们将要在&ldquo;currently&rdquo;div块前面添加当前类别的url通道。代码如下：</p>
<pre><code>&lt;?php $obj = new Mage_Catalog_Block_Navigation(); ?&gt;
&lt;?php $_current_category=$obj-&gt;getCurrentCategory()-&gt;getUrlPath(); ?&gt; //getting url path of current category
&lt;?php $subs = $obj-&gt;getCurrentCategory()-&gt;getAllChildren(true); ?&gt; //getting ids of subcategories of current category
</code></pre>
<p>现在，我们编辑 &ldquo;currently&rdquo;div块。我将它重新命名为state。因为它不再显示当前筛选器。</p>
<pre><code>&lt;?php if(!empty($_filters)): ?>
&lt;div class="state">
    &lt;p class="block-subtitle">&lt;?php echo $this->__('Currently Shopping by:') ?>&lt;/p>
    &lt;dl>
    &lt;?php foreach ($_filters as $_filter): ?>
            &lt;dd>
                &lt;ol>
                    &lt;?php $attributemodel=$_filter->filter->_data["attribute_model"]; ?>    // getting attribute model that has all filter options in it from currently active filter
                    &lt;?php $attroptions=$attributemodel->getSource()->getAllOptions();?>   // getting attribute options (filters) from attribute model
                    &lt;?php $_categ= Mage::getModel('catalog/category');?>   // object  containing all categories and their information
 
                &lt;?php foreach($subs as $cat_id): ?>
                        &lt;?php $_categ->load($cat_id)?>           //get the subcategory you need
                        &lt;?php $collection = $_categ->getProductCollection(); ?>  //get the product collection (object containing all product information)
                        &lt;?php $collection->addAttributeToSelect('color')?>   // get the desired attribute
                &lt;?php endforeach; ?>
</code></pre>
<p>接下来，我们需要提取属性模型的信息和组合链接。每一个属性选项 ($attroptions)都包含属性值和属性标签。</p>
<pre><code>&lt;?php foreach($attroptions as $attr): ?&gt;   // get value and label of each attribute
                        &lt;?php $count=0; ?&gt;
                        &lt;?php if($attr["value"]!=""): ?&gt;
                               &lt;?php $val=$attr["value"] ?&gt;
                                &lt;?php $collection-&gt;addFieldToFilter(array(array('attribute'=&gt;'themes','gt'=&gt;10)))?&gt;  // collection of attribute values and labels for all values

//greater then 10 (in this case attribute values range was 18-39)
                                &lt;?php $proddata=$collection-&gt;getData() ?&gt;  // get product data for all attribute values
                                &lt;?php if($attr["label"]!= $this-&gt;stripTags($_filter-&gt;getLabel())): ?&gt;  // make a nice looking label
                                    &lt;?php foreach($proddata as $prod):?&gt;
                                        &lt;?php if($prod["type_id"]=="configurable"): ?&gt;    // in this store all products were configurable
                                            &lt;?php $split=split(",", $prod["color"]);?&gt;     // get the attribute values that correspond with one product (a product may have more

// then one attribute value and they're separated by commas that's why we split the string with "," as deliminator)
</code></pre>
<p>即使你设置属性Filterable(with results) ，你仍然需要统计产品，这样只显示有产品的属性值。</p>
<pre><code> &lt;?php foreach($split as $color): ?&gt;  //check out how many products have the same attribute value
                                                &lt;?php if($color==$attr["value"]): ?&gt;
                                                    &lt;?php $count++;?&gt;
                                                &lt;?php endif; ?&gt;
                                            &lt;?php endforeach; ?&gt;
 
                                        &lt;?php endif;?&gt;
 
                                    &lt;?php endforeach; ?&gt;
 
                                    &lt;?php if($count&gt;0):?&gt;  // check if any product has that attribute value
                                        &lt;li&gt;&lt;a href="&lt;?php echo $this-&gt;getUrl('').$_current_category ?&gt;?color=&lt;?php echo $attr["value"]?&gt;" &gt;&lt;?php echo  $attr["label"]; ?&gt;&lt;/a&gt;&lt;/li&gt;  // if not currently active filter make a link
                                    &lt;?php endif; ?&gt;
 
                                &lt;?php else:?&gt;
                                    &lt;li class="current"&gt; &lt;?php echo $this-&gt;stripTags($_filter-&gt;getLabel()); ?&gt;&lt;/li&gt;  // if currently active filter write out the label
                                &lt;?php endif;?&gt;
                        &lt;?php endif; ?&gt;
&lt;?php endforeach;  ?&gt;
 
&lt;?php endforeach; ?&gt; // ending the first for loop (foreach($filters as $filter))
                &lt;/ol&gt;
 
            &lt;/dd&gt;
    &lt;/dl&gt;
    &lt;a class="all" style="float:right;" href="&lt;?php echo $this-&gt;getClearUrl()?&gt;"&gt;All&lt;/a&gt;    // show all products, return from current state back to category view
&lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 18 Oct 2015 14:39:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ 如何创建自定义属性源类型]]></title>
      <link>https://www.360magento.com/blog/attribute-source-type/</link>
      <description><![CDATA[<p>你是否曾经需要创建自定义属性源类型？下面的小示例可能会对你有所帮助。</p>
<p>首先你需要创建sql安装文件，这个文件将把源类型的属性加入到你的系统中。源类型定义在数组： <strong>&lsquo;source&rsquo; =&gt; &lsquo;sourcetype/attribute_source_type&rsquo;</strong>。</p>
<pre><code>startSetup();
 
$installer-&gt;addAttribute('catalog_product', 'product_type', array(
        'group'             =&gt; 'Product Options',
		'label'             =&gt; 'Product Type',
		'note'              =&gt; '',
        'type'              =&gt; 'int',	//backend_type
		'input'             =&gt; 'select',	//frontend_input
		'frontend_class'	=&gt; '',
		'source'			=&gt; 'sourcetype/attribute_source_type',
        'backend'           =&gt; '',
        'frontend'          =&gt; '',
        'global'            =&gt; Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE,
		'required'          =&gt; true,
        'visible_on_front'  =&gt; false,
        'apply_to'          =&gt; 'simple',
        'is_configurable'   =&gt; false,
        'used_in_product_listing'	=&gt; false,
        'sort_order'        =&gt; 5,
    ));
 
$installer-&gt;endSetup();
</code></pre>
<p>接着你需要创建自定义源类型或者名为<strong>Alwayly_Sourcetype_Model_Attribute_Source_Type</strong>的类，下面是我的例子：</p>
<pre><code>class Alwayly_Sourcetype_Model_Attribute_Source_Type extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
	const MAIN = 1;
	const OTHER = 2;
 
    public function getAllOptions()
    {
        if (is_null($this-&gt;_options)) {
            $this-&gt;_options = array(
                array(
                    'label' =&gt; Mage::helper('sourcetype')-&gt;__('Main Product'),
                    'value' =&gt;  self::MAIN
                ),
                array(
                    'label' =&gt; Mage::helper('sourcetype')-&gt;__('Other Product'),
                    'value' =&gt;  self::OTHER
                ),
            );
        }
        return $this-&gt;_options;
    }
 
    public function toOptionArray()
    {
        return $this-&gt;getAllOptions();
    }
 
    public function addValueSortToCollection($collection, $dir = 'asc')
    {
        $adminStore  = Mage_Core_Model_App::ADMIN_STORE_ID;
        $valueTable1 = $this-&gt;getAttribute()-&gt;getAttributeCode() . '_t1';
        $valueTable2 = $this-&gt;getAttribute()-&gt;getAttributeCode() . '_t2';
 
        $collection-&gt;getSelect()-&gt;joinLeft(
            array($valueTable1 =&gt; $this-&gt;getAttribute()-&gt;getBackend()-&gt;getTable()),
            "`e`.`entity_id`=`{$valueTable1}`.`entity_id`"
            . " AND `{$valueTable1}`.`attribute_id`='{$this-&gt;getAttribute()-&gt;getId()}'"
            . " AND `{$valueTable1}`.`store_id`='{$adminStore}'",
            array()
        );
 
        if ($collection-&gt;getStoreId() != $adminStore) {
            $collection-&gt;getSelect()-&gt;joinLeft(
                array($valueTable2 =&gt; $this-&gt;getAttribute()-&gt;getBackend()-&gt;getTable()),
                "`e`.`entity_id`=`{$valueTable2}`.`entity_id`"
                . " AND `{$valueTable2}`.`attribute_id`='{$this-&gt;getAttribute()-&gt;getId()}'"
                . " AND `{$valueTable2}`.`store_id`='{$collection-&gt;getStoreId()}'",
                array()
            );
            $valueExpr = new Zend_Db_Expr("IF(`{$valueTable2}`.`value_id`&gt;0, `{$valueTable2}`.`value`, `{$valueTable1}`.`value`)");
 
        } else {
            $valueExpr = new Zend_Db_Expr("`{$valueTable1}`.`value`");
        }
 
 
 
        $collection-&gt;getSelect()
            -&gt;order($valueExpr, $dir);
 
        return $this;
    }
 
    public function getFlatColums()
    {
        $columns = array(
            $this-&gt;getAttribute()-&gt;getAttributeCode() =&gt; array(
                'type'      =&gt; 'int',
                'unsigned'  =&gt; false,
                'is_null'   =&gt; true,
                'default'   =&gt; null,
                'extra'     =&gt; null
            )
        );
        return $columns;
    }
 
 
    public function getFlatUpdateSelect($store)
    {
        return Mage::getResourceModel('eav/entity_attribute')
            -&gt;getFlatUpdateSelect($this-&gt;getAttribute(), $store);
    }
}
</code></pre>
<p>如果安装正确地完成，进入Magento后台admin -&gt; Catalog -&gt; Product，你会看到一个名为&ldquo;Product Options&rdquo;的选项。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 18 Oct 2015 14:18:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中“Google +1”插件]]></title>
      <link>https://www.360magento.com/blog/magento-google-1/</link>
      <description><![CDATA[<p>嵌入谷歌+1按钮很简单，你所要做的就是在你的网页里加两段代码。一个在网页的头部，还有一个在你想要呈现的地方。你需要按照Google官方的指引来做：<a title="google+1" href="http://www.google.com/intl/en/webmasters/+1/button/index.html">http://www.google.com/intl/en/webmasters/+1/button/index.html</a>。</p>
<p>我们把插件的名字定为&ldquo;GPlusOne&rdquo;，在&ldquo;Alwayly&rdquo;命名空间里。让我们用下面的代码创建<strong>/app/etc/modules/Alwayly_GPlusOne.xml</strong>。</p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_GPlusOne&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;community&lt;/codePool&gt;
        &lt;/Alwayly_GPlusOne&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>接着，用下面的代码创建我们的第二个文件<strong>app/code/community/Alwayly/GPlusOne/etc/config.xml</strong>：</p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_GPlusOne&gt;
            &lt;version&gt;1.0.0.0&lt;/version&gt;
        &lt;/Alwayly_GPlusOne&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;alwayly_gplusone&gt;
                &lt;class&gt;Alwayly_GPlusOne_Block&lt;/class&gt;
            &lt;/alwayly_gplusone&gt;
        &lt;/blocks&gt;      
    &lt;/global&gt;
 
    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;alwayly_gplusone&gt;
                    &lt;file&gt;alwayly/gplusone.xml&lt;/file&gt;
                &lt;/alwayly_gplusone&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;        
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>如你所见，我们声明了<strong>gplusone.xml</strong>这个布局文件，<strong>app/design/frontend/default/default/layout/alwayly/gplusone.xml</strong>的代码：</p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;layout version="1.0.0"&gt;
    &lt;catalog_product_view&gt;
        &lt;reference name="head"&gt;
            &lt;block type="core/template" name="alwayly_gplusone_head" template="alwayly/gplusone_head.phtml" /&gt;
        &lt;/reference&gt;        
        &lt;reference name="alert.urls"&gt;
            &lt;block type="alwayly_gplusone/PlusButton" name="alwayly_gplusone" /&gt;
        &lt;/reference&gt;
    &lt;/catalog_product_view&gt;
&lt;/layout&gt;
</code></pre>
<p>仔细观察，你会发现gplusone.xml更新产品详细页。由于嵌入谷歌+1按钮需要在页面读取两个脚本，我们就将它们分别放到下面两个文件中：</p>
<p><strong>app/design/frontend/default/default/template/alwayly/gplusone_head.phtml</strong></p>
<p><strong>app/design/frontend/default/default/template/alwayly/gplusone_button.phtml</strong></p>
<p><strong>app/design/frontend/default/default/template/alwayly/gplusone_head.phtml</strong>文件通过<strong>&lsquo;reference name=&rdquo;head&rdquo;&lsquo;</strong>来更新布局，代码如下：</p>
<pre><code>&lt;script type="text/javascript" src="https://apis.google.com/js/plusone.js"&gt;&lt;/script&gt;
</code></pre>
<p><strong>app/design/frontend/default/default/template/alwayly/gplusone_button.phtml</strong>通过<strong>&lsquo;reference name=&rdquo;alert.urls&rdquo;</strong>'载入到页面的alert.urls块中。<strong>gplusone_button.phtml</strong>的代码如下：</p>
<pre>&lt;code&lt;&lt;g:plusone &lt;?php if($size = $this-&gt;getSize()) { echo ' size="'.$size.'"'; } ?&gt;&gt;&lt;/g:plusone&gt;
</pre>
<p>最后，用下面的代码创建<strong>app/code/community/Alwayly/GPlusOne/Block/PlusButton.php</strong></p>
<pre><code>&lt;?php
 
class Alwayly_GPlusOne_Block_PlusButton extends Mage_Core_Block_Template
{
    /**
     * Constructor. Set template.
     */
    protected function _construct()
    {
        parent::_construct();
        $this-&gt;setTemplate('inchoo/gplusone_button.phtml');
    }
 
    public function getSize() 
    {
        //Here we can implement the code to read the config values for sizes
        return '';
    }
}
</code></pre>
<p>如果你观察gplusone_button.phtml文件，你会发现它调用<strong>Alwayly_GPlusOne_Block_PlusButton</strong>类里的<strong>getSize()</strong>方法。目前，这个方法没有什么作用，是为了以后扩展用的。鉴于谷歌+1按钮支持多钟尺寸（小，中等，高以及标准大小），你可以在插件里添加些简单的逻辑来获取Magento后台中输入的值。</p>
<p>本文不是给你一个不成熟的插件，而是向你展示以Magento的方式实现一个简单的谷歌+插件需要哪些东西。（这不一样是最好的方法）</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 17 Oct 2015 10:16:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[获取Magento中属性的值，名字和其它信息]]></title>
      <link>https://www.360magento.com/blog/magento-attribute-info/</link>
      <description><![CDATA[<p>产品的属性是一个非常重要的功能，我们经常会用到。在这篇文章中我将总结的一些产品属性信息的输出方法跟大家分享一下。</p>
<p>1、获取属性集合 </p>
<pre><code>$attribute = $_product-&gt;getResource()-&gt;getAttribute(&lsquo;attribute_code&rsquo;); </code></pre>
<p>2、获取属性类型</p> 
<pre><code>$attribute-&gt;getAttributeType(); </code></pre>
<p>3、获取属性Label</p>
<pre><code> $attribute-&gt;getFrontendLabel(); </code></pre>
<p>4、获取属性默认值 </p>
<pre><code>$attribute-&gt;getDefaultValue(); </code></pre>
<p>5、获取属性设置值 </p>
<pre><code>$attribute-&gt;getFrontend()-&gt;getValue($_product); </code></pre>
<p>6、检查属性是否可见 </p>
<pre><code>$attribute-&gt;getIsVisible(); </code></pre>
<p>7、检查属性是否是必填项 </p>
<pre><code>$attribute-&gt;getIsRequired();</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 17 Oct 2015 10:05:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何禁用Magento事件]]></title>
      <link>https://www.360magento.com/blog/disable-magento-event/</link>
      <description><![CDATA[<p>有些情况下你希望禁用Magento事件。例如，在一个我们的项目中，我们决定禁用所有的&ldquo;Mage_Log&rdquo;事件来减少数据库的sql查询。我们将在这篇文章中描述我们是怎么做的，但我相信这个方法可以在很多场景中应用。</p>
<p>Magento事件是怎么定义的呢？例如，你到Magento模型<strong>&ldquo;Mage_Log&rdquo;</strong>的<strong>config.xml</strong>文件中，你会发现下一个内容在&ldquo;events&rdquo;标签里。</p>
<p>&ldquo;Events&rdquo;标签包含子事件，你可以看<strong>config.xml</strong>文件中的块。</p>
<pre><code>&lt;frontend&gt;
	&lt;events&gt;
            &lt;controller_action_predispatch&gt;
                &lt;observers&gt;
                    &lt;log&gt;
                        &lt;class&gt;log/visitor&lt;/class&gt;
                        &lt;method&gt;initByRequest&lt;/method&gt;
                    &lt;/log&gt;
                &lt;/observers&gt;
            &lt;/controller_action_predispatch&gt;
            .... other events
        &lt;/events&gt;
&lt;/frontend&gt;
</code></pre>
<p>例如，如果你想要禁用<strong> &ldquo;controller_action_predispatch&rdquo; </strong>事件，你需要创建自己的模型并将它放到你的<strong>config.xml</strong>文件中。</p>
<pre><code>&lt;frontend&gt;
	&lt;events&gt;
		&lt;controller_action_predispatch&gt;
			&lt;observers&gt;&lt;log&gt;&lt;type&gt;disabled&lt;/type&gt;&lt;/log&gt;&lt;/observers&gt;
		&lt;/controller_action_predispatch&gt;
	&lt;/events&gt;
&lt;/frontend&gt;
</code></pre>
<p>也许你注意到了，我们添加值为&ldquo;disable&ldquo;的&ldquo;type&rdquo;标签。进入Magento类<strong> &ldquo;Mage_Core_Model_App&rdquo;</strong> ，在&ldquo;dispatchEvent&rdquo;方法中，你将看到：</p>
<pre><code> foreach ($events[$eventName]['observers'] as $obsName=&gt;$obs) {
                $observer-&gt;setData(array('event'=&gt;$event));
                Varien_Profiler::start('OBSERVER: '.$obsName);
                switch ($obs['type']) {
                    case 'disabled': // if we set disabled type, event will not be executed.
                        break;
                    case 'object': case 'model':
                        $method = $obs['method'];
                        $observer-&gt;addData($args);
                        $object = Mage::getModel($obs['model']);
                        $this-&gt;_callObserverMethod($object, $method, $observer);
                        break;
                    default:
                        $method = $obs['method'];
                        $observer-&gt;addData($args);
                        $object = Mage::getSingleton($obs['model']);
                        $this-&gt;_callObserverMethod($object, $method, $observer);
                        break;
                }
                Varien_Profiler::stop('OBSERVER: '.$obsName);
            }
</code></pre>
<p>如果设置事件type为&ldquo;disabled&rdquo;，事件将不会被执行。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 16 Oct 2015 12:15:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[编辑Magento中的PDF地址]]></title>
      <link>https://www.360magento.com/blog/edit-pdf-address/</link>
      <description><![CDATA[<p>在Magento中编辑PDF是受限制的，但是如果你需要编辑的只是一个地址，你可以使用事件。</p>
<p>首先在config.xml中设置你的观测者：</p>
<pre><code>&lt;adminhtml&gt;
    	&lt;events&gt;
    	    &lt;customer_address_format&gt;
    		&lt;observers&gt;
                    &lt;alwayly_sales_customer_address_format_observer&gt;
                        &lt;type&gt;model&lt;/type&gt;
                        &lt;class&gt;alwayly_sales/observer&lt;/class&gt;
                        &lt;method&gt;addAdditionalDataToAddress&lt;/method&gt;
                    &lt;/alwayly_sales_customer_address_format_observer&gt;
                &lt;/observers&gt;
    	    &lt;/customer_address_format&gt;
    	&lt;/events&gt;
&lt;/adminhtml&gt;
</code></pre>
<p>在设置完观测者之后，你需要写代码来编辑地址模版：</p>
<pre><code>/**
 * Observer printing invoices in PDF
 *
 * @category    Alwayly
 * @package     Alwayly_Sales
 */
class Alwayly_Sales_Model_Observer
{
    public function addAdditionalDataToAddress(Varien_Event_Observer $address)
    {
    	$data = $address-&gt;getEvent();
    	if($data-&gt;type['code']=="pdf")
    	{
    		$customerData = $data["address"]-&gt;getOrder()-&gt;getData();
    		$customerId = $customerData['customer_id'];
    		//we are using customer object because it give us latest user data, if you want data from user on order creation use $customerData
			$customer = Mage::getModel('customer/customer')-&gt;load($customerId);
			$customerVariable = $customer-&gt;get?????;
 
			//prevent of multiple insertion
    		if(strpos($data-&gt;type['default_format'],"Customer Variable")===false)
    		{
    		 	$stringToInsert = "{{var company}}|{{/depend}}|Customer Variable: ".$customerVariable."|";
    		 	$data-&gt;type['default_format'] = str_replace("{{var company}}|{{/depend}}",$stringToInsert, $data-&gt;type['default_format']);
    		};
    	};
    }
}
</code></pre>
<p>如果你想要获取最后一个用户的数据，你要使用<strong>Mage::getModel(&lsquo;customer/customer&rsquo;) </strong>对象。注意，用你自己的数据替换?????。我们获取地址模版并做修改。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 16 Oct 2015 12:05:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中展示产品选项的HTML代码（块）]]></title>
      <link>https://www.360magento.com/blog/product-options-html/</link>
      <description><![CDATA[<p>这个简单的助手可以帮你显示产品选项的html代码。它适用于简单（simple）, 虚拟（virtual）和可配置（configurable）产品。我相信你也可以将同样的方法应用到其它产品上。获取可配置产品选项的HTML代码会一点。</p>
<p>对于简单产品，我们有一种非常&ldquo;干净的方法&rdquo;。</p>
<p>首先，我们为产品设置一个块，接着我们添加物品渲染器（template和type）到产品选项块。最后一步就是创建迭代选择并与我们的产品选项块一起显示。</p>
<p>我们可以看到一些不错的松耦合和代码分离。另一方面，获取可配置产品选项的html代码并不这么灵活。实例块，实例化产品。我们获取选项的html。</p>
<h1>抽样：</h1>
<pre><code>echo Mage::helper("alwayly_checkout")-&gt;getProductOptionsHtml(Mage::getModel("catalog/product")-&gt;load(171));</code></pre>
<h1>助手：</h1>
<pre><code>&lt;!--?php &lt;br ?--&gt;/**
 * @category    Alwayly
 * @package     Alwayly_Checkout
 * @author      Alwayly
 */
class Alwayly_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
{
	/**
	 * 
	 * getting html for options of products
	 * @param Mage_Catalog_Model_Product $product
	 */
	public function getProductOptionsHtml(Mage_Catalog_Model_Product $product)
	{ 
		$blockOption = Mage::app()-&gt;getLayout()-&gt;createBlock("Mage_Catalog_Block_Product_View_Options");
                $blockOption-&gt;addOptionRenderer("default","catalog/product_view_options_type_default","catalog/product/view/options/type/default.phtml");
		$blockOption-&gt;addOptionRenderer("text","catalog/product_view_options_type_text","alwayly_catalog/product/view/options/type/text.phtml");
		$blockOption-&gt;addOptionRenderer("file","catalog/product_view_options_type_file","catalog/product/view/options/type/file.phtml");
		$blockOption-&gt;addOptionRenderer("select","inchoo_checkout/product_view_options_type_select","catalog/product/view/options/type/select.phtml");
		$blockOption-&gt;addOptionRenderer("date","catalog/product_view_options_type_date","catalog/product/view/options/type/date.phtml") ;
 
 
		$blockOptionsHtml = null;
 
		 if($product-&gt;getTypeId()=="simple"||$product-&gt;getTypeId()=="virtual"||$product-&gt;getTypeId()=="configurable")
		 {  
		 	$blockOption-&gt;setProduct($product);
			if($product-&gt;getOptions())
			{  
				foreach ($product-&gt;getOptions() as $o) 
	    		{     
	    			$blockOptionsHtml .= $blockOption-&gt;getOptionHtml($o); 
	    		};    
			}  
		 }  
 
		 if($product-&gt;getTypeId()=="configurable")
		 {   
		 	$blockViewType = Mage::app()-&gt;getLayout()-&gt;createBlock("Mage_Catalog_Block_Product_View_Type_Configurable");
		 	$blockViewType-&gt;setProduct($product);   
		 	$blockViewType-&gt;setTemplate("inchoo_catalog/product/view/type/options/configurable.phtml");
			$blockOptionsHtml .= $blockViewType-&gt;toHtml(); 
		 }  
		 return $blockOptionsHtml; 
	}
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 15 Oct 2015 09:50:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[删除Magento中的测试订单]]></title>
      <link>https://www.360magento.com/blog/delete-magento-orders/</link>
      <description><![CDATA[<p>当你开发一个Magento项目，你会创建一个Magento主题，放置初始产品和类别，还放置一些订单来测试送货方式和支付方法的正常运行。一切都很好，客户也想要看看网站。可是运行中，你将看到一些本应该删除的测试订单。</p>
<p>当你想在后台删除订单的时候你会发现，你只能将订单状态改为&ldquo;取消&rdquo;，而订单仍然在那里。Magento不允许我们通过后台来删除这些，所以你看不到任何&ldquo;删除订单&rdquo;按钮。这对商家和开发人员来说都是让人沮丧的。来自SAP的人发现不能删除订单有些好处，但是应该有一个状态来从报告中消除销售、库存等信息的销售计数。</p>
<p>那么，怎么做呢？</p>
<p>你可以在你的Magento根目录下创建一个php脚本，粘贴下面的代码：</p>
<pre><code>&lt;?php
/**
* @copyright Alwayly
*/

if (version_compare(phpversion(), '5.2.0', '&lt;')===true) {
echo '&lt;div style="font:12px/1.35em arial, helvetica, sans-serif;"&gt;&lt;div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;"&gt;&lt;h3 style="margin:0; font-size:1.7em; font-weight:normal; text-transform:none; text-align:left; color:#2f2f2f;"&gt;Whoops, it looks like you have an invalid PHP version.&lt;/h3&gt;&lt;/div&gt;&lt;p&gt;Magento supports PHP 5.2.0 or newer. &lt;a href="http://www.magentocommerce.com/install" target=""&gt;Find out&lt;/a&gt; how to install&lt;/a&gt; Magento using PHP-CGI as a work-around.&lt;/p&gt;&lt;/div&gt;';
exit;
}

error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);

$mageFilename = 'app/Mage.php';

if (!file_exists($mageFilename)) {
echo $mageFilename." was not found";
exit;
}

require_once $mageFilename;

Mage::app();

$executionPath = null;

/*
* determine Magento Edition
*/
if (file_exists('LICENSE_EE.txt')) {
$edition = 'EE';
}elseif (file_exists('LICENSE_PRO.html')) {
$edition = 'PE';
} else {
$edition = 'CE'; 
}

if(($edition=='EE' &amp;&amp; version_compare(Mage::getVersion(), '1.11.0.0.', '&lt;')===true)
|| ($edition=='PE' &amp;&amp; version_compare(Mage::getVersion(), '1.11.0.0.', '&lt;')===true)
|| ($edition=='CE' &amp;&amp; version_compare(Mage::getVersion(), '1.6.0.0.', '&lt;')===true)
){
$executionPath = 'old'; 
} else {
$executionPath = 'new'; 
}

$xpathEntity = 'global/models/sales_entity/entities//table';

if ($executionPath == 'old') {
$xpathResource = 'global/models/sales_mysql4/entities//table';
} else {
$xpathResource = 'global/models/sales_resource/entities//table';
}

$salesEntitiesConf = array_merge(
Mage::getSingleton('core/config')-&gt;init()-&gt;getXpath($xpathEntity), 
Mage::getSingleton('core/config')-&gt;init()-&gt;getXpath($xpathResource)
);

$resource = Mage::getSingleton('core/resource');
$connection = $resource-&gt;getConnection('core_write');


/*
* If you want delete System/Order Statuses (Status and State) you
* should comments below lines (46-51)
*/
$skipTables = array (
$resource-&gt;getTableName('sales_order_status'),
$resource-&gt;getTableName('sales_order_status_state'),
$resource-&gt;getTableName('sales_order_status_label')
);
$salesEntitiesConf = array_diff($salesEntitiesConf, $skipTables);


/*

Multiple RDBMS Support in Magento CE 1.6+ / EE 1.11+
http://www.magentocommerce.com/images/uploads/RDBMS_Guide2.pdf

2.2. Adapters:

... The new Varien_DB_Adapter_Interface was added to sign a contract that all 
developed adapters must execute in order to get Magento working on an actual 
database. The interface describes the list of methods and constants that can be used by resource models...

Used below in the loop:

* If $executionPath == 'old'
* Varien_Db_Adapter_Pdo_Mysql::showTableStatus()
* Varien_Db_Adapter_Pdo_Mysql::truncate() 
* Else
* Varien_Db_Adapter_Interface::isTableExists()
* Varien_Db_Adapter_Interface::truncateTable()

*/

while ($table = current($salesEntitiesConf) ){
$table = $resource-&gt;getTableName($table);

if ($executionPath == 'old') {
$isTableExists = $connection-&gt;showTableStatus($table);
} else {
$isTableExists = $connection-&gt;isTableExists($table);
}
if ($isTableExists) {
try {
if ($executionPath == 'old') {
$connection-&gt;truncate($table);
} else {
$connection-&gt;truncateTable($table);
}

printf('Successfully truncated the &lt;i style="color:green;"&gt;%s&lt;/i&gt; table.&lt;br /&gt;', $table);
} catch(Exception $e) {
printf('Error &lt;i style="color:red;"&gt;%s&lt;/i&gt; occurred truncating the &lt;i style="color:red;"&gt;%s&lt;/i&gt; table.&lt;br /&gt;', $e-&gt;getMessage(), $table);
}
}

next($salesEntitiesConf);
}

exit('All done...');
</code></pre>
<p>代码执行后，数据库里再也不会有测试订单了。记住，这将删除所有数据库中订单。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 15 Oct 2015 09:45:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用自定义输入渲染器添加Magento属性]]></title>
      <link>https://www.360magento.com/blog/attribute-input-renderer/</link>
      <description><![CDATA[<p>这个例子将给你解释如何用自定义输入渲染添加新属性。你将修改已有的功能，添加JavaScript，一些其它的选项或者改变默认的输入渲染。</p>
<p>你可能会问什么是Magento输入渲染器。这是一个负责呈现HTML表单元素的Magento php类。在Magento里有不同的渲染类，你可以在<strong>/lib/Varien/Data/Form/Element</strong>的文件夹里找到它们。</p>
<p>让我们开始我们的示例吧。</p>
<p>首先创建Magento安装文件，下面是示例：</p>
<pre><code>&lt;?php
$installer = $this;
 
$installer-&gt;startSetup();
 
$installer-&gt;addAttribute(Mage_Catalog_Model_Product::ENTITY, 'example_field', array(
    'group'             =&gt; 'General',
    'type'              =&gt; 'text',
    'backend'           =&gt; '',
    'input_renderer'    =&gt; 'test/catalog_product_helper_form_example',//definition of renderer
    'label'             =&gt; 'Example field',
    'class'             =&gt; '',
    'global'            =&gt; Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE,
    'visible'           =&gt; true,
    'required'          =&gt; false,
    'user_defined'      =&gt; true,
    'searchable'        =&gt; false,
    'filterable'        =&gt; false,
    'comparable'        =&gt; false,
    'visible_on_front'  =&gt; false,
    'unique'            =&gt; false,
    'apply_to'          =&gt; 'simple,configurable,bundle,grouped',
    'is_configurable'   =&gt; false,
));
 
$installer-&gt;endSetup();
</code></pre>
<p>你可以看到，我们用&ldquo;addAttribute&rdquo;方法来添加属性，变量<strong>&ldquo;$installer&rdquo;是&ldquo;Mage_Catalog_Model_Resource_Setup&rdquo</strong>;的实例，前端输入渲染定义在数组<strong> &lsquo;input_renderer&rsquo; =&gt; &lsquo;test/catalog_product_helper_form_example&rsquo;</strong></p>
<p>下一步，你需要创建自己的输入渲染器。下面是我的例子<strong>(Alwayly_Test_Block_Catalog_Product_Helper_Form_Price)</strong>，一个简单的类，为了用来演示。</p>
<pre><code>&lt;?php
class Alwayly_Test_Block_Catalog_Product_Helper_Form_Example extends Varien_Data_Form_Element_Text
{
    public function getAfterElementHtml()
    {
        $html = parent::getAfterElementHtml();
        return $html."
<script type="text/javascript">// <![CDATA[
$('".$this->getHtmlId()."').disable();
// ]]]]><![CDATA[></script>
"; } <br />} </code></pre>
<p>在我的例子里，我添加java代码来禁用输入元素，管理员用户无法编辑此字段。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 14 Oct 2015 11:15:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[来自Magento的苹果推送通知]]></title>
      <link>https://www.360magento.com/blog/apple-push-notifications/</link>
      <description><![CDATA[<p>不是每个人都对这个标题很熟悉，苹果推送通知服务（APNS）是苹果公司为其移动设备(iPhone, iPad …) 提供的基础服务，可以给特定的监听应用发送特定的信息。</p>
<p>对于APNS的正确用法，他们可能需要集成到移动应用程序里，也需要苹果移动层面上发送信息的证书。</p>
<p>我不是一个IOS开发人员，所以我没有资格去写这个故事的移动端，但是，这里还有另一个方面需要被覆盖。我会尽量解释如何利用Magento来发送推送信息到目标移动设备。</p>
<p>使用Magento时思路可以是多样的：当新订单被创建或者客户注册我们可以发推送信息，或者我们可以用在Magento移动端来发送类似通讯的消息……</p>
<p>这篇教程假设你已经参加了苹果开发计划，注册了APNS并集成APNS功能到你的移动应用。</p>
<p>为了在Magento中使用APNS我先要做点准备工作。</p>
<h1>从源代码中准备可用的APNS证书</h1>
<p>登录到你的苹果开发者网站，下载APNS使用证书。将证书拷贝到你插件文件系统中的，另外记得写下证书的密码。</p>
<h1>在数据库中创建自定义的表单来存储独特的标记和其它APNS需要的参数</h1>
<p>在我们的APNS表中，我们将为每一个接收推送信息的设备保存独特的标记。这个设备的标记可能是应用启动时移动设备发出的。为了在数据库保存device_token。我们需要创建独立的Magento web服务方法，当移动应用启动时被调用。</p>
<p>我们需要从移动应用发送APNS设备标记到apns_save Web服务方法。在web服务方法中我们应该要对设备标记添加/更新来避免重复。</p>
<p>下面是一个web服务API方法的示例：</p>
<pre><code>&lt;!--?php &lt;br ?-->
/*
 * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
 
class Alwayly_Mapy_Model_Core_Apns_Api_V2 extends Mage_Api_Model_Resource_Abstract {
 
    public function setParams($token, $events, $appversion, $period) {
 
        $api_user = Mage::getSingleton('api/session')->getUser();
        $userExists = ($api_user && $api_user->getId()) ? true : false;
 
        if (!$userExists) {
            $this->_fault('not_exists', 'User does not exist!');
        }
        if (!$token) {
            $this->_fault('data_invalid', 'Device token not set!');
        }
        if ($token == '') {
            $this->_fault('data_invalid', 'Device token invalid!');
        }
 
        $collection = Mage::getSingleton('inchoo_mapy/core_apns')->getCollection();
 
        $collection->addFieldToFilter('user_id', $api_user->getId());
        $collection->addFieldToFilter('device_token', $token);
 
        $app = explode('-', $appversion);
        if (count($app) > 0) {
            $collection->addFieldToFilter('app_version',array('like'=>$app[0] . '%'));
        } else {
            $this->_fault('data_invalid', 'App version not supported!');
        }
        $param = $collection->getFirstItem();
 
        $currentTime = now();
 
        if ($period < 60) {             $period = 60;         }         $sess_id = Mage::getSingleton('api/session')-

>getSessionId();
 
        $param->setUserId($api_user->getId());
        $param->setAppVersion($appversion);
        $param->setDeviceToken($token);
        $param->setEvents($events);
        $param->setStatus('active');
        $param->setNotificationPeriod($period);
        $param->setUpdatedAt($currentTime);
        $param->setLastSession($sess_id);
 
        $param->save();
 
        return true;
    }
</code></pre>
<h1>创建用于发送推送信息的助手</h1>
<p>当我们存储设备标记到我们的表里时，我们决定从Magento中何时，发送什么，发送给哪些设备信息的逻辑。当然，也要实现发送-间隔的逻辑来避免垃圾信息。</p>
<pre><code>&lt;!--?php &lt;br ?-->
/*
 * @license http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
 
class Alwayly_Mapy_Helper_ApnsLite extends Mage_Core_Helper_Abstract {
 
    const CONFIG_XML_PATH_APPLE_SSL = 'inchoo_mapy/settings/apnsssl';
    const CONFIG_XML_PATH_APPLE_FEEDBACK = 'inchoo_mapy/settings/apnsfeedback';
 
    private function _getCertificate() {
        return Mage::getBaseDir() . DS . 'app' . DS . 'code' . DS . 'community' . DS .
                'Inchoo' . DS . 'Mapy' . DS . 'lib' . DS . 'apple' .
                DS . 'certificate' . DS . 'ck_production_lite.pem';
    }
 
    public function sendPushNotifications() {
 
        $certificate = $this->_getCertificate();
        $devices = $this->_getDevicesForNotification();
 
        $messages = array();
        foreach ($devices as $device) {
 
            if ($device['received_at'] == null) {
                $now = Zend_Date::now();
                $now->sub(1, Zend_Date::HOUR);
 
                $from_time = $now;
            } else {
                $from_time = new Zend_Date($device['received_at'], Varien_Date::DATETIME_INTERNAL_FORMAT);
            }
 
            $data = array();
            if (strpos($device['events'], 'new_orders') !== false) {
                $result = $this->_getNewOrders($from_time);
                $data['orders_sum'] = $result['sales_total'];
                $data['orders_count'] = $result['num_orders'];
            }
            if (strpos($device['events'], 'new_customers') !== false) {
                $result = $this->_getNewCustomers($from_time);
                $data['customers_count'] = $result['new_customers'];
            }
 
            $message = $this->_prepareMessage($data);
 
            if (md5($message) == $device['last_msg_hash']) {
                $message = null;
            }
 
            $sess_id = $device['last_session'];
            $session = Mage::getSingleton('api/session');
 
            $user = Mage::getModel('api/user')->loadBySessId($sess_id);
 
            $user = Mage::getModel('api/user')->loadBySessId($sess_id);
            if ((!$session->isLoggedIn($sess_id))||(!$user->hasUserId())) {
                $message = null;
                $collection = Mage::getModel('inchoo_mapy/core_apns')->getCollection();
                $collection->addFieldToFilter('last_session', $sess_id);
 
                foreach ($collection as $val) {
                    if ($val->getId()) {
                        $val->setStatus('inactive');
                        $val->save();
                    }
                }
            }
 
            if ($message != null) {
                $messages[] = array(
                    'msg' => $message,
                    'device' => $device['device_token'],
                );
            }
        }
 
        if (count($messages) > 0) {
            $this->_pushMessage($messages, $certificate);
        }
    }
 
    private function _prepareMessage($data) {
 
        $helper = Mage::helper('inchoo_mapy');
 
        $message = '';
        $badge = 0;
        $mage_events = array();
 
        if (isset($data['orders_sum'])) {
            if ($data['orders_sum'] > 0) {
                $message.='Sales total: ' . $helper->currencyToBaseFormat($data['orders_sum']);
            }
        }
 
        if (isset($data['orders_count'])) {
            if ($data['orders_count'] > 0) {
                $message.=' Orders count: ' . $data['orders_count'];
                $badge+=$data['orders_count'];
                $mage_events[] = array('mage_event' => 'new_orders', 'count' => $data['orders_count']);
            }
        }
 
        if (isset($data['customers_count'])) {
            if ($data['customers_count'] > 0) {
                $message.=' New customers count: ' . $data['customers_count'];
                $badge+=$data['customers_count'];
                $mage_events[] = array('mage_event' => 'new_customers', 'count' => $data['customers_count']);
            }
        }
 
        if ($badge == 0) {
            return;
        }
 
        $body['aps'] = array(
            'sound' => 'tick.caf',
            'alert' => $message,
            'badge' => (int) $badge,
            'mage-events' => $mage_events
        );
 
        $payload = json_encode($body);
 
        return $payload;
    }
 
    private function _getDevicesForNotification() {
 
        $collection = Mage::getModel('inchoo_mapy/core_apns')->getCollection();
        $collection->addFieldToFilter('status', 'active');
 
        $where_expr = 'DATE_ADD(IFNULL(sent_at, DATE_SUB(UTC_TIMESTAMP(), INTERVAL 3600 SECOND )),INTERVAL notification_period 

SECOND)                 $param->save();
            }
        }
    }
 
}
</code></pre>
<p>如果你阅读了代码，你会发现我们有些公用的方法来发送通知。这些方法里我们先读取设备，然后我们再读取个准备信息的数据并在条件满足时发送它们。</p>
<ul>
<li>_prepareMessage方法是用来将数据加入到合适的json信息格式</li>
<li>_pushMessage是信息发送方法</li>
<li>_checkFeedback用来列出关闭推送信息的苹果设备，我们需要在表中把它们标记为inactive。</li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 14 Oct 2015 11:07:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[注入变量到Magento CMS静态块]]></title>
      <link>https://www.360magento.com/blog/injecting-variables-static/</link>
      <description><![CDATA[<p>在这篇教程中我将演示如何注入你需要的自定义变量到一个cms静态块，使用{{var variable_name}}标签。如果你正在处理email模版，那么你会看到这个。（本质是我们使用和email模版同样的用来注入变量的筛选器。</p>
<p>首先，让我们假设几件事情：</p>
<ol>
</li>包命名为'Company'，模块命名为'Module'<li>
</li>你知道如何创建一个php模型和新的块类。例子中的块别名是‘module/dynamic’<li>
</li>动态块的模版是dynamic.phtml<li>
</li>静态cms块的id是‘static_block’（你需要在后台创建它）<li>
</li>你需要添加当前用户的email到静态块。什么时候显示模块和文本范围的逻辑。<li>
</ol>
<p>第一步，我们看下模版文件，里面只使用我们想要创建块类的方法：</p>
<pre><code>&lt;?php if(Mage::getSingleton('customer/session')->getCustomer()->getId()) : ?>
	&lt;?php echo $this->getStaticBlock();?>
&lt;?php endif;?>
</code></pre>
<p>如你所见，我们只检查客户是否存在。下面我们看动态块类里的逻辑：</p>
<pre><code>&lt;?php
/**
 * Just another block class
 */
class Company_Module_Block_Dynamic extends Mage_Core_Block_Template
{
	/**
	 * This getter will return the html of your static block
	 * @return string
	 */
	public function getStaticBlock()
	{
		// loading the static block
		$block = Mage::getModel('cms/block')
		->setStoreId(Mage::app()->getStore()->getId())
		->load('static_block');
		/* @var $block Mage_Cms_Model_Block */
 
		// setting the assoc. array we send to the filter.
		$array = array();
		// the array keys are named after the tags in the static block. let's say $array['customer_email'] is {{var customer_email}} in the static block. you can set as many variables you need.
		$array['customer_email'] = Mage::getSingleton('customer/session')->getCustomer()->getEmail();
 
		// loading the filter which will get the array we created and parse the block content
		$filter = Mage::getModel('cms/template_filter');
		/* @var $filter Mage_Cms_Model_Template_Filter */
		$filter->setVariables($array);
 
		// return the filtered block content.
		return $filter->filter($block->getContent());
 
	}
}
?>
</code></pre>
<p>现在，在你CMS中的static_block块中添加 {{var customer_email}}标签，它将被动态地添加到CMS块。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>
]]></description>
      <pubDate>Tue, 13 Oct 2015 10:53:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[使用xpath和varien_object运行模块xml文件中指定的方法]]></title>
      <link>https://www.360magento.com/blog/xpath-varien_object/</link>
      <description><![CDATA[<p>去年，我们为用户开发了一些定制的EPR系统。客户的文件中指出他们需要运行一些在config.xml中定义的方法，在出口订单的时候用方法代码作为ID。很快，根据订单的付款代码他们想在出口订单时添加一些自定义计算。如果你对我们如何实现的感兴趣，那么继续阅读吧。</p>
<p>举例会让解释变得简单。首先创建我们的config.xml，最后我们将让Magento呼应我们的模块。</p>
<h1>Step 1: Creating module&rsquo;s configuration（创建模型配置）</h1>
<p>这里只是个简单的示例代码，你可以用它创建<strong>app/code/local/Alwayly/XmlMethodCall/etc/config.xml </strong></p>
<pre><code>&lt; ?xml version="1.0"?&gt;
 
&lt;config&gt;
 
    &lt;modules&gt;
       &lt;alwayly_xmlmethodcall&gt;
           &lt;version&gt;1.0.0.0&lt;/version&gt;
       &lt;/alwayly_xmlmethodcall&gt;
    &lt;/modules&gt;
 
    &lt;global&gt;
       &lt;xml_method_call&gt;
           &lt;payment_checkmo&gt;
               &lt;name&gt;Check / Money order &lt;/name&gt;
               &lt;code&gt;checkmo&lt;/code&gt;
               &lt;add&gt;
                   &lt;model&gt;alwayly_xmlmethodcall/checkmoAddVal&lt;/model&gt;
                   &lt;method&gt;addValue&lt;/method&gt;
               &lt;/add&gt;
               &lt;return&gt;
                   &lt;model&gt;alwayly_xmlmethodcall/checkmoGetCod&lt;/model&gt;
                   &lt;method&gt;getCode&lt;/method&gt;
               &lt;/return&gt;
           &lt;/payment_checkmo&gt;
       &lt;/xml_method_call&gt;
       &lt;xml_method_call&gt;
           &lt;payment_ccsave&gt;
               &lt;name&gt;Credit Card (saved) &lt;/name&gt;
               &lt;code&gt;ccsave&lt;/code&gt;
               &lt;add&gt;
                   &lt;model&gt;alwayly_xmlmethodcall/ccsaveAddVal&lt;/model&gt;
                   &lt;method&gt;addValue&lt;/method&gt;
               &lt;/add&gt;
               &lt;return&gt;
                   &lt;model&gt;alwayly_xmlmethodcall/ccsaveGetCod&lt;/model&gt;
                   &lt;method&gt;getCode&lt;/method&gt;
               &lt;/return&gt;
           &lt;/payment_ccsave&gt;
       &lt;/xml_method_call&gt;
       &lt;models&gt;
           &lt;alwayly_xmlmethodcall&gt;
               &lt;class&gt;Alwayly_XmlMethodCall_Model&lt;/class&gt;
               &lt;resourcemodel&gt;alwayly_xmlmethodcall_mysql4&lt;/resourcemodel&gt;
           &lt;/alwayly_xmlmethodcall&gt;
       &lt;/models&gt;
    &lt;/global&gt;
 
    &lt;frontend&gt;
       &lt;routers&gt;
           &lt;alwayly_xmlmethodcall&gt;
               &lt;use&gt;standard&lt;/use&gt;
               &lt;args&gt;
                   &lt;module&gt;Alwayly_XmlMethodCall&lt;/module&gt;
                   &lt;frontname&gt;xmlmethodcall&lt;/frontname&gt;
               &lt;/args&gt;
           &lt;/alwayly_xmlmethodcall&gt;
       &lt;/routers&gt;
    &lt;/frontend&gt;
 
&lt;/config&gt;
</code></pre>
<p>深入研究下xml_method_call结点和全球结点的第一子节点。你会看到两兄弟有同样的名字， xml_method_call结点。</p>
<p>让我们描述下下一个xml块：</p>
<pre><code>&lt;payment_checkmo>
    &lt;name>Check / Money order &lt;/name>
    &lt;code>checkmo&lt;/code>
    &lt;add>
        &lt;model>alwayly_xmlmethodcall/checkmoAddVal&lt;/model>
        &lt;method>addValue&lt;/method>
    &lt;/add>
    &lt;return>
        &lt;model>alwayly_xmlmethodcall/checkmoGetCod&lt;/model>
        &lt;method>getCode&lt;/method>
    &lt;/return>
&lt;/payment_checkmo>
</code></pre>
<ul>
<li>payment_checkmo 包含一些数据的唯一结点</li>
<li>name 这个唯一结点的名字，与代码无关</li>
<li>code 支付方式的代码（id）</li>
<li>add,return 两种方法定义他们应该调用的东西（模块/模型和方法调用的定义）</li>
</ul>
<p>现在我希望你对我们需要怎么实现有一个清晰的认识。在订单出口的时候我们调用一些方法做计算并返回结果。要求是方法需要是可配置的，这样非开发人员可以通过配置文件来改变它们。当然，你可以在system.xml中做到这点。</p>
<h1>Step 2: Creating module&rsquo;s models, described in config.xml（创建模块的模型，在config.xml中写描述）</h1>
<p>Create files:</p>
<ul>
<li>&ndash; app/code/local/Alwayly/XmlMethodCall/Model/CheckmoAddVal.php</li>
<li>&ndash; app/code/local/Alwayly/XmlMethodCall/Model/CheckmoGetCod.php</li>
<li>&ndash; app/code/local/Alwayly/XmlMethodCall/Model/CcsaveAddVal.php</li>
<li>&ndash; app/code/local/Alwayly/XmlMethodCall/Model/CcsaveGetCod.php</li>
</ul>
<p>分别添加下面的代码到对应的文件中：</p>
<pre><code>&lt; ?php
 
/**
*
*/
class Alwayly_XmlMethodCall_Model_CheckmoAddVal extends Mage_Core_Model_Abstract
{
 
   public function addValue()
   {
       return 1;
   }
}
</code></pre>
<pre><code>&lt; ?php
 
/**
*
*/
class Alwayly_XmlMethodCall_Model_CheckmoGetCod extends Mage_Core_Model_Abstract
{
 
   public function getCode()
   {
       return 'a';
   }
}
</code></pre>
<pre><code>&lt; ?php
 
/**
*/
class Alwayly_XmlMethodCall_Model_CcsaveAddVal extends Mage_Core_Model_Abstract
{
 
   public function addValue()
   {
       return 2;
   }
}
</code></pre>
<pre><code>&lt; ?php
 
/**
*
*/
class Alwayly_XmlMethodCall_Model_CcsaveGetCod extends Mage_Core_Model_Abstract
{
 
   public function getCode()
   {
       return 'b';
   }
}
</code></pre>
<p>因为是一个简单的教学示例，我们将只创建控制器并在里面的几个列数组里的订单。</p>
<h1>Step 3: Creating controller（创建控制器）</h1>
<pre><code>&lt; ?php
 
/**
*
*/
class Alwayly_XmlMethodCall_IndexController extends Mage_Core_Controller_Front_Action
{
 
   public function indexAction()
   {
       $orders = array();
       $orders[] = array (
           'order_no'    =&gt; 101,
           'method'    =&gt; 'checkmo',
           'amount'    =&gt; 99
       );
       $orders[] = array (
               'order_no'    =&gt; 102,
               'method'    =&gt; 'ccsave',
               'amount'    =&gt; 100
       );
       $orders[] = array (
               'order_no'    =&gt; 101,
               'method'    =&gt; 'checkmo',
               'amount'    =&gt; 199
       );
 
       foreach ($orders as $row) {
           $orderNo = $row['order_no'];
           $conf = Mage::getSingleton('core/config')-&gt;init()
               -&gt;getXpath('global/xml_method_call//code[.="' . $row['method'] . '"]/..');
 
           if ($conf) {
               $conf = new Varien_Object(current($conf)-&gt;asArray());
               $add = new Varien_Object($conf-&gt;getAdd());
               $code = new Varien_Object($conf-&gt;getReturn());
 
               if (method_exists(Mage::getModel($add-&gt;getModel()), $add-&gt;getMethod())) {
                   $amountValue = $row['amount'] + Mage::getModel($add-&gt;getModel())-&gt;{$add-&gt;getMethod()}();
               }
               if (method_exists(Mage::getModel($code-&gt;getModel()), $code-&gt;getMethod())) {
                   $codeValue = Mage::getModel($code-&gt;getModel())-&gt;{$code-&gt;getMethod()}();
               }
           } else {
               //throw an error
               die("or exit... or something goes wrong...");
           }
           echo "&lt;pre&gt;"                     . PHP_EOL;
           echo 'ID: '     . $orderNo         . PHP_EOL;
           echo 'VALUE: '     . $amountValue     . PHP_EOL;
           echo 'CODE: '     . $codeValue     . PHP_EOL;
       }
       print_r($orders);
   }
}
</code></pre>
<p>首先，我们创建了包含一些$orders里数据的订单集合。这可能是一个真实的集合，但是现在为了简化，我决定用个简单的二维数组。</p>
<p>下一个重要的部分是：</p>
<pre><code>$conf = Mage::getSingleton('core/config')-&gt;init()-&gt;getXpath('global/xml_method_call//code[.="' . $row['method'] . '"]/..');
</code></pre>
<p>如你所见，我们调用code/config模型里的XPath。如果你不知道this -&gt;getXpath(&lsquo;global/xml_method_call//code[.=&rdquo;&lsquo; . $row[&lsquo;method&rsquo;] . &lsquo;&rdquo;]/..&rsquo;)的意思，那么你可以去w3schools/XPath学些新东西。</p>
<p>我们将要实例化$conf对象，把xml_method_call作为根节点。我们不知道哪一个是它，但我们知道方法的代码并可以在config.xml搜索它。</p>
<p>"//"意味着同一级别。比temp结点深，确认你所能找到的所有结点然后挑选出含有你所需值的那个。</p>
<p>"/.."意味着返回当前位置的上一级结点，获取你想要的xml_method_call结点。这样所有事情就变得简单了。</p>
<p>下一个有趣的部分是：</p>
<pre><code> $conf = new Varien_Object(current($conf)-&gt;asArray());
 $add = new Varien_Object($conf-&gt;getAdd());
 $code = new Varien_Object($conf-&gt;getReturn());
</code></pre>
<p>设置我们的$conf, $add和$code作为Varien_Object实例（我们将有自己的getter和setter）。</p>
<p>最后确认我们的方法是否存在。如果存在就在显示器上打印出结果。</p>
<p>那么让Magento配置对象呼应我们的模块，接着访问我们的控制器。</p>
<h1>Step 4: Magento, we are here!（Magento，我们在这儿！）</h1>
<p>用下面的代码创建文件<strong>app/etc/modules/Alwayly_Xmlmethodcall.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;config&gt;
	&lt;modules&gt;
		&lt;Alwayly_XmlMethodCall&gt;
			&lt;active&gt;true&lt;/active&gt;
			&lt;codePool&gt;local&lt;/codePool&gt;
		&lt;/Alwayly_XmlMethodCall&gt;
	&lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<h1>Step 5: Visit something like: <strong>http://magento1510.loc/index.php/xmlmethodcall</strong>（访问类似http://magento1510.loc/index.php/xmlmethodcall的地址）</h1>
<p>你会看到类似这样的结果：</p>
<pre><code>ID: 101
VALUE: 100
CODE: a
 
ID: 102
VALUE: 102
CODE: b
 
ID: 101
VALUE: 200
CODE: a
Array
(
    [0] =&gt; Array
        (
            [order_no] =&gt; 101
            [method] =&gt; checkmo
            [amount] =&gt; 99
        )
 
    [1] =&gt; Array
        (
            [order_no] =&gt; 102
            [method] =&gt; ccsave
            [amount] =&gt; 100
        )
 
    [2] =&gt; Array
        (
            [order_no] =&gt; 101
            [method] =&gt; checkmo
            [amount] =&gt; 199
        )
 
)
</code></pre>
<p>我希望你们中的一些人能看到如何使用Varien_Object以及使用XPath表达式会让事情变得多么有趣。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 13 Oct 2015 10:42:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用*s实现通过Magento后台网格进行搜索]]></title>
      <link>https://www.360magento.com/blog/search-through-grids/</link>
      <description><![CDATA[<p>为什么在Magento后台列里搜索某些值时不能使用索引？（例如order#）</p>
<p>当你的网站有几个管理员的时候，这篇简短的文章将非常有用。我在一个项目中有超过2000个有不同角色的管理员（这个数字还在增长）。你可以想像下当大量管理员在使用后台时是有多慢，特别是他们在搜索或者为数据排序时。</p>
<p>2000名管理员对Magento来说是个大数字吗？取决于他们如何使用后台部分，但是他们中的大部分要排列东西，搜索些有时他们并不需要的东西。</p>
<p>在实现新功能前，我们做了一次测试。试图在Magento后台寻找你的销售订单网格中的#: 10。记住有多少搜索结果，花了多长时间。</p>
<p><strong>为什么通过Magento网格搜索花费如此大？</strong></p>
<p>因为当你在搜索语句两侧都使用Like语句时MySQL服务不能使用索引。记住MySQL（innodb）有B-Tree索引。</p>
<p>一个例子，当你想要找出所有使用gmail作为邮箱的客户。你可以搜索Magento后台客户网格的邮箱列，像&ldquo;@gmail&rdquo;这样。结果是你找出了所有的gmail邮箱地址。在这个过程中，MySQL浏览所有的客户行和所有的customer_email区域字符在你得到结果前。这种特殊的情况没什么问题，但是当你搜索订单#: 10001时呢？</p>
<p>同样的事情，因为Magento针对特定的列时，经常在你的字符串前后添加"%"。所以如果你想要搜索#: 10001订单，Magento会转换成&ldquo;%10001%&rdquo;并在你的字符串前加Like语句。所以在最后Magento会发送这样的语句到MySQL&ldquo;SELECT customer_email FROM&hellip;. WHERE customer_email LIKE &lsquo;%10001%';这可能不是你所期待的，但它就是这么实现的。</p>
<p>如果我们想要改变这种行为并给MySQL（Magento）索引提速。我们需要在后台网格搜索时做些改变。最通用和用户友好的方式就是使用"*"字符替换MySQL的特殊字符"%"。</p>
<p>现在如果你想要使用&ldquo;like&rdquo;操作符，你将需要在字符串前、后或两侧添加。所以在我们改变后，你讲能找到所有的gmail通过在你的字符串前后添加"*"。所以，&ldquo;@gmail&rdquo;将变成&ldquo;*@gmail*&rdquo;。我希望你能看到这背后的思想。</p>
<p>让我们用下面的内容替换<strong>app/code/core/Mage/Adminhtml/Block/Widget/Grid.php</strong>中的私有方法<strong>_addColumnFilterToCollection($column)</strong>。我们只影响sales_order网格。</p>
<pre><code>/**
 *
 */
protected function _addColumnFilterToCollection($column)
    {
       if ($this-&gt;getCollection()) {
           $field = ( $column-&gt;getFilterIndex() ) ? $column-&gt;getFilterIndex() : $column-&gt;getIndex();
           if ($column-&gt;getFilterConditionCallback()) {
               call_user_func($column-&gt;getFilterConditionCallback(), $this-&gt;getCollection(), $column);
           } else {
               $cond = $column-&gt;getFilter()-&gt;getCondition();
               /**  START WITH CODE FOR A NEW WAY OF SEARCHING
                * - if you look in app/code/core/Mage/Adminhtml/Block/Widget/Grid/Column/Filter/Abstract.php
                * - you'll see that -&gt;getCondition(); returns an array:
                * public function getCondition()
                * {
                *      return array('like'=&gt;'%'.$this-&gt;_escapeValue($this-&gt;getValue()).'%');
                * }
                * - and _escapeValue returns:
                * protected function _escapeValue($value)
                * {
                *     return str_replace('_', '\_', $value);
                * }
                * - so we'll "unescape" it in case where we have [$cond['eq'] and unset($cond['like']);]
                */
               if ($field &amp;&amp; isset($cond)) {
                   if($this-&gt;getAction() instanceof Mage_Adminhtml_Sales_OrderController) {
                       if (isset($cond['like'])) {
 
                           //cover case where like should go to equal; else means that we have at least one * so like should stay...
                           if (!(substr($cond['like'], -2) === '*%') &amp;&amp; !(substr($cond['like'], 0,2) === '%*')) {
                               $cond['eq'] = str_replace('%', '', $cond['like']);
                               $cond['eq'] = str_replace('\_', '_', $cond['eq']); //This line was added with new revision
                               unset($cond['like']);
                           } else {
                               if (substr($cond['like'], 0,2) !== '%*') {
                                   $cond['like'] = substr($cond['like'],1);
                               } else {
                                   $cond['like'] = '%' . substr($cond['like'],2);
                               }
                               if (substr($cond['like'], -2) !== '*%') {
                                   $cond['like'] = substr($cond['like'], 0, -1);
                               } else {
                                   $cond['like'] = substr($cond['like'], 0, -2) . '%';
                               }
                           }
                       }
                   }
                   /*END WITH CODE FOR A NEW WAY OF SEARCHING*/
                   $this-&gt;getCollection()-&gt;addFieldToFilter($field , $cond);
               }
           }
       }
       return $this;
    }
</code></pre>
<p>在我们改变Magento核心文件后，再次尝试搜索订单#: 10。现在你能看到多少结果？花了多长时间呢？Magento现在使用order#索引。现在你所能搜索的数字10的类型是：&ldquo;10&rdquo;, &ldquo;*10&Prime;, &ldquo;*10*&rdquo;和&ldquo;10*&rdquo;。注意，只有第一个是同等的，其它的使用了Like语句。</p>
<p>注意，你可以去掉&ldquo;<strong>if($this-&gt;getAction() instanceof Mage_Adminhtml_Sales_OrderController) { &hellip; }</strong>&rdquo;这个判断来将改变应用到整个后台。</p>
<p>你也可以选择重写<strong>Mage_Adminhtml_Block_Widget_Grid</strong>类而不是修改Magento核心文件。这个小技巧可以有效地提高我们客户的MySQL服务，</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 12 Oct 2015 12:09:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在单个店铺用所有语言和本地日期打印信息]]></title>
      <link>https://www.360magento.com/blog/print-languages-date/</link>
      <description><![CDATA[<p>你是否尝试过在单个页面用所有语言打印一条信息？</p>
<p>首先，让我来告诉你何时我需要这么做。最近我需要开发一个发送些定制邮件的功能。你已经知道我们可以在网站/店铺设置交易邮件并将这些邮件在administration/db翻译。我所要面对的挑战就是需要翻译一些交易邮件中的随机句子，所以使用预定义的模版是不可能的。在email模版我们是可以用and/or连接变量，但对我来说没什么帮助。</p>
<p>如果你安装的Magento社区版在1.4.2.0以上，那么我可以开始我们的翻译模块了。</p>
<ol>
<li>告诉Magento我们模块的信息；</li>
<li>创建模块结构；</li>
<li>编写config.xml；</li>
<li>编写Translate.php模型；</li>
<li>编写Locale.php模型；</li>
<li>编写Data.phph助手；</li>
<li>编写index.php。</li>
</ol>
<h2>1.用下面的代码创建app/etc/modules/Alwayly_Translation.xml:</h2>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
       &lt;Alwayly_Translate&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_Translate&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<h2>2.创建app/code/local/Alwayly/Translate下的文件夹: etc, controllers, Model, Helper</h2>
<h2>3.用下面的代码创建app/code/local/Alwayly/Translate/config.xml:</h2>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
 
	&lt;modules&gt;
		&lt;Alwayly_Translate&gt;
			&lt;version&gt;0.1.0&lt;/version&gt;
		&lt;/Alwayly_Translate&gt;
	&lt;/modules&gt;
 
	&lt;frontend&gt;
		&lt;routers&gt;
			&lt;Alwayly_Translate&gt;
				&lt;use&gt;standard&lt;/use&gt;
				&lt;args&gt;
					&lt;module&gt;Alwayly_Translate&lt;/module&gt;
					&lt;frontName&gt;Alwayly&lt;/frontName&gt;
				&lt;/args&gt;
			&lt;/Alwayly_Translate&gt;
		&lt;/routers&gt;
	&lt;/frontend&gt;
 
	&lt;global&gt;
		&lt;models&gt;
			&lt;Alwayly_translate&gt;
				&lt;class&gt;Alwayly_Translate_Model&lt;/class&gt;
			&lt;/Alwayly_translate&gt;
 
			&lt;core&gt;
				&lt;rewrite&gt;
					&lt;locale&gt;Alwayly_Translate_Model_Mage_Core_Model_Locale&lt;/locale&gt;
					&lt;translate&gt;Alwayly_Translate_Model_Mage_Core_Model_Translate&lt;/translate&gt;
				&lt;/rewrite&gt;
			&lt;/core&gt;
		&lt;/models&gt;
 
		&lt;helpers&gt;
			&lt;Alwayly_translate&gt;
				&lt;class&gt;Alwayly_Translate_Helper&lt;/class&gt;
			&lt;/Alwayly_translate&gt;
		&lt;/helpers&gt;
	&lt;/global&gt;
 
&lt;/config&gt;
</code></pre>
<p>如你所见，我们需要重写两个Magento模型。我们需要删除一个Translate模型中的if语句，在Locale模型中添加几个&ldquo;*ByLocaleCode&rdquo;方法，这样就可以在我们所有的Action里使用商店代码。</p>
<p>在助手文件中我们将添加方法处理日期（关于本地化）。因为当Magento初始化，一些请求会为特定的本地读取内存中的各种缓存。当你尝试想要做类似的事情：Mage::helper(&lsquo;core&rsquo;)-&gt;__(&ldquo;translate me&rdquo;)Magento将使用cache/memory。你可以看到：</p>
<pre><code>/**
 * Translate model
 *
 * @author      Magento Core Team &lt;core@magentocommerce.com&gt;
 */
class Mage_Core_Model_Translate
//...
 
/**
     * Return translated string from text.
     *
     * @param string $text
     * @param string $code
     * @return string
     */
    protected function _getTranslatedString($text, $code)
    {
        $translated = '';
        if (array_key_exists($code, $this-&gt;getData())) {
            $translated = $this-&gt;_data[$code];
        }
        elseif (array_key_exists($text, $this-&gt;getData())) {
            $translated = $this-&gt;_data[$text];
        }
        else {
            $translated = $text;
        }
        return $translated;
    }
</code></pre>
<h2>4.用下面的代码创建app/code/local/app/code/local/Alwayly/Translate/Model/Mage/Core/<br />Model/Locale.php/Translate/Model/Mage/Core/Model/Translate.php</h2>
<pre><code>&lt;?php
 
/**
 * Translate model
 *
 */
class Alwayly_Translate_Model_Mage_Core_Model_Translate extends Mage_Core_Model_Translate
{
     /**
     * Retrieve locale
     *
     * @return string
     */
    public function getLocale()
    {
		$this-&gt;_locale = Mage::app()-&gt;getLocale()-&gt;getLocaleCode();
		return $this-&gt;_locale;
	}
}
</code></pre>
<p>我们只是移除了getLocale()方法中的if语句。</p>
<h2>5.创建app/code/local/Alwayly/Translate/Model/Mage/Core/Model/Locale.php</h2>
<pre><code>&lt;?php
/**
 * Locale model
 * 
 */
 
class Alwayly_Translate_Model_Mage_Core_Model_Locale extends Mage_Core_Model_Locale
{
    /**
     * Create Zend_Date object with date converted to store timezone and store Locale
     *
     * @param   mixed $store Information about store
     * @param   string|integer|Zend_Date|array|null $date date in UTC
     * @param   boolean $includeTime flag for including time to date
     * @return  Zend_Date
     */
    public function getStoreDate($store=null, $date=null, $includeTime=false)
    {
        $timezone = Mage::app()-&gt;getStore($store)-&gt;getConfig(self::XML_PATH_DEFAULT_TIMEZONE);
        $locale = Mage::app()-&gt;getStore($store)-&gt;getConfig(self::XML_PATH_DEFAULT_LOCALE);
        $date = new Zend_Date($date, null, $locale);
        $date-&gt;setTimezone($timezone);
        if (!$includeTime) {
            $date-&gt;setHour(0)
                -&gt;setMinute(0)
                -&gt;setSecond(0);
        }
        return $date;
    }
 
    /**
	 * Returns a localized information string, supported are several types of informations.
	 * For detailed information about the types look into the documentation
	 *
	 * @param  string             $value  Name to get detailed information about
	 * @param  string             $path   (Optional) Type of information to return
	 * @return string|false The wished information in the given language
	 */
	public function getTranslationByLocaleCode($value = null, $path = null, $localeCode = null)
	{
		return $this-&gt;getLocale()-&gt;getTranslation($value, $path, $localeCode/*$this-&gt;getLocale()*/);
	}
	/**
	 * Retrieve ISO date format
	 *
	 * @param   string $type
	 * @return  string
	 */
	public function getDateFormatByLocaleCode($type=null, $localeCode)
	{
		return $this-&gt;getTranslationByLocaleCode($type, 'date', $localeCode);
	}
 
	/**
	 * Retrieve ISO time format
	 *
	 * @param   string $type
	 * @return  string
	 */
	public function getTimeFormatByLocaleCode($type=null, $localeCode)
	{
		return $this-&gt;getTranslationByLocaleCode($type, 'time', $localeCode);
	}
 
	/**
	 * Retrieve ISO datetime format
	 *
	 * @param   string $type
	 * @return  string
	 */
	public function getDateTimeFormatByLocaleCode($type, $localeCode)
	{
		return $this-&gt;getDateFormatByLocaleCode($type, $localeCode) . ' ' . $this-&gt;getTimeFormatByLocaleCode($type, $localeCode);
	}
}
</code></pre>
<p>注意，我添加了几个&ldquo;*ByLocaleCode&rdquo; 方法，这样能使得Magento核心文件不被修改。</p>
<h2>6、创建助手文件在app/code/local/Alwayly/Translate/Helper/Data.php</h2>
<pre><code>&lt;?php
 
/**
 * Translate helper
 *
 */
class Alwayly_Translate_Helper_Data extends Mage_Core_Helper_Abstract
{
 
	/**
	 * Format date using specifed locale
	 *
	 * @param   date|Zend_Date|null $date in GMT timezone
	 * @param   string $format
	 * @param   bool $showTime
	 * @return  string
	 */
	public function formatDateByLocaleCode($date=null, $format='short', $showTime=false, $localeCode=null)
	{
		if ($localeCode === null || !is_string($localeCode)) {
			$localeCode = Mage::getStoreConfig('general/locale/code');
		}
		if (Mage_Core_Model_Locale::FORMAT_TYPE_FULL    	!==$format &amp;&amp;
				Mage_Core_Model_Locale::FORMAT_TYPE_LONG    !==$format &amp;&amp;
				Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM  !==$format &amp;&amp;
				Mage_Core_Model_Locale::FORMAT_TYPE_SHORT   !==$format) {
			return $date;
		}
		if (!($date instanceof Zend_Date) &amp;&amp; $date &amp;&amp; !strtotime($date)) {
			return '';
		}
		if (is_null($date)) {
			$date = Mage::app()-&gt;getLocale()-&gt;date(Mage::getSingleton('core/date')-&gt;gmtTimestamp(), null, null);
		}
		elseif (!$date instanceof Zend_Date) {
			$date = Mage::app()-&gt;getLocale()-&gt;date(strtotime($date), null, null, $showTime);
		}
 
		if ($showTime) {
			$format = Mage::app()-&gt;getLocale()-&gt;getDateTimeFormatByLocaleCode($format, $localeCode);
		}
		else {
			$format = Mage::app()-&gt;getLocale()-&gt;getDateFormatByLocaleCode($format, $localeCode);
		}
		return $date-&gt;toString($format);
	}
}
</code></pre>
<p>注意，我们最后在if/else判断里调用-&gt;getDate(Time/Format)ByLocaleCode方法来替换我们的Locale模型。</p>
<h2>7、创建控制器文件app/code/local/Alwayly/Translate/controllers/IndexController.php</h2>
<pre><code>&lt;?php
 
/**
 * http://films.local/index.php/ExpiringFilmsNotifier/index/notify
 */
class Alwayly_Translate_IndexController extends Mage_Core_Controller_Front_Action
{
    public function translateAction()
    {
    	echo "</code></pre>
<pre>";
 
    	$defaultStore = Mage::app()-&gt;getStore()-&gt;getCode();
    	$defaultLocale = Mage::app()-&gt;getLocale()-&gt;getLocaleCode();
    	$stores = array(1,2,3);
 
    	foreach ($stores as $storeId) {
    		Mage::app()-&gt;setCurrentStore($storeId);
    		$currentStore 	= Mage::app()-&gt;getStore()-&gt;getCode();
    		$currentLocale 	= Mage::getModel('core/locale')-&gt;getLocaleCode();
    		Mage::app()-&gt;getLocale()-&gt;setLocale($currentLocale);
    		// reinitialize translation cache
    		Mage::app()-&gt;getTranslator()-&gt;init('frontend', true);
 
    		echo Mage::helper('core')-&gt;__("Welcome, %s!", Mage::helper('alwayly_translate')
    			-&gt;formatDateByLocaleCode('2012-05-05 00:00:00', 'medium', false, $currentLocale))  . PHP_EOL;
    	}
    	//restore app to default values
    	Mage::app()-&gt;setCurrentStore($defaultStore);
    	Mage::app()-&gt;getLocale()-&gt;setLocale($defaultLocale);
    	Mage::app()-&gt;getTranslator()-&gt;init('frontend', true);
 
    	echo 'Did system restore default initialization?' . PHP_EOL;
    	echo Mage::helper('core')-&gt;__("Welcome, %s!", Mage::helper('alwayly_translate')
    			-&gt;formatDateByLocaleCode('2012-05-05 00:00:00', 'medium', false, $currentLocale))  . PHP_EOL;
    	exit;
    }
}
</pre>
<p>注意，我们先创建了两个变量$defaultStore和$defaultLocale，这样我妈就可以在customer页面回复Magento自定义。如果你有三个店铺确认为它们设置了本地化。</p>
<p>我在in app/etc/locale/de_DE/和app/etc/locale/fr_FR/ 创建了Mage_Page.csv ，代码如下：</p>
<pre><code>For German:
&ldquo;Welcome, %s!&rdquo;,&rdquo;de_DE Welcome, %s!&rdquo;
For France :
&ldquo;Welcome, %s!&rdquo;,&rdquo;fr_FR Welcome, %s!&rdquo;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 12 Oct 2015 11:49:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[编程的方式创建，应用和删除Magento中的购物车价格规则]]></title>
      <link>https://www.360magento.com/blog/price-rule-magento/</link>
      <description><![CDATA[<p>默认的Magento中有个很棒的功能叫做&ldquo;促销&rdquo;。有两种类型的促销：目录价格跪着和购物车价格规则。这篇文章中我将演示如何以编程的方式来创建，应用和删除购物车价格规则。</p>
<p>有很多理由让你使用它。例如：你想模拟某种奖励功能，对达到要求的客户进行打折。除非正在使用Magento　EE就不用了（带有奖励积分的功能），那么你将编写代码或者购买第三方插件。我个人不太喜欢用第三方插件，除非它是必须的或者能达到功能需求的90-95%。否则你将花费时间在修改插件上。让我们看看我们如何自己实现这个功能。一种方式是用代码粉方式创建和应用购物车价格规则，然后在执行的时候删除购物车价格规则。</p>
<p>首先，我们创建购物车价格规则。我们将以手动创建一个规则，然后学习后台进程来以编程的方式来复制它。我们将进入Magento后台，在&ldquo;Promotions &gt; Shopping Cart Price Rules&rdquo;下，点击&ldquo;Add New Rule&rdquo;右上角按钮。在这个例子中，我们将限制一个客户每次只能使用一个优惠券。我们填上必须字段并用POST变量提交数据，最后的url会像这样：http://shop.net/index.php/admin/promo_quote/save/</p>
<pre><code>form_key =&gt; YYhUwcLXX6sezYPY
product_ids =&gt; 
name =&gt; CUSTOMER_1 - 30% Summer discount
description =&gt; 
is_active =&gt; 1
website_ids[] =&gt; 1
customer_group_ids[] =&gt; 3
coupon_type =&gt; 2
coupon_code =&gt; leIYc4g1dbCCOlT1
uses_per_coupon =&gt; 1
uses_per_customer =&gt; 1
from_date =&gt; 
to_date =&gt; 
sort_order =&gt; 
is_rss =&gt; 1
rule[conditions][1][type] =&gt; salesrule/rule_condition_combine
rule[conditions][1][aggregator] =&gt; all
rule[conditions][1][value] =&gt; 1
rule[conditions][1][new_child] =&gt; 
simple_action =&gt; by_percent
discount_amount =&gt; 30
discount_qty =&gt; 0
discount_step =&gt; 
apply_to_shipping =&gt; 0
simple_free_shipping =&gt; 0
stop_rules_processing =&gt; 0
rule[actions][1][type] =&gt; salesrule/rule_condition_product_combine
rule[actions][1][aggregator] =&gt; all
rule[actions][1][value] =&gt; 1
rule[actions][1][new_child] =&gt; 
store_labels[0] =&gt; 
store_labels[1] =&gt; 
</code></pre>
<p>现在，如果我们研究http://shop.net/index.php/admin/promo_quote/save/ 后面的Mage_Adminhtml_Promo_QuoteController -&gt; saveAction()，我们可以看到规则的创建：</p>
<pre><code>$data = array(
    'product_ids' =&gt; null,
    'name' =&gt; sprintf('AUTO_GENERATION CUSTOMER_%s - 30%% Summer discount', Mage::getSingleton('customer/session')-&gt;getCustomerId()),
    'description' =&gt; null,
    'is_active' =&gt; 1,
    'website_ids' =&gt; array(1),
    'customer_group_ids' =&gt; array(1),
    'coupon_type' =&gt; 2,
    'coupon_code' =&gt; Mage::helper('core')-&gt;getRandomString(16),
    'uses_per_coupon' =&gt; 1,
    'uses_per_customer' =&gt; 1,
    'from_date' =&gt; null,
    'to_date' =&gt; null,
    'sort_order' =&gt; null,
    'is_rss' =&gt; 1,
    'rule' =&gt; array(
        'conditions' =&gt; array(
            array(
                'type' =&gt; 'salesrule/rule_condition_combine',
                'aggregator' =&gt; 'all',
                'value' =&gt; 1,
                'new_child' =&gt; null
            )
        )
    ),
    'simple_action' =&gt; 'by_percent',
    'discount_amount' =&gt; 30,
    'discount_qty' =&gt; 0,
    'discount_step' =&gt; null,
    'apply_to_shipping' =&gt; 0,
    'simple_free_shipping' =&gt; 0,
    'stop_rules_processing' =&gt; 0,
    'rule' =&gt; array(
        'actions' =&gt; array(
            array(
                'type' =&gt; 'salesrule/rule_condition_product_combine',
                'aggregator' =&gt; 'all',
                'value' =&gt; 1,
                'new_child' =&gt; null
            )
        )
    ),
    'store_labels' =&gt; array('30% Summer discount')
);
 
$model = Mage::getModel('salesrule/rule');
$data = $this-&gt;_filterDates($data, array('from_date', 'to_date'));
 
$validateResult = $model-&gt;validateData(new Varien_Object($data));
 
if ($validateResult == true) {
 
    if (isset($data['simple_action']) &amp;&amp; $data['simple_action'] == 'by_percent'
            &amp;&amp; isset($data['discount_amount'])) {
        $data['discount_amount'] = min(100, $data['discount_amount']);
    }
 
    if (isset($data['rule']['conditions'])) {
        $data['conditions'] = $data['rule']['conditions'];
    }
 
    if (isset($data['rule']['actions'])) {
        $data['actions'] = $data['rule']['actions'];
    }
 
    unset($data['rule']);
 
    $model-&gt;loadPost($data);
 
    $model-&gt;save();
}
</code></pre>
<p>上面涵盖了&ldquo;create&rdquo;部分，现在让我们转到应用部分。想法是：在执行chechout之前以编程的方式来应用优惠券。如果我们在像http://shop.net/checkout/cart/这样的url里应用优惠券，表单可能提交数据到http://shop.net/checkout/cart/couponPost/的controller动作。</p>
<p>提交数据非常简单：</p>
<pre><code>remove =&gt; 0
coupon_code =&gt; da4K53cGuhNoTc10
</code></pre>
<p>现在，让我们看看http://shop.net/checkout/cart/couponPost/后面的controller动作。我们要看得更远点，我们将先寻找之前我们创建的特殊规则名。当筛选出特殊的数据check等等时。你留下类似&ldquo;apply Shopping Cart Price Rule&rdquo;代码的东西。</p>
<pre><code>/* START This part is my extra, just to load our coupon for this specific customer */
$model = Mage::getModel('salesrule/rule')
        -&gt;getCollection()
        -&gt;addFieldToFilter('name', array('eq'=&gt;sprintf('AUTO_GENERATION CUSTOMER_%s - 30%% Summer discount', Mage::getSingleton

('customer/session')-&gt;getCustomerId())))
        -&gt;getFirstItem();
 
$couponCode = $model-&gt;getCouponCode();
/* END This part is my extra, just to load our coupon for this specific customer */
 
Mage::getSingleton('checkout/cart')
    -&gt;getQuote()
    -&gt;getShippingAddress()
    -&gt;setCollectShippingRates(true);
 
Mage::getSingleton('checkout/cart')
    -&gt;getQuote()
    -&gt;setCouponCode(strlen($couponCode) ? $couponCode : '')
    -&gt;collectTotals()
    -&gt;save();
</code></pre>
<p>现在我们需要做的就是这个代码转移到合适的位置，像事件观察。最后一旦客户结账完成，我们就用一个简单的代码删除这个规则。</p>
<pre><code>$model = Mage::getModel('salesrule/rule')
        -&gt;getCollection()
        -&gt;addFieldToFilter('name', array('eq'=&gt;sprintf('AUTO_GENERATION CUSTOMER_%s - 30%% Summer discount', Mage::getSingleton('customer/session')-&gt;getCustomerId())))
        -&gt;getFirstItem();
 
$model-&gt;delete();
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 11 Oct 2015 15:44:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento前台隐藏送货方式，但在后台保留]]></title>
      <link>https://www.360magento.com/blog/hide-shipping-method/</link>
      <description><![CDATA[<p>对于你们中的某些人，这可能是个惊喜，但是Magento不支持在前台禁止Magento方法但在后台保留。你也许可以做些调整配置来达到效果，但那不是100%正确的。虽然Magento支持&ldquo;global/website/store&rdquo;设置，在全球和网站级别，运输方法被打开或者关闭。在商店级别，你可以简单的编辑运输方式的title和其它东西，但你不能打开/关闭运输方式。</p>
<p>现在，想像下你Magento系统里只有一个网站，如果你在后台&ldquo;Sales &gt; Orders&rdquo;点击&ldquo;Create New Order&rdquo;按钮。下面你将看到&ldquo;please select a customer&rdquo;来选择你想要创建订单的客户。但当你的Magento系统中有两个或更多网站时，你在后台&ldquo;Sales &gt; Orders&rdquo;点击&ldquo;Create New Order&rdquo;按钮，下一个出来的就是&ldquo;please select a website&rdquo; ，之后才会看到&ldquo;please select a customer&rdquo;。这意味着Magento使用默认的网站或者你选择的网站来创建用户订单。无论哪种方式，它都从网站读取配置和运输数据。这意味着这种设置没办法在后台只显示某某运输方式&hellip;&hellip;</p>
<p>我们如何绕过这点？简单，只需要重写Mage_Shipping_Model_Config和Mage_Sales_Model_Quote_Address。注意，这不一定是最好或者最优的方法，但却是一个可行的方法。</p>
<p><strong>app/code/local/Mycompany/Myextension/etc/config.xml</strong></p>
<pre><code>&lt;models&gt;
    &lt;shipping&gt;
        &lt;rewrite&gt;
            &lt;config&gt;Mycompany_Myextension_Model_Shipping_Config&lt;/config&gt;
        &lt;/rewrite&gt;                
    &lt;/shipping&gt;
    &lt;sales&gt;
        &lt;rewrite&gt;
            &lt;quote_address&gt;Mycompany_Myextension_Model_Sales_Quote_Address&lt;/quote_address&gt;
        &lt;/rewrite&gt;
    &lt;/sales&gt;
&lt;/models&gt;
</code></pre>
<p><strong>app/code/local/Mycompany/Myextension/Model/Adminhtml/System/Config/Source/Shipping/Methods.php</strong></p>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Model_Adminhtml_System_Config_Source_Shipping_Methods 
{
    protected $_options;
 
    public function toOptionArray()
    {
        $carriers = Mage::getSingleton('shipping/config')-&gt;getAllCarriers();
 
        $carriersActive = Mage::getSingleton('shipping/config')-&gt;getActiveCarriers();
        $carriersActive = array_keys($carriersActive);
 
        if (!$this-&gt;_options) {
            foreach ($carriers as $carrier) {
                $carrierCode = $carrier-&gt;getId();
                $carrierTitle = Mage::getStoreConfig('carriers/'.$carrierCode.'/title', Mage::app()-&gt;getStore()-&gt;getId());
                $carrierTitle = trim($carrierTitle);
 
                if (empty($carrierTitle)) {
                    continue;
                }
 
                if (in_array($carrierCode, $carriersActive)) {
                    $carrierTitle = sprintf('%s (currently active)', $carrierTitle);
                } else {
                    $carrierTitle = sprintf('%s (currently inactive)', $carrierTitle);
                }
 
                $this-&gt;_options[] = array('value'=&gt;$carrierCode, 'label'=&gt;$carrierTitle);
            }
        }
 
        $options = $this-&gt;_options;
 
        array_unshift($options, array('value'=&gt;'', 'label'=&gt; ''));
 
        return $options;
    }
}
</code></pre>
<p>这个文件被systemxml的&ldquo;source_model&rdquo;定义调用</p>
<pre><code>&lt;fields&gt;
    &lt;frontend_hidden_methods&gt;
        &lt;label&gt;Hide Shipping Methods on Frontend&lt;/label&gt;
        &lt;comment&gt;<![CDATA[If a shipping method has been enabled under its settings, you can choose to hide it on the frontend by selecting it here from the list. This way, the shipping method would be available from the admin area but not from the frontend.]]]]><![CDATA[>&lt;/comment&gt;
        &lt;frontend_type&gt;multiselect&lt;/frontend_type&gt;
        &lt;source_model&gt;mycompany_myextension/adminhtml_system_config_source_shipping_methods&lt;/source_model&gt;
        &lt;sort_order&gt;2&lt;/sort_order&gt;
        &lt;show_in_default&gt;1&lt;/show_in_default&gt;
        &lt;show_in_website&gt;1&lt;/show_in_website&gt;
        &lt;show_in_store&gt;1&lt;/show_in_store&gt;
    &lt;/frontend_hidden_methods&gt;
&lt;/fields&gt;
</code></pre>
<p>注意！上面的system.xml只是部分的，只用于实际字段的配置定义。</p>
<p><strong>app/code/local/Mycompany/Myextension/Helper/Data.php</strong></p>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Helper_Data extends Mage_Core_Helper_Abstract
{
    const CONFIG_PATH_HIDE_FRONTEND_SHIPPING_METHODS = 'some-path-to-system-xml-field';
 
    public function getHiddenFrontendShippingMethods()
    {
        $methods = Mage::getStoreConfig(self::CONFIG_PATH_HIDE_FRONTEND_SHIPPING_METHODS);
        $methods = explode(',', $methods);
 
        return $methods;
    }
}
</code></pre>
<p><strong>app/code/local/Mycompany/Myextension/Model/Shipping/Config.php</strong></p>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Model_Shipping_Config extends Mage_Shipping_Model_Config
{
    public function getActiveCarriers($store = null)
    {
        $carriers = parent::getActiveCarriers($store);
 
        if (Mage::getDesign()-&gt;getArea() === Mage_Core_Model_App_Area::AREA_FRONTEND) {
 
            $carriersCodes = array_keys($carriers);
            $hiddenShippingMethods = Mage::helper('mycompany_myextension')-&gt;getHiddenFrontendShippingMethods();
 
            foreach ($carriersCodes as $carriersCode) {
                if (in_array($carriersCode, $hiddenShippingMethods)) {
                    unset($carriers[$carriersCode]);
                }
            }            
        }
 
        return $carriers;
    }
}
</code></pre>
<p><strong>app/code/local/Mycompany/Myextension/Model/Sales/Quote/Address.php</strong></p>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Model_Sales_Quote_Address extends Mage_Sales_Model_Quote_Address
{
    public function getShippingRatesCollection()
    {
        parent::getShippingRatesCollection();
 
        $hiddenFrontendShippingMethods = Mage::helper('mycompany_myextension')-&gt;getHiddenFrontendShippingMethods();
 
        $removeRates = array();
 
        foreach ($this-&gt;_rates as $key =&gt; $rate) {
            if (in_array($rate-&gt;getCarrier(), $hiddenFrontendShippingMethods)) {
                $removeRates[] = $key;
            }   
        }
 
        foreach ($removeRates as $key) {
            $this-&gt;_rates-&gt;removeItemByKey($key);
        }
 
        return $this-&gt;_rates;
    }
}
</code></pre>
<p>基本上就是这样了。现在你的后台里有了多选框来选择特定的方法在前台隐藏后台保留。记住，运输方式必须是开启的，不要和启用/禁止&ldquo;hide on frontend&rdquo;相混淆。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 11 Oct 2015 15:39:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中自定义路由器]]></title>
      <link>https://www.360magento.com/blog/custom-router-magento/</link>
      <description><![CDATA[<p>当我们想要分开同一路由的一些业务逻辑而又不想重定向到控制器里的其它路由时，创建自定义路由器是非常有的。</p>
<p>为什么我们不为不同的逻辑创建分开的独立的路由呢？</p>
<p>我来稍微解释下：我结合一个我们项目中的OneStepCheckout插件（已经重写了Core Checkout路由）来谈下。我需要重写路由，根据URL中的字段将它们分到两个不同的控制器中。我发现最好的方法就是创建一个新的路由器重定向到由字段决定的不同控制器。</p>
<p>在&ldquo;&hellip;/app/code/local/Mynamespace/Myextension/etc/config.xml&rdquo;创建我们自己的路由器</p>
<pre><code>&lt;default&gt;
    &lt;web&gt;
      &lt;routers&gt;
         &lt;myextension_myrouter&gt;
             &lt;area&gt;frontend&lt;/area&gt;
             &lt;class&gt;Mynamespace_Myextension_Controller_Router&lt;/class&gt;
         &lt;/myextension_myrouter&gt;
     &lt;/routers&gt;
    &lt;/web&gt;
   &lt;/default&gt;
 &lt;/stores&gt;
</code></pre>
<p>在 &ldquo;&hellip;/app/code/local/Mynamespace/Myextension&rdquo;新建Controller文件夹，在文件夹里新建Mynamespace_Myextension_Controller_Router.php文件：</p>
<pre><code>&lt;?php
//Mynamespace_Myextension_Controller_Router.php
 
/**
 * Router for deciding to go on party checkout or regular onestepcheckout
 */
class Mynemaspace_Myextension_Controller_Router extends 

Mage_Core_Controller_Varien_Router_Standard {
 
 
}
?&gt;
</code></pre>
<p>拷贝Mage_Core_Controller_Varien_Router_Standard.php中对应的方法到我们的类，进行修改：</p>
<pre><code>/**
     * Match the request
     *
     * @param Zend_Controller_Request_Http $request
     * @return boolean
     */
    public function match(Zend_Controller_Request_Http $request)
    {
        //checking before even try to find out that current module
        //should use this router
        if (!$this-&gt;_beforeModuleMatch()) {
            return false;
        }
 
        $this-&gt;fetchDefault();
 
        $front = $this-&gt;getFront();
        $path = trim($request-&gt;getPathInfo(), '/');
 
        if ($path) {
            $p = explode('/', $path);
        } else {
            $p = explode('/', $this-&gt;_getDefaultPath());
        }
 
        // get module name
        if ($request-&gt;getModuleName()) {
            $module = $request-&gt;getModuleName();
        } else {
            if (!empty($p[0])) {
                $module = $p[0];
            } else {
                $module = $this-&gt;getFront()-&gt;getDefault('module');
                $request-&gt;setAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, '');
            }
        }
        if (!$module) {
            if (Mage::app()-&gt;getStore()-&gt;isAdmin()) {
                $module = 'admin';
            } else {
                return false;
            }
        }
 
        /**
         * Searching router args by module name from route using it as key
         */
        $modules = $this-&gt;getModuleByFrontName($module);
 
        if ($modules === false) {
            return false;
        }
 
        //checkings after we foundout that this router should be used for current module
        if (!$this-&gt;_afterModuleMatch()) {
            return false;
        }
 
        /**
         * Going through modules to find appropriate controller
         */
        $found = false;
        foreach ($modules as $realModule) {
            $request-&gt;setRouteName($this-&gt;getRouteByFrontName($module));
 
            // get controller name
            if ($request-&gt;getControllerName()) {
                $controller = $request-&gt;getControllerName();
            } else {
                if (!empty($p[1])) {
                    $controller = $p[1];
                } else {
                    $controller = $front-&gt;getDefault('controller');
                    $request-&gt;setAlias(
                        Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
                        ltrim($request-&gt;getOriginalPathInfo(), '/')
                    );
                }
            }
 
            // get action name
            if (empty($action)) {
                if ($request-&gt;getActionName()) {
                    $action = $request-&gt;getActionName();
                } else {
                    $action = !empty($p[2]) ? $p[2] : $front-&gt;getDefault('action');
                }
            }
 
            //checking if this place should be secure
            $this-&gt;_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action);
 
            $controllerClassName = $this-&gt;_validateControllerClassName($realModule, $controller);
            if (!$controllerClassName) {
                continue;
            }
 
            // instantiate controller class
            $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, 

$front-&gt;getResponse());
 
            if (!$controllerInstance-&gt;hasAction($action)) {
                continue;
            }
 
            $found = true;
            break;
        }
 
        /**
         * if we did not found any siutibul
         */
        if (!$found) {
            if ($this-&gt;_noRouteShouldBeApplied()) {
                $controller = 'index';
                $action = 'noroute';
 
                $controllerClassName = $this-&gt;_validateControllerClassName($realModule, 

$controller);
                if (!$controllerClassName) {
                    return false;
                }
 
                // instantiate controller class
                $controllerInstance = Mage::getControllerInstance($controllerClassName, $request,
                    $front-&gt;getResponse());
 
                if (!$controllerInstance-&gt;hasAction($action)) {
                    return false;
                }
            } else {
                return false;
            }
        }
 
        // set values only after all the checks are done
        $request-&gt;setModuleName($module);
        $request-&gt;setControllerName($controller);
        $request-&gt;setActionName($action);
        $request-&gt;setControllerModule($realModule);
 
        // set parameters from pathinfo
        for ($i = 3, $l = sizeof($p); $i &lt; $l; $i += 2) {
            $request-&gt;setParam($p[$i], isset($p[$i+1]) ? urldecode($p[$i+1]) : '');
        }
 
        // dispatch action
        $request-&gt;setDispatched(true);
        $controllerInstance-&gt;dispatch($action);
 
        return true;
    }
</code></pre>
<p>例如，现在我想重定向路由到&ldquo;Party&rdquo;控制器。我们可以给控制器名添加前缀。一般控制器是：Mynamespace/Myextension/controllers/Somecontrollername.php，&ldquo;Party&rdquo;控制器就是：Mynamespace/Myextension/controllers/Party/Somecontrollername.php。要实现这个，那么我们需要在上面代码的57行到62行之间添加些代码：</p>
<pre><code>$party_prefix = '';
 
        if ($this-&gt;isPartyOrder($request)) {
            foreach ($modules as $key =&gt; $realModule) {
                $modules[$key].='_Party';
            }
 
            $party_prefix = '_party';
        }
</code></pre>
<p>当然，我们的isParty方法是这样的：</p>
<pre><code>..
    /**
     * Determine if order is "Party order"
     * @param Mage_Core_Controller_Request_Http $request
     * @return boolean
     */
    private function isPartyOrder($request) {
 
        if (isset($_SESSION['is_party_checkout']) &amp;&amp; $_SESSION['is_party_checkout']) {
            return true;
        }
 
        $pathInfo = $request-&gt;getPathInfo();
 
        if (stristr($pathInfo, 'onestepcheckout/index/index')) {
            $params = Mage::app()-&gt;getRequest()-&gt;getParams();
            if (isset($params['id'])) {
                return true;
            }
        }
 
        return false;
    }
..
</code></pre>
<p>这里，我们检查Party是否在session或者URL的GET参数里。</p>
<p>下一步，让我们修改一个将被layout.xml文件使用的路由名，替换这段代码</p>
<pre><code>/**
         * Going through modules to find appropriate controller
         */
        $found = false;
        foreach ($modules as $realModule) {
            $request-&gt;setRouteName($this-&gt;getRouteByFrontName($module));
</code></pre>
<p>为</p>
<pre><code>//...
        /**
         * Going through modules to find appropriate controller
         */
        $found = false;
        foreach ($modules as $realModule) {
            $request-&gt;setRouteName('ourextension_' . $this-&gt;getRouteByFrontName($module) . 

$party_prefix);
        ...
//...
</code></pre>
<p>现在我们可以在布局xml文件里定义布局句柄来将&ldquo;Party&rdquo; 和其它路由区分开。</p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;layout version="0.1.0"&gt;
    &lt;&lt;ourmodule_controllername_actionname&gt;
      &lt;block ....... some layout updates ... etc
    &lt;/ourmodule_controllername_actionname&gt;
 
   &lt;ourmodule_party_controllername_actionname&gt;
      &lt;block ....... some different layout updates ... etc
   &lt;/ourmodule_party_controllername_actionname&gt;
&lt;/layout&gt;
</code></pre>
<p>这样我们就可以单独实现两种完全不同的布局。这只是个简单的例子来创建和修改路由器。你可以定制自己的路由器来实现你的需求。</p>
<p>下面让我们看看onestepcheckout的config.xml文件，看它的路由器是如何设置模块的：</p>
<pre><code>&lt;frontend&gt;
        &lt;routers&gt;
            &lt;onestepcheckout&gt;
                &lt;use&gt;myextension_myrouter&lt;/use&gt;
                &lt;args&gt;
                   &lt;modules&gt;
                        &lt;Mynamespace_Mymodule before="Idev_OneStepCheckout"&gt;Mynamespace_Mymodule_Onestepcheckout&lt;/Mynamespace_Mymodule&gt;
                    &lt;/modules&gt;
                &lt;/args&gt;
            &lt;/onestepcheckout&gt;
        &lt;/routers&gt;
</code></pre>
<p>Onestepcheckout模块重写一些Magento核心路由，这样当客户访问checkout/onepage地址时，他们会得到 onestepcheckout地址。</p>
<p>当我们创建像上面的自定义路由器时，客户仍然会访问onestepcheckout路由，但会根据isParty的判断结果来执行不同的控制器。</p>
<p>由于同样的URL分为Party和regular支付，我们在路由里为每个支付状态(Party and regular) 设置自定义路由名而更新xml句柄。</p>
<p>虽然第一次读起来可能会有些乱，但我希望在某些人的项目，插件和定制中起到作用。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 10 Oct 2015 13:11:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ 在Magento的销售网格中添加“用户组”列]]></title>
      <link>https://www.360magento.com/blog/customer-group-sales/</link>
      <description><![CDATA[<p>令人惊讶的是Magento后台的&ldquo;Sales &gt; Orders&rdquo;和&ldquo;Sales &gt; Orders &gt; Create New Order&rdquo; 网格里没有&ldquo;用户组&rdquo;这一列。为什么我们需要这一列呢？也许你需要在网格中列出/筛选&ldquo;经销商&rdquo;组支付的订单。也许你能够筛选 &ldquo;Sales &gt; Orders &gt; Create New Order&rdquo; 网格通过在创建订单前的用户组来查看&ldquo;经销商&rdquo;客户数量。</p>
<p>默认情况下&ldquo;Sales &gt; Orders&rdquo; 网格使用&ldquo;sales_flat_order_grid&rdquo;进行渲染。这个表基本上是&ldquo;sales_flat_order&rdquo;表的冗余子组。令人惊讶的是&ldquo;sales_flat_order&rdquo; 表里有&ldquo;customer_group_id&rdquo;列，而&ldquo;sales_flat_order_grid&rdquo;表中没有。所以我们第一步就是要添加&ldquo;customer_group_id&rdquo;列到&ldquo;sales_flat_order_grid&rdquo;表中。</p>
<p>我们通过一个类似这样的简单升级脚本来实现：</p>
<pre><code>$installer-&gt;getConnection()
        -&gt;addColumn($installer-&gt;getTable('sales/order_grid'), 'customer_group_id', array(
            'TYPE' =&gt; Varien_Db_Ddl_Table::TYPE_SMALLINT,
            'NULLABLE'  =&gt; false,
            'DEFAULT'   =&gt; '0',
            'COMMENT' =&gt; 'Customer Group'
        ));
</code></pre>
<p>如果这个安装/升级脚本执行成功，我们就会在&ldquo;sales_flat_order_grid&rdquo;表中看到&ldquo;customer_group_id&rdquo;列。注意，Magento会在新订单保存时自动填充&ldquo;sales_flat_order_grid.customer_group_id&rdquo;中的数据。</p>
<p>然后我们将重写Mage_Adminhtml_Block_Sales_Order_Grid和Mage_Adminhtml_Block_Sales_Order_Create_Customer_Grid。但只做些小的修改来让我们的&ldquo;Customer Group&rdquo;显示。</p>
<p>我们通过config.xml来添加合适的入口：</p>
<pre><code>&lt;global&gt;
    &lt;blocks&gt;
        &lt;adminhtml&gt;
            &lt;rewrite&gt;      &lt;sales_order_create_customer_grid&gt;Mycompany_Myextension_Block_Adminhtml_Sales_Order_Create_Customer_Grid&lt;/sales_order_create_customer_grid&gt;
                &lt;sales_order_grid&gt;Mycompany_Myextension_Block_Adminhtml_Sales_Order_Grid&lt;/sales_order_grid&gt;
            &lt;/rewrite&gt;
        &lt;/adminhtml&gt;
    &lt;/blocks&gt;
&lt;/global&gt;
</code></pre>
<p>最后，添加重写模块</p>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid 
{
    protected function _prepareColumns()
    {
        $groups = Mage::getResourceModel('customer/group_collection')
            -&gt;addFieldToFilter('customer_group_id', array('gt'=&gt; 0))
            -&gt;load()
            -&gt;toOptionHash();
 
        $this-&gt;addColumn('customer_group_id', array(
            'header'    =&gt;  Mage::helper('customer')-&gt;__('Customer Group'),
            'width'     =&gt;  '100',
            'index'     =&gt;  'customer_group_id',
            'type'      =&gt;  'options',
            'options'   =&gt;  $groups,
        ));
 
        $this-&gt;addColumnsOrder('customer_group_id', 'shipping_name');
 
        return parent::_prepareColumns();
    }
}
</code></pre>
<pre><code>&lt;?php
 
class Mycompany_Myextension_Block_Adminhtml_Sales_Order_Create_Customer_Grid extends 

Mage_Adminhtml_Block_Sales_Order_Create_Customer_Grid
{
    protected function _prepareColumns()
    {
        $groups = Mage::getResourceModel('customer/group_collection')
            -&gt;addFieldToFilter('customer_group_id', array('gt'=&gt; 0))
            -&gt;load()
            -&gt;toOptionHash();
 
        $this-&gt;addColumn('group', array(
            'header'    =&gt;  Mage::helper('customer')-&gt;__('Group'),
            'width'     =&gt;  '100',
            'index'     =&gt;  'group_id',
            'type'      =&gt;  'options',
            'options'   =&gt;  $groups,
        ));
 
        $this-&gt;addColumnsOrder('group', 'email');
 
        return parent::_prepareColumns();
    }
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 10 Oct 2015 12:52:38 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中创建简单的社交链接]]></title>
      <link>https://www.360magento.com/blog/simple-social-sharing/</link>
      <description><![CDATA[<p>有很多方法来添加社交共享按钮到你的Magento商店。你可以选择几种不同的免费或者付费的插件，创建自己的，使用AddThis服务或者从官方粘贴脚本（像 Facebook Like）。然而，在设置样式是会收到一些限制。如果你需要一个简单的解决方法，那么这篇文章适用于你。</p>
<p>我将指出一些你应该知道的官方按钮潜在问题。首先，你生成的每个按钮有一些JavaScript代码。这些代码在远程服务器上，每次用户打开一个页面时被读取。虽然这些代码的读取是异步的，但是当你有很多这些代码时会影响页面读取速度。另一方面，如果这些按钮有些复杂（或者写得不好的）JavaScript可能会弄乱你的商店。有一次我用AddThis插件在Magento产品页面添加社交按钮时，可配置产品因为Twitter按钮而失效，总价不更新，&ldquo;添加产品到购物车&rdquo;无效。我记不清具体的报错JavaScript代码但是我认为和全局变量名或者类似的东西相关。重点是，这些按钮会产生一些问题，让你话费不必要的时间去调试。我已经记不清多少次因为Facebook Like按钮失效而让我绝望了。</p>
<h1>把事情简单化</h1>
<p>我总是让喜欢让事情简单地工作。每一个社交网站都有一个简单的接受一些基础参数的&ldquo;共享地址&rdquo;，允许你分享任何URL。因为这是一个简单的URL，你能以你喜欢的风格做一个链接或者任何类型的按钮。另外一个好处就是，使用简单&ldquo;共享地址&rdquo;是没有外部脚本的。</p>
<p>下面是一些流行的社交网站共享URL：</p>
<ul>
<li><strong>Google Plus:</strong> https://plus.google.com/share?url=[URL TO SHARE]</li>
<li><strong>Facebook: </strong>https://www.facebook.com/sharer/sharer.php?u=[URL TO SHARE]&amp;t=[TITLE]</li>
<li><strong>Twitter: </strong>http://twitter.com/home/?status=[TITLE] ([URL TO SHARE])</li>
<li><strong>Pinterest: </strong>https://pinterest.com/pin/create/button/?url=[LINKBACK URL]&amp;media=[IMAGE TO SHARE]&amp; description=[DESCRIPTION]</li>
</ul>
<h1>实现</h1>
<p>如果你关注可用性，那么利用打开新窗口的方式来远离简单链接元素并不是一个完美的解决方案。最简单的方式就是以弹窗的方式打开链接。如果你的网站里有些这样的JavaScript模式，你可以使用它们。但为了简单起见，我将使用默认的Magento弹出窗口。</p>
<p>社交按钮最合理的位置当然是产品页面了，所以我们以此为例。我将添加Google Plus, Facebook, Twitter 和Pinterest按钮，但我不确定你能轻易地添加其它社交网站。为了与文章标题一致，我将添加简单的链接而不是按钮，但是你可以用一些基础的CSS来创建按钮。</p>
<p>跟着下面这些简单的步骤你就能轻易地拥有社交共享链接。</p>
<p>打开<strong>app/design/frontend/YOUR_PACKAGE/YOUR_THEME/template/catalog/product/view.phtml</strong>找到你要添加链接/按钮的位置，添加下面的代码：</p>
<pre><code>&lt;?php $productName = $_helper-&gt;productAttribute($_product, $_product-&gt;getName(), 'name'); ?&gt;
&lt;?php $productUrl = $_helper-&gt;productAttribute($_product, $_product-&gt;getProductUrl(), 'product_url'); ?&gt;
&lt;?php $productImage = $_product-&gt;getImageUrl() ?&gt;
</code></pre>
<p>我们将使用这些变量来设置URL，标题，描述或者其它需要的字段。在我们刚才添加的代码后面添加：</p>
<pre><code>// Google Plus
&lt;a href="javascript:popWin('https://plus.google.com/share?url=&lt;?php echo urlencode($productUrl); ?&gt;', 'google', 'width=640,height=480,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes');" title="&lt;?php echo $this-&gt;__('Share on Google Plus') ?&gt;"&gt;Google Plus&lt;/a&gt;
// Facebook
&lt;a href="javascript:popWin('https://www.facebook.com/sharer/sharer.php?u=&lt;?php echo urlencode($productUrl); ?&gt;&amp;t=&lt;?php echo urlencode($productName); ?&gt;', 'facebook', 'width=640,height=480,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes');" title="&lt;?php echo $this-&gt;__('Share on Facebook') ?&gt;"&gt;Facebook&lt;/a&gt;
// Twitter
&lt;a href="javascript:popWin('http://twitter.com/home/?status=&lt;?php echo urlencode($productName . ' (' . $productUrl . ')'); ?&gt;', 'twitter', 'width=640,height=480,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes');" title="&lt;?php echo $this-&gt;__('Tweet') ?&gt;"&gt;Twitter&lt;/a&gt;
// Pinterest
&lt;a href="javascript:popWin('https://pinterest.com/pin/create/button/?url=&lt;?php echo urlencode($productUrl); ?&gt;&amp;media=&lt;?php echo urlencode($productImage); ?&gt;&amp;description=&lt;?php echo urlencode($productName); ?&gt;', 'pinterest', 'width=640,height=480,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes');" title="&lt;?php echo $this-&gt;__('Pin it') ?&gt;"&gt;Pinterest&lt;/a&gt;
</code></pre>
<p>尽管所有社交网站都善于提取你共享链接的内容（产品名称，图片，描述&hellip;&hellip;）但尽可能地帮助它们也是很好的做法。最常用的做法就是为你的页面添加meta标签。你有许多不同的方法可用，但是为了简单起见，我将使用OpenGraph，因为Facebook在用它。如果你的页面有些复杂的改变，它将不会正确地提取产品信息。</p>
<p>另一方面，使用分享链接在Google Plus提取产品信息时我没遇到过任何问题。Twitter简单些，因为你只分享了定义的文本。Pinterest要求你指定所有的信息，所以这些站不需要meta标签。</p>
<p>添加OpenGraph meta标签到你的Magento商店非常简单。只要添加下面的代码到<strong>app/design/frontend/YOUR_PACKAGE/YOUR_THEME/template/page/html/head.phtml</strong>的最后一个meta标签后面（如果你用Magento默认的head文件就是名为&ldquo;robots&rdquo;meta标签）。</p>
<pre><code>&lt;?php $product = Mage::registry('current_product');
if ($product): ?&gt;
&lt;meta property="og:title" content="&lt;?php echo $product-&gt;getName(); ?&gt;" /&gt;
&lt;meta property="og:type" content="product" /&gt;
&lt;meta property="og:url" content="&lt;?php echo $this-&gt;helper('catalog/product')-&gt;getProductUrl($product); ?&gt;" /&gt;
&lt;meta property="og:image" content="&lt;?php echo $this-&gt;helper('catalog/image')-&gt;init($product, 'image')-&gt;resize(300, 300); ?&gt;" /&gt;
&lt;meta property="og:description" content="&lt;?php echo strip_tags($product-&gt;getShortDescription()); ?&gt;" /&gt;
&lt;meta property="og:site_name" content="&lt;?php echo Mage::app()-&gt;getStore()-&gt;getName() ?&gt;" /&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>我们共享一个产品，所以我们需要在meta标签添加到唯一的产品页面，但head.phtml的每一页上加载。这意味着，我们需要检查，如果当前页面是产品页面，然后才加入我们的meta标签。同时，我们需要得到的产品对象，所以我们可以提取我们需要投入meta标签中的数据。在上面的代码中的前两行会做到这一点。我们创建一个变量$product来获取当前的产品。如果我们在产品页面，这个变量将包含当前产品的对象。如果不是，$product会被设置为false。我用一些标准的meta标签去描述产品，但你可以按需使用更多标签。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 09 Oct 2015 13:13:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[选择一个合适的事件去监听]]></title>
      <link>https://www.360magento.com/blog/right-event-observe/</link>
      <description><![CDATA[<p>当你开发你的Magento模块或者通过事件监听做修改时，选对合适的事件是非常重要的。</p>
<p>一个方法是在你的PHP IDE里搜索Magento核心文件<strong>&ldquo;Mage::dispatchEvent(&ldquo;</strong>，结果大概会出现400处。大部分这些方法调用静态字符串作为事件名称，如：</p>
<pre><code>Mage::dispatchEvent('catalog_product_is_salable_before', array('product' =&gt; $this));</code></pre>
<p>也有些事件的名字是由一些变量串联到静态字符串组成的，如：</p>
<pre><code>Mage::dispatchEvent($this-&gt;_eventPrefix.'_validate_before', array($this-&gt;_eventObject=&gt;$this));</code></pre>
<p>在这种情况下，我们不能确定最终的事件名称。由于Magento不允许我们同时观察超过一个事件，我们要想办法得到一个确定需求的所有事件。</p>
<p>如果我们查看<strong>app/Mage.php</strong>中声明的<strong>Mage::dispatchEvent</strong>，你可以看到以下代码：</p>
<pre><code>public static function dispatchEvent($name, array $data = array())
    {
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
        $result = self::app()-&gt;dispatchEvent($name, $data);
        #$result = self::registry('events')-&gt;dispatch($name, $data);
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
        return $result;
    }</code></pre>
<p>我们不能重写Mage类去添加事件名称抓取功能。<strong>Mage::dispatchEvent</strong>方法从<strong>Mage_Core_Model_App</strong>调用<strong>dispatchEvent</strong>方法。我们也不能重写<strong>Mage_Core_Model_App</strong>，因为应用程序对象被直接实例化，而不是从<strong>Mage::getModel</strong>工厂方法。所以，获取指定需求的所有事件名称的唯一方法就是在<strong>Mage::dispatchEvent</strong>中添加一个简单的硬编码行。我们可以加类似这样的东西：</p>
<pre><code>Mage::log($name, null, 'events.log', true);</code></pre>
<p>它记录需求中被调用的每一个事件的名称。<strong>app/Mage.php</strong>里的<strong>dispatchEvent</strong>方法被修改后看起来像是这样的：</p>
<pre><code>public static function dispatchEvent($name, array $data = array())
    {
        // log event name
        Mage::log($name, null, 'events.log', true);
 
        Varien_Profiler::start('DISPATCH EVENT:'.$name);
        $result = self::app()-&gt;dispatchEvent($name, $data);
        #$result = self::registry('events')-&gt;dispatch($name, $data);
        Varien_Profiler::stop('DISPATCH EVENT:'.$name);
        return $result;
    }</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 09 Oct 2015 13:02:28 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento自动识别性别的插件]]></title>
      <link>https://www.360magento.com/blog/magento-automatic-gender/</link>
      <description><![CDATA[<p>今天我们要为客户创建一个Magento自动识别性别的插件。插件基于Rapleaf的个性化API。Rapleaf公司提供人口统计和消费者个人数据（年龄，性别，婚姻状况，收入等），不能用作商业电子邮件。他们的合作伙伴，一些大（小）型数据公司将数据汇总并绑定到邮箱地址。你可以创建一个免费的Rapleaf账户来获取API。 让我们开始吧。</p>
<h1>Alwayly_Autogender.xml</h1>
<p>首先，我们要在/app/etc/modules文件夹里创建Alwayly_Autogender.xml</p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Autogender&gt;
           &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_Autogender&gt;
   &lt;/modules&gt;
&lt;/config&gt;</code></pre>
<h1>config.xml</h1>
<p>第二步是在 /app/code/local/Alwayly/Autogender/etc文件夹里创建config.xml</p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Autogender&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Alwayly_Autogender&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;alwayly_autogender&gt;
                &lt;class&gt;Alwayly_Autogender_Model&lt;/class&gt;
            &lt;/alwayly_autogender&gt;
        &lt;/models&gt;
        &lt;events&gt;
            &lt;customer_register_success&gt;
                &lt;observers&gt;
                    &lt;alwayly_autogender_add_email&gt;
                        &lt;class&gt;alwayly_autogender/observer&lt;/class&gt;
                        &lt;method&gt;getGender&lt;/method&gt;
                    &lt;/alwayly_autogender_add_email&gt;
                &lt;/observers&gt;
            &lt;/customer_register_success&gt;
        &lt;/events&gt;
    &lt;/global&gt;
&lt;/config&gt;</code></pre>
<h1>Observer.php</h1>
<p>最后一步是/app/code/local/Alwayly/Autogender/Model文件夹里创建Observer.php</p>
<pre><code>&lt;?php
 
class Alwayly_Autogender_Model_Observer
{
    public function getGender($observer = null)
    {
        if($observer)
        {
            try
            {
                $customer = $observer-&gt;getCustomer();
 
                $api_key = '... your api key ...';
 
                $client = new Zend_Http_Client();
 
                $client-&gt;setUri('https://personalize.rapleaf.com/v4/dr?api_key=' . $api_key .
                                '&amp;email=' . urlencode($customer-&gt;getEmail()) .
                                '&amp;first=' . urlencode($customer-&gt;getFirstname()) .
                                '&amp;last=' . urlencode($customer-&gt;getLastname())
                );
 
                $client-&gt;setConfig(array('maxredirects' =&gt; 0, 'timeout' =&gt; 2));
 
                $response = $client-&gt;request();
 
                if ($response-&gt;getStatus() &lt; 200 || $response-&gt;getStatus() &gt;= 300)
                {
                    Mage::log(
                        sprintf("Rapleaf query failed. (status: %s), (message: %s)",
                            $response-&gt;getStatus(),
                            strip_tags($response-&gt;getBody())),
                        null,
                        'rapleaf_api.log',
                        false);
                }
                else
                {
                    $data = json_decode($response-&gt;getBody(), true);
                    if(array_key_exists('gender', $data))
                    {
                        $customer-&gt;setGender(
                            Mage::getResourceSingleton('customer/customer')
                                -&gt;getAttribute('gender')
                                -&gt;getSource()
                                -&gt;getOptionId($data['gender'])
                        );
                    }
                }
            }
            catch (Exception $e)
            {
                Mage::log(
                    sprintf("Exception in Rapleaf query. (message: %s)",
                       strip_tags($e-&gt;getMessage())),
                    null,
                    'rapleaf_api.log',
                    false);
            }
        }
    }
}</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 08 Oct 2015 13:16:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[为你的Magento项目创建Windows虚拟主机]]></title>
      <link>https://www.360magento.com/blog/vhosts-for-ymagento/</link>
      <description><![CDATA[<p>这篇文章是为那些准备或者刚刚开始网站开发冒险的初学者而写的。这不是唯一一种管理你本地环境的方式，但是是比较好的一种。</p>
<p>如果长期在一个本地Windows机器上开发Magento项目，你会注意到很严重的性能下降。这是因为Magento是一个有很多小文件和大量数据表/项的巨大系统。例如，最新的Magento CE有11900多个文件，默认有4435个以上的文件夹（不包含SVN文件，如果你必须用它或者没意识到git的优势）。将其乘以一打项目（活跃的和处于支持状态的），你就会有严重的碎片问题。SSD磁盘是不错，但就个人而言，我觉得这并不是一个可靠的解决方案。</p>
<h1>创建Windows虚拟主机</h1>
<p>在一个独立的分区里为你正在开发的Magento项目创建虚拟主机。使用分区还有个好处：在系统故障时有更高的可能性恢复数据。（墨菲定律：没有被版本控制系统跟踪的重要文件会先丢失）。下面是步骤：</p>
<p>1.用你喜欢的分区工具创建一个新的分区。使它的大小比你预估的项目大小大两倍（如果使用SVN就大三倍）。创建一个新文件夹来保留你的Magento项目（例如，X:\yourmagentoproject\）</p>
<p>2.关闭Apache服务并显示Windows隐藏文件。</p>
<p>3.以管理员身份打来你最喜欢的文本编辑工具。记事本就可以完成这个工作。如果你不知道怎么做，即便有管理员权限也不会自动拥有所有文件的编辑权限。使用Windows搜索找到记事本，在右键菜单中选择&ldquo;以管理员身份运行&rdquo;。</p>
<p>4.用文本编辑器打开hosts文件（默认在"Windows\System32\drivers\etc\"），在文件的最后添加新的域名</p>
<pre><code>127.0.0.1 yourmagentoproject.loc</code></pre>
<p>5.打开Apache的主要配置文件httpd.conf。默认在Apache安装目录的conf文件夹内。找到下面一行</p>
<pre><code># This should be changed to whatever you set DocumentRoot to.</code></pre>
<p>这是定义默认文件目录的块。添加下面的代码：</p>
<pre><code>&lt;Directory "X:/yourmagentoproject/"&gt;
   Options Indexes FollowSymLinks
   AllowOverride All
   Order Deny,Allow
   Allow from all

</code></pre>
<p>6.打开Apache虚拟主机配置文件，一般在Apache文件的\extra\httpd-vhosts.conf，在文件最后添加下面的代码：</p>
<pre><code>	DocumentRoot "X:/yourmagentoproject/"
	ServerName yourmagentoproject.loc
	ServerAlias yourmagentoproject.loc
	DirectoryIndex index.php index.html index.htm not-a-file

</code></pre>
<p>如果你想知道&hellip;&hellip;是的，目录索引在虚拟主机文件中被定义。</p>
<h1>移动MySQL数据文件到独立分区</h1>
<p>Magento数据库中有大量的表，每张表都存储在对应的.frm文件放置在一个以数据库命名的文件夹里。你在Magento后台对数据进行的增删改查操作都会跟前端访问日志，统计信息一起保存在数据库中。当一个已经存在的网站不再被需要或是要被替换时，你还得处理客户数据库。那么就有很多的文件管理任务等着你的磁盘来处理。这意味着大量的文件碎片随着时间堆积起来。</p>
<p>将MySQL数据文件移到一个独立分区的步骤：</p>
<p>1.为你的MySQL数据文件创建一个独立的分区。记得要能满足你的数据库大小需求。</p>
<p>2.关闭MySQL服务</p>
<p>3.找到你的MySQL数据文件，默认在你MySQL安装目录的data文件夹里。拷贝整个文件夹到你新分区里。新的路径应该看起来是这样：Y:\data\。打开my.ini文件，添加或者修改下面的代码：</p>
<pre><code>#Path to the database root
datadir="Y:/data/"</code></pre>
<p>以及</p>
<pre><code>#*** INNODB Specific options ***
innodb_data_home_dir="Y:/data/"</code></pre>
<p>4.开启MySQL服务。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 08 Oct 2015 13:07:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[选择Magento的十大理由]]></title>
      <link>https://www.360magento.com/blog/top-10-magento/</link>
      <description><![CDATA[<p>自Magento发布以来，因其作为电商平台展现出的强大受到了开发人员和商人的极大关注。开发人员喜欢它的模块化，因为他们可以利用模块化几乎完成客户的所有需求。商人则喜欢它提供的多种多样的功能。</p>
<p>下面我总结了下，选择Magento的十大理由：</p>
<ol>
<li><strong>SEO友好</strong>：搜索引擎友好，Google站地图，产品，类别和内容的meta信息，等等&hellip;&hellip;</li>
<li><strong>国际化支持</strong>：支持本地化，多货币和税率。支持重音符号和从右到左文字。允许针对某些国家的配置。欧盟增值税ID验证，欧盟cookie通知，等等&hellip;&hellip;</li>
<li><strong>内置大量电商相关功能（相比其它任何PHP开源竞争对手）</strong>：支持多站点和多域名设置。你可以在http://www.magentocommerce.com/images/uploads/magento-feature-list.pdf下载功能列表。</li>
<li><strong>高度模块化设计</strong>：使得前端（布局和模版）和后端（事件，观察者，重写，网格等..）的深度定制成为可能。</li>
<li><strong>Magento专家咨询小组（不是免费服务，但是对于需要的人来说还是很重要的）</strong>：官方培训&amp;专业认证开发：为后端开发人员，前端开发人员和商家等培训。Magento认证工程师，Magento认证高级工程师，Magento认证目录（搜集全球Magento认证工程师）</li>
<li><strong>安全</strong>：Magento高度重视安全并给予高优先级。Magento EE（企业版）更是提供为安全支付桥提供PCI数据安全标准（PCI PA-DSS）。</li>
<li><strong>Magento的连接</strong>：世界上最大的电子商务应用市场。</li>
<li><strong>开源</strong>：让你可以玩转PHP代码。</li>
<li><strong>Web服务API</strong>：内置支持SOAP v1, SOAP v2, XMLRPC，REST with 3-legged OAuth 1.0a.</li>
<li><strong>因为它真的很棒 :)</strong></li>
</ol>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 07 Oct 2015 15:57:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[跟踪Magento“添加产品到购物车”动作]]></title>
      <link>https://www.360magento.com/blog/tracking-magento-addtocart/</link>
      <description><![CDATA[<p>最近，我一直在忙一个关于第三方客户分析和定位服务的插件，考虑替换Google分析。其中一个要被实现的电商追踪功能是&ldquo;添加产品到购物车&rdquo;动作。由于这种追踪服务是使用JavaScript来触发它们的追踪代码，在Magento中何时何地嵌套追踪JavaScript是由我们决定的。有趣的是，&ldquo;添加产品到购物车&rdquo;动作不是你想执行JavaScript就执行的普通页面。</p>
<p>在Magento中，当你点击任何&ldquo;添加产品到购物车&rdquo;页面，通常会以像<strong>http://magentoce1800.loc/index.php/checkout/cart/add/uenc/aHR0&hellip;0bWw,/product/16/form_key/oTSbNJ4ZIUC46W0R/</strong>的链接结束。其中<strong>checkout/cart/add</strong>是最有趣的一部分，由于它指向Mage_Checkout模型，它的CartController和对应的addAction()。第二个有趣的部分是<strong>product/16</strong>，它告诉Magento，ID为16的产品被添加到了购物车。此外，addAction()方法里进行了很多事情。比较重要，需要你记住的是：当Magento中addAction()方法添加产品到购物车的时候，它指向它本身的购物车页面。也就是说，实际的checkout/cart/add页面从不呈现在浏览器，所以你无法在这个页面是执行任何JavaScript。</p>
<p>那么，我们要从哪里开始呢？好了，Magento一个比较炫酷的功能就是定义它的事件/监听系统。如果你仔细想想，每一个控制器动作支持<strong>controller_action_predispatch</strong>事件（定义在<strong>app/code/core/Mage/Core/Controller/Varien/Action.php</strong> 527行左右）。之后一些具体的时间匹配到它的模块前端名，控制器和动作。在这里，解析为前端事件<strong>controller_action_predispatch_checkout_cart_add</strong>。</p>
<p>考虑到这一点，这里有了个通过JavaScript追踪&ldquo;添加产品到购物车&rdquo;行动的简单想法。</p>
<ol>
<li>为定义<strong>controller_action_predispatch_checkout_cart_add</strong>事件定义事件监听方法；</li>
<li>在事件监听方法中，当添加产品到购物车时做个记录。例如<strong>Mage::getModel(&lsquo;core/session&rsquo;)-&gt;setProductToShoppingCart(&hellip;)</strong>这样的东西。</li>
<li>写个布局更新<strong>checkout_cart_index</strong>句柄，读取一个自定义的.phtml模版文件，你可以用core/template或者你自己的模块类来定义块的类型。</li>
<li>在自定义的.phtml文件中使用<strong>Mage::getModel(&lsquo;core/session&rsquo;)-&gt;getProductToShoppingCart()</strong>来生成你的&ldquo;添加产品到购物车&rdquo;追踪点，获取刚刚添加到购物车的产品的信息。在完成这些之后，使用<strong>Mage::getModel(&lsquo;core/session&rsquo;)-&gt;unsProductToShoppingCart()</strong>清除session。</li>
</ol>
<p>下面是代码示例：</p>
<p>第一步中描述的 <strong>app/code/community/Alwayly/Test/etc/config.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Test&gt;
            &lt;version&gt;1.0.0.0&lt;/version&gt;
        &lt;/Alwayly_Test&gt;
    &lt;/modules&gt;
    &lt;&lt;global&gt;
        &lt;models&gt;
            &lt;alwayly_test&gt;
                &lt;class&gt;Alwayly_Test_Model&lt;/class&gt;
            &lt;/alwayly_test&gt;
        &lt;/models&gt;
    &lt;/global&gt;
    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;alwayly_test&gt;
                    &lt;file&gt;alwayly_test.xml&lt;/file&gt;
                &lt;/alwayly_test&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;
        &lt;events&gt;
            &lt;controller_action_predispatch_checkout_cart_add&gt;
                &lt;observers&gt;
                    &lt;alwayly_test_log_cart_add&gt;
                        &lt;class&gt;alwayly_test/observer&lt;/class&gt;
                        &lt;method&gt;logCartAdd&lt;/method&gt;
                    &lt;/alwayly_test_log_cart_add&gt;
                &lt;/observers&gt;
            &lt;/controller_action_predispatch_checkout_cart_add&gt;
        &lt;/events&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>第二步中描述的：<strong>app/code/community/Alwayly/Test/Model/Observer.php</strong></p>
<pre><code>&lt;?php
 
class Alwayly_Test_Model_Observer
{
    public function logCartAdd() {
 
        $product = Mage::getModel('catalog/product')
                        -&gt;load(Mage::app()-&gt;getRequest()-&gt;getParam('product', 0));
 
        if (!$product-&gt;getId()) {
            return;
        }
 
        $categories = $product-&gt;getCategoryIds();
 
        Mage::getModel('core/session')-&gt;setProductToShoppingCart(
            new Varien_Object(array(
                'id' =&gt; $product-&gt;getId(),
                'qty' =&gt; Mage::app()-&gt;getRequest()-&gt;getParam('qty', 1),
                'name' =&gt; $product-&gt;getName(),
                'price' =&gt; $product-&gt;getPrice(),
                'category_name' =&gt; Mage::getModel('catalog/category')-&gt;load($categories[0])-&gt;getName(),
            ))
        );
    }
}
</code></pre>
<p>很显然，上面的代码比较基础。不包括Magento各种产品类型，因为它直接从产品模块获取产品价格。所以，当有捆绑或者批量销售产品时，你需要做一点扩展。你可以用产品id引到产品表，以此来找到子产品。</p>
<p>第三步所描述的：<strong>app/design/frontend/default/default/layout/alwayly_test.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;layout version="0.1.0"&gt;
    &lt;checkout_cart_index&gt;
        &lt;reference name="before_body_end"&gt;
            &lt;block type="alwayly_test/event_checkout_cart_index" name="alwayly_test_event_checkout_cart_index" template="alwayly/test/event/checkout/cart/index.phtml" /&gt;
        &lt;/reference&gt;
    &lt;/checkout_cart_index&gt;
&lt;/layout&gt;</code></pre>
<p>第四部所描述的：<strong>app/design/frontend/default/default/template/alwayly/test/event/checkout/cart/index.phtml</strong></p>
<pre><code>&lt;?php $_product = Mage::getModel('core/session')-&gt;getProductToShoppingCart() ?&gt;
&lt;<!--?php if ($_product && $_product--->getId()): ?&gt;
    &lt;&lt;script type="text/javascript"&gt;
        //Some 3rd party JS tracking code
    &lt;/script&gt;
    &lt;?php Mage::getModel('core/session')-&gt;unsProductToShoppingCart(); ?&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>这就是一个简单的为你的分析服务追踪&ldquo;添加产品到购物车&rdquo;动作的方式。</p>
<p>好处是：你不需要更改已有的.phtml文件增加JS点击事件或者类似的事情。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 07 Oct 2015 15:51:59 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento允许的最大订单金额]]></title>
      <link>https://www.360magento.com/blog/magento-maximumr-amount/</link>
      <description><![CDATA[<p>最近我在做的一个项目中，有一个小的防欺诈功能。这个功能就是允许的最大订单金额。也许一开始听起来很奇怪，怎么会有人想限制订单的最大金额呢？鉴于该商店销售产品的性质（这里不能透露），这个功能要求似乎很合理。如果你看下Magento后台管理，你会在<strong>System &gt; Configuration &gt; Sales &gt; Sales &gt; Minimum Order Amount</strong>看到与它相反的功能。</p>
<p>最小订单金额功能和我们最大订单金额略有不同。最大的区别就是，你无法添加超出金额的商品到购物车。那么我们该如何做呢？答案很简单事件/监听（event/observer）系统。我们所要做的是找到相对应的时间并挂钩一个观测者。经过仔细追查，一些尝试和失败以后，最合乎逻辑的事件似乎是：sales_quote_save_before。此外，只实现最大订单金额功能在前端是有道理的，因为我们不希望限制管理员创建订单。考虑到这一点，我们只需要添加以下代码到我们扩展的config.xml文件中：</p>
<pre><code>&lt;config&gt;
    &lt;frontend&gt;
        &lt;events&gt;
            &lt;sales_quote_save_before&gt; 
                &lt;observers&gt;
                    &lt;alwayly_maxorderamount_enforceSingleOrderLimit&gt;
                        &lt;class&gt;alwayly_maxorderamount/observer&lt;/class&gt;
                        &lt;method&gt;enforceSingleOrderLimit&lt;/method&gt;
                    &lt;/alwayly_maxorderamount_enforceSingleOrderLimit&gt;
               &lt;/observers&gt;
            &lt;/sales_quote_save_before&gt;
        &lt;/events&gt;
    &lt;/frontend&gt;
&lt;config&gt;
</code></pre>
<p>创建我们<strong>Observer.php</strong>，在类中添加逻辑：</p>
<pre><code>class Alwayly_MaxOrderAmount_Model_Observer
{
    private $_helper;
 
    public function __construct() 
    {
        $this-&gt;_helper = Mage::helper('alwayly_maxorderamount');
    }
 
    /**
     * No single order can be placed over the amount of X
     */
    public function enforceSingleOrderLimit($observer)
    {
        if (!$this-&gt;_helper-&gt;isModuleEnabled()) {
            return;
        }
 
        $quote = $observer-&gt;getEvent()-&gt;getQuote();
 
        if ((float)$quote-&gt;getGrandTotal() &gt; (float)$this-&gt;_helper-&gt;getSingleOrderTopAmount()) {
 
            $formattedPrice = Mage::helper('core')-&gt;currency($this-&gt;_helper-&gt;getSingleOrderTopAmount(), true, false);
 
            Mage::getSingleton('checkout/session')-&gt;addError(
                $this-&gt;_helper-&gt;__($this-&gt;_helper-&gt;getSingleOrderTopAmountMsg(), $formattedPrice));
 
            Mage::app()-&gt;getFrontController()-&gt;getResponse()-&gt;setRedirect(Mage::getUrl('checkout/cart'));
            Mage::app()-&gt;getResponse()-&gt;sendResponse();
            exit;
        }
    }
}
</code></pre>
<p>这个方法的实现在代码的<strong>&ldquo;Mage::getSingleton(&lsquo;checkout/session&rsquo;)-&gt;addError() &hellip;&rdquo;</strong>这行。这里触发<strong>sales_quote_save_before</strong>事件，当新添加的商品超过最大订单金额时，Magento不更新购物车。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 06 Oct 2015 13:09:31 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[重写Magento块，模型，助手和控制器]]></title>
      <link>https://www.360magento.com/blog/overriding-magento/</link>
      <description><![CDATA[<p>没有一个项目是使用原有的框架，都是时不时地要修改些东西。增加新的东西或者重写已经写好的东西。由于很多原因，修改核心文件是一个坏习惯，不被推荐。因此，Magento带来一种很好的方式来重写/覆盖这些文件。</p>
<p>我们已经写过如何重写Magento模型类，但需要修改助手,块和控制器，不论是前端还是后台。</p>
<h2>重写Magento块</h2>
<p>让我们以重写核心标签块开始。假设要对<strong>Mage_Tag_Block_Product_List</strong>类做些改变。我们要做的是在这个类的基础上添加我们自己的文件来扩展它。所有要做的就是添加下面的代码到当前模块的<strong>config.xml</strong>文件中。</p>
<pre><code>&lt;config&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;tag&gt;
               &lt;rewrite&gt;
                    &lt;product_list&gt;Alwayly_Tag_Block_Product_List&lt;/product_list&gt;
                &lt;/rewrite&gt;
           &lt;/tag&gt;
        &lt;/blocks&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>由类名可以得出，文件要被创建在<strong>app/code/local/Alwayly/Tag/Block/Product/List.php</strong>，其中要定义类：</p>
<pre><code>class Alwayly_Tag_Block_Product_List extends Mage_Tag_Block_Product_List
{
// some code
}
</code></pre>
<p>等效于上面的例子，同样的规则可以应用在aminhtml中，当我们想要重写<strong>Mage_Adminhtml_Block_Tag_Edit</strong>类时。</p>
<pre><code>&lt;config&gt;
    &lt;global&gt;
       &lt;blocks&gt;
            &lt;adminhtml&gt;
                &lt;rewrite&gt;
                    &lt;tag_edit&gt;Alwayly_Tag_Block_Adminhtml_Tag_Edit&lt;/tag_edit&gt;
                &lt;/rewrite&gt;
            &lt;/adminhtml&gt;
        &lt;/blocks&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>那么需要创建<strong>app/code/local/Alwayly/Tag/Block/Adminhtml/Tag/Edit.php</strong>，在文件中写下类的代码：</p>
<pre><code>class Alwayly_Tag_Block_Adminhtml_Tag_Edit extends Mage_Adminhtml_Block_Tag_Edit
{
// some code
}
</code></pre>
<h2>重写Magento助手</h2>
<p>按照同样的规则，Magento助手也可以轻松地被重写。config.xml中的代码：</p>
<pre><code>&lt;config&gt;
    &lt;global&gt;
        &lt;helpers&gt;
            &lt;tag&gt;
                &lt;rewrite&gt;
                   &lt;data&gt;Alwayly_Tag_Helper_Data&lt;/data&gt;
               &lt;/rewrite&gt;
            &lt;/tag&gt;
        &lt;/helpers&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>创建<strong>app/code/local/Alwayly/Tag/Helper/Data.php</strong>文件并定义类：</p>
<pre><code>class Alwayly_Tag_Helper_Data extends Mage_Tag_Helper_Data
{
// some code
}
</code></pre>
<h2>重写Magento模型</h2>
<p>我们已经重写过Magento模型，但是资源文件和集合文件呢？和核心模型文件一样，资源和集合文件的重写和其它文件一样。文件将扩展：</p>
<ul>
<li>Mage_Tag_Model_Tag</li>
<li>Mage_Tag_Model_Resource_Tag</li>
</ul>
<p>Config.xml代码：</p>
<pre><code>&lt;config&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;tag&gt;
                &lt;rewrite&gt;
                    &lt;!-- Model --&gt;
                    &lt;tag&gt;Alwayly_Tag_Model_Tag&lt;/tag&gt;
                &lt;/rewrite&gt;
            &lt;/tag&gt;
            &lt;tag_resource&gt;
               &lt;rewrite&gt;
                    &lt;!-- Resource --&gt;
                    &lt;tag&gt;Alwayly_Tag_Model_Resource_Tag&lt;/tag&gt;
                    &lt;!-- Collection --&gt;
                    &lt;tag_collection&gt;Alwayly_Tag_Model_Resource_Tag_Collection&lt;/tag_collection&gt;
                &lt;/rewrite&gt;
            &lt;/tag_resource&gt;
        &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>接着，创建下面这些文件：</p>
<ul>
<li>app/code/local/Alwayly/Tag/Model/Tag.php</li>
<li>app/code/local/Alwayly/Tag/Model/Resource/Tag.php</li>
<li>app/code/local/Alwayly/Tag/Model/Resource/Tag/Collection.php.</li>
</ul>
<p><strong>注意：这里只是个示例，在你的项目里只重写你需要的类。</strong></p>
<h2>重写Magento控制器</h2>
<p>重写控制器比上面的示例要难一点，和我们之前例子中看到的Magento重写规则不一样。那如何重写Mage_Tag控制器呢？让我们看看代码吧。在config.xml中：</p>
<pre><code>&lt;config&gt;
    &lt;frontend&gt;
        &lt;routers&gt;
           &lt;tag&gt;
                &lt;args&gt;
                    &lt;modules&gt;
                        &lt;alwayly_tag before="Mage_Tag"&gt;Alwayly_Tag&lt;/alwayly_tag&gt;
                    &lt;/modules&gt;
                &lt;/args&gt;
            &lt;/tag&gt;
        &lt;/routers&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>在配置结点的孩子定义我们是否正在改变前端或者管理文件。我们定义的路由器结点将用它的参数重写核心标签模型。在底部结点出现当前模块前端的域名（alwayly_tag)和我们的模块名(Alwayly_Tag)。</p>
<p>你注意到，这里没有严格定义的文件。这样我们需要由控制器名定义这个路径下的文件。如果我们要重写<strong>app/code/core/Mage/Tag/controllers/TagController.php</strong>，那么具有相同名称的文件将被创建在<strong>app/code/local/Alwayly/Tag/controllers/TagController.php</strong>。</p>
<p>在新文件中定义类：</p>
<pre><code>require_once(Mage::getModuleDir('controllers','Mage_Tag').DS.'TagController.php');
 
class Alwayly_Tag_TagController extends Mage_Tag_TagController
{
// some code
}
</code></pre>
<p>类似地，要修改后台控制器的话。Config.xml代码：</p>
<pre><code>&lt;config&gt;
    &lt;admin&gt;
        &lt;routers&gt;
            &lt;adminhtml&gt;
                &lt;args&gt;
                    &lt;modules&gt;
                        &lt;alwayly_tag before="Mage_Adminhtml"&gt;Alwayly_Tag_Adminhtml&lt;/alwayly_tag&gt;
                    &lt;/modules&gt;
                &lt;/args&gt;
            &lt;/adminhtml&gt;
        &lt;/routers&gt;
    &lt;/admin&gt;
&lt;/config&gt;
</code></pre>
<p>创建<strong>app/code/local/Alwayly/Tag/controllers/Adminhtml/TagController.php</strong>文件并定义类：</p>
<pre><code>require_once(Mage::getModuleDir('controllers','Mage_Adminhtml').DS.'TagController.php');
 
class Alwayly_Tag_Adminhtml_TagController extends Mage_Adminhtml_TagController
{
// some code
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 06 Oct 2015 13:05:06 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[对Magento进行shell语言]]></title>
      <link>https://www.360magento.com/blog/php-shell-magento/</link>
      <description><![CDATA[<p>有时候我们需要从Magento外部访问Magento系统。一种方式是使用PHP shell语言引导Magento。一个普通PHP开发者会在自己代码的底部创建一个引导文件来访问Magento根目录。如你猜测的一样，有两种引导Magento的方式，常用方式和Magento方式。在这篇文章中，我们将概述如何以Magento的方式创建PHP shell脚本来引导Magento。</p>
<p>对于初学者来说，这里是引导Magento的常规方法（Magento中index.php中使用的）：</p>
<pre><code>require_once 'app/Mage.php';
Mage::app();
 
// Our own code goes here
</code></pre>
<p>虽然这种方法没有错误，但是和Magento方式相比有些不足。</p>
<h2>The Magento way</h2>
<p>现在，让我们看看用Magento方式来实现。如果你访问Magento根目录下shell文件夹，你会发现一些"Magento方式的"shell语言。比如，你有index.php可以使用所选的索引来重建索引，或者compiler.php去控制Magento编译器功能状态。如果你看了PHP shell脚本，你会看到在abstract.php文件包含Mage_Shell_Abstract类和其所包含、扩展Mage_Shell_Abstract类。</p>
<p>有些人想知道这样比单纯请求Mage.php好在哪。特别是当你看到Mage_Shell_Abstract结构体后，发现做的同样的事情。</p>
<p>使用Magento方式的有点之一是Mage_Shell_Abstract类提供解析命令行参数。第二，Mage_Shell_Abstract结构体会调用Mage_Shell_Abstract::__applyPhpVariables() function函数来解析.htaccess文件并应用php设置到shell脚本。</p>
<p>执行过程很明显。我将粘贴出Magento PHP shell脚本的骨架类：</p>
<pre><code>&lt;?php
require_once 'abstract.php';
 
class Inchoo_Shell_Myscript extends Mage_Shell_Abstract
{
    protected $_argname = array();
 
    public function __construct() {
        parent::__construct();
 
        // Time limit to infinity
        set_time_limit(0);     
 
        // Get command line argument named "argname"
        // Accepts multiple values (comma separated)
        if($this-&gt;getArg('argname')) {
            $this-&gt;_argname = array_merge(
                $this-&gt;_argname,
                array_map(
                    'trim',
                    explode(',', $this-&gt;getArg('argname'))
                )
            );
        }
    }
 
    // Shell script point of entry
    public function run() {
 
    }
 
    // Usage instructions
    public function usageHelp()
    {
        return &lt;&lt;       Argument description
 
  help                   This help
 
USAGE;
    }
}
// Instantiate
$shell = new Inchoo_Shell_Myscript();
 
// Initiate script
$shell-&gt;run();
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 05 Oct 2015 01:50:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[禁用Magento默认的通讯交易邮件]]></title>
      <link>https://www.360magento.com/blog/disabling-newsletter-emails/</link>
      <description><![CDATA[<p>并不是每个人对Magento中的通讯选项满意，所以他们选择第三方服务。在这种情况下，关闭Magento默认的通讯交易邮件并让第三方服务来接管电子邮件是一个好主意。在这篇文章中我将演示如何关闭Magento中默认的通讯交易邮件。</p>
<p>首先，我们重写核心文件中的<strong>config.xml</strong></p>
<pre><code>&lt;newsletter&gt;
	&lt;rewrite&gt;
		&lt;subscriber&gt;Alwayly_Newsletter_Model_Newsletter_Subscriber&lt;/subscriber&gt;
	&lt;/rewrite&gt;
&lt;/newsletter&gt;
</code></pre>
<p>创建system.xml，把下面的代码放进去：</p>
<pre><code>&lt;?xml version="1.0"?&gt;
 
&lt;config&gt;
   &lt;tabs&gt;
        &lt;alwayly_tab translate="label"&gt;
            &lt;label&gt;Alwayly&lt;/label&gt;
            &lt;sort_order&gt;200&lt;/sort_order&gt;
        &lt;/alwayly_tab&gt;
    &lt;/tabs&gt;
 
    &lt;sections&gt;
        &lt;alwayly_newsletter translate="label"&gt;
            &lt;label&gt;Newsletter Configuration&lt;/label&gt;
            &lt;tab&gt;alwayly_test_tab&lt;/tab&gt;
           &lt;frontend_type&gt;text&lt;/frontend_type&gt;
            &lt;sort_order&gt;1&lt;/sort_order&gt;
            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
            &lt;groups&gt;
                &lt;newsletter_subscription_transactional_mails&gt;
                   &lt;label&gt;Newsletter Subscription Transactional Mails&lt;/label&gt;
                    &lt;frontend_type&gt;text&lt;/frontend_type&gt;
                    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                    &lt;show_in_website&gt;1&lt;/show_in_website&gt;
                    &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                    &lt;sort_order&gt;120&lt;/sort_order&gt;
                    &lt;fields&gt;
                        &lt;enabled translate="label"&gt;
                           &lt;label&gt;Enable&lt;/label&gt;
                            &lt;frontend_type&gt;select&lt;/frontend_type&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_yesno&lt;/source_model&gt;
                            &lt;sort_order&gt;40&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;1&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;1&lt;/show_in_store&gt;
                        &lt;/enabled&gt;
                    &lt;/fields&gt;
                &lt;/newsletter_subscription_transactional_mails&gt;
            &lt;/groups&gt;
        &lt;/alwayly_newsletter&gt;
    &lt;/sections&gt;
&lt;/config&gt;
</code></pre>
<p>下一步，我们将添加我们的配置路径到Helper类和一个获取值的方法：</p>
<pre><code>class Alwayly_Newsletter_Helper_Data extends Mage_Core_Helper_Abstract
{
    const XML_PATH_NEWSLETTER_MAILS  = 'alwayly_newsletter/newsletter_subscription_transactional_mails/enabled';
 
    public function getNewsletterSubscriptionMailEnabled()
    {
        return Mage::getStoreConfig(self::XML_PATH_NEWSLETTER_MAILS);
    }
}
</code></pre>
<p>最后一步就是编辑几个以前我们改写过的核心方法。我们新的模型类是<strong>Alwayly_Newsletter_Model_Newsletter_Subscriber</strong>，它扩展自<strong>Mage_Newsletter_Model_Subscriber</strong>类。类名取决于你的模块，我们经常要扩展核心类，否则将无法正常工作。</p>
<p>你将需要从核心类里拷贝3个方法到我们的新类中并做一些调整。</p>
<ul>
<li>公用方法subscribe($email)</li>
<li>公用方法subscribeCustomer($customer)</li>
<li>公用方法unsubscribe()</li>
</ul>
<p>在subscribe方法中找到：</p>
<pre><code>if ($isConfirmNeed === true
	&amp;&amp; $isOwnSubscribes === false
) {
	$this-&gt;sendConfirmationRequestEmail();
} else {
	$this-&gt;sendConfirmationSuccessEmail();
}
</code></pre>
<p>用下面的代码替换：</p>
<pre><code>if ((bool) Mage::helper('alwayly_newsletter')-&gt;getNewsletterSubscriptionMailEnabled()) {
    if ($isConfirmNeed === true &amp;&amp; $isOwnSubscribes === false) {
        $this-&gt;sendConfirmationRequestEmail();
    } else {
        $this-&gt;sendConfirmationSuccessEmail();
    }
}
</code></pre>
<p>在subscribeCustomer方法中找到：</p>
<pre><code>if ($this-&gt;getIsStatusChanged() &amp;&amp; $status == self::STATUS_UNSUBSCRIBED) {
    $this-&gt;sendUnsubscriptionEmail();
} elseif ($this-&gt;getIsStatusChanged() &amp;&amp; $status == self::STATUS_SUBSCRIBED) {
    $this-&gt;sendConfirmationSuccessEmail();
}
</code></pre>
<p>替换成：</p>
<pre><code>if ((bool) Mage::helper('alwayly_newsletter')-&gt;getNewsletterSubscriptionMailEnabled()) {
    if ($this-&gt;getIsStatusChanged() &amp;&amp; $status == self::STATUS_UNSUBSCRIBED) {
        $this-&gt;sendUnsubscriptionEmail();
    } elseif ($this-&gt;getIsStatusChanged() &amp;&amp; $status == self::STATUS_SUBSCRIBED) {
        $this-&gt;sendConfirmationSuccessEmail();
    }
}
</code></pre>
<p>最后一个unsubscribe方法中：</p>
<pre><code>$this-&gt;sendUnsubscriptionEmail();
</code></pre>
<p>替换为：</p>
<pre><code>if ((bool) Mage::helper('alwayly_newsletter')-&gt;getNewsletterSubscriptionMailEnabled()) {
    $this-&gt;sendUnsubscriptionEmail();
}
</code></pre>
<p>这意味着，我们首先检查我们的配置选项设置为启用或禁用。如果设置为禁用则不执行if语句里的代码。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 05 Oct 2015 01:36:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento配置计划任务]]></title>
      <link>https://www.360magento.com/blog/magento-configurable-cron/</link>
      <description><![CDATA[<p>Magento中的计划任务很容易配置。<strong>config.xml</strong>中的几行代码加一个方法就完成了。但如果你想更有意思点，创建一个日程计划任务呢？幸运的是，Magento系统中已经有了这个功能，实现起来也很简单。</p>
<p>计划任务本身比较直接。正如下面代码所见，它在<strong>config.xml</strong>中由两部分被定义：日程和一个被执行的方法。下面的例子展示了一个名为"my_cron"的计划任务，每5分钟执行观测者文件中的<strong>"doSomething"</strong>方法。如果你不熟悉计划任务的格式，网上有一堆关于计划任务的文章。</p>
<pre><code>&lt;config&gt;
    &lt;crontab&gt;
        &lt;jobs&gt;
            &lt;my_cron&gt;
                &lt;schedule&gt;
                    &lt;cron_expr&gt;*/5 * * * *&lt;/cron_expr&gt;
               &lt;/schedule&gt;
                &lt;run&gt;
                    &lt;model&gt;mymodule/observer::doSomething&lt;/model&gt;
                &lt;/run&gt;
            &lt;/my_cron&gt;
        &lt;/jobs&gt;
   &lt;/crontab&gt;
&lt;/config&gt;
</code></pre>
<p>计划任务不能被配置。在计划任务被生成的<strong>Mage_Cron_Model_Observer</strong>类里，有一个生成方法，以同样的方式检查<strong>core_config_data</strong>表中的值和<strong>configxml</strong>文件。知道了这一点，我们就可以保存路径和设置我们想要的值。让我们开始吧。</p>
<h2>Admin configuration（管理员配置）</h2>
<p>因为我们想要日程配置计划任务，所以我们需要有一个对应的管理员配置。你可以随你喜欢地完成它，但是我将使用Magento中提供给我们的。</p>
<p>在<strong>system.xml</strong>中会有Magento中封装好的时间（小时，分钟和秒）和频率选择器（每日，每周和每月）。代码所要完成的是创建我们的后台块来格式化和保存我们想要的路径值。在这里，它将在<strong>mymodule/adminhtml_system_config_backend_mymodel_cron</strong>。</p>
<pre><code>&lt;config&gt;
    &lt;sections&gt;
        &lt;catalog&gt;
          &lt;groups&gt;
                &lt;configurable_cron translate="label"&gt;
                    &lt;label&gt;Cron Schedule&lt;/label&gt;
                    &lt;sort_order&gt;100&lt;/sort_order&gt;
                    &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                    &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                    &lt;show_in_store&gt;0&lt;/show_in_store&gt;
                    &lt;fields&gt;
                        &lt;time translate="label"&gt;
                            &lt;label&gt;Start Time&lt;/label&gt;
                            &lt;frontend_type&gt;time&lt;/frontend_type&gt;
                            &lt;sort_order&gt;10&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                           &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;0&lt;/show_in_store&gt;
                        &lt;/time&gt;
                        &lt;frequency translate="label"&gt;
                            &lt;label&gt;Frequency&lt;/label&gt;
                            &lt;frontend_type&gt;select&lt;/frontend_type&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_cron_frequency&lt;/source_model&gt;
                            &lt;backend_model&gt;mymodule/adminhtml_system_config_backend_mymodel_cron&lt;/backend_model&gt;
                            &lt;sort_order&gt;20&lt;/sort_order&gt;
                            &lt;show_in_default&gt;1&lt;/show_in_default&gt;
                            &lt;show_in_website&gt;0&lt;/show_in_website&gt;
                            &lt;show_in_store&gt;0&lt;/show_in_store&gt;
                        &lt;/frequency&gt;
                    &lt;/fields&gt;
                &lt;/configurable_cron&gt;
            &lt;/groups&gt;
        &lt;/catalog&gt;
    &lt;/sections&gt;
&lt;/config&gt;
</code></pre>
<h2>Backend model（后台模块）</h2>
<p>管理员配置中的前端类型不保存计划任务选择器读取的输入类型。由于这个，我们必须后台模块来填补我们想要的输入类型。</p>
<p>从上面设置普通计划任务的示例代码中，同样的路径也被<strong>core_config_data</strong>表使用，我们将要处理它。由上面的代码可知，我们日程的路径是<strong>"crontab/jobs/my_cron/schedule/cron_expr"</strong>。下面的代码格式化输入并保存值到表。</p>
<pre><code>class Alwayly_MyModule_Model_Adminhtml_System_Config_Backend_MyModel_Cron extends Mage_Core_Model_Config_Data
{
    const CRON_STRING_PATH = &lsquo;crontab/jobs/my_cron/schedule/cron_expr';
 
    protected function _afterSave()
    {
        $time = $this-&gt;getData('groups/configurable_cron/fields/time/value');
 
        $frequencyDaily = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_DAILY;
        $frequencyWeekly = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_WEEKLY;
        $frequencyMonthly = Mage_Adminhtml_Model_System_Config_Source_Cron_Frequency::CRON_MONTHLY;
 
        $cronDayOfWeek = date('N');
 
        $cronExprArray = array(
            intval($time[1]),                                   # Minute
            intval($time[0]),                                   # Hour
            (frequency == $frequencyMonthly) ? '1' : '*',       # Day of the Month
            '*',                                                # Month of the Year
            (frequency == $frequencyWeekly) ? '1' : '*',        # Day of the Week
        );
        $cronExprString = join(' ', $cronExprArray);
 
        try {
            Mage::getModel('core/config_data')
                -&gt;load(self::CRON_STRING_PATH, 'path')
                -&gt;setValue($cronExprString)
                -&gt;setPath(self::CRON_STRING_PATH)
                -&gt;save();
        }
        catch (Exception $e) {
            throw new Exception(Mage::helper('cron')-&gt;__('Unable to save the cron expression.'));
 
        }
    }
}
</code></pre>
<p>计划任务生成器浏览计划任务，选择日程被定义的那个。从config表中读取日程，日程调度结点必须从config.xml中被移除，仅定义了模型，如下所示：</p>
<pre><code>
&lt;config&gt;
    &lt;crontab&gt;
        &lt;jobs&gt;
            &lt;my_cron&gt;
                &lt;run&gt;
                    &lt;model&gt;mymodule/observer::doSomething&lt;/model&gt;
                &lt;/run&gt;
            &lt;/my_cron&gt;
        &lt;/jobs&gt;
    &lt;/crontab&gt;
&lt;/config&gt;
</code></pre>
<p>后台发生了什么？计划任务生成器浏览<strong>config.xml</strong>文件和<strong>config</strong>表，寻找计划任务日程并填充计划日程表。此时和模型是不相关的。没有被定义日程的计划任务被跳过。另一种方法，从计划日程表中读取计划任务，从<strong>config.xml</strong>文件和<strong>config</strong>表中收集方法并执行。</p>
<h2>Observer（观测者）</h2>
<p>观测者中是将被计划任务执行的方法。这里的代码由你决定。</p>
<pre><code>
class Alwayly_MyModule_Model_Observer
{
    public function doSomething()
    {
	// do something
    }
}
</code></pre>
<p>这只是个使用日程计划任务的例子。当你理解它如何工作后，这里还有很大的提升空间。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 04 Oct 2015 11:31:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[根据多个ID筛选订单网格]]></title>
      <link>https://www.360magento.com/blog/filter-order-ids/</link>
      <description><![CDATA[<p>我们都知道Magento的网格很棒，是有效显示数据的不二选择。</p>
<p>我们的客户在选择Magento后有时（基本是经常）会有些特殊的需求。其中有人提出通过订单ID来过滤订单网格。</p>
<p>当你有大批订单要跟踪的时候就显得很有用了。一个一个筛选是个繁琐而又耗时的任务。</p>
<p>我要告诉你的诀窍可以处理几乎所有的网格，只要你知道它是如何做的。</p>
<p>首先，重写你的订单网格块<strong>(app\code\core\Mage\Adminhtml\Block\Sales\Order\Grid.php)<strong>&mdash;&mdash;我想你知道怎么做。</strong></strong></p>
<p>在你的<strong> _prepareColumns() </strong>方法里，向数组里添加一个元素，如下：</p>
<pre><code>protected function _prepareColumns()
{
	$this-&gt;addColumn('real_order_id', array(
		'header'=&gt; Mage::helper('sales')-&gt;__('Order #'),
		'width' =&gt; '250px',
		'type'  =&gt; 'text',
		'index' =&gt; 'increment_id',
		'filter_condition_callback' =&gt; array($this, 'spaceSeparatedFilter')//calling spaceSeparatedFilter method
	));
....
}
</code></pre>
<p>在我们网格中一行被渲染时，渲染器被调用。通过cell被渲染成一个字段。过滤器回调，另一方面，调用整个列和集合作为字段。结果是，我们可以创建自己的方法，调用变量filter_condition_callback元素，向数据库执行自定义查询语句，获取我们网格中的输入框等等&hellip;&hellip;</p>
<p>这正是我们要做的&hellip;&hellip;</p>
<p>我们的过滤器回调将调用spaceSeparatedFilter()方法并把real_order_id列作为一个参数。让我们声明我们的方法（在Grid.php文件中）：</p>
<pre><code>protected function spaceSeparatedFilter($collection, $column)
{
	if (!$value = $column-&gt;getFilter()-&gt;getValue()) {
		return $this;
	}
	//if there was a space input
		else if(preg_match('/\s+/', $value))
	{
		//explode by space, getting array of IDs
		$val = explode(" ", $value);
		//filter the collection, where collection index (order_id) is present in $val array
		$this-&gt;getCollection()-&gt;addAttributeToFilter($column-&gt;getData('index'), array('in'=&gt;$val));
	}
	else
	{
	//else use default grid filter functionality (like $value input)
	$this-&gt;getCollection()-&gt;addAttributeToFilter($column-&gt;getData('index'), array('like' =&gt; '%'.$value.'%'));
	}
	return $this;
}
</code></pre>
<p>这两段代码可以让你通过多个订单ID来过滤订单，只要你用空间将他们分开。如果你没有进入一个空间，那么会按默认的工作。</p>
<p>你也可以使用网格的所有功能：排序，筛选，导出。没有任何问题。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 04 Oct 2015 11:18:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento中用getModel和getData方法来获取东西]]></title>
      <link>https://www.360magento.com/blog/magento-getmodel-getdata/</link>
      <description><![CDATA[<p>如果你正在Magento中开发，迟早有一天你会需要从数据库中获取信息。这篇文章将会给你展示用getModel,getData和getter方法获取几乎任何东西。</p>
<p>例如：假设你正在尝试找出产品名字，描述和价格。首先你要做的就是获取产品模型：</p>
<p><strong>$productModel = Mage::getModel('catalog/product');</strong></p>
<p>通过调用<strong>getModel('catalog/product')</strong>，你将<strong>Mage_Catalog_Model_Product</strong>类（定义在<strong>app/code/core/Mage/Catalog/Model/Product.php</strong>）实例化。但是Magento如何知道这个类在哪呢？</p>
<p>参数<strong>&lsquo;catalog/product&rsquo;</strong>的第一部分来自模块配置，通常和模块文件夹名一样。如果你看了<strong>app/code/core/Mage/Catalog/etc/config.xml</strong>文件，你将会看到：</p>
<pre><code>&lt;config&gt;
    &hellip;
    &lt;global&gt;
        &lt;models&gt;
            &lt;catalog&gt;
                &lt;class&gt;Mage_Catalog_Model&lt;/class&gt;
                &hellip;
            &lt;/catalog&gt;
            &hellip;
        &lt;/models&gt;
        &hellip;
    &lt;/global&gt;
    &hellip;
&lt;/config&gt;
</code></pre>
<p>从这里，你可以看到，所有名字以<strong>Mage_Catalog_Model</strong>开始的模块都被定义在Model文件夹下。参数<strong>&lsquo;catalog/product&rsquo;</strong>的第二部分告诉Magento定义类的文件。在这里，是Product.php。</p>
<p>现在，我们有了对的模型，下一步就是告诉我们的模块，哪个产品要被读取。用load($id)方法很容易实现。</p>
<pre><code>$product = $productModel-&gt;load(42);</code></pre>
<p>注意，这里的42只是个id的例子，应该被你需要读取的产品id替换。</p>
<p>在读取我们的产品之后，这里有两种方法从对象里读取数据。</p>
<pre><code>$name = $product-&gt;getName(); // same as $product-&gt;getData('name');
$description = $product-&gt;getData('description'); // same as $product-&gt;getDescription();
</code></pre>
<p>两种方法都很好。但是当读取价格时就有点不一样了。</p>
<pre><code>$price = $product-&gt;getPrice(); // same as $product-&gt;getData('price');
$finalPrice = $product-&gt;getFinalPrice();
</code></pre>
<p>万一我们的产品在任何价格规则下，这两个变量就会有不一样的值。有什么不一样呢？$price变量会显示后台被你编辑过的产品原价。 $finalPrice变量在这里是经过价格规则处理后的价格。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 03 Oct 2015 07:55:41 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中的畅销产品]]></title>
      <link>https://www.360magento.com/blog/bestseller-magento/</link>
      <description><![CDATA[<p>畅销产品是一类人逛Magento商店时会询问和浏览的。默认安装就已经有畅销产品这个功能&hellip;&hellip;但是需要在CMS页面定义一个静态块。我们打算把它提升一下。</p>
<p>Magento已经使用了畅销产品的聚合，你可以在Admin-&gt;Reports-&gt;Products-&gt;Bestsellers下确认。得益于这个被聚合的数据，我们不再需要确认所有订单来知道哪件产品卖得最多。通过各种聚合数据，我们能够获取从开始或者特定时间最受欢迎的产品。</p>
<p>有很多实现的方法。我找到对我最有用的就是每月畅销产品的集合。这个方法快速而且即使聚合表为空时也可以访问产品。</p>
<pre><code>class Alwayly_Luckcy_Block_Bestsellers extends Mage_Core_Block_Template
{
    public function getBestsellerProducts()
    {
        $storeId = (int) Mage::app()-&gt;getStore()-&gt;getId();
 
        // Date
        $date = new Zend_Date();
        $toDate = $date-&gt;setDay(1)-&gt;getDate()-&gt;get('Y-MM-dd');
        $fromDate = $date-&gt;subMonth(1)-&gt;getDate()-&gt;get('Y-MM-dd');
 
        $collection = Mage::getResourceModel('catalog/product_collection')
            -&gt;addAttributeToSelect(Mage::getSingleton('catalog/config')-&gt;getProductAttributes())
            -&gt;addStoreFilter()
            -&gt;addPriceData()
            -&gt;addTaxPercents()
            -&gt;addUrlRewrite()
            -&gt;setPageSize(6);
 
        $collection-&gt;getSelect()
            -&gt;joinLeft(
                array('aggregation' =&gt; $collection-&gt;getResource()-&gt;getTable('sales/bestsellers_aggregated_monthly')),
                "e.entity_id = aggregation.product_id AND aggregation.store_id={$storeId} AND aggregation.period BETWEEN '{$fromDate}' AND '{$toDate}'",
                array('SUM(aggregation.qty_ordered) AS sold_quantity')
            )
            -&gt;group('e.entity_id')
            -&gt;order(array('sold_quantity DESC', 'e.created_at'));
 
        Mage::getSingleton('catalog/product_status')-&gt;addVisibleFilterToCollection($collection);
        Mage::getSingleton('catalog/product_visibility')-&gt;addVisibleInCatalogFilterToCollection($collection);
 
        return $collection;
    }
}
</code></pre>
<p>这段代码的作用是返回上月卖得最多的产品的集合。如果这个逻辑将是或者被使用超过一次，推荐将逻辑加入到分类产品集合文件（扩展这个文件或者使用事件）并在构建集合时作为方法来调用。现在，当产品集合准备好了，这里有更多的方法来将它们展示到前台。我们就以修改首页为例。后台进入CMS-&gt;Page，选择Identifier为'home'的那项。用下面的代码替代content。</p>
<pre><code>&lt;div class="col-left side-col"&gt;
    &lt;p class="home-callout"&gt;&nbsp;
    &lt;p class="home-callout"&gt;&lt;img src="<span>{</span>{skin url='images/ph_callout_left_rebel.jpg'}}" alt="" border="0" /&gt;&lt;/p&gt;
    <span>{</span>{block type="tag/popular" template=&ldquo;tag/popular.phtml"}}
&lt;/div&gt;
&lt;div class="home-spot"&gt;
    &lt;p class="home-callout"&gt;&lt;img src="<span>{</span>{skin url='images/home_main_callout.jpg'}}" alt="" width="470" border="0" /&gt;&lt;/p&gt;
    &lt;p class="home-callout"&gt;&lt;img src="<span>{</span>{skin url='images/free_shipping_callout.jpg'}}" alt="" width="470" border="0" /&gt;&lt;/p&gt;
    <span>{</span>{block type="damir/bestsellers" template=&ldquo;luckcy/bestsellers.phtml"}}
</code></pre>
<p>上面的代码包含了畅销产品块。最后一件事就是创建模版文件。模版文件使用了CMS页面同样的html结构：</p>
<pre><code>
&lt;div class="box best-selling"&gt;
&lt;h3&gt;Best Selling Products&lt;/h3&gt;
&lt;table border="0" cellspacing="0"&gt;
    &lt;tbody&gt;
    &lt;?php $counter=0; foreach ($this-&gt;getBestsellerProducts() as $product): ?&gt;
        &lt;?php if ($counter%2 == 0): ?&gt;&lt;tr class="&lt;?php echo $counter%4 ? 'even' : 'odd'; ?&gt;"&gt;&lt;?php endif ?&gt;
        &lt;td&gt;
            &lt;a href="&lt;?php echo $product-&gt;getProductUrl() ?&gt;"&gt;&lt;img class="product-img" src="&lt;?php echo $this-&gt;helper('catalog/image')-&gt;init($product, 'small_image')-&gt;resize(99); ?&gt;" alt="&lt;?php echo $this-&gt;stripTags($this-&gt;getImageLabel($product, 'small_image'), null, true) ?&gt;" width="95" border="0" /&gt;&lt;/a&gt;
            &lt;div class="product-description"&gt;
                &lt;p&gt;&lt;a href="&lt;?php echo $product--&amp;gtgetProductUrl() ?&gt;"&gt;&lt;?php echo $this-&gt;stripTags($product-&gt;getName(), null, true); ?&gt;&lt;/a&gt;&lt;/p&gt;
            &lt;/div&gt;
        &lt;/td&gt;
        &lt;?php if ($counter++%2): ?&gt;&lt;/tr&gt;&lt;?php endif ?&gt;
    &lt;?php endforeach; ?&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</code></pre>
<p>这个例子使用的是每月聚合，我觉得是最实用的。这里也有每日聚合和每年聚合，但是使用得并不多。许多插件都有同样的功能，只是进行了些包装，最底层的逻辑都是一样的。</p>
<p>由于强烈不推荐修改核心文件，所以每个项目必须至少有一个模型来放置自己的块。如果你对如何创建模块不熟悉，那么可以看看<a href="www.360magento.net" title="magento建站开发">360magento.net</a>中插件开发文章。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 03 Oct 2015 07:40:04 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[以编程的方式添加一个新的客户到Magento商店]]></title>
      <link>https://www.360magento.com/blog/programmaticaly-customers-magento/</link>
      <description><![CDATA[<p>我们程序员喜欢以编程的方式来添加东西。虽然你可以通过一个注册表单或者管理界面来创建一个新的客户。在某些情况下，这可能需要很长时间。如果你有一群来自不同国家的客户要分配给不同的群体，那你最好选择用代码来实现。</p>
<p>首先，我们添加一个带有一些基础信息的客户。</p>
<pre><code>$websiteId = Mage::app()-&gt;getWebsite()-&gt;getId();
$store = Mage::app()-&gt;getStore();
 
$customer = Mage::getModel("customer/customer");
$customer   -&gt;setWebsiteId($websiteId)
            -&gt;setStore($store)
            -&gt;setFirstname('John')
            -&gt;setLastname('Doe')
            -&gt;setEmail('jd1@ex.com')
            -&gt;setPassword('somepassword');
 
try{
    $customer-&gt;save();
}
catch (Exception $e) {
    Zend_Debug::dump($e-&gt;getMessage());
}
</code></pre>
<p>正如我们所见，上面的代码添加的用户只有姓、名、邮箱和密码。有时这些就够了，但我们可以做到更多。你可以添加中间名，把客户分配到特定的客户群，甚至给他们的名字加前缀或后缀。</p>
<pre><code>$customer   -&gt;setWebsiteId($websiteId)
            -&gt;setStore($store)
            -&gt;setGroupId(2)
            -&gt;setPrefix('Sir')
            -&gt;setFirstname('John')
            -&gt;setMiddleName('2')
            -&gt;setLastname('Doe')
            -&gt;setSuffix('II')
            -&gt;setEmail('jd2@ex.com')
            -&gt;setPassword('somepassword');
</code></pre>
<p>为了让客户能下订单，我们需要添加一个地址并分配给客户。让我们实现它吧。</p>
<pre><code>$address = Mage::getModel("customer/address");
$address-&gt;setCustomerId($customer-&gt;getId())
        -&gt;setFirstname($customer-&gt;getFirstname())
        -&gt;setMiddleName($customer-&gt;getMiddlename())
        -&gt;setLastname($customer-&gt;getLastname())
        -&gt;setCountryId('HR')
		//-&gt;setRegionId('1') //state/province, only needed if the country is USA
        -&gt;setPostcode('31000')
        -&gt;setCity('Osijek')
        -&gt;setTelephone('0038511223344')
        -&gt;setFax('0038511223355')
        -&gt;setCompany('Inchoo')
        -&gt;setStreet('Kersov')
        -&gt;setIsDefaultBilling('1')
        -&gt;setIsDefaultShipping('1')
        -&gt;setSaveInAddressBook('1');
 
try{
    $address-&gt;save();
}
catch (Exception $e) {
    Zend_Debug::dump($e-&gt;getMessage());
}
</code></pre>
<p>要注意的是，setCountryID需要国家代码来作为值（你可以在后台通过检索客户创建页面'Country'输入框来获值）。上面的setGroupId方法也一样，你需要获取客户群的ID。</p>
<p>我希望大部分代码是不言自明的，由于我们从管理页面添加客户时知道哪些是必填项。唯一你要注意的就是必填项。</p>
<p>万一你有多个用户要添加，你可以花几秒钟为这段代码添加一个循环。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 02 Oct 2015 10:57:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中以编程的方式创建捆绑产品]]></title>
      <link>https://www.360magento.com/blog/programmatically-magento-bundle/</link>
      <description><![CDATA[<p>如果说这是一个系列文章，那么这就是第三个了。如果你之前看过了Magento中简单产品和可配置产品的创建，那你已经了解了基础。</p>
<p>这篇文章中我们将扩展知识，学习如何用编程的方式创建Magento的捆绑产品。</p>
<p>捆绑产品就是你想要批量销售的产品。从图片中可能会让你有更好的了解。我们以Magento示例数据中的一个产品为例：</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento在首页显示登陆注册框，创建magento下拉登陆框" src="http://7xjryy.com1.z0.glb.clouddn.com/bundle-sample1-600x362.png" height="362" width="600" /></div>
<p>我们可以看到这个产品的每个自定义选项值都会对应一个捆绑相关的简单产品。例如，Camera选项有 Madison LX2200和Madison RX3400，它们对应不同的简单产品。现在我们跳过基础部分，我们将创建一个捆绑产品必要的两个选项，每一个选项有两个值来表示不同的产品。</p>
<pre><code>$bundleProduct = Mage::getModel('catalog/product');
    $bundleProduct
    -&gt;setStoreId(Mage_Core_Model_App::ADMIN_STORE_ID) //you can set data in store scope
        -&gt;setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
        -&gt;setAttributeSetId(20) //ID of a attribute set named 'default'
        -&gt;setTypeId('bundle') //product type
        -&gt;setCreatedAt(strtotime('now')) //product creation time
//    -&gt;setUpdatedAt(strtotime('now')) //product update time
        -&gt;setSkuType(0) //SKU type (0 - dynamic, 1 - fixed)
        -&gt;setSku('bundlexx1') //SKU
        -&gt;setName('test bundle product96') //product name
        -&gt;setWeightType(0) //weight type (0 - dynamic, 1 - fixed)
//        -&gt;setWeight(4.0000)
        -&gt;setShipmentType(0) //shipment type (0 - together, 1 - separately)
        -&gt;setStatus(1) //product status (1 - enabled, 2 - disabled)
        -&gt;setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) //catalog and search visibility
        -&gt;setManufacturer(28) //manufacturer id
        -&gt;setColor(24)
        -&gt;setNewsFromDate('06/26/2014') //product set as new from
        -&gt;setNewsToDate('06/30/2014') //product set as new to
        -&gt;setCountryOfManufacture('AF') //country of manufacture (2-letter country code)
        -&gt;setPriceType(0) //price type (0 - dynamic, 1 - fixed)
        -&gt;setPriceView(0) //price view (0 - price range, 1 - as low as)
        -&gt;setSpecialPrice(00.44) //special price in form 11.22
        -&gt;setSpecialFromDate('06/1/2014') //special price from (MM-DD-YYYY)
        -&gt;setSpecialToDate('06/30/2014') //special price to (MM-DD-YYYY)
        /*only available if price type is 'fixed'*/
//        -&gt;setPrice(11.22) //price, works only if price type is fixed
//        -&gt;setCost(22.33) //price in form 11.22
//        -&gt;setMsrpEnabled(1) //enable MAP
//        -&gt;setMsrpDisplayActualPriceType(1) //display actual price (1 - on gesture, 2 - in cart, 3 - before order confirmation, 4 - use config)
//        -&gt;setMsrp(99.99) //Manufacturer's Suggested Retail Price
//        -&gt;setTaxClassId(4) //tax class (0 - none, 1 - default, 2 - taxable, 4 - shipping)
        /*only available if price type is 'fixed'*/
        -&gt;setMetaTitle('test meta title 2')
        -&gt;setMetaKeyword('test meta keyword 2')
        -&gt;setMetaDescription('test meta description 2')
        -&gt;setDescription('This is a long description')
        -&gt;setShortDescription('This is a short description')
        -&gt;setMediaGallery(array('images' =&gt; array(), 'values' =&gt; array())) //media gallery initialization
        -&gt;setStockData(array(
                'use_config_manage_stock' =&gt; 1, //'Use config settings' checkbox
                'manage_stock' =&gt; 1, //manage stock
                'is_in_stock' =&gt; 1, //Stock Availability
            )
        )
        -&gt;setCategoryIds(array(4, 10)); //assign product to categories
 
    $bundleOptions = array();
    $bundleOptions = array(
        '0' =&gt; array( //option id (0, 1, 2, etc)
            'title' =&gt; 'item01', //option title
            'option_id' =&gt; '',
            'delete' =&gt; '',
            'type' =&gt; 'select', //option type
            'required' =&gt; '1', //is option required
            'position' =&gt; '1' //option position
        ),
        '1' =&gt; array(
            'title' =&gt; 'item02',
            'option_id' =&gt; '',
            'delete' =&gt; '',
            'type' =&gt; 'multi',
            'required' =&gt; '1',
            'position' =&gt; '1'
        )
    );
 
    $bundleSelections = array();
    $bundleSelections = array(
        '0' =&gt; array( //option ID
            '0' =&gt; array( //selection ID of the option (first product under this option (option ID) would have ID of 0, second an ID of 1, etc)
                'product_id' =&gt; '554', //if of a product in selection
                'delete' =&gt; '',
                'selection_price_value' =&gt; '10',
                'selection_price_type' =&gt; 0,
                'selection_qty' =&gt; 1,
                'selection_can_change_qty' =&gt; 0,
                'position' =&gt; 0,
                'is_default' =&gt; 1
            ),
 
            '1' =&gt; array(
                'product_id' =&gt; '553',
                'delete' =&gt; '',
                'selection_price_value' =&gt; '10',
                'selection_price_type' =&gt; 0,
                'selection_qty' =&gt; 1,
                'selection_can_change_qty' =&gt; 0,
                'position' =&gt; 0,
                'is_default' =&gt; 1
            )
        ),
        '1' =&gt; array( //option ID
            '0' =&gt; array(
                'product_id' =&gt; '552',
                'delete' =&gt; '',
                'selection_price_value' =&gt; '10',
                'selection_price_type' =&gt; 0,
                'selection_qty' =&gt; 1,
                'selection_can_change_qty' =&gt; 0,
                'position' =&gt; 0,
                'is_default' =&gt; 1
            ),
 
            '1' =&gt; array(
                'product_id' =&gt; '551',
                'delete' =&gt; '',
                'selection_price_value' =&gt; '10',
                'selection_price_type' =&gt; 0,
                'selection_qty' =&gt; 1,
                'selection_can_change_qty' =&gt; 0,
                'position' =&gt; 0,
                'is_default' =&gt; 1
            )
        )
    );
    //flags for saving custom options/selections
    $bundleProduct-&gt;setCanSaveCustomOptions(true);
    $bundleProduct-&gt;setCanSaveBundleSelections(true);
    $bundleProduct-&gt;setAffectBundleProductSelections(true);
 
    //registering a product because of Mage_Bundle_Model_Selection::_beforeSave
    Mage::register('product', $bundleProduct);
 
    //setting the bundle options and selection data
    $bundleProduct-&gt;setBundleOptionsData($bundleOptions);
    $bundleProduct-&gt;setBundleSelectionsData($bundleSelections);
 
    $bundleProduct-&gt;save();
    echo 'success';
} catch (Exception $e) {
    Mage::log($e-&gt;getMessage());
    echo $e-&gt;getMessage();
}
</code></pre>
<p>你可以在每行代码找到注释。我尽可能多地注释，这样有利于你们去理解。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 01 Oct 2015 09:31:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[实现Magento中的rel备用链接]]></title>
      <link>https://www.360magento.com/blog/magento-rel-links/</link>
      <description><![CDATA[<p>随着电子商务的发展，商品销往全球比以前容易多了。互联网没有界限，任何人都可以在舒适的家里访问你的商店。对于多店铺的需求也是日益明显。也许你希望让你的客户访问你的网站时看到的是自己的语言。</p>
<p>当你设置你的多店铺时，Google有些指导和建议。这样能让你的网站索引更正确，排名更高。其中一条建议就是：如果你有翻译成其它语言的页面，使用rel="alternate"的链接。</p>
<p>我们使用的语法看起来就像这样：</p>
<pre><code>&lt;link rel="alternate" hreflang="es" href="http://es.example.com/" /&gt;
</code></pre>
<p>如果把这个语法应用到Magento里，那看起来就像这样：</p>
<pre><code>
<link href="url-of-the-page-in-other-language" rel="alternate" />
</code></pre>
<p>现在我们就有了思路。让我们以注册我们的模块开始。</p>
<p><strong>app/etc/modules/Alwayly_Alternate.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Alternate&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_Alternate&gt;
   &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>让我们谈下模块的设置。我们需要做的就是把alternate链接放到每个页面的头部。一种方法就是在head.phtm文件里创建逻辑请求。更好的方式是，使用观测者监听一些时间，然后使用Magento中已经存在的addLinkRel（）方法加入到head里。</p>
<p>在这个例子里，我们将使用<strong>controller_action_layout_generate_blocks_after</strong>事件。也许这儿还有些更合适的事件，但这一次就用它了。</p>
<p><strong>app/code/local/Alwayly/Alternate/etc/config.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Alternate&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
        &lt;/Alwayly_Alternate&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;helpers&gt;
            &lt;alwayly_alternate&gt;
                &lt;class&gt;Alwayly_Alternate_Helper&lt;class&gt;
            &lt;/alwayly_alternate&gt;
        &lt;/helpers&gt;
    &lt;/global&gt;
    &lt;frontend&gt;
        &lt;events&gt;
            &lt;controller_action_layout_generate_blocks_after&gt;
                &lt;observers&gt;
                    &lt;alwayly_alternate&gt;
                        &lt;type&gt;singleton&lt;/type&gt;
                        &lt;class&gt;Alwayly_Alternate_Model_Observer&lt;/class&gt;
                        &lt;method&gt;alternateLinks&lt;/method&gt;
                    &lt;/alwayly_alternate&gt;
                &lt;/observers&gt;
            &lt;/controller_action_layout_generate_blocks_after&gt;
        &lt;/events&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>我们只是定义了观测者的名字和方法，现在来创建它。</p>
<p><strong>app/code/local/Alwayly/Alternate/Model/Observer.php</strong></p>
<pre><code>
class Alwayly_Alternate_Model_Observer
{
 public function alternateLinks()
 {
   $headBlock = Mage::app()-&gt;getLayout()-&gt;getBlock('head');
 
   $stores = Mage::app()-&gt;getStores();
   $prod = Mage::registry('current_product');
   $categ = Mage::registry('current_category');
 
   if($headblock)
   {
     foreach ($stores as $store)
     {
       if($prod){
         $categ ? $categId=$categ-&gt;getId() : $categId = null;
         $url = $store-&gt;getBaseUrl() . Mage::helper('alwayly_alternate')-&gt;rewrittenProductUrl($prod-&gt;getId(), $categId, $store-&gt;getId());
       }else{
         $store-&gt;getCurrentUrl();
       }
       $storeCode = substr(Mage::getStoreConfig('general/locale/code', $store-&gt;getId()),0,2);
       $headBlock-&gt;addLinkRel('alternate"' . ' hreflang="' . $storeCode, $url);
     }
   }
   return $this;
 }
}
</code></pre>
<p>如你所见，我们循环所有的商店。当一个产品被设置，我们检查它的URL是否被重写。这是我们的助手要做的。如果一个产品没被设置，用getCurrentUrl()方法，我们能获取不同商店中的当前URL。</p>
<p>例如我们现在的URL是 www.example.com/shirts.html，在德语版的商店，它会是www.example.com/shirts.html?___store=german或者是www.example.com/de/shirts.html，这取决于你的Magento设置。</p>
<p>下一步，我们将获取区域代码的前一到两个字母。如果你有两个英文商店，一个为英国，一个为美国，那就完美了。在得到我们所要的信息后，我们将调用head块，使用addLinRel()方法将链接加到head。</p>
<p>现在，创建你的助手。</p>
<pre><code>
&lt;?php
class Alwayly_Alternate_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function rewrittenProductUrl($productId, $categoryId, $storeId)
    {
        $coreUrl = Mage::getModel('core/url_rewrite');
        $idPath = sprintf('product/%d', $productId);
        if ($categoryId) {
            $idPath = sprintf('%s/%d', $idPath, $categoryId);
        }
        $coreUrl-&gt;setStoreId($storeId);
        $coreUrl-&gt;loadByIdPath($idPath);
        return $coreUrl-&gt;getRequestPath();
    }
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 01 Oct 2015 09:23:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在Magento网格列表中展示产品缩略图]]></title>
      <link>https://www.360magento.com/blog/grids-show-thumbnail/</link>
      <description><![CDATA[<p>编辑产品和改变产品在类别中的位置是一项不小的任务。特别是有一大堆产品需要编辑和排列，而且其中有些又很相似。</p>
<p>当然，你可以通过SKU，ID，价格或者其它的一些东西来区别它们。但是都不会比在网格列表中展示缩略图好。</p>
<p>在产品网格列表里展示缩略图并不复杂。有几种方法可以实现这个功能，但是几乎所有的方法都用到了渲染器去展示产品图片，就和我们即将做的一样。</p>
<p>在这个例子中，我们将注册我们的模块，重写一个Magento后太网格的块&mdash;&mdash;特别是<strong>&ldquo;Manage Categories&rdquo;</strong>，还要添加我们的代码来显示缩略图这个附加列。</p>
<p>让我们开始吧！</p>
<p>首先，注册我们的模块</p>
<p><strong>app/etc/modules/Alwayly_Thumbnail.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Thumbnail&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_Thumbnail&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>现在，配置你的模块，用你自己的版本来重写 <strong>&lsquo;catalog_category_tab_product&lsquo; </strong>块。</p>
<p><strong>app/code/local/Alwayly/Thumbnail/etc/config.xml</strong></p>
<pre><code>&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Thumbnail&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
        &lt;/Alwayly_Thumbnail&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;adminhtml&gt;
                &lt;rewrite&gt;                    &lt;catalog_category_tab_product&gt;Alwayly_Thumbnail_Block_Adminhtml_Catalog_Category_Tab_Product&lt;/catalog_category_tab_product&gt;
                &lt;/rewrite&gt;
            &lt;/adminhtml&gt;
        &lt;/blocks&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>将<strong>app/code/core/Mage/Adminhtml/Block/Catalog/Category/Tab/Product.php</strong>中的代码粘贴到<strong>app/code/local/Alwayly/Thumbnail/Block/Adminhtml/Catalog/Category/Tab/Product.php</strong></p>
<pre><code>&lt;?php
class Alwayly_Thumbnail_Block_Adminhtml_Catalog_Category_Tab_Product extends Mage_Adminhtml_Block_Widget_Grid
{
    public function __construct()
    {
        parent::__construct();
        $this-&gt;setId('catalog_category_products');
        $this-&gt;setDefaultSort('entity_id');
        $this-&gt;setUseAjax(true);
    }
 
    public function getCategory()
    {
        return Mage::registry('category');
    }
 
    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in category flag
        if ($column-&gt;getId() == 'in_category') {
            $productIds = $this-&gt;_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column-&gt;getFilter()-&gt;getValue()) {
                $this-&gt;getCollection()-&gt;addFieldToFilter('entity_id', array('in'=&gt;$productIds));
            }
            elseif(!empty($productIds)) {
                $this-&gt;getCollection()-&gt;addFieldToFilter('entity_id', array('nin'=&gt;$productIds));
            }
        }
        else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }
 
    protected function _prepareCollection()
    {
        if ($this-&gt;getCategory()-&gt;getId()) {
            $this-&gt;setDefaultFilter(array('in_category'=&gt;1));
        }
        $collection = Mage::getModel('catalog/product')-&gt;getCollection()
                          -&gt;addAttributeToSelect('name')
                          -&gt;addAttributeToSelect('sku')
                          -&gt;addAttributeToSelect('price')
                          -&gt;addAttributeToSelect('thumbnail')
                          -&gt;addStoreFilter($this-&gt;getRequest()-&gt;getParam('store'))
                          -&gt;joinField('position',
                                      'catalog/category_product',
                                      'position',
                                      'product_id=entity_id',
                                      'category_id='.(int) $this-&gt;getRequest()-&gt;getParam('id', 0),
                                      'left');
        $this-&gt;setCollection($collection);
 
        if ($this-&gt;getCategory()-&gt;getProductsReadonly()) {
            $productIds = $this-&gt;_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            $this-&gt;getCollection()-&gt;addFieldToFilter('entity_id', array('in'=&gt;$productIds));
        }
 
        return parent::_prepareCollection();
    }
 
    protected function _prepareColumns()
    {
        if (!$this-&gt;getCategory()-&gt;getProductsReadonly()) {
            $this-&gt;addColumn('in_category', array(
                'header_css_class' =&gt; 'a-center',
                'type'      =&gt; 'checkbox',
                'name'      =&gt; 'in_category',
                'values'    =&gt; $this-&gt;_getSelectedProducts(),
                'align'     =&gt; 'center',
                'index'     =&gt; 'entity_id'
            ));
        }
        $this-&gt;addColumn('entity_id', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('ID'),
            'sortable'  =&gt; true,
            'width'     =&gt; '60',
            'index'     =&gt; 'entity_id'
        ));
        $this-&gt;addColumn('name', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Name'),
            'index'     =&gt; 'name'
        ));
        $this-&gt;addColumn('image', array(
            'header' =&gt; Mage::helper('catalog')-&gt;__('Image'),
            'align' =&gt; 'left',
            'index' =&gt; 'image',
            'width'     =&gt; '97',
            'renderer' =&gt; 'Alwayly_Thumbnail_Block_Adminhtml_Template_Grid_Renderer_Image'
        ));
        $this-&gt;addColumn('sku', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('SKU'),
            'width'     =&gt; '80',
            'index'     =&gt; 'sku'
        ));
        $this-&gt;addColumn('price', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Price'),
            'type'  =&gt; 'currency',
            'width'     =&gt; '1',
            'currency_code' =&gt; (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE),
            'index'     =&gt; 'price'
        ));
        $this-&gt;addColumn('position', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Position'),
            'width'     =&gt; '1',
            'type'      =&gt; 'number',
            'index'     =&gt; 'position',
            'editable'  =&gt; !$this-&gt;getCategory()-&gt;getProductsReadonly()
            //'renderer'  =&gt; 'adminhtml/widget_grid_column_renderer_input'
        ));
 
        return parent::_prepareColumns();
    }
 
    public function getGridUrl()
    {
        return $this-&gt;getUrl('*/*/grid', array('_current'=&gt;true));
    }
 
    protected function _getSelectedProducts()
    {
        $products = $this-&gt;getRequest()-&gt;getPost('selected_products');
        if (is_null($products)) {
            $products = $this-&gt;getCategory()-&gt;getProductsPosition();
            return array_keys($products);
        }
        return $products;
    }
}
</code></pre>
<p>现在，插入上面的代码，这将选择一个产品的附加属性&mdash;&mdash;&ldquo;thumbnail&rdquo;，创建一个名为&ldquo;Image&rdquo;的列。注意到，你可以在任何包含产品的网格里做这些，只需要重写一个不同的块。</p>
<p>最后，我们将创建一个在89行被调用的自己的渲染器。</p>
<pre><code>
'renderer' =&gt; 'Alwayly_Thumbnail_Block_Adminhtml_Template_Grid_Renderer_Image'

app/code/local/Alwayly/Thumbnail/Block/Adminhtml/Template/Grid/Renderer/Image.php
&lt;?php
class Alwayly_Thumbnail_Block_Adminhtml_Template_Grid_Renderer_Image extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
    public function render(Varien_Object $row)
    {
        $val = Mage::helper('catalog/image')-&gt;init($row, 'thumbnail')-&gt;resize(97);
        $out = "&lt;img src=". $val ." width='97px'/&gt;";
        return $out;
    }
}
</code></pre>
<p>这个渲染器获取了一行对象作为一个参数。它调用的图像助手初始化缩略图大小并重新调整为97像素（你可以改成你需要或喜欢的大小）。之后，它返回出现在你网格里的图像标签。我们还需要考虑到产品没有图片的情况。</p>
<p>最快捷的方式是复制产品占位符（placeholder）图像。我将Magento默认的占位符图像<strong>（skin\adminhtml\default\default\images\placeholder\thumbnail.jpg）</strong>拷贝到<strong>skin\adminhtml\default\default\images\catalog\product\placeholder\thumbnail.jpg</strong></p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 30 Sep 2015 08:07:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用编程的方式创建一个可配置产品]]></title>
      <link>https://www.360magento.com/blog/programmatically-magento-configurable/</link>
      <description><![CDATA[<p>之前写过一篇关于在Magento中用编程创建简单产品的文章。那么，对于可配置产品来说，事情就变得复杂了点。</p>
<p>如你所知，可配置产品就是由配置了不同选项（属性）的简单产品组成的。我们可以用这个结论来扩展我们创建简单产品的代码来进行配置。</p>
<pre><code>Mage::app()-&gt;setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$simpleProduct = Mage::getModel('catalog/product');
try {
$simpleProduct
//    -&gt;setStoreId(1) //you can set data in store scope
    -&gt;setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
    -&gt;setAttributeSetId(20) //ID of a attribute set named 'default'
    -&gt;setTypeId('simple') //product type
    -&gt;setCreatedAt(strtotime('now')) //product creation time
//    -&gt;setUpdatedAt(strtotime('now')) //product update time
    -&gt;setSku('simple99y') //SKU
    -&gt;setName('test simple product99') //product name
    -&gt;setWeight(4.0000)
    -&gt;setStatus(1) //product status (1 - enabled, 2 - disabled)
    -&gt;setTaxClassId(4) //tax class (0 - none, 1 - default, 2 - taxable, 4 - shipping)
    -&gt;setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) //catalog and search visibility
    -&gt;setManufacturer(28) //manufacturer id
    -&gt;setColor(24)
    -&gt;setNewsFromDate('06/26/2014') //product set as new from
    -&gt;setNewsToDate('06/30/2014') //product set as new to
    -&gt;setCountryOfManufacture('AF') //country of manufacture (2-letter country code)
    -&gt;setPrice(11.22) //price in form 11.22
    -&gt;setCost(22.33) //price in form 11.22
    -&gt;setSpecialPrice(00.44) //special price in form 11.22
    -&gt;setSpecialFromDate('06/1/2014') //special price from (MM-DD-YYYY)
    -&gt;setSpecialToDate('06/30/2014') //special price to (MM-DD-YYYY)
    -&gt;setMsrpEnabled(1) //enable MAP
    -&gt;setMsrpDisplayActualPriceType(1) //display actual price (1 - on gesture, 2 - in cart, 3 - before order confirmation, 4 - use config)
    -&gt;setMsrp(99.99) //Manufacturer's Suggested Retail Price
    -&gt;setMetaTitle('test meta title 2')
    -&gt;setMetaKeyword('test meta keyword 2')
    -&gt;setMetaDescription('test meta description 2')
    -&gt;setDescription('This is a long description')
    -&gt;setShortDescription('This is a short description')
    -&gt;setMediaGallery(array('images' =&gt; array(), 'values' =&gt; array())) //media gallery initialization
    -&gt;setStockData(array(
            'use_config_manage_stock' =&gt; 0, //'Use config settings' checkbox
            'manage_stock' =&gt; 1, //manage stock
            'min_sale_qty' =&gt; 1, //Minimum Qty Allowed in Shopping Cart
            'max_sale_qty' =&gt; 2, //Maximum Qty Allowed in Shopping Cart
            'is_in_stock' =&gt; 1, //Stock Availability
            'qty' =&gt; 999 //qty
        )
    )
    -&gt;setCategoryIds(array(3, 10)); //assign product to categories
    $simpleProduct-&gt;save();
} catch (Exception $e) {
    Mage::log($e-&gt;getMessage());
    echo $e-&gt;getMessage();
}
</code></pre>
<p>上面的代码将创建一个简单产品，这里我就不详细讲了。如果你想要深入了解，你可以点击<a title="电商网站建设" href="http://www.360magento.com/blog/programmatically-magento-simple">这个链接</a>看看我之前的那篇文章。</p>
<p>现在我们要做的就是创建一个可配置产品并把这个简单产品指向它。</p>
<pre><code>$configProduct = Mage::getModel('catalog/product');,
try {
$configProduct
//    -&gt;setStoreId(1) //you can set data in store scope
        -&gt;setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
        -&gt;setAttributeSetId(20) //ID of a attribute set named 'default'
        -&gt;setTypeId('configurable') //product type
        -&gt;setCreatedAt(strtotime('now')) //product creation time
//    -&gt;setUpdatedAt(strtotime('now')) //product update time
        -&gt;setSku('configurable96') //SKU
        -&gt;setName('test config product96') //product name
        -&gt;setWeight(4.0000)
        -&gt;setStatus(1) //product status (1 - enabled, 2 - disabled)
        -&gt;setTaxClassId(4) //tax class (0 - none, 1 - default, 2 - taxable, 4 - shipping)
        -&gt;setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) //catalog and search visibility
        -&gt;setManufacturer(28) //manufacturer id
        -&gt;setNewsFromDate('06/26/2014') //product set as new from
        -&gt;setNewsToDate('06/30/2014') //product set as new to
        -&gt;setCountryOfManufacture('AF') //country of manufacture (2-letter country code)
        -&gt;setPrice(11.22) //price in form 11.22
        -&gt;setCost(22.33) //price in form 11.22
        -&gt;setSpecialPrice(00.44) //special price in form 11.22
        -&gt;setSpecialFromDate('06/1/2014') //special price from (MM-DD-YYYY)
        -&gt;setSpecialToDate('06/30/2014') //special price to (MM-DD-YYYY)
        -&gt;setMsrpEnabled(1) //enable MAP
        -&gt;setMsrpDisplayActualPriceType(1) //display actual price (1 - on gesture, 2 - in cart, 3 - before order confirmation, 4 - use config)
        -&gt;setMsrp(99.99) //Manufacturer's Suggested Retail Price
        -&gt;setMetaTitle('test meta title 2')
        -&gt;setMetaKeyword('test meta keyword 2')
        -&gt;setMetaDescription('test meta description 2')
        -&gt;setDescription('This is a long description')
        -&gt;setShortDescription('This is a short description')
        -&gt;setMediaGallery(array('images' =&gt; array(), 'values' =&gt; array())) //media gallery initialization
        -&gt;setStockData(array(
                'use_config_manage_stock' =&gt; 0, //'Use config settings' checkbox
                'manage_stock' =&gt; 1, //manage stock
                'is_in_stock' =&gt; 1, //Stock Availability
            )
        )
        -&gt;setCategoryIds(array(3, 10)) //assign product to categories
    ;
    /**/
    /** assigning associated product to configurable */
    /**/
    $configProduct-&gt;getTypeInstance()-&gt;setUsedProductAttributeIds(array(92)); //attribute ID of attribute 'color' in my store
    $configurableAttributesData = $configProduct-&gt;getTypeInstance()-&gt;getConfigurableAttributesAsArray();
 
    $configProduct-&gt;setCanSaveConfigurableAttributes(true);
    $configProduct-&gt;setConfigurableAttributesData($configurableAttributesData);
 
    $configurableProductsData = array();
    $configurableProductsData['920'] = array( //['920'] = id of a simple product associated with this configurable
        '0' =&gt; array(
            'label' =&gt; 'Green', //attribute label
            'attribute_id' =&gt; '92', //attribute ID of attribute 'color' in my store
            'value_index' =&gt; '24', //value of 'Green' index of the attribute 'color'
            'is_percent' =&gt; '0', //fixed/percent price for this option
            'pricing_value' =&gt; '21' //value for the pricing
        )
    );
    $configProduct-&gt;setConfigurableProductsData($configurableProductsData);
    $configProduct-&gt;save();
 
    echo 'success';
} catch (Exception $e) {
    Mage::log($e-&gt;getMessage());
    echo $e-&gt;getMessage();
}
</code></pre>
<p>就是这样了！你的可配置产品被合理设置并在前台可见。值得注意的是，你需要分配同样的属性集到可配置产品和它相关的产品。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 30 Sep 2015 07:33:53 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[以编程方式（手动）创建Magento中的简单产品]]></title>
      <link>https://www.360magento.com/blog/programmatically-magento-simple/</link>
      <description><![CDATA[<p>在开发过程中，你经常需要一些可用的数据来做测试。Magento提供了包含一些产品的示例数据。可事实是，当你创建了自己的属性集或者产品类型，想要加入到你的产品里去时，这个示例数据就显得没什么用了。针对这点，你需要自己添加一些商品。</p>
<p>有时在后台添加就可以了，但当你要添加多种产品、继续开发新特征或者做一些大的改动时，用后台操作就变得很痛苦了。这个问题用编程方式来添加产品就能轻松解决了。我将用这种方法来添加一个简单产品。你可以修改一下这个代码来适应其它产品类型，也可以用它来作为产品导入脚本。</p>
<p>你可以通过一个observer来调用，设置为一个控制器方法，或者从一个视图文件中调用，随你喜欢。要注意的是，当你观测一些事件时不要使用调用每个控制器方法的那个。如果你使用了，那么确定产品中是否存在同样的SKU。针对这种情况，你可以用下面代码中第四行的&ldquo;if&rdquo;判断。</p>
<p>如果你没有按照我说的做，那么会出现下面的SQL报错：</p>
<pre><code>SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '193-1' for key 'UNQ_CATALOGINVENTORY_STOCK_ITEM_PRODUCT_ID_STOCK_ID'
</code></pre>
<p>下面就是我提到的代码：</p>
<pre><code>&lt;?php
Mage::app()-&gt;setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
$product = Mage::getModel('catalog/product');
//    if(!$product-&gt;getIdBySku('testsku61')):
 
try{
$product
//    -&gt;setStoreId(1) //you can set data in store scope
    -&gt;setWebsiteIds(array(1)) //website ID the product is assigned to, as an array
    -&gt;setAttributeSetId(9) //ID of a attribute set named 'default'
    -&gt;setTypeId('simple') //product type
    -&gt;setCreatedAt(strtotime('now')) //product creation time
//    -&gt;setUpdatedAt(strtotime('now')) //product update time
 
    -&gt;setSku('testsku61') //SKU
    -&gt;setName('test product21') //product name
    -&gt;setWeight(4.0000)
    -&gt;setStatus(1) //product status (1 - enabled, 2 - disabled)
    -&gt;setTaxClassId(4) //tax class (0 - none, 1 - default, 2 - taxable, 4 - shipping)
    -&gt;setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH) //catalog and search visibility
    -&gt;setManufacturer(28) //manufacturer id
    -&gt;setColor(24)
    -&gt;setNewsFromDate('06/26/2014') //product set as new from
    -&gt;setNewsToDate('06/30/2014') //product set as new to
    -&gt;setCountryOfManufacture('AF') //country of manufacture (2-letter country code)
 
    -&gt;setPrice(11.22) //price in form 11.22
    -&gt;setCost(22.33) //price in form 11.22
    -&gt;setSpecialPrice(00.44) //special price in form 11.22
    -&gt;setSpecialFromDate('06/1/2014') //special price from (MM-DD-YYYY)
    -&gt;setSpecialToDate('06/30/2014') //special price to (MM-DD-YYYY)
    -&gt;setMsrpEnabled(1) //enable MAP
    -&gt;setMsrpDisplayActualPriceType(1) //display actual price (1 - on gesture, 2 - in cart, 3 - before order confirmation, 4 - use config)
    -&gt;setMsrp(99.99) //Manufacturer's Suggested Retail Price
 
    -&gt;setMetaTitle('test meta title 2')
    -&gt;setMetaKeyword('test meta keyword 2')
    -&gt;setMetaDescription('test meta description 2')
 
    -&gt;setDescription('This is a long description')
    -&gt;setShortDescription('This is a short description')
 
    -&gt;setMediaGallery (array('images'=&gt;array (), 'values'=&gt;array ())) //media gallery initialization
    -&gt;addImageToMediaGallery('media/catalog/product/1/0/10243-1.png', array('image','thumbnail','small_image'), false, false) //assigning image, thumb and small image to media gallery
 
    -&gt;setStockData(array(
                       'use_config_manage_stock' =&gt; 0, //'Use config settings' checkbox
                       'manage_stock'=&gt;1, //manage stock
                       'min_sale_qty'=&gt;1, //Minimum Qty Allowed in Shopping Cart
                       'max_sale_qty'=&gt;2, //Maximum Qty Allowed in Shopping Cart
                       'is_in_stock' =&gt; 1, //Stock Availability
                       'qty' =&gt; 999 //qty
                   )
    )
 
    -&gt;setCategoryIds(array(3, 10)); //assign product to categories
$product-&gt;save();
//endif;
}catch(Exception $e){
Mage::log($e-&gt;getMessage());
}</code></pre>
<p>我们设定这款产品在&ldquo;默认值&rdquo;范围。您可以为一个特定的商店取消第5行的代码来设置产品数据，。例如，你可以这样做：</p>
<pre><code>...
    -&gt;setMetaTitle('test meta title 2')
    -&gt;setMetaKeyword('test meta keyword 2')
    -&gt;setMetaDescription('test meta description 2')
    -&gt;setStoreId(2)
    -&gt;setMetaTitle('Some other meta title')
    -&gt;setMetaKeyword('Some other meta keyword')
    -&gt;setMetaDescription('Some other meta description')
$product-&gt;save();
</code></pre>
<p>上面的代码将为ID为2的商店设置不同的meta name。</p>
<p>你可以通过登录到产品存储传输数据来找到所有你能设置的产品值。我在考虑当你存储商品是后台调用的ProductController里的saveAction方法。 <strong>app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php</strong></p>
<pre><code>public function saveAction()
{
    $storeId        = $this-&gt;getRequest()-&gt;getParam('store');
    $redirectBack   = $this-&gt;getRequest()-&gt;getParam('back', false);
    $productId      = $this-&gt;getRequest()-&gt;getParam('id');
    $isEdit         = (int)($this-&gt;getRequest()-&gt;getParam('id') != null);
 
    $data = $this-&gt;getRequest()-&gt;getPost();
    if ($data) {
        Mage::log($data);</code></pre>
<p>只需要把最后一行代码加入到相应的位置。当你完成开发以后记得删除。这将获取一个你存储的数据的数组。例如，为了设置 [meta_title]，你会使用setMetaTitle(&lsquo;somevalue&rsquo;)魔术方法。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 29 Sep 2015 03:16:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[获取magento可配置产品里被选中的简单产品]]></title>
      <link>https://www.360magento.com/blog/simple-id-in-configurable/</link>
      <description><![CDATA[<p>如果你想在Magento客户端获取可配置产品里被选中的简单产品，你有很多种不同的方法。</p>
<p>这里有一种简单的方法，不用代码修改，不要新的模版甚至模。值需要一个Java脚本和布局更新。</p>
<pre><code>
Product.Config.prototype.getIdOfSelectedProduct = function()
{
     var existingProducts = new Object();
 
     for(var i=this.settings.length-1;i&gt;=0;i--)
     {
         var selected = this.settings[i].options[this.settings[i].selectedIndex];
         if(selected.config)
         {
         	for(var iproducts=0;iproducts&lt;selected.config.products.length;iproducts++)
         	{
         		var usedAsKey = selected.config.products[iproducts]+"";
         		if(existingProducts[usedAsKey]==undefined)
         		{
         			existingProducts[usedAsKey]=1;
         		}
         		else
         		{
         			existingProducts[usedAsKey]=existingProducts[usedAsKey]+1;
         		}
             }
         }
     }
 
     for (var keyValue in existingProducts)
     {
     	for ( var keyValueInner in existingProducts)
         {
         	if(Number(existingProducts[keyValueInner])&lt;Number(existingProducts[keyValue]))
         	{
         		delete existingProducts[keyValueInner];
         	}
         }
     }
 
     var sizeOfExistingProducts=0;
     var currentSimpleProductId = "";
     for ( var keyValue in existingProducts)
     {
     	currentSimpleProductId = keyValue;
     	sizeOfExistingProducts=sizeOfExistingProducts+1
     }
 
     if(sizeOfExistingProducts==1)
     {
    	 alert("Selected product is: "+currentSimpleProductId)
     }
}
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 29 Sep 2015 01:38:21 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[中国2015上半年跨境电商交易额达7.64万亿 ]]></title>
      <link>https://www.360magento.com/blog/news-ecommerce-china/</link>
      <description><![CDATA[<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>交易规模：2015上半年<a title="magento跨境电商系统" href="http://www.360magento.com/">中国跨境电商</a>交易规模达2万亿</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">2015年上半年，中国跨境电商交易规模为2万亿，同比增长42.8%，占我国进出口总值的17.3%。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">从上述数据分析可以知道，上半年中国对外贸易呈现低迷态势，而跨境电子商务则呈现出蓬勃的发展态势。未来会有更多企业加入跨境电子商务行列，中国跨境电子商务从规模到质量都会有大幅度的提高，在国际市场的影响力会进一步增强。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">随着跨境电商试点城市数量的增多，电商平台跨境业务将借机不断扩大，地方政府也将加速建设自有电商服务平台，由此产生的大量跨境贸易交易规模将在未来予以呈现。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>进出口比例：出口84.8% 进口比例15.2%</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">2015年上半年，中国跨境电商的进出口结构出口占比达到84.8%，进口比例15.2%。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">&ldquo;目前，中国出口电商仍为跨境电商的主角，随着政策的推动以及消费需求的旺盛，进口电商得到了快速的发展，占比比例有所上升，但幅度不大。试点政策的逐步放开以及更多企业的参与，都将推动进口电商的发展。&rdquo;中国电子商务研究中心高级分析师张周平表示。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>模式结构：跨境电商B2B占比91.9% B2C占比8.1%</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">2015年上半年，中国跨境电商的交易模式跨境电商B2B交易占比达到91.9%，跨境电商B2B交易占据绝对优势，跨境电商B2C交易占比8.1%。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">对此，中国电子商务研究中心高级分析师张周平认为，B2B模式的交易方式始终占据行业主流，这跟两种模式针对的对象有关。B2B交易量级大、且订单稳定， 所以该种方式在未来仍是主流。B2C模式下订单趋向碎片化和小额化，但需求强劲，在未来几年，B2C占比比例也将会逐步提升。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>市场趋势</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>　　趋势一：<a title="magento跨境电商系统" href="http://www.360magento.com/">跨境电商</a>成为对外贸易&ldquo;新增长点&rdquo;</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">2015年是中国跨境电商的转折年。激烈的价格战和同质化竞争，传统跨境电商的经营模式和增长模式受到严峻考验。以草根创业和价格战为特色的第一波跨境电 商已经过去，未来一段时期将迎来第二波跨境电商热潮。传统企业和品牌商的觉醒和爆发，中小制造型企业面对买家需求封闭、订单周期长、汇率风险高、利润空间 低等传统外贸限制，对跨境电子商务的需求更为迫切。出口易在原来的基础上更要抓住机遇发展自身，满足市场对新型跨境电商的需求。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>趋势二：产品品类和销售市场更加多元化</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">随着<a title="magento跨境电商系统" href="http://www.360magento.com/">跨境电商</a>的发展，跨境电商交易呈现新的特征：交易产品向多品类延伸、交易对象向多区域拓展。从销售产品品类看，跨境电商企业销售的产品品类从服装服饰、3C电子、计算机及配件、家居园艺、珠宝、汽车配件、食品药品等便捷运输产品向家居、汽车等大型产品扩展。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>趋势三：跨境进口电商将集中爆发</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">未来跨境进口电商将集中爆发，随着政策倾斜进入快速&ldquo;成长期&rdquo;。2014年，在&ldquo;跨境交易&rdquo;与&ldquo;电子商务&rdquo;双引擎的拉动下，跨境进口型电商风生水起。先是 天猫、亚马逊中国，继而是苏宁、聚美优品纷纷挤进跨境电商2.0时代，进入产业信息化时代，即结合传统资源，打造海外供应链，多渠道运营(自营或招商的形 式)，拉开了品牌国际化战略的序幕。</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><strong>趋势四：品牌争夺战打响，成关键转折点</strong></p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;">各大电商平台开始盯上有限的品牌资源，中小电商也在激烈的价格战中意识到品牌的重要性。但品牌建立需要一定的历史背景，市场条件等多种因素，中国跨境电商 创牌之路将会异常艰辛，但机会尚存，如在新兴市场国家创牌就相对较易，比如M2C供销平台的品质供销品牌聚焦，为各大电商卖家提供了更多机会。在技术日新 月异的电子产品、智能产品方面，中国和发达国家之间其实处于同一起跑线，更加容易创牌成功，中国跨境电商的发展其实已经到了一个非常关键的转折点。（来 源：<span style="color: #333333; font-family: 宋体; font-size: 14px; line-height: 26px; background-color: #ffffff;">中国电子商务研究中心</span>）</p>
<p style="color: #333333; font-family: 宋体; font-size: 14px; text-indent: 2em; background-color: #ffffff;"><a title="magento跨境电商系统" href="http://www.360magento.com/">360Magento</a>为中国大中小企业的跨境电商提供有力的技术支持后盾，为中国创建跨境<a title="magento跨境电商系统" href="http://www.360magento.com/">电商独立品牌</a>做出重要贡献，请联系我们，竭诚为您服务，祝君生意红红火火</p>]]></description>
      <pubDate>Mon, 28 Sep 2015 14:15:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中上一个/下一个产品按钮]]></title>
      <link>https://www.360magento.com/blog/magento-prevnext-extension/</link>
      <description><![CDATA[<p>现在，已经有好几个Magento的上一个/下一个插件。说实话，我并不知道它们功能如何，因为我没用过。我打算自己写这个功能，依靠分层导航筛选并按网格列表中的顺序排列。这儿是插件代码的示例（部分但是功能齐全）</p>
<p>首先我们创建Alwayly_Prevnext插件的config.xml</p>
<pre><code>...
    &lt;frontend&gt;         
        &lt;events&gt;
            &lt;controller_action_postdispatch&gt;
                &lt;observers&gt;
                    &lt;alwayly_prevnext_set_filtered_category_product_collection&gt;
                        &lt;class&gt;alwayly_prevnext/observer&lt;/class&gt;
                        &lt;method&gt;setAlwaylyFilteredCategoryProductCollection&lt;/method&gt;
                    &lt;/alwayly_prevnext_set_filtered_category_product_collection&gt;
                &lt;/observers&gt;                
            &lt;/controller_action_postdispatch&gt;
        &lt;/events&gt;   
    &lt;/frontend&gt;
...

</code></pre>
<p>现在，我们实现观测方法。在这里，我抓取已经读取的产品集合，产品网格网格列表的最后一个产品。如你所见，我注重 &ldquo;category&rdquo; 控制器, &ldquo;view&rdquo;动作，从集合中提取产品ID并将它们设置到alwayly_filtered_category_product_collection的session关键字下。这样一来我就能获取最后被详细页最后被浏览的产品，然后确定它的前一个和后一个产品。</p>
<pre><code>class Alwayly_Prevnext_Model_Observer
{
    public function setAlwaylyFilteredCategoryProductCollection()
    {
        /**
         * There might be some illogical buggy behavior when coming directly 
         * from "Related products" / "Recently viewed" products block. 
         * Nothing that should break the page however.
         */
	if (Mage::app()-&gt;getRequest()-&gt;getControllerName() == 'category' &amp;&amp; Mage::app()-&gt;getRequest()-&gt;getActionName() == 'view') {
 
		$products = Mage::app()-&gt;getLayout()
				-&gt;getBlockSingleton('Mage_Catalog_Block_Product_List')
				-&gt;getLoadedProductCollection()
				-&gt;getColumnValues('entity_id');
 
		Mage::getSingleton('core/session')
				-&gt;setAlwaylyFilteredCategoryProductCollection($products);
 
		unset($products);
	}
 
	return $this;        
    }
} 
</code></pre>
<p>最后，助手类支持getPreviousProduct和getNextProduct方法</p>
<pre><code>class Alwayly_Prevnext_Helper_Data extends Mage_Core_Helper_Abstract
{
    /**
     * @return Mage_Catalog_Model_Product or FALSE
     */
    public function getPreviousProduct()
    {
            $prodId = Mage::registry('current_product')-&gt;getId();
 
            $positions = Mage::getSingleton('core/session')-&gt;getAlwaylyFilteredCategoryProductCollection();
 
            if (!$positions) {
                $positions = array_reverse(array_keys(Mage::registry('current_category')-&gt;getProductsPosition()));
            }
 
            $cpk = @array_search($prodId, $positions);
 
            $slice = array_reverse(array_slice($positions, 0, $cpk));
 
            foreach ($slice as $productId) {
                    $product = Mage::getModel('catalog/product')
                                                    -&gt;load($productId);
 
                    if ($product &amp;&amp; $product-&gt;getId() &amp;&amp; $product-&gt;isVisibleInCatalog() &amp;&amp; $product-&gt;isVisibleInSiteVisibility()) {
                            return $product;
                    }
            }
 
            return false;
    }
 
    /**
     * @return Mage_Catalog_Model_Product or FALSE
     */
    public function getNextProduct()
    {
            $prodId = Mage::registry('current_product')-&gt;getId();
 
            $positions = Mage::getSingleton('core/session')-&gt;getAlwaylyFilteredCategoryProductCollection();
 
            if (!$positions) {
                $positions = array_reverse(array_keys(Mage::registry('current_category')-&gt;getProductsPosition()));
            }            
 
            $cpk = @array_search($prodId, $positions);
 
            $slice = array_slice($positions, $cpk + 1, count($positions));
 
            foreach ($slice as $productId) {
                    $product = Mage::getModel('catalog/product')
                                                    -&gt;load($productId);
 
                    if ($product &amp;&amp; $product-&gt;getId() &amp;&amp; $product-&gt;isVisibleInCatalog() &amp;&amp; $product-&gt;isVisibleInSiteVisibility()) {
                            return $product;
                    }
            }
 
            return false;
    }
}
</code></pre>
<p>这个方法里有个问题，它不能弥补剩余类别产品中可能的页。事实是，抓去类别产品ID的时候我们仍然不知道其它可能页面中这个产品的ID。然而，这将要求在服务器上更多的负载，因为它需要一个或两个额外的数据库查询。此外，时不时地可能出现一些不合逻辑的上一个/下一个。因此，这个方法还有提升的空间。但要知道的是，这种方法并不会破坏什么。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 28 Sep 2015 11:00:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[15分钟内创建一个magento"Facebook like"按钮插件]]></title>
      <link>https://www.360magento.com/blog/facebook-like-button-extension/</link>
      <description><![CDATA[<p>Facebook Like按钮很简单，也容易实现。你所要做的只是从Facebook开发者的网站粘贴2-3节，然后调整下。</p>
<p>既然我们要给Magento编代码，那么何不做一个插件呢，Alwayly_Flike。考虑到工作的预算和时间，我要尽可能快地完成编码，但是任然要按照&ldquo;Magento规则&rdquo;。考虑到这一点，下面是我插件的config.xml内容：</p>
<pre><code>&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Flike&gt;
            &lt;version&gt;1.0.0.0&lt;/version&gt;
        &lt;/Alwayly_Flike&gt;
    &lt;/modules&gt;
    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;alwayly_flike&gt;
                    &lt;file&gt;alwayly/flike/flike.xml&lt;/file&gt;
                &lt;/alwayly_flike&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;        
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>由于上面的配置中包含了flike.xml，所以我们需要添加<strong>alwayly/flike/flike.xml</strong>到我能的主题布局文件夹下。这是flike.xml代码：</p>
<pre><code>&lt;layout version="0.1.0"&gt;
   &lt;catalog_product_view&gt;
        &lt;reference name="head"&gt;
            &lt;block type="core/template" name="alwayly_flike_tags" template="alwayly/flike/tags.phtml" before="-" /&gt;
        &lt;/reference&gt;        
        &lt;reference name="after_body_start"&gt;
            &lt;block type="core/template" name="alwayly_flike_js" template="alwayly/flike/js.phtml" before="-" /&gt;          
        &lt;/reference&gt;
        &lt;reference name="alert.urls"&gt;
            &lt;block type="core/template" name="alwayly_flike_button" template="alwayly/flike/button.phtml" before="-" /&gt;
        &lt;/reference&gt;
    &lt;/catalog_product_view&gt;
&lt;/layout&gt;
</code></pre>
<p>为了简单起见和预算的限制，我决定用&ldquo;core/template&rdquo;模块。现在我们就要开始写flike.xml中提到的tags.phtml，js.phtml和button.phtml文件了。</p>
<p>tags.phtml文件包含&ldquo;开放图形标签&rdquo;，当我们Like我们的产品时，我们要获取正确的产品图片描述等等。由于这些都需要在网页的&ldquo;head&rdquo;下，所以我引用了head模块。下面是tags.phtml的代码：</p>
<pre><code>&lt;?php $_product = Mage::registry('current_product') ?&gt;
&lt;?php if ($_product &amp;&amp; $_product-&gt;getId()): ?&gt;
&lt;meta property="og:title" content="&lt;?php echo $this-&gt;stripTags($_product-&gt;getName(), null, true) ?&gt;" /&gt;
&lt;meta property="og:type" content="product" /&gt;
&lt;meta property="og:image" content="&lt;?php echo $this-&gt;helper('catalog/image')-&gt;init($_product, 'small_image')-&gt;resize(130, 110); ?&gt;" /&gt;
&lt;meta property="og:url" content="&lt;?php echo $_product-&gt;getProductUrl() ?&gt;" /&gt;
&lt;meta property="og:site_name" content="&lt;?php echo Mage::app()-&gt;getStore()-&gt;getName() ?&gt;" /&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>注意图片大小周围的细节。这符合Facebook官方对og的定义：图像作为Feed链接。缩略图的宽和高超过50像素，不超过130x110像素。高和宽的比或者宽和高的比不超过3.例如139x39像素的图片就不会显示，宽和高的比为3.23超过了3。图片会被重新定义成合适的大小。</p>
<p>js.phtml文件包含Like按钮的JAVA脚本：</p>
<pre><code>&lt;?php $_product = Mage::registry('current_product') ?&gt;
&lt;?php if ($_product &amp;&amp; $_product-&gt;getId()): ?&gt;
&lt;div id="fb-root"&gt;&lt;/div&gt;
&lt;script&gt;
(function(d, s, id) {
  var js, fjs = d.getElementsByTagName(s)[0];
  if (d.getElementById(id)) return;
  js = d.createElement(s); js.id = id;
  js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
  fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
&lt;/script&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>最后，button.phtml包含实际的按钮：</p>
<pre><code>&lt;?php $_product = Mage::registry('current_product') ?&gt;
&lt;?php if ($_product &amp;&amp; $_product-&gt;getId()): ?&gt;
&lt;div class="fb-like" data-href="&lt;?php echo $_product-&gt;getProductUrl() ?&gt;" data-send="true" data-width="450" data-show-faces="true"&gt;&lt;/div&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>就是这样了。如果你没有在你的主题你做过多的修改，更确切地说删除产品详细页的&ldquo;alert.urls&rdquo; 块。那么你就能在产品名字附近看到Facebook Like按钮了。</p>
<p>鉴于这是一个简单的例子，它还有很大的空间可供你开发。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 28 Sep 2015 08:47:33 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[管理Magento账户面板的导航链接]]></title>
      <link>https://www.360magento.com/blog/managing-navigation-links/</link>
      <description><![CDATA[<p>在本文中，我将演示如何管理用户账户面板里的导航链接：一种去掉账户面板链接时要避免的方式和另一种要执行的方式。</p>
<p>一种删除指定链接的方法是注释掉显示这个链接的动作。我将以账户面板的 &ldquo;Account Information&rdquo;链接为例，这个链接位于<strong> app/design/frontend/base/default/layout/customer.xml</strong>。</p>
<pre><code>&lt;action method="addLink" translate="label" module="customer"&gt;
  &lt;name&gt;account&lt;/name&gt;
  &lt;path&gt;customer/account/&lt;/path&gt;
  &lt;label&gt;Account Dashboard&lt;/label&gt;
&lt;/action&gt;
</code></pre>
<p>然而，编辑Magento的核心文件从来都不是一个好的想法。我们将用些不一样的东西来替代这个方法。</p>
<p>首先，我们必须编辑我们的config.xml文件，我们要重写Magento的核心文件。</p>
<pre><code>
&lt;global&gt;
    &lt;blocks&gt;
        &lt;customer&gt;
            &lt;rewrite&gt;
                &lt;account_navigation&gt;Alwayly_Core_Block_Customer_Account_Navigation&lt;/account_navigation&gt;
            &lt;/rewrite&gt;
        &lt;/customer&gt;
    &lt;/blocks&gt;
&lt;/global&gt;
</code></pre>
<p>接着，我们要定义我们的布局文件：</p>
<pre><code>    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;alwayly_core&gt;
                    &lt;file&gt;alwayly_core.xml&lt;/file&gt;
                &lt;/alwayly_core&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;
    &lt;/frontend&gt;
</code></pre>
<p>下一步就是用下面的代码创建<strong>Block/Customer/Account/Navigation.php</strong></p>
<pre><code>class Alwayly_Core_Block_Customer_Account_Navigation extends Mage_Customer_Block_Account_Navigation
{
    public function removeLinkByName($name) {
        unset($this-&gt;_links[$name]);
    }
}
</code></pre>
<p>最后要做的就是创建布局文件<strong>app/design/frontend/default/default/layout/alwayly_core.xml</strong></p>
<pre><code>
&lt;?xml version="1.0" ?&gt;
&lt;layout version="0.1.0"&gt;
    &lt;customer_account translate="label"&gt;
        &lt;reference name="customer_account_navigation"&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;billing_agreements&lt;/name&gt;&lt;/action&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;recurring_profiles&lt;/name&gt;&lt;/action&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;tags&lt;/name&gt;&lt;/action&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;my_wishlist&lt;/name&gt;&lt;/action&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;OAuth Customer Tokens&lt;/name&gt;&lt;/action&gt;
            &lt;action method="removeLinkByName"&gt;&lt;name&gt;my_downloadable_products&lt;/name&gt;&lt;/action&gt;
        &lt;/reference&gt;
    &lt;/customer_account&gt;
&lt;/layout&gt;
</code></pre>
<p>现在，对于每个我们想要移除的导航链接，我们需要加上连接名并把链接名写入名字标签。</p>
<p>下面列举出账户面板导航链接名（按默认显示排列）</p>
<ul>
<li>Account Dashboard</li>
<li>Account Information</li>
<li>Address Book</li>
<li>My Orders</li>
<li>Billing Agreements</li>
<li>Recurring Profiles</li>
<li>My Product Reviews</li>
<li>My Wishlist</li>
<li>My Applications</li>
<li>Newsletter Subscriptions</li>
<li>My Downloadable Products</li>
</ul>
<p>添加一个新的导航链接相对来说简单一些。我们要做的只是将以下代码加到我们的布局文件中</p>
<pre><code>&lt;?xml version="1.0" ?&gt;
&lt;layout version="0.1.0"&gt;
   &lt;customer_account translate="label"&gt;
        &lt;reference name="customer_account_navigation"&gt;
            &lt;action method="addLink"&gt;
                &lt;name&gt;test checkout&lt;/name&gt;
                &lt;path&gt;checkout&lt;/path&gt;
                &lt;label&gt;Alwayly Checkout&lt;/label&gt;
            &lt;/action&gt;
        &lt;/reference&gt;
    &lt;/customer_account&gt;
&lt;/layout&gt;
</code></pre>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 28 Sep 2015 04:43:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中产品库存不报警解决方案]]></title>
      <link>https://www.360magento.com/blog/product-stock-alerts/</link>
      <description><![CDATA[<p>最近我们的一个客户联系我们，告诉我们产品报警功能不再工作。在调查后，我发现最后的一封产品报警邮件是几个月前的。在此期间，我们已经在网站升级到Magento的EE，起初我想，也许在升级过程中出了问题。另一种可能是，客户也许修改了Transactional Email Template。在看完日志文件后，我没发现任何相关的邮件。系统虽然没有发送其它电子邮件。</p>
<p>在调查过程中，我看论坛上的其它开发者有相似的问题也没解决的。在追寻和查找后，我们发现问题所在。</p>
<p>简单说来，这个事件在Magento处理产品报库存警的集合方法里。我们的客户有超过40000封订阅和超过30000个需要将&ldquo;缺货&rdquo;状态改为&ldquo;有货&rdquo;。所以当Magento尝试从product_alert_stock表读取40000条记录到集合里的时候，由于内存限制而失败了。可能你的product_alert_stock表有超过20000记录时，产品库存报警功能就失效了。</p>
<p>解决方案相对简单。通过以1000为集合创建分页来遍历超过30000条记录。正如Magento在系统中所做的那样。新的功能是通过遍历所有的这些记录，循环出status=0（未处理）的记录，检查产品现在是否有货。当true=&gt; set status=1就发送电子邮件通知客户。</p>
<p>那么，让我们创建我们的模块，Alwayly_ProductAlert，这将提高Magento方法。</p>
<h2>1. Create file in app/etc/modules/ Alwayly_ProductAlert.xml with the following content:</h2>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_ProductAlert&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_ProductAlert&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<h2>2. Create file in app/code/local/Alwayly/ProductAlert/etc/ config.xml with the following content:</h2>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_ProductAlert&gt;
            &lt;version&gt;1.0.0.0&lt;/version&gt;
        &lt;/Alwayly_ProductAlert&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;models&gt;
            &lt;productalert&gt;
                &lt;rewrite&gt;
                    &lt;observer&gt;Alwayly_ProductAlert_Model_Observer&lt;/observer&gt;
                &lt;/rewrite&gt;
            &lt;/productalert&gt;
        &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>你可以看到我们重写了Mage_ProductAlert_Model_Observer类</p>
<h2>Create file in /www/app/code/local/Alwayly/ProductAlert/Model/ Observer.php with the following content:</h2>
<pre><code>
&lt;?php
 
/*
 * ProductAlert observer
*/
class Alwayly_ProductAlert_Model_Observer extends Mage_ProductAlert_Model_Observer
{
     /**
     * Process stock emails
     *
     * @param Mage_ProductAlert_Model_Email $email
     * @return Mage_ProductAlert_Model_Observer
     */
    protected function _processStock(Mage_ProductAlert_Model_Email $email)
    {
 
        $email-&gt;setType('stock');
 
        foreach ($this-&gt;_getWebsites() as $website) {
 
            /* @var $website Mage_Core_Model_Website */
 
            if (!$website-&gt;getDefaultGroup() || !$website-&gt;getDefaultGroup()-&gt;getDefaultStore()) {
 
                continue;
            }
            if (!Mage::getStoreConfig(
                self::XML_PATH_STOCK_ALLOW,
                $website-&gt;getDefaultGroup()-&gt;getDefaultStore()-&gt;getId()
            )) {
 
                continue;
            }
            try {
 
                $wholeCollection = Mage::getModel('productalert/stock')
                    -&gt;getCollection()
//                   -&gt;addWebsiteFilter($website-&gt;getId())
                    -&gt;addFieldToFilter('website_id', $website-&gt;getId())
                    -&gt;addFieldToFilter('status', 0)
                ;
//                $wholeCollection-&gt;getSelect()-&gt;order('alert_stock_id DESC');
 
                /*       table: !product_alert_stock!
                alert_stock_id: 1
                   customer_id: 1
                    product_id: 1
                    website_id: 1
                      add_date: 2013-04-26 12:08:30
                     send_date: 2013-04-26 12:28:16
                    send_count: 2
                        status: 1
                */
            }
            catch (Exception $e) {
                Mage::log('error-1-collection $e=' . $e-&gt;getMessage(), false, 'product_alert_stock_error.log', true);
                $this-&gt;_errors[] = $e-&gt;getMessage();
                return $this;
            }
 
            $previousCustomer = null;
            $email-&gt;setWebsite($website);
 
            try {
 
                $originalCollection = $wholeCollection;
                $count = null;
                $page  = 1;
                $lPage = null;
                $break = false;
 
                while ($break !== true) {
                    $collection = clone $originalCollection;
                    $collection-&gt;setPageSize(1000);
                    $collection-&gt;setCurPage($page);
                    $collection-&gt;load();
                    if (is_null($count)) {
                        $count = $collection-&gt;getSize();
                        $lPage = $collection-&gt;getLastPageNumber();
                    }
                    if ($lPage == $page) {
                        $break = true;
                    }
 
                    Mage::log('page=' . $page, false, 'check_page_count.log', true);
                    Mage::log('collection=' . (string)$collection-&gt;getSelect(), false, 'check_page_count.log', true);
 
                    $page ++;
 
                    foreach ($collection as $alert) {
 
                        try {
 
                            if (!$previousCustomer || $previousCustomer-&gt;getId() != $alert-&gt;getCustomerId()) {
 
                                $customer = Mage::getModel('customer/customer')-&gt;load($alert-&gt;getCustomerId());
                                if ($previousCustomer) {
                                    $email-&gt;send();
                                }
                                if (!$customer) {
                                    continue;
                                }
                                $previousCustomer = $customer;
                                $email-&gt;clean();
                                $email-&gt;setCustomer($customer);
 
                            }
                            else {
 
                                $customer = $previousCustomer;
                            }
 
                            $product = Mage::getModel('catalog/product')
                                -&gt;setStoreId($website-&gt;getDefaultStore()-&gt;getId())
                                -&gt;load($alert-&gt;getProductId());
                            /* @var $product Mage_Catalog_Model_Product */
                            if (!$product) {
 
                                continue;
                            }
 
                            $product-&gt;setCustomerGroupId($customer-&gt;getGroupId());
 
                            if ($product-&gt;isSalable()) {
 
                                $email-&gt;addStockProduct($product);
 
                                $alert-&gt;setSendDate(Mage::getModel('core/date')-&gt;gmtDate());
                                $alert-&gt;setSendCount($alert-&gt;getSendCount() + 1);
                                $alert-&gt;setStatus(1);
                                $alert-&gt;save();
 
                            }
                        }
                        catch (Exception $e) {
                            Mage::log('error-2-alert $e=' . $e-&gt;getMessage(), false, 'product_alert_stock_error.log', true);
                            $this-&gt;_errors[] = $e-&gt;getMessage();
                        }
                    }
                }
 
                Mage::log("\n\n", false, 'check_page_count.log', true);
 
            } catch (Exception $e) {
                Mage::log('error-3-steps $e=' . $e-&gt;getMessage(), false, 'product_alert_stock_error.log', true);
            }
 
            if ($previousCustomer) {
                try {
                    $email-&gt;send();
                }
                catch (Exception $e) {
                    $this-&gt;_errors[] = $e-&gt;getMessage();
                }
            }
        }
 
        return $this;
    }
 
    /**
     * Run process send product alerts
     */
    public function process()
    {
        Mage::log('ProductAlert started @' . now(), false, 'product_alert_workflow.log', true);
 
        $email = Mage::getModel('productalert/email');
        /* @var $email Mage_ProductAlert_Model_Email */
        $this-&gt;_processPrice($email);
        $this-&gt;_processStock($email);
        $this-&gt;_sendErrorEmail();
 
        Mage::log('ProductAlert finished @' . now(), false, 'product_alert_workflow.log', true);
 
        return $this;
    }
}
</code></pre>
<p>你可以看到，我们重写了process()和 _processStock()方法。在process()方法中，我们添加了Mage::log()创建起止时间到var/log/product_alert_workflow.log。这样我们就能知道脚本是否执行完成。同样的，我们增强_processStock()方法的功能，我们增加了一些Mage:log()调用来跟踪，看所有的行为是否按期待的方式表现。</p>
<p>最后，如果你不想等待你的Cron被触发，你可以在Magento根目录下创建一个文件，让我们调用它。</p>
<h2>Alwayly_cron.php</h2>
<pre><code>
&lt;?php

require_once 'app/Mage.php';
Mage::app();
 
try {
    Mage::getModel('productalert/observer')-&amp;gtprocess();
} catch (Exception $e) {
    Mage::log('error-0-start $e=' . $e-&amp;gtgetMessage() . ' @' . now(), false, 'product_alert_stock_error.log', true);
}
</code></pre>
<p>就是这些了，这个解决思路同样适用于产品价格报警。</p>
<p><span>360magento提供专业的基于magento系统的</span><a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a><span>，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></p>]]></description>
      <pubDate>Sun, 27 Sep 2015 15:10:56 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[向magento顶部菜单添加链接]]></title>
      <link>https://www.360magento.com/blog/adding-links-to-topmenu/</link>
      <description><![CDATA[<p>向顶部菜单或者主菜单中添加东西听起来很简单。但是，我们这里谈论的是<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">Magento</a>，它并不像听起来的那么容易。一种特殊的方式创建菜单项（不使用后台categories）让这个听起来简单的任务成了一场噩梦。幸运的是，Magento中藏有这么一个方法。</p>
<p>Magento的逻辑只允许类别（categories）出现在顶部导航。当创建一个类别的时候只要设置Include in Navigation Menu就会显示在导航里。Magento已经解释了通过创建一个假的类别和重定向一个特殊的页面来添加一个菜单项。但他们也给了个事件挂钩去对顶部菜单做更灵活的事情。</p>
<h2>Config</h2>
<p>首先，在config.xml中通过添加下面的代码来定义挂钩。通过这个我们简单地添加当一个时间，当挂钩、模型、方法名被请求时调度事件就会去掉它。</p>
<pre><code>
&lt;config&gt;
    &lt;frontend&gt;
        &lt;events&gt;
            &lt;page_block_html_topmenu_gethtml_before&gt;
                &lt;observers&gt;
                    &lt;my_module&gt;
                        &lt;class&gt;my_module/observer&lt;/class&gt;
                        &lt;method&gt;addToTopmenu&lt;/method&gt;
                    &lt;/my_module&gt;
                &lt;/observers&gt;
            &lt;/page_block_html_topmenu_gethtml_before&gt;
        &lt;/events&gt;
   &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<h2>Observer</h2>
<p>现在，一个包含addTopmenu方法的观察者已经在config.xml中被定义。下面的代码只是个例子，添加一个名为 &ldquo;Categories&rdquo;的顶部菜单项以及子分类项，类别名。好了，这样我们就能创建嵌套菜单项。</p>
<pre><code>
public function addToTopmenu(Varien_Event_Observer $observer)
{
    $menu = $observer-&gt;getMenu();
    $tree = $menu-&gt;getTree();
 
    $node = new Varien_Data_Tree_Node(array(
            'name'   =&gt; 'Categories',
            'id'     =&gt; 'categories',
            'url'    =&gt; Mage::getUrl(), // point somewhere
    ), 'id', $tree, $menu);
 
    $menu-&gt;addChild($node);
 
    // Children menu items
    $collection = Mage::getResourceModel('catalog/category_collection')
            -&gt;setStore(Mage::app()-&gt;getStore())
            -&gt;addIsActiveFilter()
            -&gt;addNameToResult()
            -&gt;setPageSize(3);
 
    foreach ($collection as $category) {
        $tree = $node-&gt;getTree();
        $data = array(
            'name'   =&gt; $category-&gt;getName(),
            'id'     =&gt; 'category-node-'.$category-&gt;getId(),
            'url'    =&gt;&gt; $category-&gt;getUrl(),
        );
 
        $subNode = new Varien_Data_Tree_Node($data, 'id', $tree, $node);
        $node-&gt;addChild($subNode);
    }
}
</code></pre>
<p><span>360magento提供专业的基于magento系统的</span><a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a><span>，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></p>]]></description>
      <pubDate>Sun, 27 Sep 2015 13:46:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中如何给特定对象创建布局句柄]]></title>
      <link>https://www.360magento.com/blog/layout-update-handles/</link>
      <description><![CDATA[<p>Magento中每个Http请求结果中都会有一些布局句柄，这些句柄可以用来定制所需页面的布局。如果你曾经尝试找出magento中的布局句柄，你会发现有很多。这些句柄基于不同的变量，不同的计算。</p>
<p>根据用户是否登录，magento使用customer_logged_in和customer_logged_out句柄。不同的店铺也有不同的布局更新（例如STORE_default，STORE_cars，STORE_fashion ...）。主题有自己的布局句柄（例如THEME_frontend_default_default，THEME_frontend_enterprise_default）。</p>
<p>当一个网站使用&ldquo;Shop by Brand&rdquo;插件的时候，客户问我们是否能改变一个brand页面的布局。为了实现这个功能，我们必须扩展这个插件，让每个brand页面有它自己的更新句柄。</p>
<p>你可能注意到Magento使用这个功能创建唯一的布局句柄给不同的类别（如CATEGORY_96，CATEGORY_35）和产品（如PRODUCT_22735，PRODUCT_225）。</p>
<p>下面我将演示如何创建一个特定对象的布局句柄功能。句柄将由对象的ID（如OUR_COOL_OBJECT_535，OUR_COOL_OBJECT_863）字符串组成。</p>
<h2>1、创建观察者</h2>
<p>为了避免增加句柄到Magento布局更新对象过晚，我们需要观察controller_action_layout_load_before时间。</p>
<pre><code>
&lt;config&gt;
    &lt;frontend&gt;
        &lt;events&gt;
            &lt;controller_action_layout_load_before&gt;
                &lt;observers&gt;
                    &lt;alwayly_controller_action_layout_load_before&gt;
                        &lt;class&gt;alwayly_layouthandle/observer&lt;/class&gt;
                        &lt;method&gt;controllerActionLayoutLoadBefore&lt;/method&gt;
                    &lt;/alwayly_controller_action_layout_load_before&gt;
                &lt;/observers&gt;
            &lt;/controller_action_layout_load_before&gt;
        &lt;/events&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<h2>2、添加句柄</h2>
<p>现在我们必须计算布局更新句柄并将它添加到布局更新对象里。</p>
<pre><code>
&lt;?php
 
    class Alwayly_LayoutHandle_Model_Observer
    {
        public function controllerActionLayoutLoadBefore(Varien_Event_Observer $observer)
        {
            /** @var $layout Mage_Core_Model_Layout */
            $layout = $observer-&gt;getEvent()-&gt;getLayout();
 
            $id = Mage::app()-&gt;getRequest()-&gt;getParam('id');
 
            /* or */
 
            if($ourCoolObject = Mage::registry('our_cool_object'))
            {
                $id = $ourCoolObject-&gt;getId();
            }
 
            $layout-&gt;getUpdate()-&gt;addHandle('OUR_COOL_OBJECT_'.$id);
        }
    }
</code></pre>
<p><span>360magento提供专业的基于magento系统的</span><a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a><span>，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></p>]]></description>
      <pubDate>Sat, 26 Sep 2015 14:16:36 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento2中的路由]]></title>
      <link>https://www.360magento.com/blog/routing-in-magento2/</link>
      <description><![CDATA[<p>我们可以说路由，是Magento中最重要的部分。Magento2中完整的进程流取决于URL进程请求和路由器类（用来响应匹配和执行请求）。这篇文章包含了Magento2中路由器流并分析一些默认的路由器。当然，这里也会演示怎么去常见一个自定义的路由器，提到路由器是如何匹配到方法（控制器类），更多关于控制器的信息将会在其它文章中提到。</p>
<h2>路由流</h2>
<p>首先，我们需要分析完整的路由流，这样我们就能为后面的部分了解更多的细节。我们之前就知道，Magento2在请求启动的流类（launch method）里创建HTTP进程。我们的流以创建前端控制器开始。</p>
<pre><code>$frontController = $this-&gt;_objectManager-&gt;get('Magento\Framework\App\FrontControllerInterface');
</code></pre>
<p>前端控制器对循环槽中所有可用的路由器和当前请求匹配的路由进行响应。稍后我们将详细讲解前端路由。现在，还是先理解整个流程，其中进程如何匹配路由器是重点。路由器列表被创建在RouterList（在前端控制器路由器循环里被调用）类里，位于<strong>Magento\Framework\App</strong>中。这个类用来排列和迭代路由器列表。路由器类负责匹配响应当前请求的路由器。让我们看看Magento2的流程。</p>
<p>index.php (runs bootstrap and create HTTP application) &rarr; HTTP app &rarr; FrontController &rarr; Routing &rarr; Controller processing &rarr; etc</p>
<p>现在我们将分析路由流程的每个部分以便更好地理解Magento2的路由。</p>
<h2>前端控制器</h2>
<p>和Magento1中一样，这是路由入口，被HTTP启动进程（launch method）调用。负责对当前请求路由进行匹配。它位于<strong>lib/internal/Magento/Framework/App/FrontController.php</strong>。你可以在HTTP启动方法FrontControllerInterface里找到。让我们看看这段代码吧。</p>
<pre><code>class Http implements \Magento\Framework\AppInterface
{
    public function launch()
    {
        ...
        	//Here Application is calling front controller and it's dispatch method
        $frontController = $this-&gt;_objectManager-&gt;get('Magento\Framework\App\FrontControllerInterface');
        $result = $frontController-&gt;dispatch($this-&gt;_request);
        ...
    }
}
</code></pre>
<p>现在，我们知道了前端控制器何时、如何被调用，让我们看看前端控制器类（Front controller class）和它的调度方法： <strong>lib/internal/Magento/Framework/App/FrontController.php</strong></p>
<pre><code>
class FrontController implements FrontControllerInterface
{
    public function dispatch(RequestInterface $request)
    {
        \Magento\Framework\Profiler::start('routers_match');
        $routingCycleCounter = 0;
        $result = null;
        while (!$request--&gt;isDispatched() &amp;&amp; $routingCycleCounter++ &lt; 100) {
            /** @var \Magento\Framework\App\RouterInterface $router */
            foreach ($this--&gt;_routerList as $router) {
                try {
                    $actionInstance = $router--&gt;match($request);
                    if ($actionInstance) {
                        $request--&gt;setDispatched(true);
                        $actionInstance--&gt;getResponse()--&gt;setNoCacheHeaders();
                        $result = $actionInstance--&gt;dispatch($request);
                        break;
                    }
                } catch (\Magento\Framework\Exception\NotFoundException $e) {
                    $request--&gt;initForward();
                    $request--&gt;setActionName('noroute');
                    $request--&gt;setDispatched(false);
                    break;
                }
            }
        }
        \Magento\Framework\Profiler::stop('routers_match');
        if ($routingCycleCounter &gt; 100) {
            throw new \LogicException('Front controller reached 100 router match iterations');
        }
        return $result;
    }
}
</code></pre>
<p>如你所见，调度方法将循环所有的路由器（可用的）直到一个路由被匹配，需求被调度($request&rarr;setDispatched(true);) ，或者路由计数器执行到100。路由器可以被匹配，但是如果没有调度，就会重复路由器循环。此外，路由器可以被重定向调度，或者它可以被匹配和处理。路由器列表类在请求流中被解析。现在，我们再看看路由器是如何匹配（匹配方法）的以及究竟什么是路由器。</p>
<h2>路由器</h2>
<p>简单来说，路由器就是负责匹配执行URL请求的PHP类。默认的Magento框架和核心里有些Base、DefaultRouter、Cms和UrlRewrite这样的路由器。所有这些我们都将讨论，解释它们的目标和如何工作的。路由器正在执行RouterInterface。现在让我们看看默认的路由器流：</p>
<p>Base Router &rarr; CMS Router &rarr; UrlRewrite Router &rarr; Default Router (这是路由器环路&mdash;&mdash; FrontController::dispatch())</p>
<h3>Base Router</h3>
<p>Base Router位于<strong>lib/internal/Magento/Framework/App/Router/Base.php</strong>，它是环路中的第一个。如果你是magento1开发者的话，你知道它作为标准路由器。匹配方法是parseRequest和matchAction，在第二个方法中会设置前端模块名，控制器路径名，动作名，控制器模和路由名。在基础路由器中标准Magento URL(front name/action path/action/param 1/etc params/) 被匹配。</p>
<h3>CMS Router</h3>
<p>CMS Router位于<strong>app/code/Magento/Cms/Controller/Router.php</strong>，用于处理CMS页面。它设置cms模块名（模块前端名），page控制器名（控制器路径名）和view（<strong>app/code/Magento/Cms/Controller/Page/View.php</strong>）动作名。为Base controller设置好格式后，它将设置页面ID并转发这个ID，但不会调度它。转发意味着它会破坏现有的路由器循环，再次开始循环（最多可执行100次）。这个路由器循环将匹配激活View controller（<strong>Cms/Controller/Page</strong>）的基础路由器，显示被存储的页面ID（根据url找到的页面ID）。</p>
<h3>UrlRewrite Router</h3>
<p>在Magento2中，UrlRewrite有了它自己的路由器。熟悉Magento1的朋友知道UrlRewrite是Standard路由器的一部分。它位于<strong>app/code/Magento/UrlRewrite/Controller/Router.php</strong>使用Url Finder获取数据库中匹配的url重写。</p>
<pre><code>$rewrite = $this-&gt;urlFinder-&gt;findOneByData(
                    [
                        UrlRewrite::ENTITY_TYPE =&gt; $oldRewrite-&gt;getEntityType(),
                        UrlRewrite::ENTITY_ID =&gt; $oldRewrite-&gt;getEntityId(),
                        UrlRewrite::STORE_ID =&gt; $this-&gt;storeManager-&gt;getStore()-&gt;getId(),
                        UrlRewrite::IS_AUTOGENERATED =&gt; 1,
                    ]
                );
</code></pre>
<p>它会转向CMS router这样的动作。</p>
<h3>Default Router</h3>
<p>它位于<strong>lib/internal/Magento/Framework/App/Router/DefaultRouter.php</strong>是路由器循环的最后一个。当其它路由都不匹配的时候才使用它。在Magento2中，我们可以为"404找不到"页面创建一个自定义的句柄来展示自定义内容。下面是DefaultRouter中没有路由处理情况下的循环。</p>
<pre><code>
foreach ($this-&gt;noRouteHandlerList-&gt;getHandlers() as $noRouteHandler) {
            if ($noRouteHandler-&gt;process($request)) {
                break;
            }
        }
</code></pre>
<h3>Custom Router (附带示例)</h3>
<p>前端控制器会浏览所有路由器列表中的路由（由routes.xml配置创建），所以我们需要将di.xml模块中新加路由器的配置添加到<strong>lib/internal/Magento/Framework/App/RouterList.php</strong>，由此来增加自定义路由器。我们将创建一个新的模块（例：Alwayly/CustomRouter），之后我们添加心得路由器到路由器列表，最后创建路由器类。</p>
<p>自定义路由器只是一个例子，在这个例子中你能了解Base router是如何匹配和跳转需求的。首先，我们需要在<strong>app/code/Alwayly/CustomRouter</strong>中为我们的模块创建一个文件夹结构，接着我们将在etc文件夹中创建modules.xml，在模块根目录下创建composer.json（带有模块信息）。现在，我们可以通过添加配置到di.xml（etc/frontend）来创建自定义路由器，这里我们的路由器只针对与前端。最后，我们将在Controller文件夹里创建Router.php来编写匹配路由器的逻辑。我们将扫描URL，确认是否有特定字，然后根据这些字简历前端模块名、控制器路径和给默认控制器的跳转请求。作为示例，我们要搜索的两个字是"examplerouter"和"exampletocms"。当搜索到"examplerouter"时，我们将跳转到Base router匹配格式（这里，我们设置前端模块名为"alwaylytest"，控制器路径名为"test"，动作名为"test"），当搜索到"exampletocms"时，我们通过Base router跳转到About us页面。</p>
<h4>di.xml(位于<strong>etc/frontend</strong>)</h4>
<pre><code>&lt; ?xml version="1.0"?&gt; 
&lt; config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd"&gt; 
    &lt; type name="Magento\Framework\App\RouterList"&gt; 
        &lt; arguments&gt; 
            &lt; argument name="routerList" xsi:type="array"&gt; 
                &lt; item name="alwaylycustomrouter" xsi:type="array"&gt; 
                    &lt; item name="class" xsi:type="string"&gt; Alwayly\CustomRouter\Controller\Router&lt; /item&gt; 
                    &lt; item name="disable" xsi:type="boolean"&gt; false&lt; /item&gt; 
                    &lt; item name="sortOrder" xsi:type="string"&gt; 22&lt; /item&gt; 
                &lt; /item&gt; 
            &lt; /argument&gt; 
        &lt; /arguments&gt; 
    &lt; /type&gt; 
&lt; /config&gt; 
</code></pre>
<h4>Router.php (位于<strong>Controller</strong>文件夹)</h4>
<pre><code>&lt;?php
namespace Alwayly\CustomRouter\Controller;
 
class Router implements \Magento\Framework\App\RouterInterface
{
    /**
     * @var \Magento\Framework\App\ActionFactory
     */
    protected $actionFactory;
 
    /**
     * Response
     *
     * @var \Magento\Framework\App\ResponseInterface
     */
    protected $_response;
 
    /**
     * @param \Magento\Framework\App\ActionFactory $actionFactory
     * @param \Magento\Framework\App\ResponseInterface $response
     */
    public function __construct(
        \Magento\Framework\App\ActionFactory $actionFactory,
        \Magento\Framework\App\ResponseInterface $response
    ) {
        $this-&gt;actionFactory = $actionFactory;
        $this-&gt;_response = $response;
    }
 
    /**
     * Validate and Match
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    public function match(\Magento\Framework\App\RequestInterface $request)
    {
        /*
         * We will search &ldquo;examplerouter&rdquo; and &ldquo;exampletocms&rdquo; words and make forward depend on word
         * -examplerouter will forward to base router to match alwaylytest front name, test controller path and test controller 

class
         * -exampletocms will set front name to cms, controller path to page and action to view
         */
        $identifier = trim($request-&gt;getPathInfo(), '/');
        if(strpos($identifier, 'exampletocms') !== false) {
            /*
             * We must set module, controller path and action name + we will set page id 5 witch is about us page on
             * default magento 2 installation with sample data.
             */
            $request-&gt;setModuleName('cms')-&gt;setControllerName('page')-&gt;setActionName('view')-&gt;setParam('page_id', 5);
        } else if(strpos($identifier, 'examplerouter') !== false) {
            /*
             * We must set module, controller path and action name for our controller class(Controller/Test/Test.php)
             */
            $request-&gt;setModuleName('alwaylytest')-&gt;setControllerName('test')-&gt;setActionName('test');
        } else {
            //There is no match
            return;
        }
 
        /*
         * We have match and now we will forward action
         */
        return $this-&gt;actionFactory-&gt;create(
            'Magento\Framework\App\Action\Forward',
            ['request' =&gt; $request]
        );
    }
}
</code></pre>
<h4>routes.xml (位于<strong>etc/frontend</strong>)</h4>
<pre><code>&lt;?xml version="1.0"?&gt; 

&lt;config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd"&gt; 
    &lt; router id="standard"&gt; 
        &lt;route id="alwaylytest" frontName="alwaylytest"&gt; 
            &lt;module name="Alwayly_CustomRouter" /&gt; 
        &lt;/route&gt; 
    &lt;/router&gt; 
&lt;/config&gt; 
</code></pre>
<h4>Test.php (test controller action class)</h4>
<pre><code>&lt;?php
namespace Alwayly\CustomRouter\Controller\Test;
 
class Test extends \Magento\Framework\App\Action\Action
{
    public function execute()
    {
        die("Alwayly\\CustomRouter\\Controller\\Test\\Test controller execute()");
    }
}</code></pre>
<p>360magento提供专业的基于magento系统的<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a>，如有需求或相关咨询，<a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 26 Sep 2015 12:30:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用magento布局给特定CMS页面添加静态块]]></title>
      <link>https://www.360magento.com/blog/layout-special-block/</link>
      <description><![CDATA[<p>有次在做一个项目的时候，我需要在头部和某些页面内容中间加入一个独有的静态块。元素必须完全在magento后台定义，而且能很轻易地在一个新的CMS页面创建、定义和移除。因此，元素必须被放置在主内容之外，不可能用后台CMS添加，而是要用magento布局添加。下面是我如何实现的：</p>
<p>正如你所知的，magento只为CMS页面提供下面的句柄</p>
<ul>
<li>首页句柄和404页面句柄</li>
<li>一个所有CMS页面公用的句柄</li>
</ul>
<p>如果一个CMS块要显示在首页，我们会在local.xml文件里使用首页句柄。同样的，如果要在所有CMS页面显示，我们可以使用所有CMS页面通用的句柄。但是，用户创建的个人CMS页面又该怎么办呢？</p>
<p>幸运的是：Magento允许我们通过后台CMS编辑器为每一个CMS页面定义一个自定义布局。这样的话，一个CMS页面的布局就被数据库中为这个特殊页面定义的值修改。</p>
<p>首先，我们为名为"static-block-1"特殊CMS页面创建一个静态块，加入下面的简单样式：</p>
<pre><code>&lt;div class=&rdquo;element-blue&rdquo;&gt;
        &lt;h3&gt;Static Block 1&lt;/h3&gt;
        &lt;p&gt;This is blue static element 1 &lt;/p&gt;
&lt;/div&gt;
</code></pre>
<p>接着，我们将创建一个包含了刚才创建的静态块的CMS页面。通过这个页面的Design标签更新布局XML，里面有头部和一个段落。今天以一列布局为例。</p>
<pre><code>&lt;reference name="root"&gt;
        &lt;block type="cms/block" name="myelement"&gt;
            &lt;action method="setBlockId"&gt;&lt;block_id&gt;static-block-1&lt;/block_id&gt;&lt;/action&gt;
        &lt;/block&gt;
&lt;/reference&gt;
</code></pre>
<p>最后，我们要更新我们的模板文件，添加一行调用我们元素的代码。打开1colum.phtml文件(app/design/frontend/default/你的主题/template/page/1column.phtml),按下面代码进行修改：</p>
<pre><code>&hellip;
&lt;div class="page"&gt;
        &lt;?php echo $this-&gt;getChildHtml('header') ?&gt;
        &lt;?php echo $this-&gt;getChildHtml('myelement') ?&gt;
&hellip;
</code></pre>
<p>虽然这个方法很快速，效果也不错，但是用同样的步骤添加元素会让人觉得乏味，特别是一个项目有6、7个这样的CMS页面。你觉得这个方法怎么样呢？你又是如何解决这个问题的呢？欢迎你和我们分享。</p>
<p>360magento提供专业的基于magento系统的<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a>，如有需求或相关咨询，<a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 26 Sep 2015 03:35:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何在magento产品详细页展示video]]></title>
      <link>https://www.360magento.com/blog/magento-product-video/</link>
      <description><![CDATA[<p>在实际情况中，有些特殊的产品需要用video来演示。Magento商店里有不少拥有video功能的插件，但是有时这些插件因为改变了你网站的布局而不符合你的需求。读完这篇文章后你就可以在magento产品详细页的任意位置添加你需要的video。</p>
<p>好了，让我们开始吧。Youtube让分享变得很简单，你只需要将video的iframe代码拷贝、粘贴到产品描述里就行了。 是不是觉得太简单了呢？那么让我们来点有难度的吧。在magento后台创建一个名为"video"的text属性(Catalog-&gt;Attributes-&gt;Manage Attributes)，再将这个属性放到一个合适的产品属性集里，刷新索引(System-&gt;Index Management)。接着打开产品详细页的phtml文件：app/design/frontend/default/你的主题名/template/catalog/product/view.phtml。下面的例子中，我把video放在产品名字的下面。找到产品名字的代码：</p>
<pre><code>&lt;div class="product-name"&gt;
     &lt;h1&gt;&lt;?php echo $_helper-&gt;productAttribute($_product, $_product-&gt;getName(), 'name') ?&gt;&lt;/h1&gt;
&lt;/div&gt;
</code></pre>
<p>在下面添加这段代码：</p>
<pre><code>&lt;?php if($_product-&gt;getVideo()): ?&gt;
       &lt;iframe width="560" height="315" src="http://www.youtube.com/embed/&lt;?php echo $_product-&gt;getVideo() ?&gt;" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;
&lt;?php endif; ?&gt;
</code></pre>
<p>最后，我们需要把video的UID填到产品中的"video"属性框里，也就是之前添加的新属性。例如http://www.youtube.com/watch?v=U0CGsw6h60k的UID就是U0CGsw6h60k。</p>
<p>还想来点更难的吗？想把video放在侧边栏？没问题。我们需要为video创建一个模块即.phtml文件。文件路径是：app/design/frontend/default/你的主题名/template/catalog/product/video.phtml。再把video放进去。代码是：</p>
<pre><code>&lt;div class="block block-video"&gt;
    &lt;div class="block-title"&gt;
        &lt;strong&gt;&lt;span&gt;&lt;?php echo $this-&gt;__('Product Video') ?&gt;&lt;/span&gt;&lt;/strong&gt;&lt;br&gt;    <br />    &lt;/div&gt;&lt;br&gt;    <br />    &lt;div class="block-content"&gt;
        &lt;object width="193" height="130"&gt;&lt;param name="movie" value="http://www.youtube.com/v/&lt;?php echo $this-&gt;__($this-&gt;getLinkUrl()) ?&gt;?hl=en_US&amp;version=3"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/&lt;?php echo $this-&gt;__($this-&gt;getLinkUrl()) ?&gt;?hl=en_US&amp;version=3" type="application/x-shockwave-flash" width="193" height="130" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;
    &lt;/div&gt;
&lt;/div&gt;
</code></pre>
<p><br />360magento提供专业的基于magento系统的<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a>，如有需求或相关咨询，<a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 25 Sep 2015 11:51:15 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento模型集合常用过滤条件]]></title>
      <link>https://www.360magento.com/blog/addFieldToFilter/</link>
      <description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a title="magento建站开发" href="https://www.360magento.com/">Magento</a>的MVC模式为大家所熟悉，其中的Model作为数据处理的模型，其集合中的方法是大家开发时必不可少的。最近，我总结了下Magento模型集合中的addFieldToFilter常用过滤条件，希望对大家的开发起到一定的帮助作用。</p>
<pre><code>
//Equals: eq
$_products-&gt;addAttributeToFilter('status', array('eq' =&gt; 1));
 
//Not Equals - neq
$_products-&gt;addAttributeToFilter('sku', array('neq' =&gt; 'test-product'));
 
//Like - like
$_products-&gt;addAttributeToFilter('sku', array('like' =&gt; 'UX%'));
 
//Not Like - nlike
$_products-&gt;addAttributeToFilter('sku', array('nlike' =&gt; 'err-prod%'));
 
//In - in
$_products-&gt;addAttributeToFilter('id', array('in' =&gt; array(1,4,98)));
 
//Not In - nin
$_products-&gt;addAttributeToFilter('id', array('nin' =&gt; array(1,4,98)));
 
//NULL - null
$_products-&gt;addAttributeToFilter('description', 'null');
 
//Not NULL - notnull
$_products-&gt;addAttributeToFilter('description', 'notnull');
 
//Greater Than - gt
$_products-&gt;addAttributeToFilter('id', array('gt' =&gt; 5));
 
//Less Than - lt
$_products-&gt;addAttributeToFilter('id', array('lt' =&gt; 5));
 
//Greater Than or Equals To- gteq
$_products-&gt;addAttributeToFilter('id', array('gteq' =&gt; 5));
 
//Less Than or Equals To - lteq
$_products-&gt;addAttributeToFilter('id', array('lteq' =&gt; 5));
</code></pre>
<p><span>360magento提供专业的基于magento系统的</span><a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a><span>，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></p>]]></description>
      <pubDate>Thu, 24 Sep 2015 15:45:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento修改后台密码]]></title>
      <link>https://www.360magento.com/blog/change-password/</link>
      <description><![CDATA[<p>&nbsp; &nbsp; &nbsp; &nbsp;今天，我要跟大家交流的是magento后台密码的修改。在某些情况下我们需要对magento后台密码修改，那么对magento后台密码的修改有哪些方法呢？</p>
<ol>
<li>magento后台登录框左下角的忘记密码(Forgot your password?)，按照提示完成密码的修改；</li>
<li>通过数据库修改 此方法的前提是你有数据库的访问权限！从phpmyadmin进入到网站的数据库中，打开"admin_user"这张表，找到'username'等于你用户名的那条记录。在修改密码之前，你先要准备好你的新密码和识别码，这里我以新密码：admin123，识别码AL为例。之后在网上找一个可以生产MD5的网站，将你的新密码进行MD5加密，我生成以后的结果是:7a01b04183e3534bd0a6be7ff822784e。接着回到刚才的数据表，在数据的password列，将新密码和识别码以新密码:识别码的形式插入表中。我这里的是7a01b04183e3534bd0a6be7ff822784e:AL。点击保存。稍后，你就可以用你新设置的密码进行登录了。</li>
<li>通过修改源码进入后台修改 此方法的前提是你有ftp的访问权限！通过ftp进入网站，打开文件app\code\core\Mage\Admin\Model\User.php，在333行左右的位置找到authenticate()方法。在
<pre><code>$this-&gt;loadByUsername($username);</code></pre>
这段代码下增加返回True值的代码，即：
<pre><code>
$this-&gt;loadByUsername($username);
return true;
</code></pre>
现在你可以用任何密码进入后台了，登录后按照System-&gt;Permission-&gt;User，进入到用户管理页面。按照表格内容修改新的密码。最后，回到User.php文件，将刚才添加的代码删除。</li>
</ol>
<p><span>360magento提供专业的基于magento系统的</span><a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a><span>，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></p>]]></description>
      <pubDate>Wed, 23 Sep 2015 15:59:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用命令操作Magento预编译的开启和关闭 ]]></title>
      <link>https://www.360magento.com/blog/implement-magento-compiler-mode/</link>
      <description><![CDATA[<p>提高Magento性能的一个很重要的方法是开启<a title="magento开发建站" href="https://www.360magento.com/">Magento</a>的编译模式，可以在后台System>Tools>Compilation，点击Run Compilation Process按钮，一段时间后，我们发现Compiler Status由Disabled变为Enabled，已经编译成功了，打开/includes/src目录，会发现生成了很多文件。</p>
<p>
因为在<a title="magento开发建站" href="https://www.360magento.com/">Magento</a>中，我们模块的代码可以放在/app/code/local，/app/code/community，以及/app/code/core这三个目录下，如果Magento需要包含某个文件，系统会依次搜索这三个目录，直到找到这个文件为止，这为我们重写系统的某些文件提供了方便，比如需要修改core目录下的Mage/Catalog/Model/Product.php文件，只需要复制这个文件到local目录下的Mage/Catalog/Model/Product.php，然后修改这个文件即可，这样无需修改核心文件，为我们以后升级系统提供了方便，但由于系统需要在不同的目录中搜索文件，所以效率比较低，使用Compiler功能，系统将把这三个目录下的文件按照优先级顺序复制到/includes/src目录，比如Mage/Catalog/Model/Product.php文件将复制为Mage_Catalog_Model_Product.php，这样系统能够很快的找到需要包含的文件，大幅的提高了效率。
</p>
<p>如果我们需要安装新的模块，或者修改已有的模块，我们需要关闭<a title="magento开发建站" href="https://www.360magento.com/">Magento</a>的编译模式，可以在后台System>Tools>Compilation，点击Disable按钮，Compiler Status将由Enabled变为Disabled，添加或修改好模块之后，需要点击Run Compilation Process按钮重新生成编译文件。</p>
<p>此外，Magento提供了一个脚本工具使我们无需进入后台就可以查看和切换编译模式，该脚本位于根目录下的/shell/compiler.php</p>
<p>打开命令行，切换至shell目录：</p>
<pre>
    $cd shell
    $ls
    abstract.php compiler.php indexer.php log.php
</pre>
<p>查看使用compiler.php的方法：</p>
<pre>    $php -f compiler.php help
    Usage: php -f compiler.php -- [options]
      state Show Compilation State
      compile Run Compilation Process
      clear Disable Compiler include path and Remove compiled files
      enable Enable Compiler include path
      disable Disable Compiler include path
      help This help</pre>
<p>查看当前的编译状态：</p>
<pre>    $php -f compiler.php state
    Compiler Status: Disabled
    Compilation State: Not Compiled
    Collected Files Count: 0
    Compiled Scopes Count: 0</pre>
<p开始编译:></p>
<pre>
    $php -f compiler.php compile
    Compilation successfully finished
    $php -f compiler.php state
    Compiler Status: Enabled
    Compilation State: Compiled
    Collected Files Count: 6000
    Compiled Scopes Count: 4
</pre>
<p>关闭和开启编译:</p>
<pre>    $php -f compiler.php disable
    Compiler include path disabled
    $php -f compiler.php state
    Compiler Status: Disabled
    Compilation State: Compiled
    Collected Files Count: 6000
    Compiled Scopes Count: 4
    $php -f compiler.php enable
    Compiler include path enabled
    $php -f compiler.php state
    Compiler Status: Enabled
    Compilation State: Compiled
    Collected Files Count: 6000
    Compiled Scopes Count: 4</pre>
<p>清除编译</p>
<pre>    $php -f compiler.php clear
    Compilation successfully cleared
    $php -f compiler.php state
    Compiler Status: Disabled
    Compilation State: Not Compiled
    Collected Files Count: 0
    Compiled Scopes Count: 0</pre>
<p>我们还可以通过修改/includes/src/config.php文件开启和关闭编译模式，在编译成功后config.php将变为：</p>
<pre>define('COMPILER_INCLUDE_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR.'src');</pre>
<p>此时只需要注释掉这个语句就可以关闭编译模式：</p>
<pre> #define('COMPILER_INCLUDE_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR.'src');</pre>
<p>在Mage.php文件中我们可以看到下面一段代码：</p>
<pre>    Mage::register('original_include_path', get_include_path()); // 保存当前的include_path

    if (defined('COMPILER_INCLUDE_PATH')) { // 如果设置为编译模式
        $appPath = COMPILER_INCLUDE_PATH;
        set_include_path($appPath . PS . Mage::registry('original_include_path')); // 添加includes/src为include_path
        include_once "Mage_Core_functions.php";
        include_once "Varien_Autoload.php";
    } else { // 没有设置为编译模式
        $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
        $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
        $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
        $paths[] = BP . DS . 'lib';

        $appPath = implode(PS, $paths);
        set_include_path($appPath . PS . Mage::registry('original_include_path')); // 添加以上四个目录为include_path
        include_once "Mage/Core/functions.php";
        include_once "Varien/Autoload.php";
    }</pre>
<p>我们可以发现，<a title="magento开发建站" href="https://www.360magento.com/">Magento</a>通过检查是否定义COMPILER_INCLUDE_PATH常量来切换编译模式并设置对应模式的文件包含路径。</p>]]></description>
      <pubDate>Wed, 23 Sep 2015 12:47:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[跨境电商在中美市场碰撞火花]]></title>
      <link>https://www.360magento.com/blog/china-america/</link>
      <description><![CDATA[<p>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;中国国家主席习近平23日将在西雅图出席中美商界科技论坛，在与会的中美两国各15位顶级商界领袖中，亚马逊创始人杰夫&middot;贝佐斯和阿里巴巴创始人马云作为<a title="magento开发" href="https://www.360magento.com/">全球电子商务</a>两大巨头同时出席，让为<a title="magento开发" href="https://www.360magento.com/">跨境电商</a>在中美市场碰撞出火花。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 虽然亚马逊与阿里巴巴的细分目标市场并不完全一样，但两者不乏短兵相接的交叉地带。阿里巴巴在美国上市后，面对强劲对手，奋力开拓北美市场；北美电商巨头亚马逊则看准中国市场，为抢占市场份额频出高招。</p>
<p>　　总部位于西雅图市中心、占地400多万平方英尺的亚马逊，在电子商务领域已历经风雨20载，其今年第二季度，北美销售额达138亿美元，比去年同期强劲增长25.5%。在中国市场，亚马逊瞄准消费者，近来接连亮剑，推出&ldquo;海外购&middot;直采&rdquo;&ldquo;海外购&middot;直邮&rdquo;&ldquo;海外购&middot;闪购&rdquo;等新业务，体现对中国市场十分重视。</p>
<p>　　亚马逊全球资深副总裁迭戈&middot;皮亚琴帝尼近日对《环球时报》记者表示，&ldquo;市场变化迅速，对亚马逊而言，应对的关键在于灵活快速地响应市场变化。中国有很强的本土电商，竞争激烈，亚马逊中国应找到跟竞争对手的区隔点、我们的优势和定位。&rdquo;</p>
<p>　　皮亚琴帝尼所说的&ldquo;区隔点&rdquo;，是亚马逊中国的国际品牌战略，包括目前引入亚马逊美国300万同质同价产品的&ldquo;海外购&rdquo;商店、进口直采、以及在此基础上今年8月推出的&ldquo;海外购&middot;闪购&rdquo;创新业务。消费者不仅可以网购海外正品，更可享受全面本地化的物流配送和购物体验，商品从保税区、自贸区直接发货，平均3天就可收到订购的商品。</p>
<p>　　产品的正品保证，是亚马逊又一与竞争对手的区隔点。亚马逊全球副总裁冯思哲对《环球时报》记者说，&ldquo;中国市场发展迅速，对本土和外国电商都非常有吸引。我们在全球有专门的供应商管理团队，同时中国建立了自己的团队，团队大部分是中国人，非常了解本地市场，与全球团队紧密配合。我们在中国一直努力提供给消费者最好的正品、最好的价格和最好的配送服务。&rdquo;</p>
<p>据介绍，亚马逊中国的出口业务正加大力度帮助中国卖家走向全球，中国卖家已成为亚马逊&ldquo;全球开店&rdquo;的生力军，并取得良好的业务表现。2015年上半年，中国卖家销售额同比增长翻番。</p>
<p>　　另一方面，亚马逊的对手阿里巴巴也毫不示弱。今年以来，阿里巴巴因为旗下网站被指涉嫌售卖假货，被欧美多家奢侈品制造商诉诸法庭。面对社会舆论对&ldquo;出售假货&rdquo;的指责，阿里巴巴已重拳出击，修改假货下架程序。</p>
<p>　　同时，阿里巴巴今年还计划在美国兴建运营配送中心，构建其跨境电商平台，使中国消费者能网上跨境购物。与亚马逊有所区别的是，阿里巴巴着重构建为买卖双方提供第三方交易平台，收取2%至5%的佣<span>金，所以在仓储基建方面的投入相对较少，因而利润</span><span>空间相对高些。</span></p>
<p><span>&nbsp; &nbsp; &nbsp; &nbsp; 中国商务部统计显示，跨境电商在2014年的交易额达到718亿美元，同比增长44%。虽然亚马逊、阿里巴巴两巨头依然难分高下，但毋庸置疑，中国跨境电子商务行业前景看好，将吸引更多海内外商家。</span></p>
<p><span><span>&nbsp; &nbsp; &nbsp; &nbsp;360magento提供专业的基于magento系统的</span><a title="magento电商网站开发" href="http://www.360magento.com/">电商网站开发</a><span>服务，如有需求或相关咨询，</span><a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a><span>。</span></span></p>]]></description>
      <pubDate>Wed, 23 Sep 2015 12:47:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[解决magento开启Compilation预编译网站无法访问]]></title>
      <link>https://www.360magento.com/blog/error-compilation/</link>
      <description><![CDATA[<p>一般来说，开启<a title="magento建站" href="https://www.360magento.com/">magento</a>的Compilation预编译功能，可以使magento的访问速度提高25%。 但由于首次用这个功能操作不当，导致<a title="magento建站" href="https://www.360magento.com/">magento网站</a>崩溃，网站前后台都访问不了，这已经有好几个客户遇到这样的问题了。那么下面介绍既简单又快捷的方法。 </p>
<p>方法一：访问phpmyadmin，进入网站数据库的core_config_data表，搜索字段"path"的值为&ldquo;advanced/modules_disable_output/Mage_Compiler&rdquo;的数据，如果查找出来的该条数据的表字段&ldquo;value&rdquo;='1',那么改成&ldquo;value&rdquo;='0' </p>
<p>方法二： 打开/includes/config.php，手动注释掉最后两行 将</p>
<pre> define(&lsquo;COMPILER_INCLUDE_PATH&rsquo;, dirname(__FILE__).DIRECTORY_SEPARATOR.&rsquo;src&rsquo;);
define(&lsquo;COMPILER_COLLECT_PATH&rsquo;, dirname(__FILE__).DIRECTORY_SEPARATOR.&rsquo;stat&rsquo;);</pre>
<p>改成</p>
<pre> #define(&lsquo;COMPILER_INCLUDE_PATH&rsquo;, dirname(__FILE__).DIRECTORY_SEPARATOR.&rsquo;src&rsquo;);
#define(&lsquo;COMPILER_COLLECT_PATH&rsquo;, dirname(__FILE__).DIRECTORY_SEPARATOR.&rsquo;stat&rsquo;);
</pre>
<p>如果 开启预编译（Compilation）后，后台插件管理（Magento Connect Manager）不能访问。 解决方法： 把 /downloader/pearlib/php 文件夹拷贝到 /includes/downloader/pearlib/php/,这样可以解决问题。 </p>
<p>正确的操作方法是，第一次开启预编译，要先运行预编译（Run Compilation Process），然后再开启(Enable)</p>]]></description>
      <pubDate>Wed, 23 Sep 2015 11:09:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento产品详细页调用系统属性]]></title>
      <link>https://www.360magento.com/blog/magento-detail/</link>
      <description><![CDATA[<p>在<a title="magento网站开发" href="https://www.360magento.com/">电子商务平台</a>中，产品的详细页是重中之重。一些刚接触<a title="magento网站开发" href="https://www.360magento.com/">magento</a>不久的朋友对详细页中的一些系统属性并不太熟悉，今天我就给大家说明下magento详细页中的一些系统属性调用方法。</p>
<p>magento详细页的文件路径：/app/design/frontend/default/你的主题/template/catalog/product/view.phtml</p>
<p>常见的几种属性代码如下：</p>
<p>简单描述(short description)：</p>
<pre><code>&lt;?php echo&nbsp;$this-&gt;helper('catalog/output')-&gt;productAttribute($this-&gt;getProduct(), nl2br($_product-&gt;getShortDescription()), 'short_description') ?&gt;</code></pre>
<p>描述(description)：</p>
<pre><code>&lt;?php echo $this-&gt;helper('catalog/output')-&gt;productAttribute($this-&gt;getProduct(), nl2br($this-&gt;getProduct()-&gt;getDescription()), 'description') ?&gt;</code></pre>
<p>产品名称(name)：</p>
<pre><code>&gt;&lt;?php echo &nbsp;$this-&gt;helper('catalog/output')-&gt;<span>productAttribute</span>(<span>$_product</span><span>, </span><span>$_product</span>-&gt;<span>getName</span>()<span>, </span><span>'name'</span>) <span>?&gt;</span></code></pre>
<p>产品编号(sku)：</p>
<pre><code>&lt;?php echo $this-&gt;htmlEscape($_product-&gt;getSku()) ?&gt;</code></pre>
<p>产品价格(price)：</p>
<pre><code>&lt;?php echo $_coreHelper-&gt;currency($_finalPrice,true,false) ?&gt;<br /></code></pre>
<p>&nbsp;360magento提供专业的基于magento系统的<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a>，如有需求或相关咨询，<a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Tue, 22 Sep 2015 16:00:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[兰亭集势员工大批离职,“中国外贸电商第一股”怎么了？]]></title>
      <link>https://www.360magento.com/blog/lightinthebox-plight/</link>
      <description><![CDATA[<p><span class="text-remarks"><span class="text-remarks">兰亭集势对于外贸人已经很熟悉了，曾一度被模仿，尤其是很多<a title="magento公司,360magento" href="http://www.360magento.com/">magento公司</a>或个人也一度仿制<a title="magento兰亭模板" href="http://www.360magento.com/magento-theme.html">magento兰亭模板</a>,而今年在 纽交所上市的&ldquo;中国外贸电商第一股&rdquo;&mdash;&mdash;兰亭集势，看起来已经陷入资金 困境。这家公司不仅员工大批离职，与供应商矛盾也在激化。&ldquo;整个部门95%的同事从6月15日至今只发底薪，提成为零。&rdquo;兰亭集势北京一位在线销售告诉 《中国经营报》记者。兰亭集势每月15日发工资，2015年6、7、8月大部分员工都是只发底薪，因此员工对公司前景的悲观情绪正在加重。</span></span></p>
<p>兰亭集势员工正在加速离职，该公司一个离职员工微信群的成员数已经接近500人。以该公司位于北京望京地区包含在线销售以及客服在内接近50人规模的eBay销售团队为例，2015年以来离职员工已在20人左右。</p>
<p>兰亭集势在2015年6月份刚刚获得A股上市公司&mdash;&mdash;奥康国际<span class="text-remarks">（603001.SH）</span>大约7700万美元战略投资，为何还如此缺钱？兰亭集势<span class="text-remarks">（北京）</span>科技有限公司相关部门负责人在接受本报记者采访时表示，资金状况属于商业秘密、无可回复。</p>
<p class="text-big-title">现实困境</p>
<p>兰亭集势北京一位在线客服2015年6月和7月的工资条显示，其实发工资只有3200元-3500元；此前，其每月平均工资水平在7000元~8000元，每月提成在3000元~4000元，6月以来的收入水平仅相当于此前的1/2。</p>
<p>据记者了解，兰亭集势销售团队按照利润计算提成，每月提成的总体规模大约为销售利润的15%，然后按照每个销售小组的排名情况以及每个员工当月的绩效考核情况，核算个人的业绩提成。</p>
<p>在2015年6月的时候，发现工资少了的员工曾向人事部门询问相关情况，得到的答复是，此前几个月的工资&ldquo;算错账了，所以要从今后几个月的工资中扣掉&rdquo;。</p>
<p>前述兰亭集势北京员工透露，从2015年6月开始，&ldquo;销售部门计算利润的公式变了，说是之前运费一直算低了，所以从2015年开始到现在大家的提成为零&rdquo;。</p>
<p>兰亭集势一位离职管理人员认为，&ldquo;应该是公司觉得提成不合理，所以重新弄了一个算法。&rdquo;</p>
<p>兰亭集势<span class="text-remarks">（北京）</span>科技有限公司相关部门负责人在接受本报记者采访时官方否认了&ldquo;只发底薪&rdquo;的现象；而对于员工离职的问题，该负责人表示，每个公司都有离职员工，这是正常情况。</p>
<p class="text-big-title">增收瓶颈</p>
<p>成立于2007年3月的兰亭集势，基本商业模型是：跨国B2C，用Google推广，用Paypal支付，用UPS和DHL发货。其实，就是通过自有电商平台，也通过在eBay和亚马逊等<a title="海外电商" href="http://www.360magento.com/">海外电商</a>平台上开店的方式，将中国商品卖到海外市场，当然主要是北美和欧洲市场。</p>
<p>兰亭集势在经历徐小平等人的天使投资，又经过2008年500万美元、2009年1127万美元、2010年3500万美元三轮融资后，于2013年6月6日登陆纽约交易所。</p>
<p>背靠着&ldquo;世界工厂&rdquo;的中国，头顶着&ldquo;中国外贸电商第一股&rdquo;的光环，兰亭集势IPO发行价为9.5美元，第一个交易日收盘价为11.61美元；在上市初期的连 续7个交易日，兰亭集势一举涨到16.98美元，较发行价涨幅达78.73%；该公司股价在2013年8月曾经触及最高点23.38美元，此后一路下跌， 截至2015年9月8日的收盘价为2.96美元，仅相当于发行价的31%，为上市以来最低值。</p>
<p>股价低迷的背后，是兰亭集势收入增速大幅放缓、支出大幅增加、亏损幅度不断扩大的现实。</p>
<p>对 于增长乏力、亏损扩大的原因，兰亭集势内部人士认为，没能找到新的卖点是兰亭集势收入增长乏力的主要原因，虽然一直在尝试把安防等电子产品发展成为新卖 点，但目前的主打产品仍然是创业时期以婚纱为代表的服装产品，服装品类在净营收中的占比还在40%左右。数据显示，在2015财年第一季度8760万美元 的净营收中，3170万美元的服装品类占比达36.18%。</p>
<p>一位国内电商人士分析，商品定位和品牌定位决定了其只能卖低毛利产品，然后花费大把的营销费用去做搜索引擎营销；除此以外，兰亭集势近几年没有储备优势资源，没能建立自己的行业壁垒，失去了发展机遇。</p>
<p>另一位内部员工表示，兰亭集势主要是把廉价国产货卖到海外，要想赢得回头客难度很大，所以只能拼命打广告、拼流量，这只能让营销成本居高不下。</p>
<p class="text-big-title">外部压力</p>
<p>增收瓶颈、资金困境之外，兰亭集势在自身所处的<a title="跨境出口电商网站建设" href="http://www.360magento.com/">跨境B2C出口电商</a>业务领域也面临越来越严峻的外部竞争。</p>
<p>前 述国内电商人士认为，相对于国内电商平台而言，亚马逊中国凭借海外市场上无人能比的电商网络与渠道，在面向中国企业的跨境出口电商业务领域显然拥有更多、 更大的优势；只要亚马逊中国能够解决物流问题，能让国内出口企业通过其平台上规模即可获利，而不是利润被物流吃掉，其前景不可小觑。</p>
<p>阿里巴巴B2C模式的全球速卖通在强大资本支持下已经迅速成为中国跨境出口电商领域的老大。</p>
<p>&ldquo;阿里巴巴鼓励卖家直接从淘宝搬过去做外贸，所以在其他<a title="跨境电商平台" href="http://www.360magento.com/">跨境电商平台</a>上还没看到的产品种类，速卖通已第一时间与淘宝同步。&rdquo;上述电商人士表示，速卖通不仅抢到了客源和新兴市场，而且占领了更多的品类，这就是平台的优势，同时也推高了广告费用、增加了竞争对手的反击门槛。</p>
<p>数据显示，兰亭集势2014财年的订单总量达到970万份，而速卖通在2014年&ldquo;双11&rdquo;期间的总订单数就超过680万份。上述电商人士认为，如果兰亭集势不能在热卖品类或者优势资源上形成独特优势，那么肯定会越来越边缘化。</p>
<p>为了塑造自身优势，兰亭集势已于2015年年初推出&ldquo;兰亭智通&rdquo;全球跨境物流开放平台。但兰亭集势内部人士担心，自建物流的结果可能使该公司资金上承受更大压力，&ldquo;京东为什么一直亏，就是因为不断自建物流&rdquo;。</p>
<p><span class="text-remarks">&nbsp;360magento提供专业的基于magento系统的<a title="跨境电商平台开发与托管" href="http://www.360magento.com/">跨境电商平台网站开发和托管服务</a>，如有需求或相关咨询，<a title="magento开发" href="http://www.360magento.com/contacts/">请与我们联系</a>。</span></p>]]></description>
      <pubDate>Tue, 22 Sep 2015 14:11:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[SEO 也分三层境界]]></title>
      <link>https://www.360magento.com/blog/seo-three/</link>
      <description><![CDATA[<p>没有人会手把手教你创业，别人没这个义务，很多东西你必须自己去研究。</p>
<p>流量获取的通道，就大方向而言，包括广告采购，搜索优化，社交营销，广告采购最大的一块是 SEM，其他还有很多；搜索优化目前包括 SEO 和 ASO，前者是针对搜索引擎，后者针对各种移动市场，但其实只要涉及搜索的平台，包括淘宝在内，都有搜索优化的空间。社交营销主要平台是微博，微信，朋友圈，陌陌等，海外是 Facebook，Twitter，YouTube，Instagram，以及 Snapchat 等。</p>
<p>SEM 这块，很早之前 Google 和百度的广告系统还不够完善的时候，有很大的空子可以钻，2004年 吴京川老师（百度元老，百度联盟的创始人，最早发现 hao123 巨大价值的人，当年我做统计系统也是受他影响和指点）讲 Google SEM 搜索套利模式的时候，我听的一愣一愣的，完全没听懂，等 2007年 我听明白的时候，这个市场已经过去了。简单点说就是，寻找 Google 搜索广告中价格被低估而转化效果好的长尾词，买这些广告，但不用做网站，直接放 ebay 的效果广告，说白了就是替 eBay 买 Google 的广告，但是如果你数据玩的好，对转化率跟踪比较做的透，就可以赚钱，这个生意有多大呢？有个公司靠做这个后来卖了几个亿美金（有意思么，那时候几亿美金绝对不是小数字，但是国内的媒体上基本没人报）。但随着 Google 和百度广告系统的不断完善，这个空子基本没有了。</p>
<p>目前依靠 SEM 的很多是<a href="https://www.360magento.com/ title=">跨境电商</a>，典型如做到上市的兰亭集势，此外香港上市的 dx.com。不确定对 SEM 的依赖度高不高。 想要具体了解 SEM 的有关数据，semrush.com 是一个非常不错的数据网站。</p>
<p>下面说一下 SEO，很多人对 SEO 有一种误解，认为追寻 SEO 就是骗取搜索引擎流量，是不入流的做法，特别是一些精英背景的创业者，往往听到 SEO 就嗤之以鼻，这是非常不对的。</p>
<p>SEO 我讲过，分三层境界，获得热门词的前几名，是第一层境界，也就是大部分人对 SEO 的理解，提升搜索引擎的收录和权值，让网站在搜索引擎中有非常多的收录，每天获得大量的长尾词来路，是第二层境界，也是通常一些专业 SEO 服务公司的目标。而第三层境界是，让自己的品牌词成为热门词，在指数上有显著的体现，达到这一境界，你就不用担心搜索引擎会封掉你的站，典型如淘宝，很早就主动屏蔽了百度的蜘蛛，但是每天通过品牌词从百度搜索过去的用户多达数百万，这就是品牌的极端案例。</p>
<p>下面说几个关于 SEO 比较成功的案例，先说重量级的，在上市公司里，汽车之家是非常非常重视 SEO 的一个典范，58 同城和赶集网当年在 SEO 上的争夺和投入都是非常巨大的，此外，同程旅游网对外接受采访的时候也公开说 SEO 是他们的核心竞争力。看到这些案例，还会觉得这是小儿科的东西么？</p>
<p>未上市公司里，4399 的品牌强度是首屈一指的，去年估值几个亿卖掉的欣欣旅游早期在 SEO 优化上也是成绩斐然，当时著名站长夏天天给他们做过一次培训，边悦同学贯彻和操盘了优化的过程，（边悦后来自己出去创业，是个典型的实用主义创业者，靠 SEM 赚的风声水气，当然，媒体上看不到他。）</p>
<p>另外两个值得一提的案例，一个是麦包包，一个是名鞋库。这涉及一个 &ldquo;出淘&rdquo; 的概念，很多淘品牌发现淘宝上运营成本越来越高，对淘宝依赖性越来越强，所以很多商家也希望自建官网，减少对淘宝的依赖度，但是官网流量和用户哪里来？在移动互联网到来之前，只有百度是最大的流量入口，但大部分淘品牌，自建官网的流量运营并不顺利，而麦包包和名鞋库则是两个非常成功的范例，在三年前的样子，麦包包是所有淘品牌里百度指数最高的一个，而且是遥遥领先于所有其他淘品牌，操盘手是柳焕斌，柳焕斌离职后，目前似乎已经不再具有如此明显的领先优势，有兴趣的同学可以到百度指数上查询一下，时间轴拉长，对比麦包包和其他淘品牌关键词，看看当年的趋势变化。<span>名鞋库我记得在 11年 还是 12年 的时候，当时每天百度来路只有 1000 多而已，我跟他们市场副总裁韩步勇一向关系不错，还拿这个取笑过他们，但转年人家知耻而后勇，定下了每天百度来路 6 万的指标，通过和刑天 SEO 团队的深度合作，到年底的时候，竟然真的实现了。成为所有鞋类电商百度来路最多的平台，是的，超过了好乐买，也超过了当时的乐淘。仅此一项，每年节省广告费数千万，形成销售额数亿。而成本真的并不高。</span></p>
<p>SEO 这个话题如果扯开实在太大，有兴趣的同学，除了多去看百度指数，百度热榜外，建议学习使用&nbsp;aizhan.com，我前几年几乎每天都在 aizhan.com 上分析关键词，分析竞争对手的搜索来路构成。</p>
<p>说一个观点，我们天天讲产品要满足用户需求，什么是用户需求？产品经理拍拍脑袋就是用户需求么？为什么用户会去搜索引擎搜索？搜索行为不就是用户需求么？搜索的频率不就是需求的强度么？按照用户的搜索词频度去设计网站，定义网站的架构，不就是满足用户需求么？你连用户搜索行为都不分析，摆出一副高高在上，我只关心用户，不关心搜索的态度，你真的关心的是用户么？</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 21 Sep 2015 15:59:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[谷歌：下一个十年 跨境电商路在何方？]]></title>
      <link>https://www.360magento.com/blog/next-step-ecomerce/</link>
      <description><![CDATA[<p>9月19日，2015第五届中国跨境电商大会暨海贸会5周年在广州召开。Google出口业务总经理黄秀兰出席并与现场嘉宾分享了Google对跨境电商未来趋势的解读。她提到，市场洞察、数据分析、营销策略将在未来<a title="magento电商网站开发'" href="https://www.360magento.com/">跨境电商</a>领域的竞争中起到越来越重要的作用。</p>
<p>10年前的2005年，中国外贸电商的一个重要品类&mdash;&mdash;婚纱悄然兴起。在著名的虎丘婚纱一条街，几十元到一两百就能买到相当不错的婚纱，而欧美市场的一条婚纱价格至少在三五百美金以上。巨大的价差促成了一大批企业通过网络将婚纱卖到海外，赢得了外贸电商的第一桶金。</p>
<p>十年来，互联网已成为<a title="magento电商网站开发'" href="https://www.360magento.com/">跨境电商</a>发展的重要驱动力。Google作为全球互联网行业的先行者，坚持为中国的企业提供前沿的数字营销理念以及全方位的数字营销解决方案和服务，帮助中国企业精准定位国际市场，推动中国跨境电商的整体成长。</p>
<p>全球与&ldquo;进出口&rdquo;相关的搜索中，中国拔得头筹</p>
<p>十年来，跨境电商也逐步从小打小闹的作坊式生意开始向资本市场靠拢。2007年成立的兰亭集势，2013年登陆纽交所。2014年，百圆裤业10亿元收购跨境电商环球易购，后来改名为跨境通，市值接近200亿。</p>
<p>从07年至今，在Google上与&ldquo;进出口&rdquo;相关的搜索中，中国最受关注。这体现了世界对一个国家进出口的关注程度。在过去几年中，&ldquo;中国&rdquo;很明显的形成了一条上扬的曲线。它的关注度，是位于第二名的美国的八倍之多。</p>
<h2>下一个十年，跨境电商路在何方？</h2>
<p>通过对数据的分析，Google提出未来十年跨境电商的五大趋势和变化，而其中有一些变化正在发生。</p>
<h3>趋势1: 从卖给&ldquo;所有人&rdquo;到卖给&ldquo;一些人&rdquo;</h3>
<p>从卖给&ldquo;所有人&rdquo;到卖给&ldquo;一些人&rdquo;，即定位的变化。在跨境电子商务刚刚兴起的几年里，海内外价格差是选择商品的唯一信号。那个时期的网站，从热卖商品到网站设计，再到季节性促销，都出奇的一致。一个网站里基本也集合了所有热卖商品，婚纱，手机，配件，水龙头，奇怪地组合在一起。&ldquo;卖给所有人&rdquo;的时代正在远去。</p>
<p>如今的跨境电商已进入一个精细化、垂直化竞争的时代。目标群体的定位也越来越清晰。他们喜欢什么，喜欢什么时候买，都要能了如指掌。</p>
<h3>趋势2: 从大规模制造到小规模定制</h3>
<p>在&ldquo;工业4.0&rdquo;时代，物联网、智能化等新技术正在提高制造业水平，制造业正向智能化转型，用户需求决定生产制造，传统供应链向柔性供应链转变。</p>
<p>以服装业为例，以前衣服从设计到打版、定型，需要半年的时间，然后采购物料，进入生产流程，到进入流通渠道，基本需要20个月。近年来，&ldquo;快时尚&rdquo;风靡全球，它反映在对潮流的快速响应，从捕捉时尚潮流到将产品送到消费者手中所用的时间短。这样的生产方式，便于企业迅速收集市场反馈数据，并基于数据做进一步的产品发展决策。受互联网影响的小而快的生产模式正在对制造业产生更深刻的变革。甚至可以在用户需求明确以后才进行生产。现在50件起订，7天快速生产的服装企业正应运而生。</p>
<h3>趋势3：从卖白牌到卖品牌</h3>
<p>如果过去十年，主要竞争的是山寨、无品牌产品，那么跨境电商的下一个十年将进入品牌的竞争，未来最终会进入一个跨境电商的品牌时代。小而美的品牌将会在跨境电商竞争中拥有重要的位置。</p>
<p>以服装行业搜索行为变化为例。服饰类一般关键字的搜索基本比较平稳，主要是季节性的波动。而品牌关键字的搜索却直线上升。2007年服装类的热门搜索词中，每300个搜索中会有1个中国服装的网站，而到了2015年，每10个搜索就有1个中国服装网站品牌。</p>
<h3>趋势4: 从硬广告到软沟通</h3>
<p>从营销的角度看，未来最重要的一个趋势就是，广告正在消失&mdash;&mdash;那些旗帜鲜明的&ldquo;硬广告&rdquo;正在消失，广告正在以&ldquo;沟通&rdquo;的形式融入到你的生活。在移动时代，无论何时何地、遇到何种状况，人们通过使用手机即时解决问题的时刻;也就是消费者产生学习、探索、观看、查找或购买意愿时，习惯于通过智能电话这类最贴身的移动设备达到目的、满足需求的时刻。</p>
<p>在过去，消费者将其转变为现实需要经历几天、几个星期甚至几个月的时间;因此过去的市场营销人员设计、从事营销活动时更专注于培养消费者的品牌意识和忠诚度，希望他们从购买意向到购买决定之间能够以此为导向。而当今的消费者从产生消费需求到实际购买可以在很短的时间内完成，这一瞬间就可能导致整个营销活动的成功或失败。</p>
<h3>趋势5: 从卖欧美到赢全球</h3>
<p>未来十年，跨境电商将真正走向全球。跨境电商在过去的竞争主要集中在欧美英语市场，但未来的竞争格局会大不同。在零售电商领域，亚太区的销售额现已超越美国和欧洲，位居全球第一。而拉丁美洲、中东等区域，他们的增长率将在2020年达到30%，是美国和欧洲的两倍。</p>
<p>据统计，跨境电商的主要投资市场和投资幅度增长最快的市场有显著不同。他们的投资市场，除去美国，澳大利亚，加拿大之外，还有三个最大的欧洲市场以及一些亚洲市场。而从增长最快的市场来看，中东地区占据着显著的位置。在前五名中，就有三个是中东国家，且增长率超过100%。</p>
<p>由此，过去的跨境电商竞争基本是以廉价商品、粗放竞争为主。而现在，跨境电商的竞争已经转型，市场洞察、数据分析、营销策略将在竞争中起到越来越重要的地位。为了更好的服务中国的跨境电商企业，Google在五年前设置了专门的&ldquo;Google 出口顾问&rdquo;来为客户提供深度市场分析，网站用户体验咨询以及营销方案优化。下一个十年，Google也将和更多的企业携手同行，迎接新的挑战。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 21 Sep 2015 15:27:40 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[亚马逊将于2016年6月关闭网店建站服务]]></title>
      <link>https://www.360magento.com/blog/amazon-webstore/</link>
      <description><![CDATA[<p>亚马逊Amozon已正式对外公布将关闭<a title="电商网站开发" href="https://www.360magento.com/">网店建站</a>业务webstore，在未来一年多的时间里，卖家们需要找到新的服务替代者，其竞争对手如加拿大电商Shopify和澳大利亚电商初创公司Bigcommerce将有望获得更多的客户。亚马逊公司未对外透露关闭该业务的原因。</p>
<p>从外媒&ldquo;recode&rdquo;3月18号的报道中获悉，亚马逊已通知各线上卖家，亚马逊Webstore服务将于2016年6月1日关闭。在此项服务取消之前，亚马逊公司的客户们将有一年多的时间寻找新的服务商。</p>
<p>由于新公司如加拿大电商Shopify和澳大利亚电商初创公司Bigcommerce已经募集到了足以扩大业务和吸引更多客户的风险投资资金，面向中小企业的电商软件业务将面临愈加剧烈的竞争环境。不少朋友可能会记起，在去年夏天，eBay公司宣布中止提供面向小型网店的产品Magento Go，并建议他们将业务转到Bigcommerce。</p>
<p>亚马逊的卖家们也渐渐得知了这一消息。由于亚马逊的发言人拒绝对此置评，亚马逊此举的动机尚不得而知。畅路销（ChannelAdvisor）首席执行官Scot Wingo表示，畅路销已经开始建议一些卖家撤离亚马逊网店平台。Scot Wingo说：&ldquo;我们将协助大约百名在使用亚马逊平台的客户将业务过渡到其它电商平台，如Shopify、Bigcommerce,、Mozu和<a title="电商网站开发" href="https://www.360magento.com/">Magento</a>等。好消息是，作为库存管理和订单配送中心，我们可以为客户实现无缝对接。&rdquo;</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Mon, 21 Sep 2015 02:44:42 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 简化URL]]></title>
      <link>https://www.360magento.com/blog/simplify-URL/</link>
      <description><![CDATA[<p>在<a title="电商网站开发" href="https://www.360magento.com/">Magento模板开发</a>中，有时候需要将多级分类的url简化，Magento的URL默认是显示多级分类的</p>
<p>例如：http://www.360magento.com/分类1/分类2/分类3</p>
<p>现在需要简化为：</p>
<p>分类2的URL为：http://www.360magento.com/分类2</p>
<p>分类3的URL为：http://www.360magento.com/分类3</p>
<p>具体修改方法如下：</p>
<p>打开app/code/core/Mage/Catalog/Model/Url.php这个php文件，找到如下代码：</p>
<pre><code>if (null === $parentPath){ 
$parentPath = $this-&gt;getResource()-&gt;getCategoryParentPath($category);
 }
elseif ($parentPath == '/'){ 
$parentPath = ''; 
}
</code></pre>
<p>把上面的代码注释，即：</p>
<pre><code>
//if (null === $parentPath){
//$parentPath = $this-&gt;getResource()-&gt;getCategoryParentPath($category); 
//}
//elseif ($parentPath == '/') { <br />//$parentPath = ''; 
//}
</code></pre>
<p>$parentPath = $this-&gt;getResource()-&gt;getCategoryParentPath($category); 是获取分类的父级分类，</p>
<p>下面将父级分类设置为空则在生成的URL中屏蔽掉父级</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 20 Sep 2015 10:56:34 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[力推金融与跨境电商融合]]></title>
      <link>https://www.360magento.com/blog/finance-cross-border-ecommerce/</link>
      <description><![CDATA[<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;9月19日，由自治区商务厅、防城港市政府共同举办的中国-东盟金融<a title="电商网站开发" href="https://www.360magento.com/">跨境电商</a>合作与发展论坛在南宁举办。</p>
<p>　　论坛围绕&ldquo;一带一路&rdquo;背景下金融与跨境电子商务如何结合发展等相关议题展开。自治区商务厅表示，目前在东南亚零售总额中，电子商务份额还不足1%，而中国、欧洲和美国已达到6%至10%。随着互联网普及率的上升，预计在未来几年，东南亚在线零售将增长25%，广西发展面向东盟的<a title="跨境电子商务" href="http://www.360magento.com">跨境电子商务</a>拥有广阔的市场空间。面向东盟跨境电子商务的快速发展必将带动跨境支付、金融快速发展。尽快完善跨境电商的生态体系，将为中国-东盟特别是广西和东盟的跨境电商合作提供有力支撑。</p>
<p>　　据介绍，2014年9月南宁获批成为国家跨境贸易电子商务服务试点城市。今年以来，一批中国-东盟跨境电商平台正式上线，与泰国、越南、新加坡、马来西亚等东盟国家建立了良好的合作关系，广西跨境电子商务企业正在不断发展壮大。</p>
<p>　　论坛上，专家学者和企业代表就中国-东盟跨境电商市场分析与政策解读、地方政府如何推动当地<a title="网站建设" href="http://www.360magento.com">&ldquo;互联网+&rdquo;</a>电商发展、重构跨境电商与农产品流通业态、跨境电商综合金融服务助力企业发展、人民币强势背景下跨境电商货币结算等议题发表真知灼见。大会还安排了电商企业项目推介、金融机构融资服务专题推介，举行了阿里巴巴1688进口货源平台&middot;防城港站上线仪式，这是&ldquo;电商入桂&rdquo;的又一重要成果。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp;360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 20 Sep 2015 10:11:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[首批区级电商重点培育名单出炉]]></title>
      <link>https://www.360magento.com/blog/district-level-ecommerce/</link>
      <description><![CDATA[<p>日前，记者从区商务局了解到，第一批萧山电子商务产业重点培育企业名单正式出炉，7家电商企业榜上有名。据悉，本次认定的企业包含5家电子商务企业和2家电子商务服务企业。</p>
<p><strong>　　电商行业巨头</strong></p>
<p>　　近日，国内知名医药巨头康恩贝与浙江珍诚医药在线股份有限公司达成合作协议，此番两大企业的强强联合，被业内誉为线下实体品牌与线上流通渠道的完美结合，有望重新定义医药电商行业。</p>
<p>　　而对珍诚医药来说，此次引入康恩贝战略投资，将进一步充实公司现金流，加速产业链布局。据悉，珍诚医药目前正处于高速扩张阶段，这其中包括建设现代物流基地、推进药联５万家项目等。</p>
<p>　　珍诚医药是萧山首批区级电商产业重点培育企业之一。除珍诚医药外，此次入选的其他６家企业分别是：杭州维卓电子商务有限公司、九州通集团杭州医药有限公司、杭州卡当礼品有限公司、浙江胜利羽绒制品有限公司、杭州珍诚<a href="http://www.360magento.com title=">网络科技有限公司</a>、杭州精纱信息技术有限公司。</p>
<p>　　根据相关评选标准，入选的电子商务企业要求从事网络销售，年网络交易额在2000万元以上，电子商务服务企业从事代运营等相关配套支撑服务，年业务收入在500万元以上。</p>
<p>　　此外，入选企业通过第三方平台或自建网站平台等形式，进行网上交易业务2年以上，或为电子商务产业发展和应用提供相关配套支撑服务2年以上。</p>
<p>　　据悉，电子商务产业重点培育企业每年认定一批，一经认定有效期为３年，期满后企业需要重新提出申请。</p>
<p><strong>　　站上<a title="360magento" href="http://www.360magento.com">&ldquo;互联网＋&rdquo;</a>风口</strong></p>
<p>　　&ldquo;从评选条件不难看出，这些企业都有一个共同点，那就是在电商行业扎根时间较长，经济效益、社会效益已经初步显现出来。&rdquo;萧山区内相关负责人表示，当前电商行业成为一大主流，很多企业纷纷涉足，但至于怎样做才更有效，这7家企业的商业模式或对其他企业具有一定参考价值，&ldquo;这也是评选首批电商重点企业的意义所在。&rdquo;该负责人说。</p>
<p>　　特别是，当前&ldquo;互联网＋&rdquo;风起云涌，各个行业各个企业都在积极对接&ldquo;互联网＋&rdquo;战略，尤其是萧山的一大批传统优势企业，更是积极投身其中，通过触网拓展销售渠道，创新商业模式，推动业务结构转型升级。</p>
<p>　　比如说浙江胜利羽绒制品有限公司，这家以出口羽绒被为主的传统生产型企业，在国内站稳脚跟之后，目前还在日本注册了电子商务公司，准备开展<a title="电商网站开发" href="https://www.360magento.com/">跨境电商</a>业务。据悉，胜利羽绒的跨境电商业务即将上线。</p>
<p>　　而另一家企业杭州卡当礼品有限公司，主打创意个性礼物定制，其产品线囊括了时尚饰品、珠宝手表、鞋包配饰等数十个大类超千款产品。事实上，该公司销售额连续多年保持了近300%的增幅，并在个性礼品定制行业处于第一品牌的优势地位。</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sun, 20 Sep 2015 10:09:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[京东云互联网+质检]]></title>
      <link>https://www.360magento.com/blog/jd-internet/</link>
      <description><![CDATA[<p><span>9月16日，第三届国际检验检测技术与装备博览会在北京雁栖湖国际会议中心正式开幕。开幕式上，京东集团与中国出入境检验检疫协会举行了战略合作签约仪式，将共同打造中国<a title="电商网站开发" href="https://www.360magento.com/">电商</a>产品质量云平台。</span></p>
<p>京东集团副总裁何刚与中国出入境检验检疫协会副秘书长段小红签署了战略合作协议。国务院参事、中国出入境检验检疫协会葛志荣会长，国家质检总局项玉章总检验师，中国出入境检验检疫协会鲍俊凯秘书长，中国检验认证集团齐京安董事长等高层领导也出席了签约仪式。据悉，双方未来将在以下三个领域重点展开深入合作。</p>
<p>一、推进建立行业标准，共同打造生态体系</p>
<p>双方将共同发起并制定电子商务产品质量标准，推动建立<a title="电商网站开发" href="https://www.360magento.com/">电子商务</a>产品认证和企业质量信用评价体系，并通过电子商务产品质量追溯体系，建立以组织机构代码和商品条码为基础的电子商务产品质量追溯制度。依托京东云计算和大数据技术，随着业务与数据的深入整合,双方将打造全新的电商产品质量生态体系。</p>
<p>二、盘活检验检测存量数据，实现数据价值真正增值</p>
<p>双方将借助京东云计算服务构建社会化的进出口商品质量信息库和质量信息服务平台，并将其与商品大数据追溯系统、电子商务产品质量信息公共服务平台进行系统整合与优化，利用京东大数据分析系统和算法模型、数据挖掘等分析技术，将进出口商品的信息数据、商品标准、认证信息、许可信息等数据进行分析整合，从而充分展现质量数据和信息的实用价值，为企业和消费者提供更多的便利和保障。</p>
<p>三、推进电商产品质量提升，服务生态企业和消费者</p>
<p>借助京东云计算服务实现对电商产品质量状况的在线监测，通过京东大数据分析技术提升电商产品质量信息服务平台的应用能力，为政府监管部门、电商企业、广大消费者提供安全、便利的商品质量信息服务。进而全面提升企业进货质量的把关能力，为消费者提供产品质量标准方面的解读服务，让消费者直观地了解产品质量标准，区分产品质量优劣，实现&ldquo;源头可溯、去向可查&rdquo;。</p>
<p>何刚表示，双方将建立长期的战略合作关系，充分发挥各自的资源优势，推进建立健全的电子商务质量管理制度规范，在电子商务领域营造人人重视质量、人人创造质量、人人享受质量的社会氛围，共同提升中国电子商务企业的质量保证能力，净化并提高<a title="电商网站建设" href="http://www.360magento.com">电子商务</a>产业的质量发展环境。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 19 Sep 2015 02:15:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[2015中国-东盟电子商务峰会开幕]]></title>
      <link>https://www.360magento.com/blog/2015-asen-ecommerce/</link>
      <description><![CDATA[<p>9月18日，2015中国-东盟电子商务峰会在南宁开幕。峰会以&ldquo;<a title="电商网站建设" href="http://www.360magento.com">互联网+</a>新战略，中国-东盟新经济&rdquo;为主题，来自中国和东盟国家政要、重要商协会负责人、著名经济学家、电商领军企业家和各界代表结合&ldquo;中国-东盟互联网+新经济&rdquo;、&ldquo;中国-东盟<a title="跨境电商平台" href="http://www.360magento.com">跨境电商</a>新基地&rdquo;、&ldquo;中国-东盟经贸信息港展望&rdquo;和&ldquo;中国-东盟创新创业新机遇&rdquo;四大议题开展主题演讲及高端对话，现场气氛活跃，反响热烈。</p>
<p>大会指出，&ldquo;互联网+&rdquo;对形成新的经济增长点、促进国际产能合作、推动区域经济一体化有重要意义。广西将秉持开放合作、互利共赢的精神，以打造中国-东盟跨境电商基地为目标，推动中国-东盟经贸信息港建设，与东盟各国朋友一道，共商、共建、共享21世纪&ldquo;电商丝路&rdquo;，为打造中国-东盟自由贸易区升级版和中国东盟命运共同体进行探索和努力。</p>
<p>&ldquo;广西是面向东盟的前沿和门户，是离东盟最近的省份。广西和东盟是山水相连、地缘相近，联系非常密切，做电商得天独厚。&rdquo;除了地域优势，广西商务厅参会领导表示，发展电商，特别是跨境电商，特别需要人，特别是东盟10国语言不同，小语种的人才非常稀缺。广西是小语种人才的培训基地，这方面广西有非常大的优势。此外，中国-东盟信息港正式落地南宁，中国-东盟信息港将要建设经贸信息港，打造电子商务云中心，利用信息中心、交流中心、商务会展中心，这些都是为电商发展提供了条件。</p>
<p>菲律宾参会嘉宾表示，广西与菲律宾的合作非常有潜力。今天有相当多的电商企业来参加会议，这些电商本身有一个非常好的平台，并且他们也志在进入菲律宾市场，所以广西在合作进程当中占有一个非常重要的作用。</p>
<p>本届峰会促成了一系列合作，广西&ldquo;互联网+&rdquo;产品二维码中心建设、广西商务厅与苏宁云商战略合作、东兴市与京东集团华南区关于电子商务进农村示范工程战略合作等一批重大合作项目落地广西发展。</p>
<p>据了解，9月19日，峰会还将举办中国-东盟电商领袖交流会、中国-东盟电商创业交流会、中国-东盟金融跨境电商合作与发展论坛等一系列活动。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 19 Sep 2015 02:09:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[告别传统搜索模式，移动电商进入场景化发展新时代]]></title>
      <link>https://www.360magento.com/blog/mobile-ecommerce/</link>
      <description><![CDATA[<p><a title="互联网" href="http://www.360magento.com">移动互联网</a>的快速发展以及智能终端的普及，培养了用户扫一扫、查一查身边出现的一些商业广告的习惯，甚至可以触发用户于&ldquo;不经意&rdquo;间完成一次网上购物。研究表明，66%的智能手机用户会通过手机查询旅途中、就餐中看到的商业广告的信息。</p>
<p>在腾讯移动事业群副总裁马斌看来，人们的购买方式正在由传统化向碎片化转变，支付方式由PC端转到移动端，随时随地购物的消费需求日益迫切。在这个过程中，&ldquo;无需搜索，按需推送&rdquo;的场景化服务应运而生。</p>
<p>&ldquo;纵观国内电子商务市场，&rdquo;业内人士认为，&ldquo;场景化或将可以撬动本地生活服务电商领域的亿万商机，成为移动电商发展新方向。&rdquo;具体说来，原因主要有以下两点：</p>
<h2>一、移动互联网时代，场景触发消费者购物欲</h2>
<p>近年来国内电商呈现蓬勃发展之势，并先后经历了电商的搜索时代和流量时代。但不管哪个阶段，消费者的购买方式始终是具有目的性的，并且必经此流程：目的&mdash;&mdash;搜索&mdash;&mdash;选择&mdash;&mdash;购买。但是科技的飞速发展，为消费者带来了更加便捷的购物体验。</p>
<p>以消费者买包为例，按照传统流程首先是广泛搜索，在某个<a title="电商网站建设" href="http://www.360magento.com">商城网站</a>通过品牌、种类来锁定某款样式;其次，看看这个包是不是时尚，是不是符合自己的个性，是不是性价比很高;然后还需要看看有没有人购买，有没有人评论;最后综合考虑进行决策。购买决策时间长，甚至还会为某种原因最终放弃购买，<a title="电商平台建设" href="http://www.360magento.com">电商平台</a>并不能了解到用户所处的购买场景。</p>
<p>如果电商网站或者店铺提供了以上这些足够丰富的场景化信息，比如消费者进店后立即推送相应的折扣优惠，那么便会直接激发出购买欲望，迅速作出购买决策。这就是商家给消费者构建了一个场景，通过这个场景来触发消费。</p>
<p>事实上，&ldquo;场景&rdquo;是一个非常重要的词，产品和营销必须基于消费者具体、特定和鲜活的场景，研究消费者场景可以发现新产品机会，制造消费者场景可以开辟新产品空间，展示消费者场景可以驱动消费者的购买行为。</p>
<p>然而很多时候，一些电商网站和电商店铺并没有关注这一点，良好的客户体验一定是基于消费者的生活场景的，在商品促销中没有生活场景，对于消费者而言就是冰冷的，有生活场景就是可以被打动的。</p>
<h2>二、场景化可以更好提高电商交易转化</h2>
<p>&ldquo;场景触发不只是为了推送信息，更希望用户产生回单和复购，这是非常重要的。&rdquo;业内人士认为。</p>
<p>在传统购物中，刷卡、现金结算往往意味着商家与消费者的关系结束，用户粘性的缺乏使商家很难形成二次消费;但在场景服务中不一样了，商家如果能够通过智能手机的传感器WIFI/ibeacon等设备定位和触发，获知用户的具体位置场景，通过对用户行为数据的收集和分析建立起对他们的画像，就可以达到个性化、精准、前置信息的推送。不但为商家提升进店率、留存率、转化率带来了可能;这时，信息推送也不再被认为是骚扰，而是商家及时贴心的服务。</p>
<p>举例来说，当小编携带安装爱街&ldquo;WiFi密探&rdquo;的手机，来到望京凯德MALL，在闲逛路过&ldquo;太平鸟&rdquo;专卖店门口时，手机上就会收到&ldquo;太平鸟&rdquo;天猫旗舰店的新款推荐，可以和实体店比比价格和款式，点击就可以在手机上下单购买。场景购物，体验真好!</p>
<p>目前，万达电商&ldquo;飞凡网&rdquo;、阿里的&ldquo;喵街&rdquo;、迈外迪、爱街、鲜老虎等众多企业正在进行线下场景布局，通过营造更轻松、更智能、更个性化的购物体验，让顾客和商家建立长久关系。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Sat, 19 Sep 2015 01:55:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento通过分类搜索产品功能]]></title>
      <link>https://www.360magento.com/blog/magento-categpry-search/</link>
      <description><![CDATA[<p>想要magento站点搜索加上分类选项，只需要在magento相应的模板中，用以下代码替换app/design/你的主题名/template/catalogsearch/form.mini.phtml文件中的源代码即可。然后刷新索引和缓存，你将会发现搜索的旁边出来一个分类选项！</p>
<pre><code>
&lt;?php
        $category = Mage::getModel('catalog/category');
        if(is_object(Mage::registry('current_category'))){
            $current_category_path=Mage::registry('current_category')-&gt;getPathIds();
        }else{
            $current_category_path = array();
        }
        $category-&gt;load(Mage::app()-&gt;getStore()-&gt;getRootCategoryId());
        $children_string = $category-&gt;getChildren();
        $children = explode(',',$children_string);
        $extra_options='';
        foreach($children as $c){
            $selected = (in_array($c, $current_category_path))?'SELECTED':'';
            $extra_options.= '&lt;option value="' . $c . '" ' . $selected . '&gt;' . $category-&gt;load($c)-&gt;getName() . '&lt;/option&gt;' . "\n";
        }
        ?&gt;
        &lt;form id="search_mini_form" action="&lt;?php echo $this-&gt;helper('catalogSearch')-&gt;getResultUrl() ?&gt;" method="get"&gt;
            &lt;fieldset&gt;
                &lt;legend&gt;&lt;?php echo $this-&gt;__('Search Site') ?&gt;&lt;/legend&gt;
                &lt;div class="mini-search"&gt;
                    &lt;input id="search" type="text" class="input-text" name="&lt;?php echo $this-&gt;helper('catalogSearch')-&gt;getQueryParamName() ?&gt;" value="&lt;?php echo $this-&gt;helper('catalogSearch')-&gt;getEscapedQueryText() ?&gt;" /&gt;
                    &lt;select name="cat" id="cat" class="input-text"&gt;
                    &lt;option value=""&gt;All Departments&lt;/option&gt;
                    &lt;?= $extra_options ?&gt;
                   &lt;/select&gt;
                    &lt;input type="submit" value="Go" style="border: 1px solid #808080;" alt="&lt;?php echo $this-&gt;__('Search') ?&gt;" /&gt;
                    &lt;div id="search_autocomplete" class="search-autocomplete"&gt;&lt;/div&gt;
                    &lt;script type="text/javascript"&gt;
                    //&lt;![CDATA[
                        var searchForm = new Varien.searchForm('search_mini_form', 'search', '&lt;?php echo $this-&gt;__('search site...') ?&gt;');
                        searchForm.initAutocomplete('&lt;?php echo $this-&gt;helper('catalogSearch')-&gt;getSuggestUrl() ?&gt;', 'search_autocomplete');
                    //]]&gt;
                    &lt;/script&gt;
                &lt;/div&gt;
            &lt;/fieldset&gt;
        &lt;/form&gt;</code></pre>
<p><span>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</span></p>]]></description>
      <pubDate>Fri, 18 Sep 2015 08:15:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[PayPal 2015中国外贸电子商务大会推出升级电商+解决方案]]></title>
      <link>https://www.360magento.com/blog/2015-paypal/</link>
      <description><![CDATA[<p>PayPal今天在深圳举办了其第四届中国<a href="http://www.360magento.com" title="外贸电商建站">外贸电子商务</a>大会，与800多名大型及中小型外贸电商、政府代表以及行业嘉宾一起探讨了全球跨境电商市场的新趋势、新机遇，共同促进中国跨境电商市场的繁荣发展。今年，PayPal 在大会上隆重推出了&ldquo;PayPal电商+&rdquo;创新解决方案，瞄准B2B2C (国内企业卖家￫国外企业买家￫国外消费者) 出口模式的巨大潜力，引领电商升级，共享全球机遇。</p>
<p><strong>挖掘跨境电商市场的新趋势、新机遇</strong></p>
<p>中国<a href="http://www.360magento.com" title="跨境电商网站建设">跨境电商</a>市场增速迅猛，截止2014年其市场规模已突破4万亿元，预计到2017年底规模将实现翻一番。其中，<a href="http://www.360magento.com" title="外贸网站建设">外贸B2B</a>(企业对企业) 模式是首要驱动力，占跨境电商整体市场份额高达80%。B2B2C蕴含大量机会，成为本次大会的焦点。</p>
<p>&ldquo;跨境电商市场充满商机，但纵观整个行业和我们的调查结果，我们发现对于中国商户来说，&gt;外贸B2B2C模式领域拥有独特机遇&mdash;&mdash;即把产品出口给面向终端消费者销售的国外企业买家。作为全球最受信赖的电子钱包，PayPal拥有无可比拟的全球闭环网络，帮助中国商户把握机遇。&rdquo; PayPal中国区跨境业务总经理胡柏迪表示，&ldquo;我们此次推出电商+创新解决方案，再次体现了PayPal对中国商户的承诺，通过持续创新，帮助他们应对商业挑战，在快速发展的电商市场中拓展海外业务。</p>
<p>PayPal调查显示，信任程度、交易便捷性和安全风险是买家和卖家双方进行跨境电商交易过程中的主要痛点，同时也是B2B2C电商市场发展面临的普遍挑战。PayPal根据中国商户的反馈，推出了&ldquo;PayPal电商+&rdquo;解决方案，通过以下一系列产品及服务，帮助中国商户应对挑战：</p>
<p>&bull; 新升级的卖家保障：PayPal卖家保障为合格的商户免费覆盖多种风险损失，包括如果买家因未经授权付款和&ldquo;物品未收到&rdquo;而提出补偿申请和退单。而即将推出的升级版卖家保障政策将涵盖通过PayPal支付平台发起的邮件交易，从而更好的保护中国商户，使之更安心的进行跨境电子交易。</p>
<p>&bull; 人民币提款服务：通过合作伙伴连连支付的支持，PayPal将于近期推出可选择性人民币提款服务。原先，中国商户们须花约7天的时间提取账户中的美金，再通过其他方式换成人民币。有了此项服务，只需约2-3天的时间，商户就能将账户中的余额以人民币的形式提取出来，从而大大减轻商户的现金流压力，提升交易便捷性。此外，中国商户还可将所提款项直接转账至全国184家银行，随时随地，轻松进行跨境电子贸易。</p>
<p>&bull; 风险管控：PayPal拥有全球领先的风险管理系统，帮助卖家从交易开始之初便着手规避恶意欺诈风险。一旦买家提交购买订单，PayPal的欺诈检测模型便即时启动跟踪，对欺诈交易做出风险预警。一旦监测到可疑交易，PayPal将立即开展专业的人工核查，由世界一流的风险管理专家亲自核查，从而判定该笔交易是否存在欺诈嫌疑。</p>
<p>&bull; 国际物流运输：PayPal通过国内外领先物流伙伴合作，为中国商户提供更经济、快捷的物流选择及服务，使其能更便利、安全地将商品运输至海外买家手中；针对B2B2C市场，PayPal正联手TNT，推出针对B2B2C商户的专属速递物流解决方案，在服务、价格等方面均有专属的优惠。同时针对B2C商户，PayPal还拥有联手中国邮政推出的贝邮宝物流解决方案，有效地解决了邮政小包的可视化，并有机地与PayPal的卖家保障政策结合，帮助商户解决了货物的安全性及可追踪等问题。</p>
<p>胡柏迪还表示：&ldquo;PayPal 明白电子支付平台只是跨境电商市场的繁荣发展中的一环。我们一直在倾听中国商户的意见，持续创新，通过开发全方位解决方案为中国商户打造更健康的全球电商生态系统，从而帮助他们拓展业务。&rdquo;</p>
<p>来自深圳市亿通趋势科技有限公司和青岛阳光五月发制品有限公司的两位商户代表在活动现场表示，PayPal外贸电子商务大会是一个很好的平台，能让商户了解跨境电商领域的新趋势和新动向。他们均对PayPal针对跨境电商市场痛点而推出的创新解决方案表示兴奋，并期待通过这些新服务在全球范围内拓展业务。</p>
<p>随着跨境电商的不断发展，外贸网站的地位也是与日俱增。360magento提供专业的基于magento系统的<a href="https://www.360magento.com/" title="magento电商网站开发">电商网站开发</a>服务，如有需求或相关咨询，<a href="https://www.360magento.com/contacts/" title="magento开发">请与我们联系</a>。</p>
<p>&nbsp;</p>]]></description>
      <pubDate>Fri, 18 Sep 2015 07:17:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[跨境电商高峰论坛带来饕餮盛宴]]></title>
      <link>https://www.360magento.com/blog/Cross-border-electricity-supplier-Forum/</link>
      <description><![CDATA[<p>&nbsp; &nbsp; &nbsp; &nbsp; 日前，在&ldquo;<a title="跨境电商平台建设" href="http://www.360magento.com">跨境电商</a>高峰论坛&rdquo;上，六位跨境电商企业的资深人士为现场观众带来一场饕餮盛宴，他们以&ldquo;跨境电商的潜力和未来&rdquo;为主题，深入解读&ldquo;互联网+&rdquo;剖析了目前跨境电商的现状和痛点，从物流、信息流、资金流三方面切入，畅谈跨境电商未来格局和潜力，集中展示外贸综合服务平台、跨境电商等新业态新模式。</p>
<p><span>　 &nbsp; &nbsp;在这次论坛上，浙江点库电子商务有限公司销售总监康山以&ldquo;<a title="跨境电商平台建设" href="http://www.360magento.com">跨境电商B2B2C</a>物流解决方案&rdquo;为主题，介绍了浙江点库一站式跨境电商物流服务体系及其全球分销平台。敦煌网副总裁王添天介以&ldquo;开拓跨境电商的新蓝海&rdquo;为主题，介绍了敦煌网作为全球领先的外贸交易平台的优势及其正在用自身优势开拓跨境电商新蓝海的方向。兰亭集势品牌事业部负责人吕然以&ldquo;传统企业在跨境电商的品牌化之路&rdquo;为主题，介绍了兰亭集势作为目前国内知名的外贸销售网站为中小型企业提供的跨境电商服务。四海商舟创始人周宁</span><span>以&ldquo;跨境电商的机遇和挑战&rdquo;为主题，剖析了传统企业在跨境电商的品牌化之路。Wish招商经理Jerry以&ldquo;移动跨境电商的未来&rdquo;为主题，解读了Wish作为移动跨境电商平台的一匹黑马对移动端未来和发展潜力的看法，Paypal华东地区负责人温从镭以&ldquo;助力中国企业 扬帆商业蓝海&rdquo;为主题，分析了Paypal作为全球知名跨境电商支付公司为跨境电商提供的领先支付服务。</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Fri, 18 Sep 2015 02:40:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento 发送邮件代码(使用数据库中模板)]]></title>
      <link>https://www.360magento.com/blog/magento-send-email/</link>
      <description><![CDATA[<pre><code>      /* @var $translate Mage_Core_Model_Translate */  
        $translate = Mage::getSingleton('core/translate');  
        $translate-&gt;setTranslateInline(false);  
        $storeId  = Mage::app()-&gt;getStore()-&gt;getId();  
        $template ='1';</code></pre>
<p><span style="color: #000000;">&nbsp; &nbsp; &nbsp; &nbsp; 这里，<span>邮件模板的ID<span>是由</span></span>$template的值来定义的，可以到后台-&gt;System-&gt;Transactional Emails获取邮件模板ID,也可以用magento默认的值，如 'contacts_email_email_template'</span><span style="color: #000000;"><br /></span></p>
<pre><code> $recipient = array(  
              'name'  =&gt; 'Alwayly',  
             'email' =&gt; 'sales@360magento.com'  
         );         
         //$recipient 是接收者的名字和邮箱地址

         $sender  = array(  
             'name'  =&gt; 'Alwayly',  
             'email' =&gt; 'sales@360magento.com'  
         );
          //$sender 是发送者的名字和邮箱地址,
         
         magento默认用的这句 $sender=Mage::getStoreConfig('sales_email/order/identity', $storeId) ,使用magento后台配置的发送人
           
         $mailTemplate = Mage::getModel('core/email_template')-&gt;load($template);  

         $mailTemplate-&gt;setDesignConfig(array('area'=&gt;'frontend', 'store'=&gt;$storeId))  
             -&gt;sendTransactional(
                 $template,  
                 $sender,  
                 $recipient['email'],  
                 $recipient['name'],  
                 array( // parameters to email  
                     'param1'=&gt; 'abc',  
                     'param2'=&gt; 'def',  
                     'param3'=&gt; 'ghi'  
</code></pre>
<p>这里是传进邮件模板里面的变量, 在模板里面用<span>{</span>{var param1 }}获取，如果传的是对象可以这样使用<span>{</span>{var object.getId()}} ) );</p>
<p>$translate-&gt;setTranslateInline(true);</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 10:13:26 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento Block应用原理分析以及magento调用其他phtml文件]]></title>
      <link>https://www.360magento.com/blog/magento-transfer-block/</link>
      <description><![CDATA[<p>如果你在本机的虚拟目录下建立了自己的magento项目，这里以项目名为magento为例，那么访问：</p>
<p>http://localhost/magento/index.php/customer/account/create/ 将进入用户注册界面。</p>
<h2>下面就从URL尝试分析Magento调用该页面的过程</h2>
<ol>
<li>1. URL中的customer表明当前访问的模块是customer，自动定位到： app\code\core\Mage\Customer</li>
<li>2. URL中的account表明当前访问的控制器文件为AccountController.php app\code\core\Mage\Customer\controllers\AccountController.php</li>
<li>3.URL中的create表明当前访问的php方法是createAction(),该方法在文件 app\code\core\Mage\Customer\controllers\AccountController.php</li>
<li>4. createAction()装载目录\app\design\frontend\default\default\layout\下名字和模块名相同的 layout文件，名字为customer.xml。然后寻找名字为&lt;customer_account_create&gt;的标签</li>
</ol>
<p><strong>Xml代码</strong></p>
<pre><code>
&lt;customer_account_create translate="label"&gt;
                &lt;label&gt;Customer Account Registration Form&lt;/label&gt;
                &lt;!-- Mage_Customer --&gt;
                &lt;remove name="right"/&gt;
                &lt;remove name="left"/&gt;

                &lt;reference name="root"&gt;
                    &lt;action method="setTemplate"&gt;&lt;template&gt;page/1column.phtml&lt;/template&gt;&lt;/action&gt;
                &lt;/reference&gt;

                &lt;reference name="content"&gt;
                    &lt;block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"&gt;
                        &lt;block type="page/html_wrapper" name="customer.form.register.fields.before" as="form_fields_before" translate="label"&gt;
                            &lt;label&gt;Form Fields Before&lt;/label&gt;
                        &lt;/block&gt;
                    &lt;/block&gt;
                &lt;/reference&gt;
            &lt;/customer_account_create&gt;
</code></pre>
<p>&lt;reference name="root"&gt; 用来说明你要使用的布局文件。</p>
<p>&lt;reference name="content"&gt;下的block就是你定义的block</p>
<p>上面的block是默认定义，可以由customer/form_register推测出来，block类文件位置： app\code\core\Mage\Customer\Block\Form\Register.php</p>
<p>template属性可找出出相应的模板文件为： app\design\frontend\default\default\template\customer\form\register.phtml</p>
<p>通过这样的配置block和template就联系起来了，可以在template文件中使用$this来访问block类的方法。</p>
<h3>下面我们实现一个新的block应用</h3>
<h4>1. 定义一个新的block文件:</h4>
<p>app\code\core\Mage\Customer\Block\Form\Register1.php</p>
<pre><code>                class Mage_Customer_Block_Form_Register1 extends Mage_Directory_Block_Data{  
                public function getHello(){  
                  return "Hello Block";  
               }  
         }
</code></pre>
<h4>2. 定义template文件：</h4>
<p>app\design\frontend\default\default\template\customer\form\register1.phtml</p>
<p>Html代码：</p>
<p>&lt;?php echo $this-&gt;getHello(); ?&gt;</p>
<h4>3. 修改customer.xml配置</h4>
<p>将Xml代码</p>
<p>&lt;block type="customer/form_register" name="customer_form_register" template="customer/form/register.phtml"/&gt;</p>
<p>修改为:</p>
<p>&lt;block type="customer/form_register1" name="customer_form_register1" template="customer/form/register1.phtml"/&gt;</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 10:06:37 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento getResourceModel()函数分析详细讲解]]></title>
      <link>https://www.360magento.com/blog/magento-getResourceModel/</link>
      <description><![CDATA[<p>getResourceModel()方法讲解</p>
<p>$collection = Mage::getResourceModel( 'catalogsearch/fulltext_collection' );</p>
<p>首先会找到app\code\core\Mage\CatalogSearch\etc\config.xml</p>
<p>找到 &lt;resourceModel&gt;</p>
<p>&lt;resourceModel&gt;catalogsearch_resource&lt;/resourceModel&gt; 得出结果：&nbsp;</p>
<p>模型文件地址为：\app\code\core\Mage\CatalogSearch\Model\Resource</p>
<p>加上参数，加载php文件地址为： \app\code\core\Mage\CatalogSearch\Model\Resource\Fulltext\Collection.php</p>
<p>获取目录分类模板 Mage::getStoreConfig('catalog/frontend/grid_per_page_values'); 它找的是app\code\core\Mage\Catalog\etc\config.xml</p>
<ol>
<li>找出&lt;catalog&gt;节点</li>
<li>找出&lt;frontend&gt;节点</li>
<li>找出节点grid_per_page_values里的值</li>
</ol>
<p>$helper = Mage::helper('catalog/category' );</p>
<p>$_categories = $helper-&gt;getStoreCategories();获取顶级分类</p>
<p>$categoryChildrens = $_category-&gt; getChildren();获取子分类</p>
<p>&lt;?php echo $_category-&gt;getUrl(); ?&gt;</p>
<p>文件位置是：app\code\core\Mage\Catalog\Model\Category.php</p>
<p>$tree = Mage::getResourceModel('catalog/category_tree');</p>
<p>Mage_Catalog_Model_Resource_Category_Tree</p>
<p><strong>获取资源模型</strong></p>
<p>加载的文件是app\code\core\Mage\Catalog\Model\Resource\Category\Tree.php</p>
<p>获取分类request_path SELECT `t1c_catalog_category_entity`.* FROM `t1c_catalog_category_entity` WHERE (`t1c_catalog_category_entity`.`entity_id` = '2')</p>
<p>$this-&gt;getResource()</p>
<p>//$this-&gt;getResource() = Mage_Catalog_Model_Resource_Category</p>
<p>Mage_Catalog_Model_Category</p>
<p>getChildrenCategories()找出子类方法</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 09:59:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento URL重写、Block重写、controller重写、model重写]]></title>
      <link>https://www.360magento.com/blog/magento-rewrite/</link>
      <description><![CDATA[<p>当我们给magento开发插件的时候，必然会碰到要改变系统的原来的行为的情况。而magento作为一种插件机制的灵活的系统，直接修改核心代码是极为不妥的方式。而有时magento的事件机制并不能解决问题的时候，重写原来的文件的需求就产生了。在此打算总结下magento中的各种重写。</p>
<h2>magento model的重写</h2>
<p>实现方法：新的model继承你要重写的model，然后配置文件配置model的rewrite。例子如下： class Zone_Test_Model_Quote extends Mage_Sales_Model_Quote { //这里写一些自定义的方法或者覆盖父类的一些方法来实现自己的逻辑 } &lt;!--model rewrite xml配置--&gt; &lt;?xml version="1.0"?&gt; &lt;config&gt; &lt;!-- 这里省略其他配置... --&gt; &lt;global&gt; &lt;models&gt; &lt;sales&gt; &lt;rewrite&gt; &lt;quote&gt;Zone_Test_Model_Quote&lt;/quote&gt; &lt;/rewrite&gt; &lt;/sales&gt; &lt;/models&gt; &lt;/global&gt; &lt;/config&gt;</p>
<p>这样当我们用Mage::getModel(&lsquo;sales/quote&rsquo;)的时候实例化的就不是Mage_Sales_Model_Quote这个类的对象，而是我们重写后的类的对象了。</p>
<h2>magento model重写的原理：</h2>
<p>追踪Mage::getModel()这静态方法会发现如下代码：</p>
<pre><span>//file: app/code/core/Mage/Core/Model/Config.php<br /></span><span>//function: getGroupedClassName<br /></span><span>if </span>(<span>empty</span>(<span>$groupRootNode</span>)) {<br />    <span>$groupRootNode </span>= <span>'global/'</span>.<span>$groupType</span>.<span>'s'</span><span>;</span>&lt;/<span>pre</span>&gt;<br />}<br /><span>$classArr </span>= explode(<span>'/'</span><span>, </span>trim(<span>$classId</span>))<span>;<br /></span><span>$group </span>= <span>$classArr</span>[<span>0</span>]<span>;<br /></span><span>$class </span>= !<span>empty</span>(<span>$classArr</span>[<span>1</span>]) ? <span>$classArr</span>[<span>1</span>] : <span>null</span><span>;<br /></span><span><br /></span><span>if </span>(<span>isset</span>(<span>$this</span>-&gt;<span>_classNameCache</span>[<span>$groupRootNode</span>][<span>$group</span>][<span>$class</span>])) {<br />    <span>return </span><span>$this</span>-&gt;<span>_classNameCache</span>[<span>$groupRootNode</span>][<span>$group</span>][<span>$class</span>]<span>;<br /></span>}<br /><br /><span>$config </span>= <span>$this</span>-&gt;<span>_xml</span>-&gt;<span>global</span>-&gt;{<span>$groupType</span>.<span>'s'</span>}-&gt;{<span>$group</span>}<span>;<br /></span><span><br /></span><span>// First - check maybe the entity class was rewritten<br /></span><span>$className </span>= <span>null</span><span>;<br /></span><span>if </span>(<span>isset</span>(<span>$config</span>-&gt;<span>rewrite</span>-&gt;<span>$class</span>)) {<br />    <span>$className </span>= (string)<span>$config</span>-&gt;<span>rewrite</span>-&gt;<span>$class</span><span>;</span><span>//这里就是重写的关键<br /></span>}</pre>
<p>通过上面的代码，我们不难看出，原理就是获取类名的时候先查找是否有rewrite的节点，有就直接用rewrite的类名去实例化对象。</p>
<h2>magento Block的重写</h2>
<p>关于Block的重写因为block的实例化和model的实例化共用的一段代码，所以方法和配置也差不多，唯一的不同是block重写的配置节点为global/blocks，而model的是global/models。</p>
<h2>magento controller的重写</h2>
<p>实现方法：和model、block的重写方法差不多，新建自己的controller，然后配置下配置下模块的配置文件，让系统实例化 controller的时候能找到对应的类名。我们举个例子，重写checkout模块的cart 这个controller。代码如下：</p>
<pre><code> 
//首先新建自己的controller在自己的模块controllers目录里面
class Zone_Test_CartController extends Mage_Checkout_CartController
{
//这里新加自己的函数或者重写覆盖父类的同名函数
}


&lt;!--然后就是配置文件：--&gt;
&lt;?xml version="1.0"?&gt;</code></pre>
<pre><span>&lt;config&gt;<br /></span><span>&lt;!-- 这里省略其他配置... --&gt;<br /></span><span>&lt;frontend&gt;<br /></span><span>    &lt;routers&gt;<br /></span><span>        &lt;checkout&gt;<br /></span><span>            &lt;args&gt;<br /></span><span>                &lt;modules&gt;<br /></span><span>                    &lt;Zone_Test </span><span>before</span><span>="Mage_Checkout"</span><span>&gt;</span>Zone_Test<span>&lt;/Zone_Test&gt;<br /></span><span>                &lt;/modules&gt;<br /></span><span>            &lt;/args&gt;<br /></span><span>        &lt;/checkout&gt;<br /></span><span>    &lt;/routers&gt;<br /></span><span>&lt;/frontend&gt;<br /></span><span>&lt;/config&gt;</span></pre>
<p>这样配置好后，当我们在浏览器上输入http://youhost/checkout/cart的时候实际上执行的是我们自己的模块里面的Zone_Test_CartController这里类的对象的indexAction方法。</p>
<h2>magento 重写实现原理：</h2>
<p>magento在路由过程中会通过url获取到frontName为&ldquo;checkout&rdquo;和controller为&ldquo;cart&rdquo;,然后通过路由器的 getModuleByFrontName方法获取到一个数组，这数组就是我们配置的modules，而且是排序过的，排序按配置节点的before或者 after来排序的。我们这个例子就array(&lsquo;Zonet_Test&rsquo;, &lsquo;Mage_Checkout&rsquo;)，然后遍历这个数组通过数组里面的值和cart去取到对应的controller类 Zone_Test_CartController，实例化然后执行对应的action方法。相关代码如下：</p>
<pre><span>//file:app/code/core/Mage/Core/Controller/Varien/Router/Standard.php<br /></span><span>//function:match<br /></span><span><br /></span><span>public function </span><span>match</span>(Zend_Controller_Request_Http <span>$request</span>)<br />{<br />    ...<br />    <span>/**<br /></span><span>     * Searching router args by module name from route using it as key<br /></span><span>     */<br /></span><span>$modules </span>= <span>$this</span>-&gt;<span>getModuleByFrontName</span>(<span>$module</span>)<span>;</span><span>//获取真实模块的数组，也就是合并模块路由配置里面的module和modules。<br /></span>...<br />    <span>/**<br /></span><span>     * Going through modules to find appropriate controller<br /></span><span>     */<br /></span><span>$found </span>= <span>false</span><span>;<br /></span><span>foreach </span>(<span>$modules </span><span>as </span><span>$realModule</span>) {<span>//这个循环里按配置的顺序去拼接controller类<br /></span><span>$request</span>-&gt;<span>setRouteName</span>(<span>$this</span>-&gt;<span>getRouteByFrontName</span>(<span>$module</span>))<span>;<br /></span><span><br /></span><span>// get controller name<br /></span><span>if </span>(<span>$request</span>-&gt;<span>getControllerName</span>()) {<br />            <span>$controller </span>= <span>$request</span>-&gt;<span>getControllerName</span>()<span>;<br /></span>} <span>else </span>{<br />            <span>if </span>(!<span>empty</span>(<span>$p</span>[<span>1</span>])) {<br />                <span>$controller </span>= <span>$p</span>[<span>1</span>]<span>;<br /></span>} <span>else </span>{<br />                <span>$controller </span>= <span>$front</span>-&gt;<span>getDefault</span>(<span>'controller'</span>)<span>;<br /></span><span>$request</span>-&gt;<span>setAlias</span>(Mage_Core_Model_Url_Rewrite::<span>REWRITE_REQUEST_PATH_ALIAS</span><span>,</span>ltrim(<span>$request</span>-&gt;<span>getOriginalPathInfo</span>()<span>, </span><span>'/'</span>))<span>;<br /></span>}<br />        }<br /><br /><span>// get action name<br /></span><span>if </span>(<span>empty</span>(<span>$action</span>)) {<br />            <span>if </span>(<span>$request</span>-&gt;<span>getActionName</span>()) {<br />                <span>$action </span>= <span>$request</span>-&gt;<span>getActionName</span>()<span>;<br /></span>} <span>else </span>{<br />                <span>$action </span>= !<span>empty</span>(<span>$p</span>[<span>2</span>]) ? <span>$p</span>[<span>2</span>] : <span>$front</span>-&gt;<span>getDefault</span>(<span>'action'</span>)<span>;<br /></span>}<br />        }<br /><br /><span>//checking if this place should be secure<br /></span><span>$this</span>-&gt;<span>_checkShouldBeSecure</span>(<span>$request</span><span>, </span><span>'/'</span>.<span>$module</span>.<span>'/'</span>.<span>$controller</span>.<span>'/'</span>.<span>$action</span>)<span>;<br /></span><span><br /></span><span>$controllerClassName </span>= <span>$this</span>-&gt;<span>_validateControllerClassName</span>(<span>$realModule</span><span>, </span><span>$controller</span>)<span>;<br /></span><span>if </span>(!<span>$controllerClassName</span>) {<br />            <span>continue</span><span>;<br /></span>}<br /><br /><span>// instantiate controller class<br /></span><span>$controllerInstance </span>= Mage::<span>getControllerInstance</span>(<span>$controllerClassName</span><span>, </span><span>$request</span><span>, </span><span>$front</span>-&gt;<span>getResponse</span>())<span>;<br /></span><span><br /></span><span>if </span>(!<span>$controllerInstance</span>-&gt;<span>hasAction</span>(<span>$action</span>)) {<br />            <span>continue</span><span>;<br /></span>}<br /><br />        <span>$found </span>= <span>true</span><span>;<br /></span><span>break</span><span>;<br /></span>}<br /><br />}</pre>
<h2>magento 抽象类的rewrite</h2>
<p>对于抽象类的重写和model的重写有点不一样，因为抽象类是直接用来继承的，并没用到方法工厂，所以只能用其他方式去重写了。方法就是复制同样的文件结构到local代码池里面，然后对整个类复制过去，新增或者修改其中的方法来实现重写。原理就是magento的自动加载优先加载local的代码。代码如下：</p>
<pre><code>
//file:app/Mage.php
/**
* Set include path
*/
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
$paths[] = BP . DS . 'lib';

$appPath = implode(PS, $paths);
set_include_path($appPath . PS . Mage::registry('original_include_path'));
include_once "Mage/Core/functions.php";
include_once "Varien/Autoload.php";
</code></pre>
<h2>magento url rewrite</h2>
<p>这里不讨论服务器上面实现的urlrewrite。magento的url rewrite有两种方法：1、xml配置。2、系统自带的产品和目录的url rewrite，这里后台也可以自定义url rewrite。关于后台的url rewrite这里不多说，不清楚的自行查看magento的使用手册。这里主要讲下xml配置及其实现原理，还有就是简答讲下系统自带的基于数据库的 rewrite的原理。</p>
<pre><code>
基于xml配置的url rewrite的例子：
&lt;!--模块配置文件：config.xml--&gt;
&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code></pre>
<pre><span>&lt;config&gt;<br /></span><span>&lt;!-- 省略的其他配置...--&gt;<br /></span><span>&lt;global&gt;<br /></span><span>&lt;!-- 省略的其他配置... --&gt;<br /></span><span>&lt;rewrite&gt;<br /></span><span>        &lt;myrewrite&gt;<br /></span><span>            &lt;from&gt;<span>&nbsp;&lt;![CDATA[#/shopby/([\w+\+]+).html#]]&gt;</span>&lt;/from&gt;<br /></span><span>            &lt;to&gt;<span>&lt;![CDATA[/catalogsearch/result/index/q/$1]]&gt;</span>&lt;/to&gt;<br /></span><span>            &lt;complete/&gt;<br /></span><span>        &lt;/myrewrite&gt;<br /></span><span>    &lt;/rewrite&gt;<br /></span><span>&lt;/global&gt;<br /></span><span>&lt;/config&gt;</span></pre>
<p>这个例子就实现了/shopby/querytext.html到/catalogsearch/result/index/q/querytext的rewrite。</p>
<p>我们看看magento是怎么实现这个的。这个rewrite是发生在magento的前端控制器分发请求的时候，顺序在基于数据库的rewrite之后。原理很简单，就是查找各个模块配置文件里面global/rewrite节点取出rewrite配置，遍历这些配置通过正则替换把符合条件的from 替换成to，然后改变request对象的pathinfo。具体实现代码如下：</p>
<pre><code> 
public function rewrite()
{
$request = $this-&gt;getRequest();
$config = Mage::getConfig()-&gt;getNode('global/rewrite');
if (!$config) {
return;
}

foreach ($config-&gt;children() as $rewrite) {
$from = (string)$rewrite-&gt;from;
$to = (string)$rewrite-&gt;to;
if (empty($from) || empty($to)) {
continue;
}

//这里实现了路由名到前端路由器的替换，把{routeName}替换成对应的frontName，不过一般来说很多模块的routeName和frontName配置成一样了，这个特性使用的不多。
$from = $this-&gt;_processRewriteUrl($from);
$to = $this-&gt;_processRewriteUrl($to);

//这里是替换的核心所在，通过这句代码也很清楚的知道from 和to该填什么内容。

$pathInfo = preg_replace($from, $to, $request-&gt;getPathInfo());

if (isset($rewrite-&gt;complete)) {
$request-&gt;setPathInfo($pathInfo);
} else {
$request-&gt;rewritePathInfo($pathInfo);
}
}
}
</code></pre>
<p>关于系统自带的关于产品和目录的url rewrite，前端控制器里面只调用了一句代码： Mage::getModel(&lsquo;core/url_rewrite&rsquo;)-&gt;rewrite()，这是调用了核心模块的url rewrite model来处理的。这里面通过数据根据请求路径查找到目标路径，然后看数据库里面是配置的301还是302做相应的类型的跳转，这是通过php的 header函数实现的。剩下的类型就直接改变request 对象的pathinfo。这块magento有一个做的很好的地方，就是对于同一个产品或者目录url rewrite修改过后，原来的记录并不会删除，而是和新的rewrite相关联，这样老的url进来也能跳转的新的url上去，有利于seo。这块具体代码就不分析了，有空专门写个文章。有兴趣的自行翻看代码。</p>
<h2>magento config path rewrite</h2>
<p>magento的后台system配置，读取的时候一般按system.xml的节点路径来的。但是有的时候当我们不想使用这个路径的时候，配置时可以指定config_path的路径。这个常用于支付插件。因为获取支付类型的时候是通过固定的一个path取的，而我们模块自己的系统配置会用自己的路径，这时候config path就派上用场了。看下面的例子：</p>
<pre><span>&nbsp;&lt;!--//file:system.xml 这是moneybookers模块的system.xml文件的一个片段--&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;active translate="label"&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;label&gt;Enabled&lt;/label&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;frontend_type&gt;select&lt;/frontend_type&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;config_path&gt;payment/moneybookers_gir/active&lt;/config_path&gt;//这里重写了config path</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;source_model&gt;adminhtml/system_config_source_yesno&lt;/source_model&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;sort_order&gt;1&lt;/sort_order&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;show_in_default&gt;1&lt;/show_in_default&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;show_in_website&gt;1&lt;/show_in_website&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &lt;show_in_store&gt;1&lt;/show_in_store&gt;</span><br /><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;/active&gt;</span></pre>
<p>实现原理就更简单了，保存store config的时候，检查下有没有confg_path有就按这个path来保存到数据库。代码如下：</p>
<pre><code>
//file: app/code/core/Mage/Adminhtml/Model/Config/Data.php
//functon: save

/**
* Look for custom defined field path
*/
if (is_object($fieldConfig)) {
$configPath = (string)$fieldConfig-&gt;config_path;
if (!empty($configPath) &amp;&amp; strrpos($configPath, '/') &gt; 0) {//这里开始对自定义的path进行处理
// Extend old data with specified section group
$groupPath = substr($configPath, 0, strrpos($configPath, '/'));
if (!isset($oldConfigAdditionalGroups[$groupPath])) {
$oldConfig = $this-&gt;extendConfig($groupPath, true, $oldConfig);
$oldConfigAdditionalGroups[$groupPath] = true;
}
$path = $configPath;
}
}

$inherit = !empty($fieldData['inherit']);

$dataObject-&gt;setPath($path)
-&gt;setValue($fieldData['value']);
</code></pre>
<h2>magento template rewrite</h2>
<p>当我们写插件的时候想改变原有系统的某个template的时候比如产品详细页面的模板，因为是插件我们没办法控制它的theme只能通过xml配置来重写template了，原理也很容易，就是利用block的配置的action 节点，通过action节点来设置template。例子如下：</p>
<pre><code>
&lt;!-- file: mylayout.xml ---&gt;</code></pre>
<pre><span>&lt;layout </span><span>version</span><span>="0.1.0"</span><span>&gt;<br /></span><span>&lt;catalog_product_view&gt;<br /></span><span>    &lt;reference </span><span>name</span><span>="product.info"</span><span>&gt;<br /></span><span>        &lt;action </span><span>method</span><span>="setTemplate"</span><span>&gt;&lt;template&gt;</span>test/product/myselfview.phtml<span>&lt;/template&gt;<br /></span><span>        &lt;/action&gt;<br /></span><span>    &lt;/reference&gt;<br /></span><span>&lt;/catalog_product_view&gt;<br /></span><span>&lt;/layout&gt;</span></pre>
<p>这样通过插件的layout配置就可以改变产品详细页面的template为自己插件的模板。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 09:51:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento newsletter发送不成功讲解及代码分析]]></title>
      <link>https://www.360magento.com/blog/magento-fail-to-send-newsletter/</link>
      <description><![CDATA[<p>今天有个同事问我，昨天在后台建了一个newsletter的队列为什么到今天队列状态还是为未发送。询问了下cronjob的运行情况，发现 magento的cronjob是正常运行的，而邮件配置也是对的，其他邮件都能正常发送。百思不得其解，于是只好拿出杀手锏，翻源码追踪整个发送过程。一追踪下来马上发现了这根本就不是个问题，问题在我们对newsletter的发送不熟悉，对什么时候修改这个状态理解错误。下面让我们系统的学习下 magento的newsletter。</p>
<h2>newsletter的订阅</h2>
<p>magento的前台页面一般都会有一个小的表单用来输入邮箱号码，客户提交就可以订阅相关产品信息了。网站后台建立邮件队列，就可以批量的对订阅者发送邮件来进行营销。后台还可以开启邮件确认的功能，开启邮件确认功能后，用户提交订阅newsletter的表单时先把订阅状态设置为2，即未确认状态，然后生成一个随机字符串保存并发送确认邮件，邮件里面的链接带有生成的随机字符串。用户点链接确认的时候就把请求传入的字符串和保存在数据库的字符串对比，如果一致就把状态改成1，即订阅状态。newsletter订阅相关数据保存到newsletter_subscriber这个表。</p>
<h2>newsletter邮件模板的创建</h2>
<p>后台newsletter =&gt; newsletter templates =&gt;add new template就可以创建newsletter的邮件模板了，和其他邮件模板差不多的写法，区别是这只有一个变量就是subscriber对象，而且不能像订单之类的邮件模板一样可以选文件模板来修改，不过还好有些默认的代码。照着改改就好了。这个邮件模板的数据保存到数据库表 newsletter_template中。</p>
<h2>newsletter队列的创建</h2>
<p>当你创建好newsletter模板的时候会回到newsletter模板列表页面，每行模板右侧都有一个action列，下拉选择Queue Newsletter就会跳到创建页面。这个页面和newsletter模板的表单差不多，就多了一个队列开始执行的时间以及选择对应店铺的地方。填好点保存就创建了一个newsletter队列。那么创建一个队列的时候都干了些什么呢？首先，肯定是把我们填写的信息都保存到数据库中，这里是保存到 newsletter_queue这个表中。然后，它还做了一个事情就是保存队列和店铺的关系，队列和店铺关联的信息保存在表 newsletter_queue_store_link。我们看看保存queue店铺关系相关的代码。</p>
<p>app/code/core/Mage/Adminhtml/controllers/Newsletter/QueueController.php文件saveAction 方法中</p>
<pre><code>       
        $queue-&gt;setStores($this-&gt;getRequest()-&gt;getParam('stores', array()))//这里保存了店铺信息
        -&gt;setNewsletterSubject($this-&gt;getRequest()-&gt;getParam('subject'))
        -&gt;setNewsletterSenderName($this-&gt;getRequest()-&gt;getParam('sender_name'))
        -&gt;setNewsletterSenderEmail($this-&gt;getRequest()-&gt;getParam('sender_email'))
        -&gt;setNewsletterText($this-&gt;getRequest()-&gt;getParam('text'))
        -&gt;setNewsletterStyles($this-&gt;getRequest()-&gt;getParam('styles'));
         
        //app/code/core/Mage/Newsletter/Model/Queue.php
         
        public function setStores(array $storesIds)
         {
         $this-&gt;setSaveStoresFlag(true);//设置保存的标志
         $this-&gt;_stores = $storesIds;
         return $this;
         }
         
        //app/code/core/Mage/Newsletter/Model/Resource/Queue.php
         
        //queue model保存的之后会执行该方法
        protected function _afterSave(Mage_Core_Model_Abstract $queue)
         {
         if ($queue-&gt;getSaveStoresFlag()) {
         $this-&gt;setStores($queue);
         }
         return $this;
         }
         
        public function setStores(Mage_Newsletter_Model_Queue $queue)
         {
        //先把对应的queue store关系在表里删除掉
         $adapter = $this-&gt;_getWriteAdapter();
         $adapter-&gt;delete(
         $this-&gt;getTable('newsletter/queue_store_link'),
         array('queue_id = ?' =&gt; $queue-&gt;getId())
         );
         
        $stores = $queue-&gt;getStores();
         if (!is_array($stores)) {
         $stores = array();
         }
         
        foreach ($stores as $storeId) {
         $data = array();
         $data['store_id'] = $storeId;
         $data['queue_id'] = $queue-&gt;getId();
         
        //插入queue和store关系到表newsletter_queue_store_link中
        $adapter-&gt;insert($this-&gt;getTable('newsletter/queue_store_link'), $data);
         }
         $this-&gt;removeSubscribersFromQueue($queue);
         
        if (count($stores) == 0) {
         return $this;
         }
         
        //取所有订阅者的信息
        $subscribers = Mage::getResourceSingleton('newsletter/subscriber_collection')
         -&gt;addFieldToFilter('store_id', array('in'=&gt;$stores))
         -&gt;useOnlySubscribed()
         -&gt;load();
         
        $subscriberIds = array();
         
        foreach ($subscribers as $subscriber) {
         $subscriberIds[] = $subscriber-&gt;getId();
         }
         
        if (count($subscriberIds) &gt; 0) {
        //把队列和订阅者的关系插入到newsletter_queue_link表中
        $this-&gt;addSubscribersToQueue($queue, $subscriberIds);
         }
        return $this;
         }
</code></pre>
<h2>newsletter邮件的发送</h2>
<p>队列创建后并不会马上就会发送邮件。newsletter的邮件发送是通过magento的cronjob机制来执行的。模块配置里面配置好执行周期以及对应的执行方法，并服务器里面定时执行网站跟目录的cron.php或者cron.sh邮件才会发送。配置如下：</p>
<pre><code>
      &lt;!--  newsletter 模块配置文件config.xml --&gt;</code></pre>
<pre><span>&lt;crontab&gt;<br /></span><span>&lt;jobs&gt;<br /></span><span>    &lt;newsletter_send_all&gt;<br /></span><span>        &lt;schedule&gt;<br /></span><span>            &lt;cron_expr&gt;</span>*/5 * * * *<span>&lt;/cron_expr&gt;<br /></span><span>        &lt;/schedule&gt;<br /></span><span>        &lt;run&gt;<br /></span><span>            &lt;model&gt;</span>newsletter/observer::scheduledSend<span>&lt;/model&gt;<br /></span><span>        &lt;/run&gt;<br /></span><span>    &lt;/newsletter_send_all&gt;<br /></span><span>&lt;/jobs&gt;<br /></span><span>&lt;/crontab&gt;</span></pre>
<p>*/5 * * * *这个和linux下的crontab一样，表示每5分钟执行一次。这里是执行Mage::getModel(&lsquo;newsletter/observer&rsquo;)-&gt;scheduledSend();我们看看这个方法：</p>
<pre><code>        
//app/code/core/Mage/Newsletter/Model/Observer.php
        public function scheduledSend($schedule)
         {
         $countOfQueue = 3;//一次只处理三个队列
         $countOfSubscritions = 20;//一个队列只发其中的20封邮件
         
        $collection = Mage::getModel('newsletter/queue')-&gt;getCollection()
         -&gt;setPageSize($countOfQueue)
         -&gt;setCurPage(1)
         -&gt;addOnlyForSendingFilter()//只对队列里面没发过邮件的订阅者发邮件，判断是否发过是通过表newsletter_queue_link表中letter_sent_at这个字段是否为空来判断的
         -&gt;load();
         
        //对每一个队列model执行sendPerSubcritber方法
        $collection-&gt;walk('sendPerSubscriber', array($countOfSubscritions));
         }
</code></pre>
<p>发邮件的代码和magento其他模块发邮件没啥区别，就是取出我们设置好的邮件模板替换变量然后调用邮件发送类发送。</p>
<p>但是这里有个需要注意的地方，那就是 一次只是发20封邮件，当队列对应的订阅者都发完了之后才会修改队列状态为已发送。</p>
<pre><code>
        //app/code/core/Mage/Newsletter/Model/Queue.php
         
        public function sendPerSubscriber($count=20, array $additionalVariables=array())
         {
         
        // .....
         
        if ($this-&gt;getSubscribersCollection()-&gt;getSize() == 0) {
         $this-&gt;_finishQueue();
         return $this;
         }
         
        //.....
         
        //发送完毕，修改成已经发送状态
        if(count($collection-&gt;getItems()) &lt; $count-1 || count($collection-&gt;getItems()) == 0) {
         $this-&gt;_finishQueue();
         }      
        }
         
        protected function _finishQueue()
         {
         $this-&gt;setQueueFinishAt(Mage::getSingleton('core/date')-&gt;gmtDate());
         $this-&gt;setQueueStatus(self::STATUS_SENT);
         $this-&gt;save();      
        return $this;
         }
</code></pre>
<p>现在回到今天同事问的那个问题。队列是昨天创建的，而我们的订阅数有很多，假设就一万个吧，newsletter每五分钟才发20封邮件，要发完一万封就需要 2500分钟，差不多42个小时。邮件还没发完嘛，状态当然不会变成已经发送了。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 09:47:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento 事务处理使用方法]]></title>
      <link>https://www.360magento.com/blog/magento-transaction-processing/</link>
      <description><![CDATA[<p>Mangeto中执行某个功能时，如update、insert、delete，magento的model会自动对事务进行处理。这些写操作都集中到 model的save方法或者delete方法来处理，执行时候会调用resource model的beginTransaction方法来开启事务，调用resource model的commit方法来提交事务，调用resource model的rollBack方法来回滚事务。save方法代码如下：</p>
<pre><code>
        public function save()
         {
         /**
         * Direct deleted items to delete method
         */
         if ($this-&gt;isDeleted()) {
         return $this-&gt;delete();
         }
         if (!$this-&gt;_hasModelChanged()) {
         return $this;
         }
         $this-&gt;_getResource()-&gt;beginTransaction();//开启事务
         $dataCommited = false;
         try {
         $this-&gt;_beforeSave();
         if ($this-&gt;_dataSaveAllowed) {
         $this-&gt;_getResource()-&gt;save($this);
         $this-&gt;_afterSave();
         }
         $this-&gt;_getResource()-&gt;addCommitCallback(array($this, 'afterCommitCallback'))
         -&gt;commit();//添加提交后的回调函数
         $this-&gt;_hasDataChanges = false;
         $dataCommited = true;
         } catch (Exception $e) {
         $this-&gt;_getResource()-&gt;rollBack();//异常时事务回滚
         $this-&gt;_hasDataChanges = true;
         throw $e;
         }
         if ($dataCommited) {
         $this-&gt;_afterSaveCommit();
         }
         return $this;
         }
</code></pre>
<p>delete方法和save类似，这里就不贴代码出来分析了。</p>
<h2>多个model的事务处理</h2>
<p>单个model的事务处理很简单，magento的model层直接就处理了，不需要额外的代码。那么当我们的业务同时涉及到多个model，并且必须是当成一个事务来处理的时候，该怎么处理呢？不用担心，像magento这么优秀的系统不可能不会考虑到这些情况的。于是类 Mage_Core_Model_Resource_Transaction派上用场了。一个典型的多model事务处理如下：</p>
<pre><code>        
$transaction = Mage::getModel('core/resource_transaction');
        $transaction-&gt;addObject($model1);
        $transaction-&gt;addObject($model2);
        $transaction-&gt;addObject($model3);
        //...
         
        try {
         $transaction-&gt;save();
        //或者进行删除操作$transaction-&gt;delete();
         } catch (Exception $e) {
        //异常处理
        }
</code></pre>
<p>那么当我们通过addObject把相关的model都添加到事务处理器 Mage_Core_Model_Resource_Transaction里面并执行save或者delete的时候，做了什么呢？我们以save为例子进行深入。</p>
<pre><code>        
public function save()
         {
         $this-&gt;_startTransaction();//开启事务
         $error = false;
         
        try {
         foreach ($this-&gt;_objects as $object) {
         $object-&gt;save();//遍历添加进来的oject并执行其save方法
         }
         } catch (Exception $e) {
         $error = $e;
         }
         
        if ($error === false) {
         try {
         $this-&gt;_runCallbacks();//执行回调函数
         } catch (Exception $e) {
         $error = $e;
         }
         }
         
        if ($error) {
         $this-&gt;_rollbackTransaction();//异常，回滚事务
         throw $error;
         } else {
         $this-&gt;_commitTransaction();
         }       
        return $this;
         }
         
        protected function _startTransaction()
         {
        //遍历相关对象执行对象的resource model的beginTransaction方法开启事务
         foreach ($this-&gt;_objects as $object) {
         $object-&gt;getResource()-&gt;beginTransaction();
         }
         return $this;
         }
         
        protected function _commitTransaction()       
        {
        //遍历相关对象执行对象的resource model的commit方法提交事务
         foreach ($this-&gt;_objects as $object) {
         $object-&gt;getResource()-&gt;commit();
         }
         return $this;
         }
         
        protected function _rollbackTransaction()
         {
        //遍历相关对象执行对象的resource model的rollBack方法提交事务
         foreach ($this-&gt;_objects as $object) {
         $object-&gt;getResource()-&gt;rollBack();
         }
         return $this;
         }
</code></pre>
<p>代码很容易理解和单个model的save方法流程是一致的，只是开启事务、提交事务或者回滚事务的时候是遍历执行各个model的相关方法。</p>
<p>那么这个时候我们就会有这样的疑惑：开启事务的方法执行了好几遍，这样会不会出问题呢？如果是真的多次执行数据库对事务相关的sql的话，那么肯定是会有问题的。 magento很好的处理了这个问题。就是resouce model层对事务有了一个层级的概念。多次提交事务，只有第一次才是真的提交事务，后面的多次只是事务的level计数器加一，同样的对于commit 和rollback只有计数器为0的时候才真正执行相关的操作，其他时候都是计数器减一，这样就避免了我们前面提出的那个问题的出现了。看相关代码：</p>
<pre><code>
        //file:lib/Varien/Db/Adapter/Pdo/Mysql.php
        public function beginTransaction()
         {
         if ($this-&gt;_transactionLevel === 0) {
         $this-&gt;_debugTimer();
         parent::beginTransaction();
         $this-&gt;_debugStat(self::DEBUG_TRANSACTION, 'BEGIN');
         }
         ++$this-&gt;_transactionLevel;
         return $this;
         }
         
        public function commit()
         {
         if ($this-&gt;_transactionLevel === 1) {
         $this-&gt;_debugTimer();
         parent::commit();
         $this-&gt;_debugStat(self::DEBUG_TRANSACTION, 'COMMIT');
         }
         --$this-&gt;_transactionLevel;
         return $this;
        }
         
        public function rollback()
         {
         if ($this-&gt;_transactionLevel === 1) {
         $this-&gt;_debugTimer();
         parent::rollback();
         $this-&gt;_debugStat(self::DEBUG_TRANSACTION, 'ROLLBACK');
         }
         --$this-&gt;_transactionLevel;
         return $this;
         }
</code></pre>
<p>最后提醒一点，对于mysql来说，只有innodb存储引擎才有事务功能。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 09:43:49 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[16条必须的magento SEO优化设置]]></title>
      <link>https://www.360magento.com/blog/16-magento-seo-configuration/</link>
      <description><![CDATA[<h2>16条必须的magento SEO优化设置</h2>
<ol>
<li>可以用文章，blog页面做长尾关键词</li>
<li>在每个页面做一个文章框，随即显示文章，这样可以更新此页面。</li>
<li>search页面在robots.txt设置不让抓取</li>
<li>URL重写开启，使用绝对地址（这个应该没有问题），URL标准化，避免多个URL指向一个页面，造成权重的分散</li>
<li>404页面的制作</li>
<li>放置统计代码，用google的统计</li>
<li>robots.txt设置成不可写吧。</li>
<li>local.xml设置成通过url不可访问</li>
<li>分类页面的产品名称，<a title="magento" href="http://www.360magento.com">magento</a>默认模板用的是H2，要改掉</li>
<li>避免一个页面出现多个h1情况。如果没有h1标签可以写一个，然后隐藏掉！</li>
<li>每一个图片的alt要写上。</li>
<li><a>标签的title也写上，尽量</a></li>
<li>在后台为首页，产品分类页面，写入&lt;h1&gt;标签的内容，作为内容标题！</li>
<li>css，js代码尽量写在对用的文件里面，html页面尽量代码简洁，去掉之间大量空格，和繁琐的注释</li>
<li>对于不希望google抓取的内容，和外部信息设置成nofollow，从而避免权重的流失。</li>
<li>开启缓存，编译，js，css合并，提速。</li>
</ol>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 08:18:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[谈magento对谷歌搜索引擎的友好]]></title>
      <link>https://www.360magento.com/blog/magento-google-seo/</link>
      <description><![CDATA[<p>if there is a word can describe the relation of magento &amp; Google Search Engine , it must be friend!</p>
<p>如果能有词形容magento和谷歌搜索引擎的关系，那么肯定是&ldquo;朋友&rdquo;！</p>
<p><a title="magento" href="http://www.360magento.com">magento</a>是目前国外使用最多的开源网店系统，而且它的使用领域已经逾越了商城，等效于博客或者CMS了。而作用一个英文站点开发人员，我们认为之所以那么多站长朋友使用magento进行网站建设，其最大的原因或者正是magento对谷歌搜索引擎高度友好。</p>
<p><strong>为什么说magento对Google友好呢？</strong></p>
<h2>magento几乎拥有自定义性</h2>
<p>无论是哪个类模型，你都可以在magento后台命名它的title，keywords以及description甚至是url以及meta。这个功能让网站在后期的推广能够获得不错的表现，而且这也是大多seo选择网站开发系统的标准之一。</p>
<h2>magento卓越的性能表现</h2>
<p>magento能够快速处理任何自身的进程，高效地反馈网站给访客。而且经过官方作过压力测试，完全能够胜任大数据处理，并不会产生冗余的垃圾文件，所以Google机器人非常愿意爬去这些页面。</p>
<p>选择网站开发的系统，我们的最重的应该就是以上两点，而magento都拥有了。用SEO经典的一句话说就是&ldquo;爬虫其实就是普通用户&rdquo;，所以受大众欢迎的，同样也会受搜索引擎欢迎。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 08:06:50 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[了解跨境电商的市场，让您更好的找到定位]]></title>
      <link>https://www.360magento.com/blog/Cross-border-e-commerce/</link>
      <description><![CDATA[<p>电子商务行业中，有不少的人在讲，现在<a title="电子商务" href="http://www.360magento.com">电商</a>越来越难做了。没错，大平台的电商已经很成熟，现在走出这一困局才是明智之举，而近两年来最为火爆的是：跨境电商，农村电商，社交电商。 这些电商新形态已在不断爆发中，今天为您分享一下<a title="跨境电商" href="http://www.360magento.com">跨境电商</a>中，值得开拓也是必须了解的跨境电商市场，这些是跨境电商中的进口大国：</p>
<p>跨境电商人必须了解的五个国家</p>
<ol>
<li>韩国
<p>韩国的网络速度全球最快，也难怪它是全球第七大、亚太地区第三大电商零售市场。预计韩国2015年总零售额达367.6亿美元，其中网络零售额占9.8%。</p>
</li>
<li>澳大利亚
<p>澳大利亚2014年电商销售额增长了17.3%，这也表明澳大利亚人是网购的忠实粉丝。数据显示，大约79.4%的互联网用户通过电子渠道购物。尽管人口数量较少，但是澳大利亚仍然充满了机遇。</p>
</li>
<li>法国
<p>法国2014年电商销售额增长了11%，电商企业应该考虑法国这个市场。作为世界上第六大、欧洲第三大的电商市场，法国有很大的发展机会。预计法国2015年的电商市场规模将增长10%，达624亿欧元。</p>
</li>
<li>英国
<p>在欧洲地区，英国人最常上网购物，这也让英国成为继美国、中国之后的第三大电商市场。英国消费者平均每年的网购开支为1174英镑，网络零售额也将持续增长，英国为电商企业提供了很多发展空间。</p>
</li>
<li>俄罗斯
<p>俄罗斯位于欧亚大陆北部，地跨欧亚两大洲，国土面积为1707.54万平方公里，是世界上面积最大的国家。人口数量1.43亿(2014年)，电子商务发展迅速，但由于本土电商平台不够影响力，并且俄罗斯人更喜欢在阿里平台上购买，所以在俄罗斯的购物平台排名中，速卖通排在第一位，而且有不少俄罗斯人还会在淘宝上购物！</p>
</li>
</ol>
<p>看了以上的国家的相关数据和基本的电商情况后，<a title="跨境电商" href="http://www.360magento.com">跨境电商</a>的小伙伴，你们有什么想法的呢？！</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Thu, 17 Sep 2015 07:44:47 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento性能优化]]></title>
      <link>https://www.360magento.com/blog/magento-optimization/</link>
      <description><![CDATA[<p><a title="magento" href="http://www.360magento.com">magento</a>模版功能强大，已被大众所熟知，但也有不少朋友反映，magento网站的速度偏慢。在参考了一些资料后，对magento性能提升做一下小结。希望对各位读者有所帮助。</p>
<ol>
<li>压缩js,css代码，如果有必要把所有的css,js分别综合到一个文件中，并压缩，缓存</li>
<li>清除magento模板中不必要的注释，为所使用到的图片瘦身</li>
<li>优化magento代码，这个步骤工作量大，但可能是效果显著的步骤，不过前提是你非常熟悉magento，彻底删除不用的模块，关闭没用的block， 清除无效，无用的xml（解析xml非常昂贵的），在一个页面中尽量不要大量调用magento的image resize功能，非常消耗内存，除非你自己优化代码。</li>
<li>mysql配置优化，充分发挥你的硬件资源，下面的数值要根据你的配置调整 key_buffer_size = 512M max_allowed_packet = 64M table_cache = 512 sort_buffer_size = 4M net_buffer_length = 8K read_buffer_size = 4M read_rnd_buffer_size = 2M myisam_sort_buffer_size = 64M tmp_table_size = 128M query_cache_size = 96M query_cache_type = 1 thread_cache_size = 8 max_connections = 400 wait_timeout = 300</li>
<li>将magento的var目录挂载到内存中，加快读取速度，如mount -t tmpfs -o size=100M,mode=0777 tmpfs var</li>
<li>安装php加速器，如APC，XCACHE,eAccelerator，安装方法参考相关的网站。然而归于根本，最大的优化来自于对模板，对代码，对block的优化。</li>
</ol>
<p>在Magento的优化中， Mysql的优化是很重要的，在Magento的官方网给出了有关Mysql的优化， 官方网并没有要我们把Mysql的存储引擎改为innodb， 但我觉的得这是很有必要的，当改成innodb后，还得把Mysql的配置文件修改修改下， 有时根据官方的文档来并不能成功， 这时就要看你的环境而定了， 下面给出我所配置的mysql文件给大家参考：</p>
<ul>[mysqld]
<li>datadir=/var/lib/mysql</li>
<li>socket=/var/lib/mysql/mysql.sock</li>
<li>user=mysql</li>
<li># Default to using old password format for compatibility with mysql 3.x</li>
<li># clients (those using the mysqlclient10 compatibility package).</li>
<li>old_passwords=1</li>
<li>default-character-set=utf8</li>
<li>#init_connect='SET NAMES utf8'</li>
<li>default-storage_engine = innodb</li>
<li># To allow mysqld to connect to a MySQL Cluster management daemon, uncomment</li>
<li># these lines and adjust the connectstring as needed.</li>
<li>#ndbcluster</li>
<li>#ndb-connectstring="nodeid=4;host=localhost:1186"</li>
</ul>
<p>[client]</p>
<ul>
<li>#default-character-set=utf8</li>
</ul>
<p>[mysqld_safe]</p>
<ul>
<li>log-error=/var/log/mysqld.log</li>
</ul>
<p>[Magento]</p>
<ul>
<li>max_connections = 1000</li>
<li>max_connect_error = 10</li>
<li>table_cache = 1024</li>
<li>max_allowed_packet = 16M</li>
<li>max_heap_table_size = 64M</li>
<li>sort_buffer_size = 8M</li>
<li>join_buffer_size = 8M</li>
<li>thread_cache_size = 8</li>
<li>thread_concurrency = 8</li>
<li>query_cache_size = 64M</li>
<li>query_cache_limit = 2M</li>
<li>tmp_tables_size = 64M</li>
<li>key_buffer_size = 32M</li>
<li>read_buffer_size = 2M</li>
<li>read_rnd_buffer_size = 16M</li>
<li>bulk_insert_buffer_size = 64M</li>
<li>myisam_sort_buffer_size = 128M</li>
<li>myisam_max_sort_file_size = 10G</li>
<li>myisam_max_extra_sort_file_size=10G</li>
<li>myisam_repair_threads = 1</li>
<li>myisam_recover</li>
<li>innodb_additional_mem_pool_size = 16M</li>
<li>innodb_log_buffer_size = 8M</li>
<li>innodb_log_file_size = 512M</li>
<li>innodb_log_files_in_group = 2</li>
<li>innodb_buffer_pool_size = 3G</li>
<li>innodb_data_file_path = ibdata1:3G;ibdata2:1G:autoextend</li>
<li>innodb_autoextend_increment=512</li>
</ul>
<p>这里主要讲的是自己编译的Apache， 而如果是系统自带的话， Apache所需的模块， 系统会自动加载。</p>
<ul>
<li>#vi httpd.conf</li>
<li>ServerTokens OS</li>
<li>ServerRoot "/etc/httpd"</li>
<li>PidFile run /httpd.pid</li>
<li>Timeout 120</li>
<li>KeepAlive off</li>
<li>MaxkeepAliveRequests 100</li>
<li>KeepAliveTimeout 15</li>
<li>StartServers 100</li>
<li>MinSpareServers 100</li>
<li>MaxSpareServers 150</li>
<li>ServerLimit 256</li>
<li>MaxClient 256</li>
<li>MaxRequestsPerChild 40000</li>
<li>Listen *:80</li>
</ul>
<p>在这里还要一些必须的Apache模块</p>
<ol><ol>
<li>mod_authz_host.so</li>
<li>mod_expires.so</li>
<li>mod_deflate.so</li>
<li>mod_mime.so</li>
<li>mod_dir.so</li>
<li>mod_rewrite.so 这个模块很重要， 当设置Magento地址重写时，要用到</li>
<li>mod_log_config.so</li>
<li>libphp5.so 你有可能用的是php4， 那就得改成libphp4.so</li>
</ol></ol>
<p><strong>注意：</strong></p>
<p>在安装好Apache后， 我们还能让Apache识别以php为后缀的文件</p>
<p>AddType application/x-httpd-php .php .phtml</p>
<p>好了， 到这就讲完了， 这章其实对Magento的优化不大， 但有些模块又不能少， 少了， Magento后台可能出问题</p>
<p>当我们安装好<a href="http://www360magento.com" target="_blank">Magento</a>时， 为了加快Magento的速度，我们一般还要做一些对于Magento服务的优化， 来提高Magento被访问的速度。 一般我们会从三个角度去考虑Magento的优化， 如： 安装Magento的系统； Magento模板中的代码； Magento所用到的数据库。 在这我们主要讲的是Magento系统的优化</p>
<p>Magento是在PHP环境下开发的， 所以优化PHP对Magento有着不小的影响，下面是Magento标准的PHP配置。</p>
<h3>对于Magento所需的扩展， 只开启所需的就可以了</h3>
<p># Required extensions</p>
<ul>
<li>extension=bcmath.so</li>
<li>extension=curl.so</li>
<li>extension=dom.so</li>
<li>extension=gd.so</li>
<li>extension=mcrypt.so</li>
<li>extension=memcache.so</li>
<li>extension=mhash.so</li>
<li>extension=pdo.so</li>
<li>extension=pdo_mysql.so</li>
<li>extension=mysql.so</li>
<li>extension=xmlwriter.so</li>
</ul>
<p>下面的一些扩展并不需要开启， 我们可以把它们关闭</p>
<p># Not&nbsp; needed extensions from default setup</p>
<ul>
<li>;;extension=dbase.so</li>
<li>;;extension=json.so</li>
&gt;
<li>;;extension=mysqli.so</li>
<li>;;extension=pdo_sqlite.so</li>
<li>;;extension=sqlite.so</li>
<li>;;extension=wddx.so</li>
<li>;;extension=smlreader.so</li>
<li>;;extension=xsl.so</li>
<li>;;extesnion=zip.so</li>
</ul>
<p>事无绝对， 当你的系统环境需要某个扩展时， 可以按照需要开启</p>
<h3>下面所要讲的， 也是PHP中优化的重点， 将会讲到二种方法，二选一就行了， 切忌， 不能同时应用二种方案</h3>
<h4>一，安装APC扩展， APC， 用来优化PHP本身， 提高PHP的运行速度</h4>
<p># APC configuration apecifics if it is used</p>
<p>extension=apc.so</p>
<p>apc.shm_size=256</p>
<p>apc.num_files_hint=10000</p>
<p>apc.user_entries_hint=10000</p>
<p>apc.max_file_size=5M</p>
<h4>二，安装eaccelerator加速器，功能跟APC类似， 在这就不多说了。</h4>
<p>安装好eaccelerator后，将会产生eaccelerator模块</p>
<p>zend_extension="/usr/lib64/php/modules/eaccelerator.so"</p>
<p>eaccelerator.shm_size = "256"</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 08:45:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento建站知识]]></title>
      <link>https://www.360magento.com/blog/magento/</link>
      <description><![CDATA[<p>外贸B2C商城网店--<a title="magento建站" href="http://www.360magento.com">Magento建站</a></p>
<p><a title="magento" href="http://www.360magento.com">Magento</a>是一套专业开源的PHP电子商务系统。Magento设计得非常灵活，具有模块化架构体系和丰富的功能。</p>
<h2>特点</h2>
<p>Magento设计得非常灵活，具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。</p>
<h2>设计</h2>
<p>在设计上，包含相当全面，以模块化架构体系，让应用组合变得相当灵活，功能也相当丰富。</p>
<h2>应用</h2>
<p>其面向企业级应用，可处理更方面的需求，以及建设一个多种用途和适用面的电子商务网站。 包括购物、航运、产品评论等等，充分利用开源的特性，提供代码库的开发，非常规范的标准，易于与第三方应用系统无缝集成。 为了打开盈利途径，Magento 同时具备收费的企业版本，积极谋求合作和第三方整合的工具，比如电子支付平台等。</p>
<h2>Magento开源网店系统的特点主要分以下几大类</h2>
<ol>
<li>网站管理</li>
<li>促销和工具</li>
<li>国际化支持</li>
<li>SEO搜索引擎优化</li>
<li>结账方式</li>
<li>运输快递</li>
<li>支付方式</li>
<li>客户服务</li>
<li>用户帐户</li>
<li>目录管理</li>
<li>目录浏览</li>
<li>产品展示</li>
<li>分析和报表</li>
<li>自动被Google收录</li>
<li>一后台多网店系统</li>
</ol>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 04:32:19 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[轻松解决你的Magento毛病：整理最全的 Magento 常用SQL命令]]></title>
      <link>https://www.360magento.com/blog/magento-sql/</link>
      <description><![CDATA[<p><a title="magento" href="http://www.360magento.com">Magento</a>&nbsp;SQL命令可以加快解决你遇到的问题，不同版本，数据库可能会有所不同，所以SQL命令可能也会有所变化，在用SQL命令的时候一定要记得备份！！</p>
<p>1. 批量调整所有产品的价格&nbsp;<br />UPDATE `catalog_product_entity_decimal` SET value=round(value*1.45) WHERE attribute_id=99;<br />执行完后，需要到缓存管理里刷新：Layered Navigation Indices ，即可同步数据库里的关联表。</p>
<p>2. 批量处理所有 exclude 状态的图片<br />UPDATE `catalog_product_entity_media_gallery_value` SET disabled=0 WHERE disabled=1;</p>
<p>3. 导出导入 Magento 所有分类和产品<br />分类和产品是存放在以 catalog 开头的所有表中，对这组表进行导出导入即可实现此功能。<br />导入分类产品的 SQL 文件前注意：<br />在首行加入：SET FOREIGN_KEY_CHECKS=0;<br />在末行加入：SET FOREIGN_KEY_CHECKS=1;<br />原因是 Magento 使用 Innodb 存储引擎。</p>
<p>4. 批量修改分类的 Display Settings &mdash;&mdash;&gt; Is Anchor 值为 No<br />UPDATE `catalog_category_entity_int` set value=0 WHERE value=1 AND attribute_id=120;</p>
<p>5. 清空邮件队列<br />TRUNCATE TABLE `newsletter_queue`;<br />TRUNCATE TABLE `newsletter_queue_link`;<br />TRUNCATE TABLE `newsletter_queue_store_link`;<br />注意：同时向上万顾客发邮件时，不要在后台查看邮件队列，不然服务器压力会很大，待邮件发完之后，</p>
<p>记着清空邮件队列，这样在后台进入邮件队列就不会大量消耗服务器资源了。</p>
<p>6. Magento 转移站后，经常会出现下面这个提示，运行一下下面的SQL命令即可恢复正常。<br />错误提示： Notice: Undefined index: 0 app/code/core/Mage/Core/Model/Mysql4/Config.php on</p>
<p>line 92<br />SET FOREIGN_KEY_CHECKS=0;<br />update `core_store` set store_id = 0 where code='admin';<br />update `core_store_group` set group_id = 0 where name='Default';<br />update `core_website` set website_id = 0 where code='admin';<br />update `customer_group` set customer_group_id = 0 where customer_group_code='NOT LOGGED IN';<br />SET FOREIGN_KEY_CHECKS=1;<br />不过要明白，这个错误是使用了第三方数据库备份工具导致的，Magento 自带的备份功能是不会出现这个</p>
<p>错误的。</p>
<p>7. 根据产品的 SKU 批量将产品自定义选项设为非必填：<br />UPDATE `catalog_product_option` SET is_require=0 WHERE product_id IN (SELECT entity_id FROM</p>
<p>`catalog_product_entity` WHERE sku LIKE 'SKU %');</p>
<p>8. 关闭/开启 所有缺货产品<br />SET FOREIGN_KEY_CHECKS=0;<br />UPDATE `catalog_product_entity_int` SET value=2 WHERE attribute_id=80 and entity_id IN</p>
<p>(SELECT product_id FROM `cataloginventory_stock_status` WHERE stock_status=0);<br />SET FOREIGN_KEY_CHECKS=1;<br />其它说明：value=2 为关闭，1为开启，attribute_id 对应不同版本的产品禁用项，最后执行完命令需要</p>
<p>重建分类索引。</p>
<p>9. 取消所有问题邮件订阅<br />UPDATE `newsletter_subscriber` SET subscriber_status=3 WHERE subscriber_id IN (SELECT</p>
<p>subscriber_id FROM `newsletter_problem`);</p>
<p>10. 清除产品与分类的描述与 Meta<br />重置所有产品short description<br />UPDATE `catalog_product_entity_text` SET value='Short Description' WHERE</p>
<p>attribute_id=506;<br />清除所有产品Meta<br />UPDATE `catalog_product_entity_text` SET value='' WHERE attribute_id=97 OR</p>
<p>attribute_id=104;<br />UPDATE `catalog_product_entity_varchar` SET value='' WHERE attribute_id=103 OR</p>
<p>attribute_id=105;<br />清除所有产品URL<br />UPDATE `catalog_product_entity_varchar` SET value='' WHERE attribute_id=481;<br />清除所有分类描述：<br />UPDATE `catalog_category_entity_text` SET value='' WHERE attribute_id=112 OR</p>
<p>attribute_id=115 OR attribute_id=116;<br />清除所有分类URL<br />UPDATE `catalog_category_entity_varchar` SET value='' WHERE attribute_id=479;</p>
<p>11. 重置 Magento 所有 ID 统计数(如订单编码、发票编码等)<br />TRUNCATE `eav_entity_store`;<br />ALTER TABLE `eav_entity_store` AUTO_INCREMENT=1;</p>
<p>12. 批量禁用产品 &mdash;&mdash; 数据库操作<br />CREATE TABLE XYTMPTB SELECT entity_id,value FROM `catalog_product_entity_varchar` WHERE</p>
<p>value LIKE 'affliction%' AND attribute_id=96;<br />UPDATE `catalog_product_entity_int` SET value=1 WHERE attribute_id=273 AND entity_id IN</p>
<p>(SELECT entity_id FROM `XYTMPTB`);<br />DROP TABLE XYTMPTB;<br />别忘了重建索引！</p>
<p>13. 分类与产品的反向开关<br />UPDATE `catalog_category_entity_int` SET value=if(value=0,1,0) WHERE attribute_id=119;<br />UPDATE `catalog_product_entity_int` SET value=if(value=1,2,1) WHERE attribute_id=273;<br />运行一下，开的关了，关的开了，再运一下反之，最后别忘了重建索引!</p>
<p>14. 清站相关提示<br />能在后台清理的就在后台清理，直接对数据库操作有造成网站出错的可能性。其他辅助命令如下：<br />清除订单命令：<br />TRUNCATE `sales_flat_invoice`;<br />TRUNCATE `sales_flat_invoice_grid`;<br />TRUNCATE `sales_flat_invoice_item`;<br />TRUNCATE `sales_flat_order`;<br />TRUNCATE `sales_flat_order_address`;<br />TRUNCATE `sales_flat_order_grid`;<br />TRUNCATE `sales_flat_order_item`;<br />TRUNCATE `sales_flat_order_payment`;<br />TRUNCATE `sales_flat_order_status_history`;<br />TRUNCATE `sales_flat_quote`;<br />TRUNCATE `sales_flat_quote_address`;<br />TRUNCATE `sales_flat_quote_address_item`;<br />TRUNCATE `sales_flat_quote_item`;<br />TRUNCATE `sales_flat_quote_item_option`;<br />TRUNCATE `sales_flat_quote_payment`;<br />TRUNCATE `sales_flat_quote_shipping_rate`;<br />清除其它日志：<br />TRUNCATE `log_url_info`;<br />TRUNCATE `log_visitor_info`;<br />TRUNCATE `log_url`;<br />TRUNCATE `log_visitor`;<br />TRUNCATE `core_url_rewrite`;<br />TRUNCATE `report_event`;<br />TRUNCATE `report_viewed_product_index`;</p>
<p>15. Magento 数据库清理</p>
<p>安全模式：清理日常数据库的无用记录<br />TRUNCATE TABLE `log_visitor`;<br />TRUNCATE TABLE `log_visitor_info`;<br />TRUNCATE TABLE `log_url`;<br />TRUNCATE TABLE `log_url_info`;<br />干净模式：清理数据库的无用记录<br />TRUNCATE `log_visitor` ;<br />TRUNCATE `log_url_info` ;<br />TRUNCATE `log_visitor_info` ;<br />TRUNCATE `dataflow_batch_import` ;<br />TRUNCATE `log_url` ;<br />TRUNCATE `report_event` ;<br />TRUNCATE `log_visitor_online` ;<br />备注：如果是转移网站，URL 重写表 core_url_rewrite 也可清空，转完站重建 URL 即可。</p>
<p>16. 批量修改 SKU、Meta、Name 等字段里的部份词<br />UPDATE `catalog_product_entity` SET sku=replace(sku,'oldskuw','newskuw') WHERE sku LIKE</p>
<p>'%oldskuw%';<br />UPDATE `catalog_product_entity_text` SET value=replace(value,'oldmetaw','newmetaw')</p>
<p>WHERE value LIKE '%oldmetaw%';<br />UPDATE `catalog_product_entity_varchar` SET value=replace(value,'oldnamew','newnamew')</p>
<p>WHERE value LIKE '%oldnamew%';</p>
<p>17. 批量调整指定产品的价格<br />create table xytmptb SELECT entity_id,value FROM `catalog_product_entity_varchar` WHERE</p>
<p>(value LIKE '%Boot%' OR value LIKE '%Shoes%') AND attribute_id=60;<br />UPDATE `catalog_product_entity_decimal` SET value=value+10 WHERE entity_id IN (SELECT</p>
<p>entity_id FROM `xytmptb`) AND attribute_id=64;<br />drop table xytmptb;<br />最后别忘了重建价格索引！</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 04:22:09 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[O2O同城电子商务平台为什么能够迅速火起来]]></title>
      <link>https://www.360magento.com/blog/o2o-platform/</link>
      <description><![CDATA[<p><a title="360magento" href="http://www.360magento.com">&ldquo;互联网+&rdquo;</a>时代在我们不知不觉中渗入到日常生活中，从一开始的摸爬滚打到现在的炉火纯青，各个O2O同城<a title="电商平台创建" href="http://www.360magento.com">电商平台</a>的出现，终于让我们对O2O这个新名词引起了关注。</p>
<p>首先我们来看看这些O2O网购用户的需求：</p>
<ol>　　
<li>宅男宅女，想吃零食，懒的去超市买。</li>
　　
<li>办公室的打印机碳粉用完了，电脑城离的挺远，来回耽误时间。</li>
　　
<li>尿不湿用完了，楼下小店的商品不放心，去大超市买，又没人照顾小孩。</li>
　　
<li>马上要装修房子了，本地的建材市场杂乱不堪，价格千差万别，怎么才能选到合适的?</li>
</ol>
<p>结果，同城几公里甚至一公里内，催生了大量的电子商务需求。2小时送货上门，货到付款，更快退换货。同城电子商务可以满足距离和本地服务的需求，传统行业入门门槛低，利润较高，单个城市的运营推广模式简单、初期投入成本较低，这是互联网资本的下一个热区。</p>
<p>那么同城电子商务的优势在哪里?由于其同城的特殊属性，企业与消费者近距离接触，在信心构建方面相对来说比较容易操作，此外，媒体和线下品牌传播方面也有不可比拟的竞争优势，各类促销、线下活动的策办以及各类展会，都对品牌的宣传有很大的促进，同时，对初具规模的电子商务企业来说，往往能得到当地城市发展政策的支持与偏向，这对企业建立良好的公关环境有巨大的帮助，在以后竞争中软环境优势凸显。</p>
<p>在价格方面，笔者坚信一点，如果能在时间上和信心上凸显相对的优势，同城电子商务企业就拥有5%-7%的相对溢价优势，对于网络消费，最大的价格因素已经在传统和电子商务之间区分开来，而由于快速的反应能力，在售后服务及公关事件的处理等诸多方面，同城电子商务企业都有独到的优势。</p>
<p>而笔者认为，对于同城电子商务来说，对网购顾客最有利的莫过于电商平台所提供第三方服务。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 04:02:54 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[任春雷扒尽电商行业七大真相]]></title>
      <link>https://www.360magento.com/blog/ecommerce/</link>
      <description><![CDATA[<p>【2015年9月15日，北京】微指(上海)信息科技有限公司今日在北京五洲皇冠国际酒店发布了微指商户版APP。CEO任春雷在发布会现场全面剖析了中国商业真相和商业运行本质规律，揭示了传统电子商务模式的时代局限，也为众多面临挑战与转型中的实体商家指明了发展方向。</p>
<h2>实体商业的断崖式难题揭示电商霸权</h2>
<p>　　发布会上，微指科技向到场的商户、嘉宾和媒体展示的视频，给大家带来了极大震撼。繁华的中关村电子大卖场开始落幕，原本著名的天河商圈出现了严重的倒闭关店潮，曾经最繁华的杭州武林路到处都是空店，从京津冀到长三角、珠三角，很多商业核心区无一例外遭遇寒流。此外很多A股上市百货公司前途未卜，截止到2015年8月国内百货商场共倒闭120余家，五大运动品牌和其他众多企业集体遭遇了滑铁卢。</p>
<p>　　事实上，2011年以来，网购交易规模快速上升，到了2014年，中国网络购物占社会消费品零售总额的比重已跃升至10.72%。中国社会科学院信息化研究中心秘书长姜奇平先生曾经提到：每6%的商品从线下转移到线上，就会导致线下实体店的利润下降50%，就是下降一半，&ldquo;任春雷用&ldquo;人马矩阵&rdquo;直观显示了电商正在迅速抢走传统商业的客流和利润."并且让网店店主们陷入 &ldquo;不做广告没销量，做了广告没利润&rdquo;的怪圈。他认为电商是信息流、现金流的垄断者，正在用手中的资源和权力在这个社会推行丛林法则，导致恶性竞争和商业退步。而微指的出现就是要拆除这个中间的控制阀门，实现B和C直接对接，面对面交易，恢复自由和平等地商业秩序。任春雷表示，传统互联网的商业交易模式是技术+功利的商业思维，不是实体商铺转型的最终方向，真正的互联网进化的结果只有一个，即最终重归一种进步的人文精神，其概括为：开放、共享、以所有人为中心。随着移动互联网的兴起，微指将致力于开创第三商业时代，建立点对点的、立体的网络，迎来真正的互联网时代。</p>
<h2>微指解决方案：帮助实体店数字化，立刻实现弯道超越</h2>
<p>　　微指商户版APP是一款是基于手机定位系统的移动互联网<a title="magento电商网站开发" href="https://www.360magento.com/">电子商务</a>平台，它把全国所有实体店搬上了手机，形成了由实体虚拟店组成的数字化O2O商业交易平台。消费者可以在纵行天下的时候随时随地&ldquo;搜索和购买&rdquo;到&ldquo;附近乃至全国&rdquo;的商户或商品。通过微指APP，连通了消费者和实体店铺，结合了本地购物和网络购物两种优势。</p>
<p>任春雷指出，目前传统电商主要有以下问题和局限：模式陈旧(传统店铺做生意的模式，与唐朝没有任何区别)、时间障碍(每天只能做半天生意)、空间障碍(只能做门前几平米的生意)、信息不对称(消费者就在你附近，可你们却彼此不知道)、无法低成本营销(没有传播途径、广告太贵、传单效果太差等)。微指将彻底解决实体商户这些问题，实现&ldquo;时时都是营业高峰，家家都是黄金旺铺&rdquo;。</p>
<p>　　微指以改善中国人的生意和生活为宗旨，将联合所有的实体店主们完成一次信息化大升级，进行一场数字化的革命。彻底推翻实体店主们身上的三座大山，不再受经营时间、经营位置、信息不对称的限制，实现弯道超越，率先进入第三商业时代。</p>
<p>&nbsp;</p>
<h2>微指覆盖海量交易和数据，打造包罗万象的中国商城。</h2>
<p>　　为了获得最准确的原始数据，三年来，微指的地推人员用双脚走遍中国。截止今日，微指商户版APP已经覆盖300多座城市，2000万家商户，10亿款商品信息，并实现位置、样品、价格、存量、服务等所有信息适时更新。微指帮助每一家实体店铺零成本升级为移动互联网商店，以每一家实体店铺为中心，形成了任意半径的服务圈和物流圈，每一家商户都以自己为圆心，为周围100米、500米、1000米、3000米，甚至全城，乃至全国的用户提供服务。</p>
<p>　　在极度商品化的今天，其实很多商品就在身边，但因为信息不对称，用户们只能上网去淘，舍近求远。而通过微指客户端，手机用户以自身所处位置为圆心，形成了移动中的任意半径生活圈、信息圈。不管走在哪里，都可以搜索到身边100米，500米、1000米、3000米、甚至全城、乃至全国所有的店铺和货品。</p>
<p>微指突破了位置的局限性，以个人为中心，建立起了移动中的生活圈、信息圈、服务圈，为每一个用户提供最近、最便捷的资源配置和服务供应。</p>
<p>　　当每一条街、每一个实体店、每一件商品都通过微指客户端实现上传，使实体店不受交易时间的限制，也不受地段和位置的影响，全城所有的商铺和商品信息，都能通过微指被准确地定位和搜索，至此，一个数字化的商业世界才会呈现。</p>
<p style="color: red;"><strong>免责声明：</strong><span>此文内容为本网站刊发或转载企业宣传资讯，该相关信息仅为宣传及传递更多信息之目的，不代表本网站观点，文章真实性请浏览者慎重核实！</span></p>
<p style="color: red;"><span style="color: #000000;">360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/"><span style="color: #000000;">电商网站开发</span></a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/"><span style="color: #000000;">请与我们联系</span></a>。</span></p>
<p>&nbsp;</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 03:56:12 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento后台简介]]></title>
      <link>https://www.360magento.com/blog/magento-adminhtml/</link>
      <description><![CDATA[<p>许多第一次使用<a href="https://www.360magento.com/ title=">Magento</a>朋友都会有些手忙脚乱，最近也有不少客户问到一些关于magento后台操作的问题。这里呢，我就对magento后台做一个简短的介绍，希望能对各位有所帮助。</p>
<p>Cms 内容管理，cms page包含前台内容页，比如about us 可定义url static block 静态块，定义一个block，方便在网站的任意地方调用，后台也可以同步修改。模板中调用方法&lt;?php echo $this-&gt;getLayout()-&gt;createBlock('cms/block')-&gt;setBlockId('block_identifier')-&gt;toHtml(); ?&gt; widget 插件，这个用的比较少，功能累似于static block，不过这个产生的内容要自动一些，比如我要新建一个挂件，显示5个最新产品，在catalog的左栏，可以在这里直接定义。 poll 投票功能。</p>
<p>catalog 这里应该是最核心的内容，包括产品，分类，url，tag，评论，属性，属性集。每一点的内容都比较多。而且，不同生产环境下呈现的方式也不一样，比如多店的情况下。</p>
<p>customer 用户管理 给用户分组，查看用户站内产品的内容，及活动。查看在线用户。</p>
<p>promotios 促销规则，分类分类促销（购买指定分类或者属性的促销）和购物车促销（优惠码，购物车满多少减等等），可自定义条件，并且可以指定规则适用于哪个用户组的store view 和 website。</p>
<p>sale 这是订单处理，包括订单列表，订单信息，订单发票，退款管理，发货等，都是国外电商的一套处理流程，还有关于税这一块的规则，很少用。</p>
<p>newsletter 用户订阅列表，和订阅邮件推送设置，如果要推送订阅邮件，可以使用第三方发件，配合插件+magento的定时任务。</p>
<p>reports 网站销售分析，自带的这一套比较简单，没有图表，如果想要图表显示，有成熟的插件可以使用。</p>
<p>style 说一下我理解的过程吧， type="catalog/product_new" 这对应的是app/code/core/Mage/Catalog/Block/Product/New.php这个block里的方法。 name 指定这个block名字 as 指定别名 用来在模板中载入这个block $this-&gt;getChildHtml('newproductlist'); template 指定模板路径，在模板里调用block里对应的方法就可以获取到相应的产品列表，foreach打印到对应的html里即可。</p>
<p>magento后台的内容比较多，我这里讲得比较浅，如果想要了解更多或者有什么疑问，欢迎到我们的官网<a title="magento电商网站开发" href="https://www.360magento.com/">360magento</a>交流 。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 03:25:11 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento网站流量飙升的seo技巧]]></title>
      <link>https://www.360magento.com/blog/magento-seo/</link>
      <description><![CDATA[<p>有效地利用Magento SEO配置才能发挥Magento的优势，这里360magento团队总结了一些Magento SEO技巧，希望能帮助大家提升网站流量。</p>
<h2>1. 基本的技术优化</h2>
<h3>1.1. 普通设置</h3>
<p>Magento 是搜索引擎最友好的商用平台之一，但有几点需要关注以优化你的 Magento SEO.开始运行Magento时，激活 Server URL rewrites. 你可以找到这个选项在系统按钮下： System =&gt; Configuration =&gt; Web =&gt; Search Engines Optimization. 激活后，在这个页面上，另一个不错的选择是设置&ldquo;Url Options &rdquo;下的 "Add store Code to Urls" ，在大多数情况下，把这个开关设为&ldquo;No&rdquo;更好。</p>
<p>1.1.1. WWW vs non-WWW</p>
<p>在 "Unsecure" 和 "Secure" 的下拉菜单里你可以找到 Base URL, 在那里你可以设置你更喜欢的域名。你可以选择WWW的URL或者没有WWW的URL。改变这些设置你不会建立一个重定向从www到non-www或者从non-www到www,而只是你设置的你喜欢的那一个。所以通过 .htaccess with mod_rewrite建立一个301重定向是一个好主意。除此之外，解决了 WWW vs non-WWW 的问题，这个重定向可以预防Magento被加入SID问题到你的URLs，像SID=b9c95150f7f70d6e77ad070259afa15d. 确保 Base URL 和重定向是一样的。编辑 .htaccess 文件时，你可以加入下面的代码到根目录下的重定向 index.php 中。 大约 119 行: RewriteBase / RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/ RewriteRule ^index\.php$ http://www.mydomain.com/ [R=301,L] 或者，你安装Magento的时候不是在根目录下而是在某个子目录下http://www.mydomain.com/magento/: RewriteBase /magento/ RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /magento/index\.php\ HTTP/ RewriteRule ^index\.php$ http://www.mydomain.com/magento/ [R=301,L]</p>
<h3>1.2. 页眉设置</h3>
<p>安装Magento时默认的标题是 "Magento Commerce"。为了你的Magento商店得到它应得得流量，以下你必须了然于胸： 搜索引擎着重于开头的词，所以如果你的关键字靠近页面标题的开头那你有更大的可能性让排名更好。 人们扫视结果页面，一般看开头的几个词。如果你的关键字位于页面的的开始，那你被点击的可能性就大很多。 首先你应该去掉默认的标题 "Magento Commerce". 后台点击 Configuration =&gt; Design =&gt; HTML Head. 为你的网站选一个描述性好的标题，这个标题也会在几个没有内容的页面中使用，比如 "Contact Us" 和 "Popular Search Terms". 把页面标题加到你的店名中，包括目录和商品，把你的店名放在&ldquo;标题后缀&rdquo;中。保持前缀空白是个不错的选择，原因上面提到过。同时保持 "Default Description" 和 "Default Keywords" 空白。对于非产品展示页面，为防止整站索引，设置 "Default Robots" 为 "NOINDEX, NOFOLLOW" 会有所帮助，但对于别的页面来说要确保设置为 "INDEX, FOLLOW". 现在我们优化你的网店页面的，好的方法是加上 new canonical tag （新的规范标签）。你可以安装 Canonical URL's for Magento Module 以便把它们加到你的head种来改进你的Magento SEO。 因某些原因Magento把未设置的meta机器人转为一个meta标签，方式如下：<meta name="robots" content="*" />这种方式会造成搜索引擎一些奇怪的行为，所以我们要把它移除。要从代码中移除这些空白的meta你可以安装 Yoast MetaRobots Module.</p>
<h3>1.3. CMS 页面</h3>
<p>第一眼看上去Magento似乎缺少华丽的CMS功能，但对于大多数使用者来说这已经足够了。简单的CMS的好处之一是你能够控制页面的每一个方面。一旦你赋予每一个CMS页面一些不错的内容，选一个SEF URL鉴别者和页面标题，（同时记住1.2小节中的要点），到Meta数据标签处为每个你想要给它排名的CMS页面写上描述。 你可以保持"Keywords"栏空白。描述有一个很重要的作用：引诱人们去点击，所以确保它描述的确实是他们所要点击页面的内容，那样可以引起他们的注意。因此，唯一的好的描述就是自己手写的，如果你考虑用自动描述软件来写描述，那还不如什么也不做，让搜索引擎负责这部分。 如果你不使用meta描述，搜索引擎会在你的文件里找到关键字，并自动选择一条，那样在结果页面里会有一到两个醒目的词。</p>
<h3>1.4. 商品目录优化</h3>
<p>Magento 给你增加目录名的权利，让你的目录指向产品的URL。因为Magento对建立相同的内容这个功能的支持不够，很好的方式就是禁用它。设置它，点击System =&gt; Configuration =&gt; Catalog =&gt; Search Engine Optimization and set "Use categories path for product URL's to "no". 现在是时候设置每一个目录的细节了。点击Catalog =&gt; Manage Categories. 最重要的区域是： Meta 描述: 在这里放上吸引人的描述；记住人们会在搜索引擎的结果列表页中看到这个描述。 页面标题: 保持页面标题空白，使用目录名包括父目录。但你按照要求制作目录时，标题会象你所输入的一样，没有父目录。 URL 要点: 尝试保持短的但是关键字丰富的URL。移除没用的词象&ldquo;the&rdquo;，&ldquo;and","for"等等。要注意的是你只能在&ldquo;all store views&rdquo;下设置, 对于多语种的商店你应该保持语言的独立。 对于每一个商店界面，你可以指定名字，描述，页面标题和Meta数据。对多语种商店来说这真的是一个很棒的功能。</p>
<h3>1.5. 商品优化</h3>
<p>商品页面的优化和目录优化有些相似。你可以设置Meta信息为 "Default Values" 并使用于每一个 "Store View". 注意对于 "Meta Title", 这个将写在完全的页面标题上，包括目录但不包括标题的前缀/后缀，而不仅仅是商品的名称。 Magento SEO中一个经常忽略的方面是你怎么处理你的图片。通过给图片写标签和考虑给你的图片起怎样的名字，你会从不同的图片搜索引擎得到不错的额外流量。</p>
<h2>2.Magento模板优化</h2>
<h3>2.1. 优化了的空白模板</h3>
<p>默认的Magento皮肤如 "Default Theme", "Blue Skin" 和 "Modern Theme" 在标题方面的工作做得不好，从SEO的角度来看，有很多的地方可以改进。为使它对你变得简单，我们开发了一款空白的Magento SEO模板，基于Magento的核心技术，空白模板合并了所有的东西，你可以下载并一起讨论它 download and discuss it here.</p>
<h3>2.2. 标题</h3>
<p>默认的 logo 是一个 &lt;h1&gt;, 应该只是出现在首页，在别的页面上它应该是一个&lt;h3&gt;. 最重要的事实让标题的内容置于 &lt;h1&gt; 标签之中，例如，在目录页它应是目录名在商品也应是商品名。 下一步是清除过量的标题。一个好主意是清除侧栏的标题，或者做一个和商店相关的文字（包括关键字）。没有什么理由加上"static" 和没有什么关键字的标题在&lt;h4&gt;中. 是的，例如，把所有的 &lt;h4&gt; 标签换成 &lt;div&gt; to &lt;strong&gt; 标签更好。现在是时候优化你的内容了，在目录页中把商品名放在 &lt;h3&gt; 里，把目录名放在 &lt;h1&gt;里。在商品页，你应该把商品名放在&lt;h1&gt;里. 想了解更多关于为什么正确的标题是重要的，可以阅读这篇文章 Semantic HTML and SEO.</p>
<h3>2.3. 清除你的代码</h3>
<p>保持你的模板清爽，把你的模板文件中的所有 javascript 和 CSS 移到外部的 javascripts 和css 文件中，因为它们对你的Magento SEO没有任何好处。这样做可以确保你的用户在首次读取文件的时候储存那些文件，搜索引擎不需要花费大量的时间来下载它们。</p>
<h2>3. 高级Magento SEO 和重复内容</h2>
<p>一旦你完成了所有基础的东西你会发现剩下的事情就是一件简单的事：相同的内容。实际上是大量的相同的内容。商品里有相同的内容，至少，在下面的URLs有完全相同的内容：</p>
<p>domain.com/product.html domain.com/category1/product.html domain.com/catalog/product/view/id/1/ domain.com/catalog/product/view/id/1/category/1/ 此外，商品回顾页面有几乎一样的内容。另一个问题是目录，你有大量相同的内容在层级导航中和索引选择中。最坏的情况是一个商品在这个页面显示之外，至少还会在这个页面以外的4个页面中显示。 我们可以通过去掉这些相同的内容，并允许它们被蜘蛛爬但不被索引，固定目录的索引选择和层级导航。</p>
<h3>3.1. 无内容页面的Noindex, follow</h3>
<p>安装 Yoast robots meta module 并确保设置成防止索引所有的无内容页面，现在搜索引擎将通过所有的链接来到这些页面上但不会再索引中显示这些页面。</p>
<h3>3.2. Nofollowing 非必需的链接</h3>
<p>另一简单的步骤来提高你的 Magento SEO 是停止链接到你的登录，付款，希望购买列表和所有其他没有内容的页面。对于RSS feeds,层级导航，增加商品到希望购买列表，增加商品到比较列表来说也是同样的设置。目前还没有插件来完成这些工作。你不得不进入你的模板文件中手工完成。</p>
<h3>3.3. 规范的URLs</h3>
<p>帮助搜索引擎理解你页面中的相同内容，你可以在每个页面使用你更喜欢的URL，使用新的 canonical URL tag （规范的URL标签），你就应该安装这个 Canonical URL's for Magento 模数。</p>
<h3>3.4. XML 地图</h3>
<p>XML 地图是让搜索引擎知道你的内容在哪里的简单方法，它不会帮助你提高排名，但它可以帮助你更快得到索引。你可以手工建立一个XML地图，后台点击 Catalog =&gt; Google Sitemap =&gt; Add Sitemap, 选择一个文件名，路径和商店界面，然后点击 "Save &amp; Generate"。然后你可以简单的把下面的代码放到你的 robots.txt 文件中指引搜索引擎向你的 sitemap.xml 文件: Sitemap: /sitemap.xml 如果你的目录更改了，记得去重新生成XML地图。</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 03:00:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento seo小技巧]]></title>
      <link>https://www.360magento.com/blog/magento-seo-addpage/</link>
      <description><![CDATA[<p>当在<a title="电商网站开发" href="https://www.360magento.com/"><strong>Magento</strong></a>后台创建一个新页面，特别是产品页面、普通页面和博客页面的时候，对页面进行SEO显得尤为重要，因为这涉及到整个网站的长尾关键词分布，是整个网站SEO极为重要的一环。</p>
<h2>1．产品页面SEO</h2>
<p>在<a title="电商网站开发" href="https://www.360magento.com/">Magento</a>后台添加产品页面的时候，产品的标题(Name)应尽量包含产品品牌、型号、应用、特点等字词；产品描述(Description)和产品简介(Short Description)最好再次写下产品标题中最重要的关键词，增加关键词出现的频率；URL路径(URL KEY) 应包含产品品牌、型号等关键词，如&ldquo;hp-lcd-panel-cq61&rdquo;。 Meta信息(Meta Information)包括meta title、meta keywords和meta description三部分。其中meta title不用填写，因为产品的标题(Name)已经加入了关键词，meta title一栏留空的话系统就会让搜索引擎抓取产品标题，所以这里就不需要进行重复劳动了。当然如果你觉得产品标题容不下你想要展示的信息时，你也可以在这里添加。Meta keywords栏目应选择1至 8个关键词放在此处。产品料号、型号、品牌、应用产品、供应商、特点等都可以作为关键词。例如，hp cq61 lcd panel,B156XW02 V.0, auo , laptop lcd panel replacement；Meta description则用一两句包含meta keywords的话概括描述产品。但是实际情况是：由于产品众多，不太可能花费那么多时间去对每个产品的meta description撰写句子，所以可以整理出所有产品都适用的句式，对于不同的产品，只要更改相应的关键词即可，或者直接留空，让搜索引擎自动抓取。上传产品图片时，产品名称最好也包含相关关键词，标记（Label）可留空，让搜索引擎自动抓取产品名称作为label即可。另外，Magento还有产品标签（product tags）功能，给产品添加各种标签，搜索引擎和用户都就能更方便地找到需要的东西了。</p>
<h2>2．普通页面和博客页面SEO</h2>
<p>网站页面SEO方法大同小异，<a title="电商网站开发" href="https://www.360magento.com/">Magento</a>产品页面方法（标题、URL路径、meta信息、图片名称）都适用于普通页面和博客页面。但是普通页面和博客页面是对文本的编辑，搜索引擎基本都是根据文本内容来爬行抓取的，所以对于文字文本的编辑也是页面SEO很重要的因素。 页面正文中应多次多出此页面标题的关键词，并且可以在第一次出现的时候加粗以示强调。同时如果正文中出现了相关关键词，可以对其设置超链接并且指向相应的页面，这样页面与页面之间就有了联系，更有利于搜索引擎蜘蛛的爬行。 如果正文中有图片，那么图片应该设置alt属性，如<span>&lt;img src=&rdquo;hp-cq61.jpg&rdquo; alt=&rdquo;hp lcd panel cq61&rdquo;/&gt;</span>。alt属性的作用是当图片无法显示时以文字作为替代显示出来，而对于SEO来说，它可以令搜索引擎有机会索引你网站上的图片。</p>
<h2>3．页面SEO应该注意的其他因素</h2>
<p>a. 太大的页面影响搜索引擎的处理速度</p>
<p>b. 关键信息应该出现在页面中靠前的位置</p>
<p>c. Javascript和stylesheet应该尽量放在页面外部</p>
<p>d. 一个页面代码部分的体积不要太大，控制在100kb内为佳</p>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 16 Sep 2015 02:43:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[服装店magento主题模板]]></title>
      <link>https://www.360magento.com/blog/clothes-store/</link>
      <description><![CDATA[<p><img class="js-preview-lazy lazy" style="display: block; width: auto;" alt="响应式magento模板主题" src="http://7xjryy.com1.z0.glb.clouddn.com/53452-responsive-layout.jpg" /></p>
<p>&nbsp;&nbsp;在上篇文章里为大家推荐了一款时尚皮包的magento主题模板，受到了不少读者的青睐。今天呢，为大家强力推荐一款服饰主题的模板。当今社会随着人们生活品质的提高，对衣着的要求也越来越高，这也意味着服装店网站也需要更加吸引顾客才行。下面我们一起来看看这款magento主题模板。</p>
<p>&nbsp;&nbsp;作为一款优秀的magento主题模板，响应式是必须的。本模板完美支持智能手机和平板电脑，在不同设备上享受不同的视觉盛宴。网站主体为简约低调的灰白风格，时尚而富有贵族气息。搜索、登录、购物车、语言切换等功能皆安置在小巧的图标里，如需使用点击即可，如图是登录等功能：</p>
<p><img class="js-preview-lazy lazy" style="display: block; width:840px;" alt="响应式magento模板主题" src="http://7xjryy.com1.z0.glb.clouddn.com/clothes-store0.png" /></p>
<p>&nbsp;&nbsp;强大的Megamenu插件也也是不可缺少的，看看展示的效果就能让你心动不已。</p>
<p><img class="js-preview-lazy lazy" style="display: block; width: 840px;" alt="响应式magento模板主题" src="http://7xjryy.com1.z0.glb.clouddn.com/clothes-store1.png" /></p>
<p>&nbsp;&nbsp;为了能更好，更多地展示出特色产品，本模版首页包含了两个幻灯片，欢迎大家点击<a href="http://www.360magento.com/magento-theme/theme027.html">http://www.360magento.com/magento-theme/theme027.html</a>查看。</p>
<p>另外，值得一提的是最新产品的展示，请看下图：</p>
<p><img class="js-preview-lazy lazy" style="display: block; width: 840px;" alt="响应式magento模板主题" src="http://7xjryy.com1.z0.glb.clouddn.com/clothes-store2.png" /></p>
<p>&nbsp;&nbsp;服装的各种款式、颜色只需轻轻点击即可切换观看，简单方便，大大节省顾客挑选产品的时间，给顾客更加友好的体验。更多功能就不一一介绍，由您自己去体验。</p>
<p>&nbsp;&nbsp;如有需要，360magento团队会为您提供magento建站，插件开发等优质服务，满足您的多钟需求，解决您所遇到的各种困难。</p>]]></description>
      <pubDate>Tue, 15 Sep 2015 12:07:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[时尚经典包包magento主题模板推荐]]></title>
      <link>https://www.360magento.com/blog/magento-handsbag/</link>
      <description><![CDATA[<p><img class="js-preview-lazy lazy" style="display: block; width: auto;" alt="响应式magento模板主题" src="http://7xjryy.com1.z0.glb.clouddn.com/53982-responsive-layout.jpg" /></p>
<p>&nbsp;&nbsp;Magento作为世界上最优秀的模板之一，正逐步地引起了过人的重视，越来越多的大小型企业选择magento作为网站的开发模板，也广受好评。众所周知的，网络的发展势不可挡，网站作为企业的门户也带来了很可观的受益。因此，选择一个优质的，符合企业需求的模版便成了网站建设的一大重点。今天就为大家推荐一个为皮包厂商量身定做的主题模版。</p>
<p>&nbsp;&nbsp;这款模板在360magento官网(www.360magento.com)中的名字是&ldquo;Stylish Bags Boutique Magento 主题模板&rdquo;。大家可点击<a href="http://www.360magento.com/magento-theme/theme023.html">http://www.360magento.com/magento-theme/theme023.html</a>来查看模板的演示效果。主题模板以橙、灰、白三色为主调，简约而符合皮包特点。强大的Megamenu能在导航中添加广告，告别传统导航仅仅只有单调文字的过去，其强大功能也只有用过的人才能体会一二。首页超大的幻灯片更是将网站特色产品尽显客户眼底。最新产品的展示也以滚动的形式展现出来，更多的产品，更小的空间，有利于顾客良好的体验。博客功能使得商家与客户的交流更加密切，商家可利用此功能普及客户对皮包的认识，让客户能更好地做出选择。</p>
<p>&nbsp;&nbsp;至于其它更多功能我就不再一一列举，欢迎各位在演示网站中去体验。 如有需要，360magento团队会为您提供magento建站，插件开发等优质服务，满足您的多钟需求，解决您所遇到的各种困难。</p>]]></description>
      <pubDate>Mon, 14 Sep 2015 15:25:32 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中避免jQuery与其它库冲突]]></title>
      <link>https://www.360magento.com/blog/avoid-conflicts-other-libraries/</link>
      <description><![CDATA[<p>大家都知道，在magento中用的js库是prototype,而现在我们想用jQuery,那么这就涉及到兼容性问题了，因为prototype控制着magento默认的所有js效果，我们不可能去花费大量时间去把prototype替换成jQuery,这样代价太大了，下面就在magento中jQuery兼容prototype解决方法做下讲解</p>
<p>jQuery命名空间里包含了它的库和所有插件。一般来说，全局对象存储在jQuery的命名空间里，所以不应该与其它库发生冲突（比如 prototype.js, MooTools,或者YUI）</p>
<p>也就是说，这里警告大家：默认地，jQuery使用$作为jQuery的缩写。因此，如果你正使用JavaScript库中的$变量，那么就会与jQuery冲突。为 了避免这些冲突，你需要在jQuery载入页面和被使用前进入无冲突模式（no-conflict mode）。</p>
<h2>让jQuery进入无冲突模式</h2>
<p>当你让jQuery进入无冲突模式时，你可以用一个新的变量名来代替$别名。</p>
<pre><code>
&lt;!-- Putting jQuery into no-conflict mode. --&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/scrip&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
var $j = jQuery.noConflict();
// $j is now an alias to the jQuery function; creating the new alias is optional.
 
$j(document).ready(function() {
    $j( "div" ).hide();
});
 
// The $ variable now has the prototype meaning, which is a shortcut for
// document.getElementById(). mainDiv below is a DOM element, not a jQuery object.
window.onload = function() {
    var mainDiv = $( "main" );
}
// ]]&gt;&lt;/script&gt;
</code></pre>
<p>在上面的代码中，$的意思会在原始库中被还原。使用jQuery函数全名和新别名$j效果是一样的。新的别名可以任由你命名，比如：jq, $J, awesomeQuery，等等。</p>
<p>最后，如果你不愿意替换掉jQuery函数名（超喜欢用$而不在乎其它库中的$方法），这里也有个方法你可以试试：简单地将$作为参数传到你的jQuery( document ).ready()方法中。这是最常用的技能利用jQuery代码简洁优势，又能避免冲突的方法。</p>
<pre><code>
&lt;!-- Another way to put jQuery into no-conflict mode. --&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
jQuery.noConflict();
 
jQuery( document ).ready(function( $ ) {
    // You can use the locally-scoped $ in here as an alias to jQuery.
    $( "div" ).hide();
});
 
// The $ variable in the global scope has the prototype.js meaning.
window.onload = function(){
    var mainDiv = $( "main" );
}
// ]]&gt;&lt;/script&gt;
</code></pre>
<p>对于大部分你的代码，这可能是理想的解决方式。考虑到一些少部分情况，你将要做些改变去达到完全兼容的效果。</p>
<h2>在其它库前载入jQuery库</h2>
<p>上面例子中，依赖jQuery的代码在prototype.js之后被读取。如果在其它库前载入jQuery，你就可以在jQuery作用的地方使用jquery，但是$会有其它库中定义的意思。这样就不需要通过调用jQuery.noConflict()放弃$别名了。</p>
<pre><code>
&lt;!-- Loading jQuery before other libraries. --&gt;
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
// Use full jQuery function name to reference jQuery.
jQuery( document ).ready(function() {
    jQuery( "div" ).hide();
});
 
// Use the $ variable as defined in prototype.js
window.onload = function() {
    var mainDiv = $( "main" );
};
// ]]&gt;&lt;/script&gt;
</code></pre>
<h2>引用jQuery函数摘要</h2>
<p>这里回顾下在冲突情况下如何引用jQuery函数</p>
<h3>创建一个新别名</h3>
<p>jQuery.noConflict()方法返回一个新的参数给jQuery函数，因此你可以在任何你想要的变量中捕捉它。</p>
<pre><code>
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
// Give $ back to prototype.js; create new alias to jQuery.
var $jq = jQuery.noConflict();
// ]]&gt;&lt;/script&gt;
</code></pre>
<h3>使用一个立即调用的函数表达式</h3>
<p>通过将你的代码包含进一个立即调用函数表达式可以让你继续使用标准的$；这也是jQuery插件编写的一个标准模式，这里笔者不知道其它库是否会接管$。</p>
<pre><code>
&lt;!-- Using the $ inside an immediately-invoked function expression. --&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
jQuery.noConflict();
 
(function( $ ) {
    // Your jQuery code here, using the $
})( jQuery );
// ]]&gt;&lt;/script&gt;
</code></pre>
<p>这里要注意的是，当你使用这项技术时，你将不能在立即调用函数内使用prototype.js方法。$将是jQuery的参数。</p>
<h3>使用jQuery( document ).ready()函数的传递</h3>
<pre><code>
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
jQuery(document).ready(function( $ ) {
    // Your jQuery code here, using $ to refer to jQuery.
});
// ]]&gt;&lt;/script&gt;
</code></pre>
<p>或者使用更简洁的语法DOM ready函数</p>
<pre><code>
&lt;script type="text/javascript" src="jquery.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" src="prototype.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;// &lt;![CDATA[
jQuery(function($){
    // Your jQuery code here, using the $
});
// ]]&gt;&lt;/script&gt;
</code></pre>]]></description>
      <pubDate>Fri, 11 Sep 2015 05:54:02 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento插件教程之计算器]]></title>
      <link>https://www.360magento.com/blog/magento-extension-study001/</link>
      <description><![CDATA[<p>这个案例的内容是，在magento前台输入两个数，然后输出结果。 这个案例的目的是 1.数值是如何在magento的Controllers传递到Block中的，又是如何在phtml文件中输出的。 2.controllers中的action使用。 3.了解使用form post参数和如何get参数。</p>
<p>首先来看下这个案例中的文件结构 <br /> /* 声明插件，指定codePool、插件开启状态等 */</p>
<pre>app/etc/modules/Alwayly_Counter.xml</pre>
<p>/* 模板.phtml文件中使用的方法在此文件中声明，此案例中此文件将计算结果传递到.phtml文件 */</p>
<pre>app/code/local/Alwayly/Counter/Block/Counter.php</pre>
<p>/* 我们此案例的的控制器 http://magento-root-folder/module-name/controller-name/action-neame 此例中IndexController控制器中的一个action获取counter.phtml中传来的参数，并将参数传递到Counter.php，在Counter.php中计算后将结果返回到counter.phtml输出 */</p>
<pre>app/code/local/Alwayly/Counter/controllers/IndexController.php</pre>
<p>/* 主要的插件配置文件 */</p>
<pre>app/code/local/Alwayly/Counter/etc/config.xml</pre>
<p>/* 前台显示模板的layout */</p>
<pre>app/design/frontend/default/default/layout/counter.xml</pre>
<p>* 前台模板文件，我们的form和结果最终就在这个文件输出，此文件直接使用$this-&gt;调用与其相应的block中的方法，本例中我们只使用这一个模板页面。 */</p>
<pre>app/design/frontend/default/default/template/counter/counter.phtml</pre>
<p>/* Helper此例不使用，放在这主要作用是显得气派，充门面 */</p>
<pre>app/code/local/Alwayly/Counter/Helper/Data.php</pre>
<p>我们先从简单的开始，那就先在前台的模板文件counter.phtml中写个提交的form吧</p>
<p>app/design/frontend/default/default/template/counter/counter.phtml文件中代码片段（详见本例文件）</p>
<pre>&lt;form action="<!--?php echo Mage::getUrl('counter') ?-->" method="post" id="orderreport-form"&gt;
        &lt;fieldset&gt;
            &lt;ul&gt;
                &lt;li&gt;
                    &lt;label for="NUM1"&gt;&lt;?php echo $this-&gt;__('NUM1: ') ?&gt;&lt;span class="required"&gt;*&lt;/span&gt;&lt;/label&gt;
                    &lt;input type="text" id="NUM1" name="NUM1" class="input-text required-entry validate-alphanum" /&gt;
                &lt;/li&gt;
                &lt;li&gt;
                    &lt;label for="NUM2"&gt;&lt;?php echo $this-&gt;__('NUM2: ') ?&gt;&lt;span class="required"&gt;*&lt;/span&gt;&lt;/label&gt;
                    &lt;input type="text" id="NUM2" name="NUM2" class="input-text required-entry validate-alphanum" /&gt;
                &lt;/li&gt;
                &lt;li&gt;
                    &lt;input type="submit" value="<!--?php echo $this--->__('submit') ?&gt;" /&gt;
                &lt;/li&gt;
            &lt;/ul&gt;
        &lt;/fieldset&gt;
&lt;/form&gt;
</pre>
<p>注意action="&lt;!--?php echo Mage::getUrl('counter') ?-->" 等同于 action="&lt;!--?php echo Mage::getUrl('counter/index/index') ?-->"</p>
<p>有数据的post了，我们就在counter/index/index这个path下的indexAction中接收这个参数 app/code/local/Alwayly/Counter/controllers/IndexController.php文件中代码片段（详见本例文件）</p>
<pre> public function indexAction()
    {
       
        if ($this-&gt;getRequest()-&gt;isPost()){ /* 首先判断是否有post发生 */
            $nu1 = $this-&gt;getRequest()-&gt;getParam('NUM1'); /* 截获参数 */
            $nu2 = $this-&gt;getRequest()-&gt;getParam('NUM2');
            Mage::register('nu1', $nu1);/* 传递到block */
            Mage::register('nu2', $nu2);
        }
           
        $this-&gt;loadLayout();    
        $this-&gt;renderLayout();
    }
</pre>
<p>既然在controllers中有了传递到block的方法，下一步就在block中获取 app/code/local/Alwayly/Counter/Block/Counter.php文件中代码片段（详见本例文件）</p>
<pre>protected $nu1 = null ;
    protected $nu2 = null;
    public function showresult(){
        $this-&gt;nu1 = Mage::registry('nu1'); /* 获得从controllers中传递来的参数 */
        $this-&gt;nu2 = Mage::registry('nu2');
        return $this-&gt;nu1 * $this-&gt;nu2;
  
    } 
</pre>
<p>此block文件中的showresult()方法在phtml文件中可以试用$this-&gt;直接调用。 这样我们就差最后一步就是在我们的模板文件中输出结果了在app/design/frontend/default/default/template/counter/counter.phtml文件中添加输出结果的代码</p>
<pre>&lt;ul&gt;
&lt;li&gt;result:&lt;?php echo $this-&gt;showresult(); ?&gt;&lt;/li&gt;
&lt;/ul&gt;
</pre>]]></description>
      <pubDate>Sun, 06 Sep 2015 01:41:29 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中自定义邮寄方式]]></title>
      <link>https://www.360magento.com/blog/custom-shipping-method-in-magento/</link>
      <description><![CDATA[<p><img alt="" src="http://7xjryy.com1.z0.glb.clouddn.com/custom-shipping-magento.png" height="300" width="760" /></p>
<p>在这篇文章中我将演示如何在Magento中编写自定义的邮寄方式。准确说来分为标准邮寄（standard shipping）和快递邮寄（express shipping）。只有当你购买的产品超过指定重量时才可能邮寄。首先说明下Magento如何处理邮寄以及为完成我们的目标需要些什么。</p>
<p>当寻找可用的邮寄方式是，Magento首先收集所有可用的载体(carriers)。一个&ldquo;Carrier&rdquo; 代表一个承运商，就像现实世界中的（例如联邦快递）。每一个载体都被表现在扩展自Mage_Shipping_Model_Carrier_Abstract的类。</p>
<p>在列出接受的载体后，邮寄方式信息（表现为Mage_Shipping_Model_Rate_Request）被送到载体去检索所有可用的费率，结果表现在Mage_Shipping_Model_Rate_Result。</p>
<p>这个过程发生在<strong>Mage_Shipping_Model_Shipping::collectRates()</strong>的这段代码里：</p>
<pre><code>
...
$carriers = Mage::getStoreConfig('carriers', $storeId);
 
foreach ($carriers as $carrierCode =&gt; $carrierConfig) {
    $this-&gt;collectCarrierRates($carrierCode, $request);
}
...
</code></pre>
<p>collectCarrierRates()功能负责确认载体是否可用以及触发你的类中的collectRates()功能。 这大致就是在屏幕后所发生的事。现在，针对上面所讲我们要写一些代码。首先你要做的就是创建一个基于Mage_Shipping的模型。除了标准的模型配置外你还需要将以下代码放入你的config.xml:</p>
<pre><code>
&lt;config&gt;
    ...
    &lt;default&gt;
        ...
        &lt;carriers&gt;
            &lt;alwayly_shipping&gt;
                &lt;active&gt;1&lt;/active&gt;
                &lt;model&gt;alwayly_shipping/carrier&lt;/model&gt;
                &lt;title&gt;Alwayly Shipping Carrier&lt;/title&gt;
                &lt;sort_order&gt;10&lt;/sort_order&gt;
                &lt;sallowspecific&gt;0&lt;/sallowspecific&gt;
                &lt;express_max_weight&gt;1&lt;/express_max_weight&gt;
            &lt;/alwayly_shipping&gt;
        &lt;/carriers&gt;
        ...
    &lt;/default&gt;
    ...
&lt;/config&gt;
</code></pre>
<p>sallowspecific和express_max_items配置条目，我们稍后解释。我们将从模型条目开始。如你所见，我们的载体表现在 Alwayly_Shipping_Model_Carrier，所以让我们实现在个类吧。前面提到的，载体需要扩展自Mage_Shipping_Model_Carrier_Abstract 并且实现Mage_Shipping_Model_Carrier_Interface来确认Magento能使用它。我们将以下面的代码开始：</p>
<pre><code>
class Alwayly_Shipping_Model_Carrier
    extends Mage_Shipping_Model_Carrier_Abstract
    implements Mage_Shipping_Model_Carrier_Interface
{
    protected $_code = 'alwayly_shipping';
</code></pre>
<p>接着，getAllowedMethods() 以key-value 形式的数组返回所有可用的方法。这正是我们的接口需要的，我们这么实现：</p>
<pre><code>
public function getAllowedMethods()
{
    return array(
        'standard'    =&gt;  'Standard delivery',
        'express'     =&gt;  'Express delivery',
    );
}
</code></pre>
<p>最后，我说过费率被collectRates()收集。这个功能将邮寄信息转换为字段，返回所有可用的费率。它还确定哪些费率可用于给定的要求。</p>
<pre><code>
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
	/** @var Mage_Shipping_Model_Rate_Result $result */
	$result = Mage::getModel('shipping/rate_result');
 
	/** @var Alwayly_Shipping_Helper_Data $expressMaxProducts */
	$expressMaxWeight = Mage::helper('alwayly_shipping')-&gt;getExpressMaxWeight();
 
	$expressAvailable = true;
	foreach ($request-&gt;getAllItems() as $item) {
	    if ($item-&gt;getWeight() &gt; $expressMaxWeight) {
		$expressAvailable = false;
	    }
	}
 
	if ($expressAvailable) {
	    $result-&gt;append($this-&gt;_getExpressRate());
	}
	$result-&gt;append($this-&gt;_getStandardRate());
 
	return $result;
}
</code></pre>
<p>如你所见，代码很明了。购物车里的产品重量都和设定的值做对比，由此来决定是否用快递费率每一种费率都是通过Mage_Shipping_Model_Rate_Result_Method 对象到append()这个我们的结果对象。我们通过alling _getExpressRate()和_getStandardRate()来获取这些费率对象，下面是代码：</p>
<pre><code>
protected function _getStandardRate()
{
    /** @var Mage_Shipping_Model_Rate_Result_Method $rate */
    $rate = Mage::getModel('shipping/rate_result_method');
 
    $rate-&gt;setCarrier($this-&gt;_code);
    $rate-&gt;setCarrierTitle($this-&gt;getConfigData('title'));
    $rate-&gt;setMethod('large');
    $rate-&gt;setMethodTitle('Standard delivery');
    $rate-&gt;setPrice(1.23);
    $rate-&gt;setCost(0);
 
    return $rate;
}
</code></pre>
<p>功能类已经完成。我们最后通过system.xml文件来添加后台配置。这里是代码的缩略版：</p>
<pre><code>
&lt;config&gt;
    &lt;sections&gt;
        &lt;carriers&gt;
            &lt;groups&gt;
                &lt;alwayly_shipping translate="label"&gt;
                    ...
                    &lt;fields&gt;
                        &lt;active translate="label"&gt;
                            ...
                        &lt;/active&gt;
                        &lt;title translate="label"&gt;
                            ...
                        &lt;/title&gt;
                        &lt;sallowspecific translate="label"&gt;
                            ...
                            &lt;frontend_type&gt;select&lt;/frontend_type&gt;
                            &lt;frontend_class&gt;shipping-applicable-country&lt;/frontend_class&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_shipping_allspecificcountries&lt;/source_model&gt;
                            ...
                        &lt;/sallowspecific&gt;
                        &lt;specificcountry translate="label"&gt;
                            ...
                            &lt;frontend_type&gt;multiselect&lt;/frontend_type&gt;
                            &lt;source_model&gt;adminhtml/system_config_source_country&lt;/source_model&gt;
                            ...
                        &lt;/specificcountry&gt;
                        &lt;express_max_weight translate="label"&gt;
                            ...
                        &lt;/express_max_weight&gt;
                    &lt;/fields&gt;
                &lt;/alwayly_shipping&gt;
            &lt;/groups&gt;
        &lt;/carriers&gt;
    &lt;/sections&gt;
&lt;/config&gt;
</code></pre>
<p>值得注意的是，active, title, sallowspecific 和specificcountry是被Magento自动处理的。所以除了把这些添加到后台外你什么也不用做。这里有两个有趣的选项，第一个是sallowspecific，告诉Magento运营商是否对所有国家可用，或者只针对specificcountry中指定的国家。这样，在支付页面添加邮寄方式的需求就实现了。</p>
<p><strong>声明：这篇文章原文写于2009。</strong></p>
<p>360团队与您同在</p>]]></description>
      <pubDate>Fri, 28 Aug 2015 12:49:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在提示框里显示Magento表单验证错误信息]]></title>
      <link>https://www.360magento.com/blog/show-validation-error-messages/</link>
      <description><![CDATA[<p><img alt="" src="http://7xjryy.com1.z0.glb.clouddn.com/messages.jpg" height="240" width="609" /></p>
<p>这是一个小技巧，它可以快速地提高你的表单验证错误信息，并且在提示框里显示。</p>
<p>这里不需要做任何的模版修改，你所要做的只是编辑你的CSS文件，用自定义代码来更新它。</p>
<p>当错误信息被触发，Magento会注入一个class为"validation-advice"的div，这就是我们要在Css文件中修改的class。</p>
<p>它必须相对于它的容器（input-box）来绝对定位。</p>
<p>所以，在你的styles.css文件中找到class .validation-advice（大约在300行左右），用以下的代码来替代它：</p>
<pre><code>
/* Form Validation */
.input-box {
	position: relative !important;
}
.validation-advice {
	background: #DB6D00;
	bottom: -7px;
	color: #fff;
	font-size: 11px;
	font-weight: bold;
	line-height: 13px;
	min-height: 13px;
	padding: 10px;
	position: absolute;
	right: -150px;
	width: 120px;
	border-radius: 5px;
	box-shadow: 0 0 4px rgba(0, 0, 0, 0.5);
 
}
.validation-advice:after {
	position: absolute;
	left: -8px;
	bottom: 8px;
	content: " ";
	width: 0;
	height: 0;
	border-top: 8px solid transparent;
	border-bottom: 8px solid transparent;
	border-right: 8px solid #DB6D00;
}
</code></pre>
<p>请注意这段代码应该重写&ldquo;.validation-advice&rdquo; class并作用于Magento默认的主题。如果你有不同的主题，这段代码可能显示的效果不一样。</p>
<p>360团队与您同在&hellip;&hellip;</p>]]></description>
      <pubDate>Fri, 28 Aug 2015 12:41:45 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中获取当前用户角色]]></title>
      <link>https://www.360magento.com/blog/get-the-current-customer-role/</link>
      <description><![CDATA[<p><img alt="magento获取用户角色" src="http://7xjryy.com1.z0.glb.clouddn.com/customer-group-featured.jpg" height="240" width="609" /></p>
<p>回顾以前些的文章，我有时能找到一些很有用的东西。其中之一是一段代码，它能对指定的客户群进行自定义操作。 在Magento后台，我们可以找到客户群。</p>
<ul>
<li>客户群管理 <strong>Customers-&gt;Customer Groups </strong></li>
<li>修改客户所在的群 <strong>Customers-&gt;Manage Customers-&gt;Click on a customer-&gt;Account Information tab-&gt;Customer group </strong>dropdown</li>
</ul>
<p>首先你要注册你的模型。我假设你已经知道如何完成，或者你已经有现成的可用。</p>
<p>现在，为你的模型创建一个配置文件。我这里使用的示例模型是存在于<strong>'Alwayly'</strong>命名空间下的<strong>'Customergroup&lsquo;</strong>，下面是代码：</p>
<p><strong>app/code/community/Alwayly/Customergroup/etc/config.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Customergroup&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
        &lt;/Alwayly_Customergroup&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;events&gt;
            &lt;controller_action_layout_generate_blocks_after&gt;
                &lt;observers&gt;
                    &lt;alwayly_customergroup&gt;
                        &lt;type&gt;singleton&lt;/type&gt;
                        &lt;class&gt;alwayly_Customergroup_Model_Observer&lt;/class&gt;
                        &lt;method&gt;placeCustomJs&lt;/method&gt;
                    &lt;/alwayly_customergroup&gt;
                &lt;/observers&gt;
            &lt;/controller_action_layout_generate_blocks_after&gt;
        &lt;/events&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>然后，我们创建观察者。</p>
<p><strong>app/code/community/Alwayly/Customergroup/Model/Observer.php</strong></p>
<pre><code>
&lt;?php
class Alwayly_Customergroup_Model_Observer
{
    public function placeCustomJs()
    {
 
        $roleId = Mage::getSingleton('customer/session')-&gt;getCustomerGroupId();
        $role = Mage::getSingleton('customer/group')-&gt;load($roleId)-&gt;getData('customer_group_code');
        $role = strtolower($role);
 
        $headBlock = Mage::app()-&gt;getLayout()-&gt;getBlock('head');
        if($headBlock &amp;&amp; $role=='wholesale')
        {
            $headBlock-&gt;addJs('test/myScript.js');
        }
        return $this;
    }
}
</code></pre>
<p>我展示只是一种用例。你可以在任何合适的地方使用它。比如给特定的用户组显示一条信息，一个不一样的订阅框，等等&hellip;&hellip;</p>
<p>一定要注意：如果用户没有登录，<strong>$role</strong>将会等于<strong> &lsquo;not logged in&lsquo;。</strong></p>
<p><strong>声明：这篇文章最初写于2009年，如有问题请及时联系我们。</strong></p>
<p><strong>360magento团队期待与您的相会:)</strong></p>]]></description>
      <pubDate>Thu, 27 Aug 2015 08:08:55 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[ Magento中添加自定义信用卡类型到支付方式]]></title>
      <link>https://www.360magento.com/blog/adding-custom-credit-card-type/</link>
      <description><![CDATA[<p><img alt="添加自定义信用卡类型" src="http://7xjryy.com1.z0.glb.clouddn.com/credit-card.jpg" height="240" width="609" /></p>
<p>在某一时刻，你也许会在Magento中添加一个自定义的信用卡支付方式。请注意，在这篇Magento教程里，你将学会如何创建和验证一个新的信 用卡类型。另外，本文并不包括整个的创建支付模型过程。</p>
<p>根据这篇文章提到的需求，我们假设要创建的支付模型名字为<strong>NewModule</strong>，对应 <strong>app/etc/modules/Alwayly_NewModule.xml</strong>文件。我们将要创建<strong>Diners Club</strong>信用卡，并在服务器端和客户端 用Magento方式进行验证。</p>
<h2>步骤</h2>
<p>这里只需要几步来实现这件神奇的事。当然，每一步都至关重要。</p>
<ul>
<li>在我们的config.xml文件中添加新的信用卡类型到global payment节点；</li>
<li>让Magento识别我们所用的支付模型</li>
<li>在我们的模型里实现服务器端的验证</li>
<li>实现客户端的验证</li>
</ul>
<h2>添加新的信用卡类型</h2>
<p>让我们创建<strong>etc/config.xml</strong>，添加下面的代码来添加信用卡类型：</p>
<pre><code>
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_NewModule&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
       &lt;/Alwayly_NewModule&gt;
    &lt;/modules&gt;
 
    &lt;global&gt;
        &lt;payment&gt;
            &lt;cc&gt;
                &lt;types&gt;
                    &lt;DC&gt;
                        &lt;code&gt;DC&lt;/code&gt;
                        &lt;name&gt;Diners Club&lt;/name&gt;
                        &lt;order&gt;60&lt;/order&gt;
                    &lt;/DC&gt;
                &lt;/types&gt;
            &lt;/cc&gt;
        &lt;/payment&gt;
    &lt;/global&gt;
&lt;/config&gt;
</code></pre>
<p>到这里，我们只是添加了一个信用卡类型到Magento，并没有说明它所用的模型以及如何验证它。</p>
<h2>创建支付模型</h2>
<p>让我添加一些代码到<strong>etc/config.xml</strong>来配置我们的模型并告知Magento，代码如下:</p>
<pre><code>
&lt;config&gt;
  ...
    &lt;global&gt;
      ...
        &lt;models&gt;
            &lt;newmodule&gt;
                &lt;class&gt;Alwayly_NewModule_Model&lt;/class&gt;
            &lt;/newmodule&gt;
        &lt;/models&gt;
      ...
    &lt;/global&gt;
 
    &lt;default&gt;
        &lt;payment&gt;
            &lt;newmodule&gt;
                &lt;model&gt;newmodule/payment&lt;/model&gt;
            &lt;/newmodule&gt;
        &lt;/payment&gt;
    &lt;/default&gt;
&lt;/config&gt;
</code></pre>
<p>现在，我们要创建<strong>Alwayly/NewModule/Model/Payment.php</strong>文件。包含扩展了<strong>Mage_Payment_Model_Method_Cc</strong>的类。在这个文件中，我们要将自己定义的正则表达式应用到信用卡号和CVV（信用卡验证码）。如果你想实现一个不同的信用卡类型，你就需要一个与之匹配的正则表达式。</p>
<pre><code>
class Alwayly_NewModule_Model_Payment extends Mage_Payment_Model_Method_Cc
{
    protected $_code = 'alwayly_newmodule';
 
    public function getVerificationRegEx()
    {
        return array_merge(parent::getVerificationRegEx(), array(
            'DC' =&gt; '/^[0-9]{3}$/' // Diners Club CCV
       ));
    }
 
    public function OtherCcType($type)
    {
        return in_array($type, array('OT', 'DC'));
    }
 
    public function validate()
    {
        parent::validate();
        /* we call parent's validate() function!
         * if the code got this far, it means the cc type is none of the supported
         * ones implemented by Magento and now it gets interesting
         */
 
        $info = $this-&gt;getInfoInstance();
        $ccNumber = $info-&gt;getCcNumber();
        $availableTypes = explode(',',$this-&gt;getConfigData('cctypes'));
        // checks if Diners Club card is allowed
        if(!in_array($info-&gt;getCcType(), $availableTypes)){
            Mage::throwException($this-&gt;_getHelper()-&gt;__('Credit card type is not allowed for this payment method.'));
        }
        // validate credit card number against Luhn algorithm
        if(!$this-&gt;validateCcNum($info-&gt;getCcNumber())){
            Mage::throwException($this-&gt;_getHelper()-&gt;__('Invalid Credit Card Number'));
        }
 
        /* this is Diners Club regex pattern.
         * it's different for every cc type, so beware
         */
        if($info-&gt;getCcType()=='DC' &amp;&amp; !preg_match('/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/', $ccNumber)){
            Mage::throwException($this-&gt;_getHelper()-&gt;__('Credit card number mismatch with credit card type.'));
        }
        // now we retrieve our CCV regex pattern and validate against it
        $verificationRegex = $this-&gt;getVerificationRegEx();
        if(!preg_match($verificationRegex[$info-&gt;getCcType()], $info-&gt;getCcCid()))
        {
            Mage::throwException($this-&gt;_getHelper()-&gt;__('Please enter a valid credit card verification number.'));
        }
 
        // further validation here (expiration month, expiration year etc.)
 
    }
 
}
</code></pre>
<p>现在，总结一下我们的Diners Club卡号和验证码部分。你可能会想对<strong>validate()</strong>方法进一步验证，例如信用卡的到期时间。</p>
<p>客户端验证 这里有两种方法可以完成这个功能。 第一种是创建一个.js文件并用布局XML包含到我们想要的地方。第二种只需要修改布局文件。 这里我们将采用第二种方式。</p>
<pre><code>
&lt;config&gt;
  ...
    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;newmodule&gt;
                    &lt;file&gt;newmodule.xml&lt;/file&gt;
                &lt;/newmodule&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>是时候修改布局文件并引入javascript到<strong>checkout onepage</strong>。如果在此之前你没创建布局文件，那么用下面的代码创建它。</p>
<p><strong>design/frontend/base/default/layout/newmodule.xml</strong></p>
<pre><code>
&lt;layout version="1.0.0"&gt;
    &lt;checkout_onepage_index&gt;
        &lt;reference name="head"&gt;
            &lt;block type="core/text" name="newmodule.diners.validation"&gt;
                &lt;action method="setText"&gt;
                    &lt;text&gt;
                        &lt;![CDATA[&lt;script type="text/javascript"&gt;
                            Validation.creditCartTypes.set('DC', [new RegExp('^3(?:0[0-5]|[68][0-9])[0-9]{11}$'), new RegExp('^[0-9]{3}$'), true]);
                        &lt;/script&gt;]]&gt;
                    &lt;/text&gt;
                &lt;/action&gt;
            &lt;/block&gt;
        &lt;/reference&gt;
    &lt;/checkout_onepage_index&gt;
&lt;/layout&gt;
</code></pre>
<p>在我们NewModule的<strong>config.xml</strong>中，我应该把Diners Club加入到许可的信用卡类型列表里。</p>
<pre><code>
&lt;config&gt;
    ...
    &lt;default&gt;
        &lt;payment&gt;
            &lt;newmodule&gt;
                &lt;model&gt;newmodule/payment&lt;/model&gt;
                &lt;cctypes&gt;VI,AE,DC&lt;/cctypes&gt; //Visa (VI), American Express (AE) and Diners Club (DC)
            &lt;/newmodule&gt;
        &lt;/payment&gt;
    &lt;/default&gt;
&lt;/config&gt;
</code></pre>
<p>大功告成！我们成功地在Magento中添加了一个自定义信用卡类型。</p>
<p><strong>360magento团队</strong>竭诚为您服务:)</p>]]></description>
      <pubDate>Thu, 27 Aug 2015 03:28:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中去掉产品图片留白的方法]]></title>
      <link>https://www.360magento.com/blog/remove-white-image-frame/</link>
      <description><![CDATA[<p><img alt="magento去图片留白" src="http://7xjryy.com1.z0.glb.clouddn.com/white-frame.jpg" height="100" width="620" /></p>
<p>Magento有漂亮整洁的助手能输出你的产品照片。今天，我的一位同事在尝试侧边栏展示调整后的图片时，对图片的留白有些不太顺心。他尝试过的一种解决方式是用CSS。然而，这里有一个更好的办法来去掉调整后图片周围的留白。</p>
<p>这个实用例子中的代码来自默认的media.phtml</p>
<p><strong>app/design/frontend/default/you_theme/template/catalog/product/view/media.phtml</strong></p>
<pre><code>
&lt;?php foreach ($this-&gt;getGalleryImages() as $_image): ?&gt;
    &lt;li&gt;
        &lt;a href="#" onclick="popWin('&lt;?php echo $this-&gt;getGalleryUrl($_image) ?&gt;', 'gallery', 'width=300,height=300,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes'); return false;" title="&lt; ?php echo $this-&gt;htmlEscape($_image-&gt;getLabel()) ?&gt;"&gt;<br />            &lt;img src="&lt;?php echo $this-&gt;helper('catalog/image')-&gt;init($this-&gt;getProduct(), 'thumbnail', $_image-&gt;getFile())-&gt;resize(56); ?&gt;" width="56" height="56" alt="&lt;?php echo $this-&gt;htmlEscape($_image-&gt;getLabel()) ?&gt;" /&gt;<br />        &lt;/a&gt;
    &lt;/li&gt;
&lt;?php endforeach; ?&gt;
</code></pre>
<p>将它改变成这样将会产生一个&ldquo;框架自由&rdquo;图片</p>
<pre><code>
&lt;?php foreach ($this-&gt;getGalleryImages() as $_image): ?&gt;
    &lt;li&gt;
        &lt;a href="#" onclick="popWin('&lt;?php echo $this-&gt;getGalleryUrl($_image) ?&gt;', 'gallery', 'width=300,height=300,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes'); return false;" title="&lt;?php echo $this-&gt;htmlEscape($_image-&gt;getLabel()) ?&gt;"&gt;<br />            &lt;img src="&lt;?php echo $this-&gt;helper('catalog/image')-&gt;init($this-&gt;getProduct(), 'thumbnail', $_image-&gt;getFile())-&gt;keepFrame(false)-&gt;resize(56); ?&gt;" alt="&lt;?php echo $this-&gt;htmlEscape($_image-&gt;getLabel()) ?&gt;" /&gt;<br />        &lt;/a&gt;
    &lt;/li&gt;
&lt;?php endforeach; ?&gt;
</code></pre>
<p>如你所见，我们所做的只是在<strong>resize()</strong>方法前面添加<strong>keepFrame(false)</strong>方法。</p>
<p>这就是脚本修改前后的结果。</p>
<p><img alt="修改前" src="http://7xjryy.com1.z0.glb.clouddn.com/mwf1-150x110.png" height="110" width="150" /> <img alt="magento修改后" src="http://inchoo.net/wp-content/uploads/2010/03/mwf2-150x114.png" height="114" width="150" /></p>
<p>希望它可以解决一些细微的样式问题。</p>
<p>360Magento团队期待与您的沟通:)</p>]]></description>
      <pubDate>Wed, 26 Aug 2015 10:44:14 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中如何添加自定义产品关系]]></title>
      <link>https://www.360magento.com/blog/add-custom-product-relations/</link>
      <description><![CDATA[<p><img alt="magento自定义产品关系" src="http://7xjryy.com1.z0.glb.clouddn.com/inchoo-customlinkedproducts.jpg" height="240" width="609" /></p>
<p>目前，在Magento中有三中产品关系：Up-sells, Related Products,和Cross-sell Products。最近在讨论客户需求的时候，我们发现在Magento中创建独立的自定义产品关系能更好地实现我们的目的。在这篇文章中，我将演示如何增加自定义的Magento产品关系.</p>
<h2>简介</h2>
<p>下面，我将用Magento插件中的代码来说明一下在Magento中添加自定义产品关系的过程。</p>
<h2>安装脚本程序</h2>
<p>首先，要让Magento数据库知道我们新的产品链接类型。以下是安装脚本： <strong>app/code/community/Alwayly/CustomLinkedProducts/sql/alwayly_customlinkedproducts_setup/install-0.0.1.php</strong></p>
<pre><code>
&lt;?php
 
$installer = $this;
 
/**
 * Install product link types
 */
$data = array(
    array(
        'link_type_id'  =&gt; Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link::LINK_TYPE_CUSTOM,
        'code'          =&gt; 'custom'
    )
);
 
foreach ($data as $bind) {
    $installer-&gt;getConnection()-&gt;insertForce($installer-&gt;getTable('catalog/product_link_type'), $bind);
}
 
/**
 * Install product link attributes
 */
$data = array(
    array(
        'link_type_id'                  =&gt; Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link::LINK_TYPE_CUSTOM,
        'product_link_attribute_code'   =&gt; 'position',
        'data_type'                     =&gt; 'int'
    )
);
 
$installer-&gt;getConnection()-&gt;insertMultiple($installer-&gt;getTable('catalog/product_link_attribute'), $data);
</code></pre>
<h2>后台界面</h2>
<p>下一步就是在后台产品信息页添加新标签。下面是相关的PHP代码，稍后我们会用我们的XML文件将它添加到布局。 <strong>app/code/community/Alwayly/CustomLinkedProducts/Block/Adminhtml/Catalog/Product/Edit/Tab.php</strong></p>
<pre><code>
&lt;?php

class Alwayly_CustomLinkedProducts_Block_Adminhtml_Catalog_Product_Edit_Tab
extends Mage_Adminhtml_Block_Widget
implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
    public function canShowTab() 
    {
        return true;
    }
 
    public function getTabLabel() 
    {
        return $this-&gt;__('Custom Linked Products');
    }
 
    public function getTabTitle()        
    {
        return $this-&gt;__('Custom Linked Products');
    }
 
    public function isHidden()
    {
        return false;
    }
 
    public function getTabUrl() 
    {
        return $this-&gt;getUrl('*/*/custom', array('_current' =&gt; true));
    }
 
    public function getTabClass()
    {
        return 'ajax';
    }
 
}
</code></pre>
<p>因为我们的标签指向&lsquo;*/*/custom&rsquo;路由，所以我们需要将它添加到<strong>Mage_Adminhtml_Catalog_ProductController</strong>。以下是代码： <strong>app/code/community/Alwayly/CustomLinkedProducts/controllers/Adminhtml/Catalog/ProductController.php</strong></p>
<pre><code>&lt;?php
 
require_once(Mage::getModuleDir('controllers','Mage_Adminhtml').DS.'Catalog'.DS.'ProductController.php');
 
class Alwayly_CustomLinkedProducts_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Catalog_ProductController
{
    /**
     * Get custom products grid and serializer block
     */
    public function customAction()
    {
        $this-&gt;_initProduct();
        $this-&gt;loadLayout();
        $this-&gt;getLayout()-&gt;getBlock('catalog.product.edit.tab.custom')
            -&gt;setProductsCustom($this-&gt;getRequest()-&gt;getPost('products_custom', null));
        $this-&gt;renderLayout();
    }
 
    /**
     * Get custom products grid
     */
    public function customGridAction()
    {
        $this-&gt;_initProduct();
        $this-&gt;loadLayout();
        $this-&gt;getLayout()-&gt;getBlock('catalog.product.edit.tab.custom')
            -&gt;setProductsRelated($this-&gt;getRequest()-&gt;getPost('products_custom', null));
        $this-&gt;renderLayout();
    }
 
}
</code></pre>
<p>为了将我们的新标签添加到后台，也为了<strong>getBlock(&lsquo;catalog.product.edit.tab.custom&rsquo;)</strong>方法能作用于<strong>customAction()</strong>和<strong>customGridAction()。</strong>我们需要在我们的布局里添加一点XML代码。</p>
<pre><code>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
 
&lt;layout&gt;
 
    &lt;adminhtml_catalog_product_edit&gt;
        &lt;reference name="product_tabs"&gt;
            &lt;action method="addTab"&gt;
                &lt;name&gt;custom&lt;/name&gt;
                &lt;block&gt;alwayly_customlinkedproducts/adminhtml_catalog_product_edit_tab&lt;/block&gt;
           &lt;/action&gt;
        &lt;/reference&gt;
    &lt;/adminhtml_catalog_product_edit&gt;
 
    &lt;adminhtml_catalog_product_custom&gt;
       &lt;block type="core/text_list" name="root" output="toHtml"&gt;
            &lt;block type="alwayly_customlinkedproducts/adminhtml_catalog_product_edit_tab_custom" name="catalog.product.edit.tab.custom"/&gt;
            &lt;block type="adminhtml/widget_grid_serializer" name="custom_grid_serializer"&gt;
                &lt;reference name="custom_grid_serializer"&gt;
                    &lt;action method="initSerializerBlock"&gt;
                        &lt;grid_block_name&gt;catalog.product.edit.tab.custom&lt;/grid_block_name&gt;
                        &lt;data_callback&gt;getSelectedCustomProducts&lt;/data_callback&gt;
                        &lt;hidden_input_name&gt;links[custom]products_custom</code></pre>
<p>接着我们要为我们的自定义产品关系标签创建一个网格，让它可以在后台显示。这有大量的代码，但大部分都是些基础的代码。唯一你所要注意的是在<strong>_prepareCollection()</strong>功能中使用<strong>useCustomLinks()。</strong>下面是代码：</p>
<pre><code>
&lt;?php

class Alwayly_CustomLinkedProducts_Block_Adminhtml_Catalog_Product_Edit_Tab_Custom extends Mage_Adminhtml_Block_Widget_Grid
{
    /**
     * Set grid params
     *
     */
    public function __construct()
    {
        parent::__construct();
        $this-&gt;setId('custom_product_grid');
        $this-&gt;setDefaultSort('entity_id');
        $this-&gt;setUseAjax(true);
        if ($this-&gt;_getProduct()-&gt;getId()) {
            $this-&gt;setDefaultFilter(array('in_products' =&gt; 1));
        }
        if ($this-&gt;isReadonly()) {
            $this-&gt;setFilterVisibility(false);
        }
    }
    /**
     * Retirve currently edited product model
     *
     * @return Mage_Catalog_Model_Product
     */
    protected function _getProduct()
    {
        return Mage::registry('current_product');
    }
    /**
     * Add filter
     *
     * @param object $column
     * @return Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Custom
     */
    protected function _addColumnFilterToCollection($column)
    {
        // Set custom filter for in product flag
        if ($column-&gt;getId() == 'in_products') {
            $productIds = $this-&gt;_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column-&gt;getFilter()-&gt;getValue()) {
                $this-&gt;getCollection()-&gt;addFieldToFilter('entity_id', array('in' =&gt; $productIds));
            } else {
                if($productIds) {
                    $this-&gt;getCollection()-&gt;addFieldToFilter('entity_id', array('nin' =&gt; $productIds));
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }
    /**
     * Prepare collection
     *
     * @return Mage_Adminhtml_Block_Widget_Grid
     */
    protected function _prepareCollection()
    {
        $collection = Mage::getModel('catalog/product_link')-&gt;useCustomLinks()
            -&gt;getProductCollection()
            -&gt;setProduct($this-&gt;_getProduct())
            -&gt;addAttributeToSelect('*');
        if ($this-&gt;isReadonly()) {
            $productIds = $this-&gt;_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = array(0);
            }
            $collection-&gt;addFieldToFilter('entity_id', array('in' =&gt; $productIds));
        }
        $this-&gt;setCollection($collection);
        return parent::_prepareCollection();
    }
    /**
     * Checks when this block is readonly
     *
     * @return boolean
     */
    public function isReadonly()
    {
        return $this-&gt;_getProduct()-&gt;getCustomReadonly();
    }
    /**
     * Add columns to grid
     *
     * @return Mage_Adminhtml_Block_Widget_Grid
     */
    protected function _prepareColumns()
    {
        if (!$this-&gt;isReadonly()) {
            $this-&gt;addColumn('in_products', array(
                'header_css_class'  =&gt; 'a-center',
                'type'              =&gt; 'checkbox',
                'name'              =&gt; 'in_products',
                'values'            =&gt; $this-&gt;_getSelectedProducts(),
                'align'             =&gt; 'center',
                'index'             =&gt; 'entity_id'
            ));
        }
        $this-&gt;addColumn('entity_id', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('ID'),
            'sortable'  =&gt; true,
            'width'     =&gt; 60,
            'index'     =&gt; 'entity_id'
        ));
        $this-&gt;addColumn('name', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Name'),
            'index'     =&gt; 'name'
        ));
        $this-&gt;addColumn('type', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Type'),
            'width'     =&gt; 100,
            'index'     =&gt; 'type_id',
            'type'      =&gt; 'options',
            'options'   =&gt; Mage::getSingleton('catalog/product_type')-&gt;getOptionArray(),
        ));
        $sets = Mage::getResourceModel('eav/entity_attribute_set_collection')
            -&gt;setEntityTypeFilter(Mage::getModel('catalog/product')-&gt;getResource()-&gt;getTypeId())
            -&gt;load()
            -&gt;toOptionHash();
        $this-&gt;addColumn('set_name', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Attrib. Set Name'),
            'width'     =&gt; 130,
            'index'     =&gt; 'attribute_set_id',
            'type'      =&gt; 'options',
            'options'   =&gt; $sets,
        ));
        $this-&gt;addColumn('status', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Status'),
            'width'     =&gt; 90,
            'index'     =&gt; 'status',
            'type'      =&gt; 'options',
            'options'   =&gt; Mage::getSingleton('catalog/product_status')-&gt;getOptionArray(),
        ));
        $this-&gt;addColumn('visibility', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('Visibility'),
            'width'     =&gt; 90,
            'index'     =&gt; 'visibility',
            'type'      =&gt; 'options',
            'options'   =&gt; Mage::getSingleton('catalog/product_visibility')-&gt;getOptionArray(),
        ));
        $this-&gt;addColumn('sku', array(
            'header'    =&gt; Mage::helper('catalog')-&gt;__('SKU'),
            'width'     =&gt; 80,
            'index'     =&gt; 'sku'
        ));
        $this-&gt;addColumn('price', array(
            'header'        =&gt; Mage::helper('catalog')-&gt;__('Price'),
            'type'          =&gt; 'currency',
            'currency_code' =&gt; (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE),
            'index'         =&gt; 'price'
        ));
        $this-&gt;addColumn('position', array(
            'header'            =&gt; Mage::helper('catalog')-&gt;__('Position'),
            'name'              =&gt; 'position',
            'type'              =&gt; 'number',
            'validate_class'    =&gt; 'validate-number',
            'index'             =&gt; 'position',
            'width'             =&gt; 60,
            'editable'          =&gt; !$this-&gt;_getProduct()-&gt;getCustomReadonly(),
            'edit_only'         =&gt; !$this-&gt;_getProduct()-&gt;getId()
        ));
        return parent::_prepareColumns();
    }
    /**
     * Rerieve grid URL
     *
     * @return string
     */
    public function getGridUrl()
    {
        return $this-&gt;getData('grid_url')
            ? $this-&gt;getData('grid_url')
            : $this-&gt;getUrl('*/*/customGrid', array('_current' =&gt; true));
    }
    /**
     * Retrieve selected custom products
     *
     * @return array
     */
    protected function _getSelectedProducts()
    {
        $products = $this-&gt;getProductsCustom();
        if (!is_array($products)) {
            $products = array_keys($this-&gt;getSelectedCustomProducts());
        }
        return $products;
    }
    /**
     * Retrieve custom products
     *
     * @return array
     */
    public function getSelectedCustomProducts()
    {
        $products = array();
        foreach (Mage::registry('current_product')-&gt;getCustomProducts() as $product) {
            $products[$product-&gt;getId()] = array('position' =&gt; $product-&gt;getPosition());
        }
        return $products;
    }
}
</code></pre>
<p>Magento后台中管理自定义产品关系的界面是这样的：</p>
<p><img style="margin: 0 auto;" alt="magento自定义产品关系后台" src="http://7xjryy.com1.z0.glb.clouddn.com/inchoo-customlinkedproducts-admin-600x418.png" height="418" width="600" /></p>
<h2>后端支持代码</h2>
<p>正如你注意到的，<strong>useCustomLinks()</strong>方法在<strong>catalog/product_link</strong>模型中是不存在的。因此，我们需要重写这个模型来添加我们自定义产品关系的功能。</p>
<p><strong>app/code/community/Alwayly/CustomLinkedProducts/Model/Catalog/Product/Link.php</strong></p>
<pre><code>
&lt;?php
 
class Alwayly_CustomLinkedProducts_Model_Catalog_Product_Link extends Mage_Catalog_Model_Product_Link
{
    const LINK_TYPE_CUSTOM   = 6;
 
    /**
     * @return Mage_Catalog_Model_Product_Link
     */
    public function useCustomLinks()
    {
        $this-&gt;setLinkTypeId(self::LINK_TYPE_CUSTOM);
        return $this;
    }
 
    /**
     * Save data for product relations
     *
     * @param   Mage_Catalog_Model_Product $product
     * @return  Mage_Catalog_Model_Product_Link
     */
    public function saveProductRelations($product)
    {
        parent::saveProductRelations($product);
 
        $data = $product-&gt;getCustomLinkData();
        if (!is_null($data)) {
            $this-&gt;_getResource()-&gt;saveProductLinks($product, $data, self::LINK_TYPE_CUSTOM);
        }
 
    }
}
</code></pre>
<p>如果你想要在同一个Magento项目中再添加一个自定义关系，那么你需要增加<strong>LINK_TYPE_CUSTOM</strong>类常量来避免冲突。现在，你也许注意到<strong>catalog/product</strong>中没有<strong>getCustomLinkData()</strong>功能。别怕，下面这段代码能解决这个问题：</p>
<p><strong>app/code/community/Alwayly/CustomLinkedProducts/Model/Catalog/Product.php</strong></p>
<pre><code>
&lt;?php
 
class Alwayly_CustomLinkedProducts_Model_Catalog_Product extends Mage_Catalog_Model_Product
{
    /**
     * Retrieve array of custom products
     *
     * @return array
     */
    public function getCustomProducts()
    {
        if (!$this-&gt;hasCustomProducts()) {
            $products = array();
            $collection = $this-&gt;getCustomProductCollection();
            foreach ($collection as $product) {
                $products[] = $product;
            }
            $this-&gt;setCustomProducts($products);
        }
        return $this-&gt;getData('custom_products');
    }
 
    /**
     * Retrieve custom products identifiers
     *
     * @return array
     */
    public function getCustomProductIds()
    {
        if (!$this-&gt;hasCustomProductIds()) {
            $ids = array();
            foreach ($this-&gt;getCustomProducts() as $product) {
                $ids[] = $product-&gt;getId();
            }
            $this-&gt;setCustomProductIds($ids);
        }
        return $this-&gt;getData('custom_product_ids');
    }
 
    /**
     * Retrieve collection custom product
     *
     * @return Mage_Catalog_Model_Resource_Product_Link_Product_Collection
     */
    public function getCustomProductCollection()
    {
        $collection = $this-&gt;getLinkInstance()-&gt;useCustomLinks()
            -&gt;getProductCollection()
            -&gt;setIsStrongMode();
        $collection-&gt;setProduct($this);
        return $collection;
    }
 
    /**
     * Retrieve collection custom link
     *
     * @return Mage_Catalog_Model_Resource_Product_Link_Collection
     */
    public function getCustomLinkCollection()
    {
        $collection = $this-&gt;getLinkInstance()-&gt;useCustomLinks()
            -&gt;getLinkCollection();
        $collection-&gt;setProduct($this);
        $collection-&gt;addLinkTypeIdFilter();
        $collection-&gt;addProductIdFilter();
        $collection-&gt;joinAttributes();
        return $collection;
    }
 
}
</code></pre>
<p>还有一件重要的事情要完成：保存我们的产品关系并让它作用于产品。我们需要粘贴<strong>catalog_product_prepare_save</strong>和<strong>catalog_model_product_duplicate</strong>事件。下面是回调了这些事件的观察员类。</p>
<pre><code>
&lt;?php
 
class Alwayly_CustomLinkedProducts_Model_Observer extends Varien_Object
{
    public function catalogProductPrepareSave($observer)
    {
        $event = $observer-&gt;getEvent();
 
        $product = $event-&gt;getProduct();
        $request = $event-&gt;getRequest();
 
        $links = $request-&gt;getPost('links');
        if (isset($links['custom']) &amp;&amp; !$product-&gt;getCustomReadonly()) {
            $product-&gt;setCustomLinkData(Mage::helper('adminhtml/js')-&gt;decodeGridSerializedInput($links['custom']));
        }
    }
 
    public function catalogModelProductDuplicate($observer)
    {
        $event = $observer-&gt;getEvent();
 
        $currentProduct = $event-&gt;getCurrentProduct();
        $newProduct = $event-&gt;getNewProduct();
 
        $data = array();
        $currentProduct-&gt;getLinkInstance()-&gt;useCustomLinks();
        $attributes = array();
        foreach ($currentProduct-&gt;getLinkInstance()-&gt;getAttributes() as $_attribute) {
            if (isset($_attribute['code'])) {
                $attributes[] = $_attribute['code'];
            }
        }
        foreach ($currentProduct-&gt;getCustomLinkCollection() as $_link) {
            $data[$_link-&gt;getLinkedProductId()] = $_link-&gt;toArray($attributes);
        }
        $newProduct-&gt;setCustomLinkData($data);
    }
 
}
</code></pre>
<h2>前台界面</h2>
<p>为了在Magento前端展示我们自定义的产品关系，我把<strong>Magento&rsquo;s related products</strong>块及相关模板文件复制到<strong>alwayly_customrelatedproducts/catalog_product_list_custom</strong>块。我们复制的相关产品块将使用我们定义的产品关系。下面是前端显示效果：</p>
<p><img alt="magento自定义产品关系前台" src="http://7xjryy.com1.z0.glb.clouddn.com/inchoo-customlinkedproducts-frontend-600x417.png" height="417" width="600" /></p>
<p>希望能对你的项目有所帮助。</p>]]></description>
      <pubDate>Wed, 26 Aug 2015 03:19:48 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento中列出特卖产品的方法]]></title>
      <link>https://www.360magento.com/blog/onsale-master/</link>
      <description><![CDATA[<p><img alt="magento特价产品展示" src="http://7xjryy.com1.z0.glb.clouddn.com/onsale_featured2.png" height="210" width="609" /></p>
<p>有些客户想要在首页显示特卖产品，或者有时想要在某个分类中筛选特卖产品。在这篇magento教程中，我将写到两种列出特卖产品的方法：</p>
<ul>
<li>Magento首页作为列表显示；</li>
<li>在产品列表页通过筛选器显示；</li>
</ul>
<p>让我们开始吧！</p>
<h2>静态CMS页面</h2>
<p>使用后台管理员上传一个.phtml文件是一个将特卖产品显示在某个页面的快速方法。用这个方法你将不能使用分页和导航。如果你喜欢这些功 能，我推荐这篇文章的第二部分。</p>
<p>用以下内容创建一个新的CMS page</p>
<pre><span>{</span>{block type="catalog/product_list" template="inchoo/onsale/sale.phtml"}}<br /><br /></pre>
<p>还有一个排列你产品的模版</p>
<p><strong>app/design/frontend/default/YOUR_THEME/template/alwayly/onsale/sale.phtml</strong></p>
<pre><code>&lt;?php
    $_productCollection = Mage::getModel('catalog/product')-&gt;getCollection();
    $_productCollection-&gt;addAttributeToSelect(array(
                                   'image',
                                   'name',
                                   'short_description'
                                              ))
                        -&gt;addFieldToFilter('visibility', array(
                                    Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
                                    Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
                            )) //showing just products visible in catalog or both search and catalog
                        -&gt;addFinalPrice()
//                        -&gt;addAttributeToSort('price', 'asc') //in case we would like to sort products by price
                        -&gt;getSelect()
                        -&gt;where('price_index.final_price &lt; price_index.price')
//                        -&gt;limit(30) //we specify how many products we want to show on this page
//                        -&gt;order(new Zend_Db_Expr('RAND()')) //in case we would like to sort products randomly
                        ;

    Mage::getModel('review/review')-&gt;appendSummary($_productCollection);
    $_helper = $this-&gt;helper('catalog/output');
?&gt;

&lt;?php if(!$_productCollection-&gt;count()): ?&gt;
    &lt;p class="note-msg"&gt;&lt;?php echo $this-&gt;__('There are no products matching the selection.') ?&gt;&lt;/p&gt;
&lt;?php else: ?&gt;
    &lt;div class="category-products"&gt;
        &lt;?php // Grid Mode ?&gt;
        &lt;?php $_collectionSize = $_productCollection-&gt;count() ?&gt;
        &lt;?php $_columnCount = $this-&gt;getColumnCount(); ?&gt;
        &lt;?php $i=0; foreach ($_productCollection as $_product): ?&gt;
        &lt;?php if ($i++%$_columnCount==0): ?&gt;
            &lt;ul class="products-grid" style="padding:0; list-style: none"&gt;
        &lt;?php endif ?&gt;
            &lt;li class="item&lt;?php if(($i-1)%$_columnCount==0): ?&gt; first&lt;?php elseif($i%$_columnCount==0): ?&gt; 

last&lt;?php endif; ?&gt;"&gt;
                &lt;a href="&lt;?php echo $_product-&gt;getProductUrl() ?&gt;" title="&lt;?php echo $this-&gt;stripTags($this-

&gt;getImageLabel($_product, 'small_image'), null, true) ?&gt;" class="product-image"&gt;&lt;img src="&lt;?php echo $_product-

&gt;getImageUrl(); ?&gt;" width="135" height="135" alt="&lt;?php echo $this-&gt;stripTags($this-&gt;getImageLabel($_product, 

'small_image'), null, true) ?&gt;" /&gt;&lt;/a&gt;
                &lt;h2 class="product-name"&gt;&lt;a href="&lt;?php echo $_product-&gt;getProductUrl() ?&gt;" title="&lt;?php 

echo $this-&gt;stripTags($_product-&gt;getName(), null, true) ?&gt;"&gt;&lt;?php echo $_helper-&gt;productAttribute($_product, 

$_product-&gt;getName(), 'name') ?&gt;&lt;/a&gt;&lt;/h2&gt;
                &lt;?php if($_product-&gt;getRatingSummary()): ?&gt;
                    &lt;?php echo $this-&gt;getReviewsSummaryHtml($_product, 'short') ?&gt;
                &lt;?php endif; ?&gt;
                &lt;?php echo $this-&gt;getPriceHtml($_product, true) ?&gt;
                &lt;div class="actions"&gt;
                    &lt;?php if($_product-&gt;isSaleable()): ?&gt;
                        &lt;button type="button" title="&lt;?php echo $this-&gt;__('Add to Cart') ?&gt;" class="button btn-

cart" onclick="setLocation('&lt;?php echo $this-&gt;getAddToCartUrl($_product) ?&gt;')"&gt;&lt;span&gt;&lt;span&gt;&lt;?php 

echo $this-&gt;__('Add to Cart') ?&gt;&lt;/span&gt;&lt;/span&gt;&lt;/button&gt;
                    &lt;?php else: ?&gt;
                        &lt;p class="availability out-of-stock"&gt;&lt;span&gt;&lt;?php echo $this-&gt;__('Out of stock') ?

&gt;&lt;/span&gt;&lt;/p&gt;
                    &lt;?php endif; ?&gt;
                    &lt;ul class="add-to-links"&gt;
                        &lt;?php if ($this-&gt;helper('wishlist')-&gt;isAllow()) : ?&gt;
                            &lt;li&gt;&lt;a href="&lt;?php echo $this-&gt;helper('wishlist')-&gt;getAddUrl($_product) ?&gt;" 

class="link-wishlist"&gt;&lt;?php echo $this-&gt;__('Add to Wishlist') ?&gt;&lt;/a&gt;&lt;/li&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if($_compareUrl=$this-&gt;getAddToCompareUrl($_product)): ?&gt;
                            &lt;li&gt;&lt;span class="separator"&gt;|&lt;/span&gt; &lt;a href="&lt;?php echo $_compareUrl ?

&gt;" class="link-compare"&gt;&lt;?php echo $this-&gt;__('Add to Compare') ?&gt;&lt;/a&gt;&lt;/li&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/ul&gt;
                &lt;/div&gt;
            &lt;/li&gt;
            &lt;?php if ($i%$_columnCount==0 || $i==$_collectionSize): ?&gt;
            &lt;/ul&gt;
        &lt;?php endif ?&gt;
        &lt;?php endforeach ?&gt;
        &lt;script type="text/javascript"&gt;decorateGeneric($$('ul.products-grid'), 

['odd','even','first','last'])&lt;/script&gt;
    &lt;/div&gt;
&lt;?php endif; ?&gt;</code></pre>
<p>完成！尝试一下，然后访问你的CMS页面。你将看到带有特价的产品以列表的形式显示出来，就像这样：</p>
<p><img alt="特卖" src="http://7xjryy.com1.z0.glb.clouddn.com/onsale1-600x579.png" height="579px" width="600px" /></p>
<p>修改一下以后，你也可以以网格的形式展示产品。</p>
<h2>产品列表中的筛选器</h2>
<p>一个集合在被读入模版前，Magento会使用筛选器并读取到分层导航。这就是我们要重写<strong> _getProductCollection</strong>方法的原 因，这样我们就能在集合被读取前使用自定义的筛选器。让我们扩展<strong>Mage_Catalog_Product_List</strong>类和渲染我们的块来替换分 类列表中默认的筛选器。</p>
<p>让我们注册这个模型。根据作用，我们给它命名"Alwayly/Onsale"</p>
<p><strong>app/etc/modules/Alwayly_Onsale.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Onsale&gt;
            &lt;active&gt;true&lt;/active&gt;
            &lt;codePool&gt;local&lt;/codePool&gt;
        &lt;/Alwayly_Onsale&gt;
    &lt;/modules&gt;
&lt;/config&gt;
</code></pre>
<p>接着配置我们的模型。我们将用到块(block)，助手(helper)并对我们模版的布局进行一点修改。</p>
<p><strong>app/code/local/Inchoo/Onsale/etc/config.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Onsale&gt;
            &lt;version&gt;1.0.0.3&lt;/version&gt;
        &lt;/Alwayly_Onsale&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;alwayly_onsale&gt;
                &lt;class&gt;Alwayly_Onsale_Block&lt;/class&gt;
            &lt;/alwayly_onsale&gt;
        &lt;/blocks&gt;
        &lt;helpers&gt;
            &lt;alwayly_onsale&gt;
                &lt;class&gt;Alwayly_Onsale_Helper&lt;/class&gt;
            &lt;/alwayly_onsale&gt;
        &lt;/helpers&gt;
    &lt;/global&gt;
    &lt;frontend&gt;
        &lt;layout&gt;
            &lt;updates&gt;
                &lt;onsale&gt;
                    &lt;file&gt;alwayly/onsale.xml&lt;/file&gt;
                &lt;/onsale&gt;
            &lt;/updates&gt;
        &lt;/layout&gt;
    &lt;/frontend&gt;
&lt;/config&gt;
</code></pre>
<p>现在，注册一个包含<strong>getOnSaleUrl</strong>和<strong>getNotOnSaleUrl</strong>方法的助手。这两个方法将被用来获取我们复选框 中链接的地址。我们将添加一个新的变量-"Sale"到网址。当sale等于1的时候，我们将显示特卖的产品，如果没有被设置就会显示这个类中的所 有产品。</p>
<p><strong>app/code/local/Inchoo/Onsale/Helper/Data.php</strong></p>
<pre>&lt;?php
class Alwayly_Onsale_Helper_Data extends Mage_Core_Helper_Abstract
{
    public function getOnSaleUrl()
    {
        $url = Mage::getUrl('', array(
            '_current' =&gt; true,
            '_use_rewrite' =&gt; true,
            '_query' =&gt; array(
                'sale' =&gt; 1,
                'p' =&gt; NULL
            )
        ));
 
        return $url;
    }
 
    public function getNotOnSaleUrl()
    {
        $url = Mage::getUrl('', array(
            '_current' =&gt; true,
            '_use_rewrite' =&gt; true,
            '_query' =&gt; array(
                'sale' =&gt; NULL,
                'p' =&gt; NULL
            )
        ));
 
        return $url;
    }
}
</pre>
<p>接着让我们创建我们的块。我们将从<strong>Mage_Catalog_Block_Product_List</strong>扩展我们的类并添加 <strong>_getProductCollection</strong>方法。</p>
<p><strong>app/code/local/Alwayly/Onsale/Block/Catalog/Product/List.php</strong></p>
<pre><code>
&lt;?php
class Alwayly_Onsale_Block_Catalog_Product_List extends Mage_Catalog_Block_Product_List
{
    protected function _getProductCollection()
    {
        if (is_null($this-&gt;_productCollection)) {
            $layer = $this-&gt;getLayer();
            /* @var $layer Mage_Catalog_Model_Layer */
            if ($this-&gt;getShowRootCategory()) {
                $this-&gt;setCategoryId(Mage::app()-&gt;getStore()-&gt;getRootCategoryId());
            }
 
            // if this is a product view page
            if (Mage::registry('product')) {
                // get collection of categories this product is associated with
                $categories = Mage::registry('product')-&gt;getCategoryCollection()
                                  -&gt;setPage(1, 1)
                                  -&gt;load();
                // if the product is associated with any category
                if ($categories-&gt;count()) {
                    // show products from this category
                    $this-&gt;setCategoryId(current($categories-&gt;getIterator()));
                }
            }
 
            $origCategory = null;
            if ($this-&gt;getCategoryId()) {
                $category = Mage::getModel('catalog/category')-&gt;load($this-&gt;getCategoryId());
                if ($category-&gt;getId()) {
                    $origCategory = $layer-&gt;getCurrentCategory();
                    $layer-&gt;setCurrentCategory($category);
                    $this-&gt;addModelTags($category);
                }
            }
            $this-&gt;_productCollection = $layer-&gt;getProductCollection();
 
//                inchoo start
            $param = Mage::app()-&gt;getRequest()-&gt;getParam('sale');
            if(isset($param) &amp;&amp; $param==='1'){
                $this-&gt;_productCollection
                    -&gt;addFinalPrice()
                    -&gt;getSelect()
                    -&gt;where('price_index.final_price &lt; price_index.price');
            }
//                inchoo end
 
            $this-&gt;prepareSortableFieldsByCategory($layer-&gt;getCurrentCategory());
 
            if ($origCategory) {
                $layer-&gt;setCurrentCategory($origCategory);
            }
        }
 
        return $this-&gt;_productCollection;
//            return parent::_getProductCollection();
    }
}
<code></code></code></pre>
<p>我们还要在工具栏中添加一个复选框来让顾客筛选特卖产品。打开我们的<strong>toolbar.phtml</strong>文件。</p>
<p><strong>app/design/frontend/default/YOUR_THEME/template/alwayly/onsale/toolbar.phtml</strong></p>
<pre><code>
&lt;!--alwayly start--&gt;
&lt;?php $helper = Mage::helper('alwayly_onsale'); ?&gt;
&lt;!--alwayly end--&gt;
&lt;?php if($this-&gt;getCollection()-&gt;getSize()): ?&gt;
    &lt;div class="toolbar"&gt;
        &lt;div class="pager"&gt;
            &lt;p class="amount"&gt;
                &lt;?php if($this-&gt;getLastPageNum()&gt;1): ?&gt;
                    &lt;?php echo $this-&gt;__('Items %s to %s of %s total', $this-&gt;getFirstNum(), $this-&gt;getLastNum(), 

$this-&gt;getTotalNum()) ?&gt;
                &lt;?php else: ?&gt;
                    <strong>&lt;?php echo $this-&gt;__('%s Item(s)', $this-&gt;getTotalNum()) ?&gt;&lt;/strong&gt;
                &lt;?php endif; ?&gt;
            &lt;/p&gt;
 
            &lt;div class="limiter"&gt;
                &lt;label&gt;&lt;?php echo $this-&gt;__('Show') ?&gt;&lt;/label&gt;
                &lt;select onchange="setLocation(this.value)"&gt;
                    &lt;?php foreach ($this-&gt;getAvailableLimit() as  $_key=&gt;$_limit): ?&gt;
                        &lt;option value="&lt;?php echo $this-&gt;getLimitUrl($_key) ?&gt;"&lt;?php if($this-&gt;isLimitCurrent

($_key)): ?&gt; selected="selected"&lt;?php endif ?&gt;&gt;
                            &lt;?php echo $_limit ?&gt;
                        &lt;/option&gt;
                    &lt;?php endforeach; ?&gt;
                &lt;/select&gt;&lt;?php echo $this-&gt;__('per page') ?&gt;
            &lt;/div&gt;
 
            &lt;?php echo $this-&gt;getPagerHtml() ?&gt;
 
       &lt;/div&gt;
 
        &lt;?php if( $this-&gt;isExpanded() ): ?&gt;
            &lt;div class="sorter"&gt;
                &lt;?php if( $this-&gt;isEnabledViewSwitcher() ): ?&gt;
                    &lt;p class="view-mode"&gt;
                        &lt;?php $_modes = $this-&gt;getModes(); ?&gt;
                        &lt;?php if($_modes &amp;&amp; count($_modes)&gt;1): ?&gt;
                            &lt;label&gt;&lt;?php echo $this-&gt;__('View as') ?&gt;:&lt;/label&gt;
                            &lt;?php foreach ($this-&gt;getModes() as $_code=&gt;$_label): ?&gt;
                                &lt;?php if($this-&gt;isModeActive($_code)): ?&gt;
                                    &lt;strong title="&lt;?php echo $_label ?&gt;" class="&lt;?php echo strtolower($_code); ?

&gt;"&gt;
                                    &lt;?php echo $_label ?&gt;&lt;/strong&gt;&nbsp;
                                    &lt;?php else: ?&gt;
                                    &lt;a href="&lt;?php echo $this-&gt;getModeUrl($_code) ?&gt;" title="&lt;?php echo $_label 

?&gt;" class="&lt;?php echo strtolower($_code); ?&gt;"&gt;&lt;?php echo $_label ?&gt;&nbsp;
                                &lt;?php endif; ?&gt;
                            &lt;?php endforeach; ?&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/p&gt;
                &lt;?php endif; ?&gt;
 
                &lt;div class="sort-by"&gt;
                    &lt;label&gt;&lt;?php echo $this-&gt;__('Sort By') ?&gt;&lt;/label&gt;
                   &lt;select onchange="setLocation(this.value)"&gt;
                        &lt;?php foreach($this-&gt;getAvailableOrders() as $_key=&gt;$_order): ?&gt;
                            &lt;option value="&lt;?php echo $this-&gt;getOrderUrl($_key, 'asc') ?&gt;"&lt;?php if($this-

&gt;isOrderCurrent($_key)): ?&gt; selected="selected"&lt;?php endif; ?&gt;&gt;
                                &lt;?php echo $this-&gt;__($_order) ?&gt;
                            &lt;/option&gt;
                        &lt;?php endforeach; ?&gt;
                    &lt;/select&gt;
                    &lt;?php if($this-&gt;getCurrentDirection() == 'desc'): ?&gt;
                        &lt;a href="&lt;?php echo $this-&gt;getOrderUrl(null, 'asc') ?&gt;" title="&lt;?php echo $this-&gt;__

('Set Ascending Direction') ?&gt;"&gt;&lt;img src="&lt;?php echo $this-&gt;getSkinUrl('images/i_desc_arrow.gif') ?&gt;" 

alt="&lt;?php echo $this-&gt;__('Set Ascending Direction') ?&gt;" class="v-middle" /&gt;&lt;/a&gt;
                    &lt;?php else: ?&gt;
                        &lt;a href="&lt;?php echo $this-&gt;getOrderUrl(null, 'desc') ?&gt;" title="&lt;?php echo $this-&gt;__

('Set Descending Direction') ?&gt;"&gt;&lt;img src="&lt;?php echo $this-&gt;getSkinUrl('images/i_asc_arrow.gif') ?&gt;" 

alt="&lt;?php echo $this-&gt;__('Set Descending Direction') ?&gt;" class="v-middle" /&gt;&lt;/a&gt;
 
                &lt;!--alwayly start--&gt;
                        &lt;label for="sale"&gt;&lt;?php echo $this-&gt;__('On Sale') ?&gt;&lt;/label&gt;
                        &lt;input name="sale" id="sale" type="checkbox"
                            value="&lt;?php
                                $currentUrl = Mage::helper('core/url')-&gt;getCurrentUrl();
                                if($currentUrl===$helper-&gt;getOnSaleUrl()):
                                    echo $helper-&gt;getNotOnSaleUrl();
                                    echo "\"checked=\"checked";
                                else:
                                    echo $helper-&gt;getOnSaleUrl();
                                endif;
                            ?&gt;" autocomplete="off" onchange="setLocation(this.value)"/&gt;
                &lt;!--alwayly end--&gt;
                    &lt;?php endif; ?&gt;
                &lt;/div&gt;
            &lt;/div&gt;
        &lt;?php endif; ?&gt;
    &lt;/div&gt;
&lt;?php endif ?&gt;
&lt;/strong&gt;</strong></code></pre>
<p>最后，创建我们的布局文件来让Magento来使用我们的toolbar.phtml。</p>
<p><strong>app/design/frontend/default/YOUR_THEME/layout/alwayly/onsale.xml</strong></p>
<pre><code>
&lt;?xml version="1.0"?&gt;
 
&lt;layout version="0.1.0"&gt;
    &lt;catalog_category_default&gt;
        &lt;reference name="category.products"&gt;
                &lt;block type="inchoo_onsale/catalog_product_list" name="product_list" template="catalog/product/list.phtml"&gt;
                    &lt;block type="catalog/product_list_toolbar" name="product_list_toolbar" template="inchoo/onsale/toolbar.phtml"&gt;
                        &lt;block type="page/html_pager" name="product_list_toolbar_pager"/&gt;
 
                        &lt;!-- The following code shows how to set your own pager increments --&gt;
                        &lt;!--
                            &lt;action method="setDefaultListPerPage"&gt;&lt;limit&gt;4&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="setDefaultGridPerPage"&gt;&lt;limit&gt;9&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;2&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;4&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;6&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;8&lt;/limit&gt;&lt;/action&gt;
                            &lt;action method="addPagerLimit" translate="label"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;all&lt;/limit&gt;&lt;label&gt;All&lt;/label&gt;&lt;/action&gt;
                        --&gt;
                    &lt;/block&gt;
                    &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;empty&lt;/layout&gt;&lt;count&gt;6&lt;/count&gt;&lt;/action&gt;
                    &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;one_column&lt;/layout&gt;&lt;count&gt;5&lt;/count&gt;&lt;/action&gt;
                    &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;two_columns_left&lt;/layout&gt;&lt;count&gt;4&lt;/count&gt;&lt;/action&gt;
                    &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;two_columns_right&lt;/layout&gt;&lt;count&gt;4&lt;/count&gt;&lt;/action&gt;
                    &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;three_columns&lt;/layout&gt;&lt;count&gt;3&lt;/count&gt;&lt;/action&gt;
                    &lt;action method="setToolbarBlockName"&gt;&lt;name&gt;product_list_toolbar&lt;/name&gt;&lt;/action&gt;
                &lt;/block&gt;
        &lt;/reference&gt;
    &lt;/catalog_category_default&gt;
 
    &lt;catalog_category_layered&gt;
        &lt;reference name="category.products"&gt;
            &lt;block type="inchoo_onsale/catalog_product_list" name="product_list" template="catalog/product/list.phtml"&gt;
                &lt;block type="catalog/product_list_toolbar" name="product_list_toolbar" template="inchoo/onsale/toolbar.phtml"&gt;
                    &lt;block type="page/html_pager" name="product_list_toolbar_pager"/&gt;
 
                    &lt;!-- The following code shows how to set your own pager increments --&gt;
                    &lt;!--
                        &lt;action method="setDefaultListPerPage"&gt;&lt;limit&gt;4&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="setDefaultGridPerPage"&gt;&lt;limit&gt;9&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;2&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;4&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;6&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="addPagerLimit"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;8&lt;/limit&gt;&lt;/action&gt;
                        &lt;action method="addPagerLimit" translate="label"&gt;&lt;mode&gt;list&lt;/mode&gt;&lt;limit&gt;all&lt;/limit&gt;&lt;label&gt;All&lt;/label&gt;&lt;/action&gt;
                    --&gt;
                &lt;/block&gt;
                &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;empty&lt;/layout&gt;&lt;count&gt;6&lt;/count&gt;&lt;/action&gt;
                &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;one_column&lt;/layout&gt;&lt;count&gt;5&lt;/count&gt;&lt;/action&gt;
                &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;two_columns_left&lt;/layout&gt;&lt;count&gt;4&lt;/count&gt;&lt;/action&gt;
                &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;two_columns_right&lt;/layout&gt;&lt;count&gt;4&lt;/count&gt;&lt;/action&gt;
                &lt;action method="addColumnCountLayoutDepend"&gt;&lt;layout&gt;three_columns&lt;/layout&gt;&lt;count&gt;3&lt;/count&gt;&lt;/action&gt;
                &lt;action method="setToolbarBlockName"&gt;&lt;name&gt;product_list_toolbar&lt;/name&gt;&lt;/action&gt;
            &lt;/block&gt;
        &lt;/reference&gt;
    &lt;/catalog_category_layered&gt;
&lt;/layout&gt;
</code></pre>
<p>看看效果：</p>
<p><img alt="显示结果" src="http://7xjryy.com1.z0.glb.clouddn.com/onsale21-600x487.png" height="487px" width="600px" /></p>
<p>我们注意到分层导航和分页一样工作正常。如我们所期待的一样&hellip;&hellip;</p>]]></description>
      <pubDate>Mon, 24 Aug 2015 13:46:52 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中获取指定attribute属性的产品列表]]></title>
      <link>https://www.360magento.com/blog/listing-products-by-attribute/</link>
      <description><![CDATA[<p><img alt="获取自定义属性产品的列表" src="http://7xjryy.com1.z0.glb.clouddn.com/article1.jpg" height="100" width="620" /></p>
<p>这是一个向magento初学者一步一步展示magento如何按属性来列出产品排序的教程. <br />我将以Magento已经创建好的新产品和促销产品功能开始. <br />以下所有说明都是针对Magento1.9.0.0的</p>
<h2>列出带有属性New的产品列表</h2>
<p>在Magento后台管理面板,在Products management里面的Manage products 你能找到设置和定义新的属性。这篇教程中，我将使用名字叫Homepage的CMS Page来作为示例<br />在CMS Page layout -&gt; Layout Update XML里面已经被原有的cms page占据着:</p>
<pre>&lt;reference name="content"&gt;
 
&lt;block type="core/template" name="home" as="home" template="page/home.phtml" &gt;
 
&lt;/block&gt;&lt;/reference&gt;

</pre>
<ol>
<li>首先，通过设置&ldquo;Set Product as New from Date&rdquo;和&ldquo;Set Product as New to Date&rdquo;来定义产品为新产品.</li>
<li>Magento默认已经指定了新产品列表的模板，你可以在app/design/frontend/pro/YourTheme/template/catalog/product/new.phtml这个路径找到它.</li>
<li>在xml布局文件中通过block块结构体来定义你想要在哪里显示新产品模板(new.phtml).</li>
<li>插入新的block块</li>
</ol>
<pre class="ish"><code class="language-html">&lt;reference name="content"&gt;
&nbsp;
&lt;block type="catalog/product_new" name="home.catalog.product.new" 	alias="product_new" as="newproducts"  	after="cms_page" template="catalog/product/new.phtml"&gt;
&lt;action method="setProductsCount"&gt;&lt;count&gt;8&lt;/count&gt;&lt;/action&gt;
&lt;action method="setColumnCount"&gt;&lt;count&gt;4&lt;/count&gt;&lt;/action&gt;
&lt;/block&gt;
&nbsp;
&lt;/reference&gt;</code></pre>
<ol>
<li>指定你想要在哪展示带有新产品模板的块（在哪里调用这个block块）
<pre class="ish"><code class="language-html">&lt; ?php echo $this-&gt;getChildHtml('newproducts') ?&gt;</code></pre>
<p>在我们的案例中,我们把Homepage模板定位于template/page/html/home.phtml</p>
</li>
<li>这就是所有你需要做的.</li>
</ol>
<p>注意:<br /> Content 是一个core/text_list类型 并且他可以支持嵌套所有的block类型.</p>
<p>你可以设置你想要显示多少个产品在magento的前台:</p>
<pre class="ish"><code class="language-html">&lt;action method="setProductsCount"&gt;&lt;count&gt;8&lt;/count&gt;&lt;/action&gt;</code></pre>
<p>和多少列:</p>
<pre class="ish"><code class="language-html">&lt;action method="setColumnCount"&gt;&lt;count&gt;4&lt;/count&gt;4&lt;/action&gt;</code></pre>
<h2>列出所有带有Promotion属性的产品列表</h2>
<p>列出所有带有Promotion属性的产品列表方法在magento中已经存在，这与列出新产品稍微有点不同</p>
<ol>
<li>首先我们需要在Magento后台为产品创建一个属性</li>
<li>创建一个名为&ldquo;Promotion&rdquo;的dropdown (Yes/No)类型的属性</li>
<li>如果你想为所有产品添加属性，那么需要将属性关联到default属性组</li>
<li>复制template/catalog/product/list.phtml文件到同级目录下，改名为promotion.phtml</li>
<li>在XML布局文件中定义block块的位置。在我们的案例中是CMS page下的&ldquo;Homepage&rdquo;&nbsp;
<pre class="ish"><code class="language-html">&lt;block type="catalog/product_list_promotion" name="promotion" template="catalog/product/promotion.phtml" /&gt;</code></pre>
</li>
<li>指定你想要在哪展示带有promotion.phtml模板的块在哪里调用这个block块）
<pre class="ish"><code class="language-html">&lt; ?php echo $this-&gt;getChildHtml('promotion') ?&gt;</code></pre>
<p>在我们的案例中,我们把Homepage模板定位于template/page/html/home.phtml</p>
</li>
</ol>
<h2>列出带有自定义模板和带有dropdown Yes/No类型属性的产品列表</h2>
<p>在这个案例中,我们将用magento的Promotion product方法来修改它.</p>
<ol>
<li>创建新的目录文件app/code/local/Mage/Catalog/Block/Product/List/Example.php</li>
<li>复制app/code/core/Mage/Catalog/Block/Product/List/Promotion.php 并粘贴到Example.php</li>
<li>改变Example.php:</li>
</ol>
<p>&nbsp;</p>
<pre class="ish"><code class="language-html">class Mage_Catalog_Block_Product_List_Promotion extends Mage_Catalog_Block_Product_List</code></pre>
<p>到:</p>
<pre class="ish"><code class="language-html">class Mage_Catalog_Block_Product_List_Example extends Mage_Catalog_Block_Product_List</code></pre>
<p>也要改变:</p>
<pre class="ish"><code class="language-html">$collection-&gt;addAttributeToFilter('promotion', 1)</code></pre>
<p>到:</p>
<pre class="ish"><code class="language-html">$collection-&gt;addAttributeToFilter('example', 1)</code></pre>
<p>之后按照我之前写过Promotion属性的步骤执行。<br />希望这篇教程能对你有所帮助。</p>]]></description>
      <pubDate>Sat, 22 Aug 2015 13:32:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中通过邮件提醒客户下第一个订单]]></title>
      <link>https://www.360magento.com/blog/remind-customers-place-order/</link>
      <description><![CDATA[<img class="attachment-full wp-post-image" alt="Inchoo OrderReminder" src="http://7xjryy.com1.z0.glb.clouddn.com/alwayly-orderreminder.jpg" height="240" width="609" /> <p>在magento建设的网店中，有时客户创建账户后需要一些鼓励来拍下他们的第一个宝贝，这样的事情原因有很多，例如，你的客户忘记了你的网站的书签，因此他们想再次找到你的网站就很困难。在本文中我将介绍一个分厂好的方法，着眼于保持客户订单数量和给客户发送第一封订单邮件提醒，你可以用我们的免费插件来实现<strong>Alwayly_OrderReminder</strong></p>
<h2>magento 订单提醒插件介绍</h2>
<p>至于Alwayly_OrderReminder插件的源码，可以去magento插件中心<a title="magento 订单提醒插件下载" href="https://www.360magento.com/magento-extensions.html">下载</a>，这里我只通过一些代码介绍他的功能。Alwayly_OrderReminder插件的特点有：</p>
<ul>
<li>当客户注册之后，隔了数天还没有下单，这是可以通过这个magento插件发送邮件提醒客户下单</li>
<li>可以配置发送邮件的最多数量，当发送最后一件邮件后可以采取一些措施（移动到不同的客户群或删除帐户）</li>
<li>通过magento的事务性邮件模板功能可以配置定期的和最后一封邮件的模板</li>
<li>配置magento订单提醒邮件的发送者，以及作为邮件副本或抄送发送给电子邮箱地址</li>
</ul>
<p>以下是配置选项提供的屏幕截图,z在你的magento后台System -&gt; Configuration -&gt; Sales Emails -&gt; Order Reminders里面</p>
<p><img alt="magento订单邮件提醒插件" src="http://7xjryy.com1.z0.glb.clouddn.com/orderreminder-options.jpg" height="393" width="523" /></p>
<h2>配置逻辑</h2>
<p>在本节中，我将介绍一些代码和在<a title="magento 订单提醒插件下载" href="https://www.360magento.com/magento-extensions.html">magento插件</a>Alwayly_OrderReminder背后一些基本的逻辑</p>
<p>Inchoo_OrderReminder_Model_Observer::processOrderReminders()方法是通过cron daily来出发，通过配置选项来处理客户，下面是config.xml文件的代码段用于此目的：</p>
<pre>&lt;config&gt;
    &lt;crontab&gt;
        &lt;jobs&gt;
            &lt;inchoo_orderreminder&gt;
                &lt;!-- Daily at 1 am --&gt;
                &lt;schedule&gt;&lt;cron_expr&gt;0 1 * * *&lt;/cron_expr&gt;&lt;/schedule&gt;
                &lt;run&gt;&lt;model&gt;inchoo_orderreminder/observer::processOrderReminders&lt;/model&gt;&lt;/run&gt;
            &lt;/inchoo_orderreminder&gt;
        &lt;/jobs&gt;
    &lt;/crontab&gt;
&lt;/config&gt;
</pre>
<p>触发后</p>
<p>下面是发送电子邮件的代码</p>
<pre>/**
 * Send transactional emails.
 * 
 * @param Varien_Object $customer Customer object
 * @param int $reminderLimit Number of days for last reminder
 * @param int $reminderKey Number of days since customer account was created
 * @param string $template Email template
 */
protected function _sendOrderReminderEmail(Varien_Object $customer, $reminderLimit, $reminderKey, $template)
{
    $this-&gt;_log('Preparing email...');
 
    // Get necessary vars
    $copyTo = $this-&gt;_getStoreConfigCopyTo();
    $copyMethod = $this-&gt;_getStoreConfigCopyMethod();
    $storeId = Mage::app()-&gt;getStore()-&gt;getId();
 
    // Uses code from Mage_Sales_Model_Order::sendNewOrderEmail()
    $mailer = Mage::getModel('core/email_template_mailer');
    $emailInfo = Mage::getModel('core/email_info');
    $emailInfo-&gt;addTo($customer-&gt;getEmail(), $customer-&gt;getName());
    if ($copyTo &amp;&amp; $copyMethod == 'bcc') {
        // Add bcc to customer email
        foreach ($copyTo as $email) {
            $emailInfo-&gt;addBcc($email);
 
            $this-&gt;_log(sprintf('Add %s to Bcc.', $email));
        }
    }
    $mailer-&gt;addEmailInfo($emailInfo);
 
    // Email copies are sent as separated emails if their copy method is 'copy'
    if ($copyTo &amp;&amp; $copyMethod == 'copy') {
        foreach ($copyTo as $email) {
            $emailInfo = Mage::getModel('core/email_info');
            $emailInfo-&gt;addTo($email);
            $mailer-&gt;addEmailInfo($emailInfo);
 
            $this-&gt;_log(sprintf('Will send a copy to  %s.', $email));
        }
    }
 
    // Set all required params and send emails
    $mailer-&gt;setSender($this-&gt;_getStoreConfigIdentity(), $storeId);
    $mailer-&gt;setStoreId($storeId);
    $mailer-&gt;setTemplateId($template);
    $mailer-&gt;setTemplateParams(
        array(
            // Customer object
            'customer' =&gt; $customer,
 
            // Reminder for number of days
            'reminder_days' =&gt; $reminderKey,
 
            // Last reminder number of days
            'reminder_limit' =&gt; $reminderLimit
        )
    );
 
    // Send
    $mailer-&gt;send();
 
    $this-&gt;_log('Email sent.');
}
</pre>
<p>接下来你可以学习下，也可以直接安装这个<a title="magento 订单提醒插件下载" href="https://www.360magento.com/magento-extensions.html">magento插件</a>来达到你想要的效果</p>]]></description>
      <pubDate>Fri, 21 Aug 2015 16:58:18 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何创建magento下拉式的登陆框效果]]></title>
      <link>https://www.360magento.com/blog/create-magento-dropdown-login/</link>
      <description><![CDATA[<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento在首页显示登陆注册框，创建magento下拉登陆框" src="http://7xjryy.com1.z0.glb.clouddn.com/login-form-homepage.jpg" height="240" width="609" /></div>
<p>下拉式登录在大部分商店中并不常用，但在一些情况下它会是一个很有用的用户体验功能。 在这篇教程中，我将讲解在magento中如何在几分钟内创建这么一个下拉式登录框,让用户可以不用打开另外链接页面直接登陆。</p>
<p>打开你的magento网站路径<strong>app/design/frontend/base/default/layout/customer.xml</strong> 并加入以下高亮代码</p>
<pre>&lt;customer_logged_out&gt;
	&lt;!---&lt;reference name="right"&gt;
		&lt;block type="customer/form_login" name="customer_form_mini_login" before="-" template="customer/form/mini.login.phtml"/&gt;
	&lt;/reference&gt;--&gt;
	&lt;reference name="top.links"&gt;
		&lt;action method="addLink" translate="label title" module="customer"&gt;&lt;label&gt;Log In&lt;/label&gt;&lt;url helper="customer/getLoginUrl"/&gt;&lt;title&gt;Log In&lt;/title&gt;&lt;prepare/&gt;&lt;urlParams/&gt;&lt;position&gt;100&lt;/position&gt;&lt;/action&gt;
		&lt;block type="core/template" name="customer_form_mini_login" before="-" template="customer/form/mini.login.phtml"/&gt;
	&lt;/reference&gt;
	&lt;remove name="reorder"&gt;&lt;/remove&gt;
&lt;/customer_logged_out&gt;
&lt;/pre&gt;</pre>
<p>打开你的magento网站路径&nbsp;<strong>app/design/frontend/base/default/template/page/template/links.phtml</strong>并添加一下高亮代码:</p>
<pre>&lt;?php $_links = $this-&gt;getLinks(); ?&gt;
&lt;?php if(count($_links)&gt;0): ?&gt;
&lt;ul class="links"&lt;?php if($this-&gt;getName()): ?&gt; id="&lt;?php echo $this-&gt;getName() ?&gt;"&lt;?php endif;?&gt;&gt;
    &lt;?php foreach($_links as $_link): ?&gt;
        &lt;?php if ($_link instanceof Mage_Core_Block_Abstract):?&gt;
            &lt;?php echo $_link-&gt;toHtml() ?&gt;
        &lt;?php else: ?&gt;
            &lt;li<!--?php if($_link--->getIsFirst()||$_link-&gt;getIsLast()): ?&gt; class="<!--?php if($_link--->getIsFirst()): ?&gt;first<!--?php endif; ?-->&lt;?php if($_link-&gt;getIsLast()): ?&gt; last&lt;?php endif; ?&gt;"&lt;?php endif; ?&gt; &lt;?php echo $_link-&gt;getLiParams() ?&gt;&gt;&lt;?php echo $_link-&gt;getBeforeText() ?&gt;&lt;a href="&lt;?php echo $_link-&gt;getUrl() ?&gt;" title="&lt;?php echo $_link-&gt;getTitle() ?&gt;" &lt;?php echo $_link-&gt;getAParams() ?&gt;&gt;&lt;?php echo $_link-&gt;getLabel() ?&gt;&lt;/a&gt;&lt;?php echo $_link-&gt;getAfterText() ?&gt;
                &lt;?php if($_link-&gt;getIsLast()): ?&gt;
                    &lt;?php echo $this-&gt;getChildHtml('customer_form_mini_login'); ?&gt;
                &lt;?php endif; ?&gt;
            &lt;/li&gt;
        &lt;?php endif;?&gt;
    &lt;?php endforeach; ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;
</pre>
<p>最后打开你的magento网站路径<strong>app/design/frontend/base/default/template/customer/form/mini.login.phtml</strong> 同样的copy下面代码.</p>
<pre>&lt;style&gt;
	#dropdown
	{
		position: absolute;
		top: 70px;
		right: 20px;
		visibility: hidden;
		float:right;
	}
	.last:hover #dropdown
	{
		visibility: visible;
	}
&lt;/style&gt;
&lt;div class="block block-login" id="dropdown"&gt;
	&lt;div class="block-title"&gt;
		&lt;strong&gt;&lt;span&gt;&lt;?php echo $this-&gt;__('Login') ?&gt;&lt;/span&gt;&lt;/strong&gt;
	&lt;/div&gt;
	&lt;form action="&lt;?php echo $this-&gt;getUrl('customer/account/loginPost') ?&gt;" method="post"&gt;
		<!--?php echo $this--->getBlockHtml('formkey'); ?&gt;
		&lt;div class="block-content"&gt;
			&lt;label for="mini-login"&gt;&lt;?php echo $this-&gt;__('Email:') ?&gt;&lt;/label&gt;&lt;input type="text" name="login[username]" id="mini-login" class="input-text" /&gt;
			&lt;label for="mini-password"&gt;&lt;?php echo $this-&gt;__('Password:') ?&gt;&lt;/label&gt;&lt;input type="password" name="login[password]" id="mini-password" class="input-text" /&gt;
			&lt;div class="actions"&gt;
				&lt;button type="submit" class="button"&gt;&lt;span&gt;&lt;span&gt;&lt;?php echo $this-&gt;__('Login') ?&gt;&lt;/span&gt;&lt;/button&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/form&gt;
&lt;/div&gt;
</pre>
<p>就是这样！当鼠标移到头部菜单<strong>&ldquo;Log In&rdquo;</strong>上时，你的magento网站顶部登录框就会出现。</p>
<p><a href="http://7xjryy.com1.z0.glb.clouddn.com/login-dropdown-example.png"><img class="alignnone size-full wp-image-21880" alt="magento在首页显示登陆注册框，创建magento下拉登陆框" src="http://inchoo.net/wp-content/uploads/2014/11/login-dropdown-example.png" height="175" width="212" /></a></p>
<p>这里值得记下的是：我们对Magento默认的mini登陆模板文件<strong>mini.login.phtml</strong>进行了一些修改让他在首页显示。</p>
<p>我们也用core/template块代替了customer/form_login。这么做的原因是让页面标题&ldquo;Customer login&rdquo;能在所有页面显示。</p>
<p>作为使用多个块的缺点，现在我们不能使用customer/form_login块中的方法。这就是我们使用$this-&gt;getUrl(&lsquo;customer/account/loginPost&rsquo;)方法来替代$this-&gt;getPostActionUrl()的原因。</p>
<p>你有一个形式存在的表关键字也是很重要的，否则你的表格将不会得到处理。</p>
<pre>&lt;code&gt;&lt;?php echo $this-&gt;getBlockHtml('formkey'); ?&gt;&lt;/code&gt;&lt;/pre&gt;</pre>
<p>最好要说的就是让magento的前端开发者（也许就是你？）好好地利用下拉式登录。</p>]]></description>
      <pubDate>Fri, 21 Aug 2015 09:59:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[在magento的其他页面显示产品的星级评价]]></title>
      <link>https://www.360magento.com/blog/display_product_rating/</link>
      <description><![CDATA[<p>产品评论功能是Magento众多优秀特征之一。用好评论可以增加客户对你的品牌的信任，由此能显著增加你产品的销量。</p>
<p>有时，你需要在评论页的其他页面展示评价星级。这正是我将要在这篇文章中写到的。</p>
<p>下面这段代码适用于已经读取的产品（或者你知道产品的ID）&mdash;&mdash;比如在购物车中调用产品评价星级；</p>
<pre>&lt;?php
$_product = $_item-&gt;getProduct(); //get the product in cart
$storeId = Mage::app()-&gt;getStore()-&gt;getId();
$summaryData = Mage::getModel('review/review_summary')
					-&gt;setStoreId($storeId)
					-&gt;load($_product-&gt;getId());
 
if ($summaryData['rating_summary']):?&gt;
	&lt;div class="ratings"&gt;
		&lt;div class="rating-box"&gt;
			&lt;div class="rating" style="width:&lt;?php echo $summaryData['rating_summary'] ?&gt;%"&gt;&lt;/div&gt; <br />                &lt;/div&gt; <br />         &lt;/div&gt; <br />&lt;?php endif; ?&gt;</pre>
<p>如果我们访问购物车页面，我们会看到客户评价过的产品都会展示评价星级。</p>
<p><img alt="在购物车中显示产品评价星级" src="http://7xjryy.com1.z0.glb.clouddn.com/cart2.png" height="203" width="620" /></p>
<p>在$summaryData对象中,我们可以获取到这个数组的键值如下：</p>
<pre>//Entity id of a summary review
["primary_id"] =&gt; string(3) "100"
//
//Product id
["entity_pk_value"] =&gt; string(3) "119"
//
//Entity type id: 1-Product; 2-Customer; 3-Category
["entity_type"] =&gt; string(1) "1"
//
//Qty of reviews
["reviews_count"] =&gt; string(1) "2"
//
//Summarized rating: the percentage which represents number of stars, each 20% step fills up one star
["rating_summary"] =&gt; string(2) "80"
//
//Store id
["store_id"] =&gt; string(1) "1"
</pre>
<p>记住展示评价星级的&ldquo;Magento方式&rdquo;是：创建一个block或者一个有接收product ID和store ID方法的helper，然后从视图文件中返回值。</p>
<p>然而，你也可以将这段代码放入视图文件中来快速地为你的产品获取星级。</p>
<p>注意，要在以上Html 标记（7-11行）之后输出星级的值，不然的话，星级将不会显示。</p>]]></description>
      <pubDate>Wed, 19 Aug 2015 15:20:23 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中产品列表增加销量排序]]></title>
      <link>https://www.360magento.com/blog/products-by-sold/</link>
      <description><![CDATA[<p><img class="attachment-full wp-post-image" alt="magento如何按产品销售量排序" src="http://7xjryy.com1.z0.glb.clouddn.com/sort-quantity.png" height="240" width="609" /></p>
<p>Magento默认提供了一些排序选项，例如：产品位置，名字，价格。在这篇文章中你将学会让产品按照销量来排序。</p>
<p>要做到这些，我们需要重写一些Magento的核心文件。重定义核心文件并不是一个好的尝试，所以我们创建一个自己的模块来完成同样的功能并保证能升级。</p>
<p>我假设你知道如何建立你自己的模块并创建对应的文件(app/etc/modules/Alwayly_Catalog.xml),所以Magento能识别我们的模块。</p>
<p>现在，我们有了自己的模块并且已经被Magento识别，让我们创建自己的config.xml，路径为Alwayly/Catalog/etc/config.xml:</p>
<pre>&lt;config&gt;
    &lt;modules&gt;
        &lt;Alwayly_Catalog&gt;
            &lt;version&gt;0.1.0&lt;/version&gt;
        &lt;/Alwayly_Catalog&gt;
    &lt;/modules&gt;
    &lt;global&gt;
        &lt;blocks&gt;
            &lt;catalog&gt;
                &lt;rewrite&gt;
                    &lt;product_list_toolbar&gt;Alwayly_Catalog_Block_Product_List_Toolbar&lt;/product_list_toolbar&gt;
                &lt;/rewrite&gt;
            &lt;/catalog&gt;
        &lt;/blocks&gt;
        &lt;models&gt;
            &lt;catalog&gt;
               &lt;rewrite&gt;
                    &lt;config&gt;Alwayly_Catalog_Model_Config&lt;/config&gt;
                &lt;/rewrite&gt;
            &lt;/catalog&gt;
            &lt;catalog_resource&gt;
                &lt;rewrite&gt;
                    &lt;product_collection&gt;Alwayly_Catalog_Model_Resource_Product_Collection&lt;/product_collection&gt;
                &lt;/rewrite&gt;
            &lt;/catalog_resource&gt;
        &lt;/models&gt;
    &lt;/global&gt;
&lt;/config&gt;
</pre>
<p>也许你会想到，我们将要重写以下三个文件：</p>
<ul>
<li>Mage_Catalog_Block_Product_List_Toolbar</li>
<li>Mage_Catalog_Model_Config</li>
<li>Mage_Catalog_Model_Resource_Product_Collection</li>
</ul>
<p>我们的<strong>app/code/local/Alwayly_Catalog_Block_Product_List_Toolbar</strong> 应该这样:</p>
<pre>&lt;?php
class Alwayly_Catalog_Block_Product_List_Toolbar extends Mage_Catalog_Block_Product_List_Toolbar
{
    public function setCollection($collection)
    {
        parent::setCollection($collection);
 
        if ($this-&gt;getCurrentOrder()) {
            if($this-&gt;getCurrentOrder() == 'qty_ordered') {
                $this-&gt;getCollection()-&gt;getSelect()
                     -&gt;joinLeft(
                            array('sfoi' =&gt; $collection-&gt;getResource()-&gt;getTable('sales/order_item')),
                             'e.entity_id = sfoi.product_id',
                             array('qty_ordered' =&gt; 'SUM(sfoi.qty_ordered)')
                         )
                     -&gt;group('e.entity_id')
                     -&gt;order('qty_ordered ' . $this-&gt;getCurrentDirection());
            } else {
                $this-&gt;getCollection()
                     -&gt;setOrder($this-&gt;getCurrentOrder(), $this-&gt;getCurrentDirection())-&gt;getSelect();
            }
        }
 
        return $this;
    }
}
</pre>
<p>我们继承了Mage_Catalog_Block_Product_List_Toolbar中所有的功能和方法但我们自己重写了setCollection()方法</p>
<p>我们的<strong>Alwayly_Catalog_Model_Config</strong>是相当简单的:</p>
<pre>&lt;?php
class Alwayly_Catalog_Model_Config extends Mage_Catalog_Model_Config
{
    public function getAttributeUsedForSortByArray()
    {
        return array_merge(
			parent::getAttributeUsedForSortByArray(),
			array('qty_ordered' =&gt; Mage::helper('catalog')-&gt;__('Sold quantity'))
		);
    }
}
</pre>
<p>到了这一步，产品的排序应该已经奏效，但我们在分页上有点小问题，无法显示正确的数目。我们可以在 <strong>Alwayly/Catalog/Model/Resource/Product/Collection.php</strong>中用以下代码来修复这个问题。</p>
<pre>&lt;?php
class Alwayly_Catalog_Model_Resource_Product_Collection extends Mage_Catalog_Model_Resource_Product_Collection
{
    protected function _getSelectCountSql($select = null, $resetLeftJoins = true)
    {
       $this-&gt;_renderFilters();
       $countSelect = (is_null($select)) ?
           $this-&gt;_getClearSelect() :
           $this-&gt;_buildClearSelect($select);
 
       if(count($countSelect-&gt;getPart(Zend_Db_Select::GROUP)) &gt; 0) {
           $countSelect-&gt;reset(Zend_Db_Select::GROUP);
       }
 
       $countSelect-&gt;columns('COUNT(DISTINCT e.entity_id)');
       if ($resetLeftJoins) {
           $countSelect-&gt;resetJoinLeft();
       }
       return $countSelect;
    }
}
</pre>
<p>就是这样，在4个简单的步骤之后，我们的Magento网站中的商品就能按销量来排序了。 希望你乐在其中~~~</p>]]></description>
      <pubDate>Tue, 18 Aug 2015 13:05:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[用local.xml来重写或更新magento模板布局的xml结构]]></title>
      <link>https://www.360magento.com/blog/magento-overwrite-xml/</link>
      <description><![CDATA[<p><img class="attachment-full wp-post-image" alt="magento使用local.xml来更新网站的布局" src="http://7xjryy.com1.z0.glb.clouddn.com/local-xml.jpg" height="100" width="620" /></p>
<p>在过去的5年magento管理代码的工作经验来看，在遵循magento的规则情况下，使用"local.xml"来重写或更新xml布局是最好的方法</p>
<p>这篇文章是针对那些还不知道&ldquo;local.xml&rdquo;方法的。如果你已经在使用它，那恭喜你。如果没有，你绝对应该使用它。</p>
<p>这个其实很简单：只使用一个文件时，就是local.xml，放置在你的主题文件夹layput下覆盖或更新主题所有设计的XML。</p>
<p><strong>优点</strong>:</p>
<p>1. 仅仅只用一个文件就可以管理和更新magento主题的xml<br /> 2. 没有必要去查找magento主题下的其他.xml文件,因为他是依赖于base文件夹下的xml<br /> 3. 每次更改local.xml文件，是显而易见的，所以没有必要寻找内部的XML文件的变化</p>
<p><strong>缺点</strong>:</p>
<p>1. 目前我还没发现，除非你不是想把代码更清晰明了，以后修改主题不是你的事情.</p>
<p>如何使用local.xml文件.你需要做的就是创建一个插入你的主题文件夹里面并写入你的xml.由于magento是通过xmk文件读取的，所以它将首先搜索新创建的local.xml的变化并且重写和更新，然后再进入base文件夹里的.xml.</p>
<p><strong>如何设置local.xml</strong>:</p>
<p>1. 在你的主题layout文件夹下创建local.xml文件 (app/frontend/default/your-theme/layout)<br /> 2. 加入基本的xml标记结构</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;layout version="0.1.0"&gt;&lt;/layout&gt;
</pre>
<p>3. 将要重写的xml结构放入，看下面的例子:</p>
<p><strong>例子</strong>:</p>
<p>1. 从这个区域删除/添加javascript:</p>
<pre>&lt;!-- Let&rsquo;s remove sleight js for IE7--&gt;
&lt;reference name="head"&gt;
&lt;action method="removeItem"&gt;&lt;type&gt;js&lt;/type&gt;&lt;name&gt;lib/ds-sleight.js&lt;/name&gt;&lt;params /&gt;&lt;if&gt;lt IE 7&lt;/if&gt;&lt;/action&gt;
&lt;/reference&gt;
 
&lt;!-- Instead, add belated.js from your theme&rsquo;s /js folder --&gt;
&lt;action method="addItem"&gt;&lt;type&gt;skin_js&lt;/type&gt;&lt;name&gt;js/belated.js&lt;/name&gt;&lt;params /&gt;&lt;if&gt;lt IE 7&lt;/if&gt;&lt;/action&gt;
</pre>
<p>2. 仅仅只为这个category page添加一个layout,设置一个模板并添加一些javascript.</p>
<pre>&lt;catalog_product_view translate="label"&gt;
&lt;reference name="root"&gt;
&lt;action method="setTemplate"&gt;
&lt;template&gt;page/1column.phtml&lt;/template&gt;
&lt;/action&gt;
&lt;/reference&gt;
&lt;reference name="head"&gt;
&lt;action method="addItem"&gt;&lt;type&gt;skin_js&lt;/type&gt;
&lt;name&gt;js/stereotabs.js&lt;/name&gt;&lt;/action&gt;
&lt;action method="addItem"&gt;&lt;type&gt;skin_js&lt;/type&gt;
&lt;name&gt;js/shadowbox/shadowbox.js&lt;/name&gt;&lt;/action&gt;
&lt;/reference&gt;
&lt;/catalog_product_view&gt;
</pre>
<p>3.从这个layput中移除指定的blocks(products compare, products viewed and related products) ,用 &ldquo;remove&rdquo;</p>
<pre>&lt;default&gt;
&lt;reference name="right"&gt;
&lt;remove name="catalog.compare.sidebar" /&gt;
&lt;remove name="left.reports.product.viewed" /&gt;
&lt;remove name="catalog.product.related" /&gt;
&lt;/reference&gt;

</pre>
<p>4. 从这个layput中移除指定的blocks(products compare, products viewed and related products), 用 method=&rdquo;unsetChild&rdquo;</p>
<pre>
&lt;!-- Removed the Newsletter from the left sidebar --&gt;
&lt;action method="unsetChild"&gt;&lt;name&gt;left.newsletter&lt;/name&gt;&lt;/action&gt;
&lt;action method="unsetChild"&gt;&lt;name&gt;tags_popular&lt;/name&gt;&lt;/action&gt;
&lt;/reference&gt;
&lt;/default&gt;
</pre>
<p>当然local.xml有许多其他用途，但我这里只指出了添加，删除和更新模块，以更好地说明local.xml在开发流程的方式。</p>
<p>希望这篇文章能给你的开发带来方便，谢谢阅读</p>]]></description>
      <pubDate>Mon, 17 Aug 2015 14:13:39 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[改变Magento Global Messages的显示方式]]></title>
      <link>https://www.360magento.com/blog/fancy-magento-global-messages/</link>
      <description><![CDATA[<p><img alt="magento global message" src="http://7xjryy.com1.z0.glb.clouddn.com/global-message.jpg" height="200" width="609" /></p>
<p>一般用magento开发的网站，客户很难看到或注意到一些提醒，也就是magento中的Global Messages</p>
<p>我们可以通过把Global Messages放到页面的顶部来增强客户的浏览性，并通过动画来美化它</p>
<p>我们可以通过下面的演示视频上的简单的三个步骤来看下我们要来达到的效果(Youtube视频，请翻墙观看)</p>
<p><object width="600" height="437" data="http://www.youtube.com/v/RUVxY0suy1s?version=3&amp;hl=en_US&amp;rel=0" type="application/x-shockwave-flash"><param name="src" value="http://www.youtube.com/v/RUVxY0suy1s?version=3&amp;hl=en_US&amp;rel=0" /><param name="allowscriptaccess" value="always" /><param name="allowfullscreen" value="true" /></object></p>
<p>1. 创建<strong>local.xml</strong>插入到你自己的主题模板的layout下面，如果你已经有了这个文件，可以插入到这个文件里面适当的地方(<a href="https://www.360magento.com/blog/magento-overwrite-xml/" target="_blank" title="用local.xml来重写或更新magento模板布局的xml结构">阅读更多关于 “local.xml 方法”</a>).</p>
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;layout version="0.1.0"&gt;
    &lt;default&gt;
		&lt;reference name="root"&gt;
			&lt;remove name="global_messages" /&gt;
		&lt;/reference&gt;
		&lt;reference name="after_body_start"&gt;
			&lt;block type="core/template" name="alwayly_global_messages" template="core/alwayly_global_messages.phtml" before="-" /&gt;
		&lt;/reference&gt;
    &lt;/default&gt;
&lt;/layout&gt;
</pre>
<p>2. 创建<strong>alwayly_global_messages.phtml</strong> 在 <br />app/design/frontend/your_package/your_theme/template/core/</p>
<pre>&lt;?php if($this-&gt;getMessagesBlock()-&gt;getMessageCollection()-&gt;count()): ?&gt;
	&lt;div id="alwayly_global_messages" style="display: none"&gt;
		&lt;a href="javascript:void(0)" id="alwayly_global_messages_close" style="display: none" title="<!--?php echo $this--->__('Hide messages') ?&gt;"&gt;<span>&amp;</span>times;&lt;/a&gt;
		&lt;?php echo $this-&gt;getMessagesBlock()-&gt;getGroupedHtml(); ?&gt;
	&lt;/div&gt;
&lt;?php $this-&gt;getMessagesBlock()-&gt;getMessageCollection()-&gt;clear(); ?&gt;
 
&lt;script type="text/javascript"&gt;
//&lt;![CDATA[
	Event.observe('alwayly_global_messages_close', 'click', function() {
		Effect.SlideUp('alwayly_global_messages', { duration: 0.4, delay: 0.3 });
		Effect.Fade('alwayly_global_messages_close', { duration: 0.2 });
	});
	Event.observe(document, 'dom:loaded', function() {
		Effect.SlideDown('alwayly_global_messages', { duration: 0.4, delay: 0.3 });
		Effect.Appear('alwayly_global_messages_close', { duration: 0.2, delay: 1 });
	});
//]]&gt;
&lt;/script&gt;
<!--?php endif; ?--></pre>
<p>3. 在你的css文件里面追加<strong>#alwayly_global_messages</strong>的样式 <br />skin/frontend/your_ package/your_theme/css/</p>
<pre>#alwayly_global_messages {
	position: relative;
	z-index: 9999;
}
#alwayly_global_messages_close {
	position: absolute;
	top: 13px;
	right: 13px;
	z-index: 10000;
	display: block;
	width: 15px;
	height: 15px;
	background: #666;
	text-align: center;
	color: #fff;
	font-size: 15px;
	line-height: 15px;
	text-decoration: none;
	-webkit-border-radius: 15px;
	-moz-border-radius: 15px;
	border-radius: 15px;
}
</pre>
<p>你也可以根据你自己喜欢的样式来设计magento global messages的样式</p>
<p>在video里面的例子，我已经添加了样式来覆盖原有的css</p>
<pre>.messages li, .messages li li { margin: 0 !important; }
.error-msg, .success-msg, .note-msg, .notice-msg {
	border: none !important;
	font-size: 14px !important;
	background-position: 13px 13px !important;
	padding: 10px 35px !important;
	min-height: 22px !important;
}
.note-msg, .notice-msg { color: #d6b501; }
</pre>
<p>就这样了，你的客户可以看到一个醒目而好看的message了</p>]]></description>
      <pubDate>Mon, 17 Aug 2015 12:27:17 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[自定义magento导航菜单]]></title>
      <link>https://www.360magento.com/blog/custom-category-menu-navigation/</link>
      <description><![CDATA[<p>magento的分类导航是top menu,但多数人用</p>
<p>但有一些客户想要在magento的sidebar一个垂直的分类菜单导航,这样当客户在进入一个分类列表时就可以看到当前分类的统计分类</p>
<p>在这篇文章中，我们将讨论建立一个完整的magento垂直菜单。我们将做3级深度的分类：类别，子类别和子类别。你可以再次基础上再扩展层级，但我相信对于大部分magento商店3级是绰绰有余。</p>
<h2>加载布局layout</h2>
<p>打开app/design/frontend/base/default/layout/page.xml或者是你自己主题下的layout文件。将下面的代码复制到default标签下面</p>
<pre>&lt;reference name="right"&gt;
     &lt;block type="core/template" name="catalog.sidenav" template="page/custom.phtml" before="cart_sidebar"/&gt;
&lt;/reference&gt;
</pre>
<p>这句代码的意思是告诉magento在把这个内容加载到我们每个页面的右边布局页面</p>
<p>现在我们来创建magento模板文件</p>
<h2>创建菜单模板</h2>
<p>我们需要做的是通过所有的商店类别，得到他们的子类别（2级），子子类别（3级），并显示它们。在这个过程中，我们在list页面需要寻找一个与当前分类id相同的分类id。当我们找到它 - 我们将会做任何事情。</p>
<p>创建app/design/frontend/base/default/template/page/custom.phtml 并复制下面代码</p>
<pre>&lt;ul&gt;
    &lt;?php
        $obj = new Mage_Catalog_Block_Navigation();
        $storeCategories = $obj-&gt;getStoreCategories();
        Mage::registry('current_category') ? $currentCategoryId = Mage::registry('current_category')-&gt;getId() : $currentCategoryId='';
        foreach ($storeCategories as $_category):
    ?&gt;
            &lt;li&gt;
                &lt;strong&gt;&lt;?php echo $_category-&gt;getName(); ?&gt;&lt;/strong&gt;
                &lt;?php $categoryChildren = $_category-&gt;getChildren(); ?&gt;
                &lt;?php if($categoryChildren-&gt;count()) : ?&gt;
                    &lt;ul&gt;
 
                        &lt;?php foreach($categoryChildren as $_categoryChild) : ?&gt;
                            &lt;?php $_categoryChildModel = Mage::getModel('catalog/category')-&gt;load($_categoryChild-&gt;getId());?&gt;
                            &lt;?php $categoryGrandchildren=$_categoryChild-&gt;getChildren(); ?&gt;
                            &lt;li&gt;
                                &lt;?php
                                    $currentCategoryId===$_categoryChild-&gt;getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
                                    echo '<span>&amp;</span>emsp;' . '<a href="&quot;'">getUrl() . '"' . $bold . '&gt;' .  $_categoryChild-&gt;getName() . '(' . $_categoryChildModel-&gt;getProductCollection()-&gt;count() . ')&lt;/a&gt;';
                                ?&gt;
                            &lt;/li&gt;
                            &lt;?php if($categoryGrandchildren-&gt;count()) : ?&gt;
                                &lt;?php foreach($categoryGrandchildren as $_categoryGrandchild) : ?&gt;
                                    &lt;?php $_categoryGrandchildModel = Mage::getModel('catalog/category')-&gt;load($_categoryGrandchild-&gt;getId());?&gt;
                                    &lt;li&gt;
                                        &lt;?php
                                            $currentCategoryId===$_categoryChild-&gt;getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
                                            echo '<span>&amp;</span>emsp;<span>&amp;</span>emsp;' . '</a><a href="&lt;span&gt;&amp;&lt;/span&gt;quot;'">getUrl() . '"' . $bold . '&gt;' .  $_categoryGrandchild-&gt;getName() . '(' . $_categoryGrandchildModel-&gt;getProductCount() . ')&lt;/a&gt;';
                                        ?&gt;
                                    &lt;/li&gt;
                                &lt;?php endforeach; ?&gt;
                            &lt;?php endif; ?&gt;
                        &lt;?php endforeach; ?&gt;
                    &lt;/ul&gt;
                &lt;?php endif; ?&gt;
            &lt;/li&gt;
        &lt;?php endforeach ?&gt;
&lt;/ul&gt;
</a></pre>
<h2>显示右边导航</h2>
<p>你应该能够看到你的页面的右边栏导航。这不正是最漂亮的菜单导航，但我相信你就可以改变风格，以满足您的需求。</p>
<p><img alt="magento自定义分类导航" src="http://7xjryy.com1.z0.glb.clouddn.com/custom-category-menu-example.png" height="315" width="620" /></p>
<p>你好可以插入这个模板文件到其他页面。例如在magento后台cms page中插入导航菜单</p>
<pre><span>{</span>{block type="core/template" template="page/custom.phtml"}}
</pre>]]></description>
      <pubDate>Sun, 16 Aug 2015 12:58:46 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento获取Base Url , Skin Url , Media Url , Js Url , Store Url 和 Current Url]]></title>
      <link>https://www.360magento.com/blog/magento-get-url/</link>
      <description><![CDATA[<h2>magento如何在phtml文件中获取url？</h2>
<h3>1. 获取 Base Url :</h3>
<pre>Mage::getBaseUrl();</pre>
<h3>2. 获取 Skin Url :</h3>
<pre>Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN);</pre>
<p>(a) Unsecure Skin Url :</p>
<pre>$this-&gt;getSkinUrl('images/imagename.jpg');</pre>
<p>(b) Secure Skin Url :</p>
<pre>$this-&gt;getSkinUrl('images/imagename.gif', array('_secure'=&gt;true));</pre>
<h3>3. 获取 Media Url :</h3>
<pre>Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA);</pre>
<h3>4. 获取 Js Url :</h3>
<pre>Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_JS);</pre>
<h3>5. 获取 Store Url :</h3>
<pre>Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);</pre>
<h3>6. 获取 Current Url</h3>
<pre>Mage::helper('core/url')-&gt;getCurrentUrl();</pre>
<h2>magento如何在cms pages或static blocks中获取Url ？</h2>
<h3>1. 获取 Base Url :</h3>
<pre><span>{</span>{store url=""}}</pre>
<h3>2. 获取 Skin Url :</h3>
<pre><span>{</span>{skin url='images/imagename.jpg'}}</pre>
<h3>3. 获取 Media Url :</h3>
<pre><span>{</span>{media url='imagename.jpg'}}</pre>
<h3>4. 获取 Store Url :</h3>
<pre><span>{</span>{store url='mypage.html'}}</pre>]]></description>
      <pubDate>Sat, 15 Aug 2015 12:53:30 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento在布局文件xml中如何添加/删除js和css]]></title>
      <link>https://www.360magento.com/blog/add-js-css-in-xml/</link>
      <description><![CDATA[<p>在magento中我们在head.phtml中调用css和js的代码是</p>
<pre>&lt;?php echo $this-&gt;getCssJsHtml() ?&gt;</pre>
<p>那么按照magento的规则，我们需要在layout中去加载css和js</p>
<h2>在magento如何通过xml加载外部js</h2>
<p>通畅我们会引用外部的css和js，比如google的字体,jquery库以及其他的库</p>
<pre> &lt;!-- Add an EXTERNAL stylesheets  --&gt;
	  &lt;action method="addLinkRel"&gt;&lt;rel&gt;stylesheet&lt;href&gt;https://fonts.googleapis.com/css?family=Roboto+Condensed:300italic,400,300,700|Open+Sans:300italic,400,300&lt;/href&gt;&lt;/action&gt;
 
         &lt;!--  Add an EXTERNAL javascript  --&gt;
         &lt;action method="addLinkRel"&gt;&lt;rel&gt;text/javascript&lt;href&gt;https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js&lt;/href&gt;&lt;/action&gt;
</pre>
<h2>如何加载magento主题下的css,jss</h2>
<h3>加载magento主题模板下面的css,js</h3>
<pre> &lt;!-- Add stylesheets from your local theme directory located in skin/frontend/ --&gt;
          &lt;action method="addCss"&gt;&lt;stylesheet&gt;css/styles.css&lt;/stylesheet&gt;&lt;/action&gt;
 
         &lt;!-- Add javascript from your local theme directory located in skin/frontend/ --&gt;
          &lt;action method="addItem"&gt;
	          &lt;type&gt;skin_js&lt;name&gt;js/bootstrap.min.js
          &lt;/action&gt;

</pre>
<h3>如何加载magento根目录js文件夹下的js文件</h3>
<pre>&lt;action method="addJs"&gt;&lt;script&gt;bootstrap.min.js&lt;/script&gt;&lt;/action&gt;
</pre>
<h2>在magento中删除css和js</h2>
<h3>在magento中的布局文件xml中删除js</h3>
<pre>&lt;action method="removeItem"&gt;
&lt;type&gt;js&lt;/type&gt;
&lt;name&gt;calendar/calendar.js&lt;/name&gt;
&lt;/action&gt;

</pre>
<h3>如何在phtm文件中删除js</h3>
<pre>$this-&gt;getLayout-&gt;getBlock('head')-&gt;removeItem('js', 'calendar/calendar.js');
</pre>]]></description>
      <pubDate>Fri, 14 Aug 2015 13:03:05 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中如何获取/判断用户登录状态]]></title>
      <link>https://www.360magento.com/blog/get-customer-loggedin/</link>
      <description><![CDATA[<p>大部分开发人员直接用</p>
<pre>Mage::getSingleton('customer/session')-&gt;isLoggedIn()</pre>
<p>来判断用户是否登录</p>
<p>比如一般magento开发人员会这样用</p>
<pre>&lt;?PHP

//get customer login status ?&gt;

&lt;?php $myStatus = Mage::getSingleton('customer/session')-&gt;isLoggedIn() ?&gt;

&lt;?php if($myStatus): ?&gt;

&lt;li&gt;&lt;a href="/customer/account/index" title="Customer Register"&gt;My account&lt;/a&gt; |&lt;/li&gt;
&lt;li&gt;&lt;?php echo $this-&gt;getLayout()-&gt;getBlock('header')-&gt;getWelcome() ?&gt;&lt;/li&gt;

&lt;?php else: ?&gt;

&lt;li&gt;&lt;a href="/customer/account/index" title="Customer Register"&gt;My account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="/customer/account/create" title="Customer Register"&gt;Register&lt;/a&gt;&lt;/li&gt;

&lt;?php endif ?&gt;</pre>
<p>但其实在magento里面用户登录状态判断函数早已封装好了.<br /> 判断用户登陆状态是否登陆的原理是：Magento在Session中检查CustomerID是否已经设置，并且该CustomerID在数据库中是有效的。</p>
<p>在app/code/core/Mage/Customer/Helper/Data.php文件中</p>
<pre>/**
     * Check customer is logged in
     *
     * @return bool
     */
    public function isLoggedIn()
    {
        return Mage::getSingleton('customer/session')-&gt;isLoggedIn();
    }</pre>
<p>在app/code/core/Mage/Customer/Model/Session.php文件中</p>
<pre>/**
     * Checking customer login status
     *
     * @return bool
     */
    public function isLoggedIn()
    {
        return (bool)$this-&gt;getId() &amp;&amp; (bool)$this-&gt;checkCustomerId($this-&gt;getId());
    }
</pre>
<p>所以我们可以在全局用</p>
<pre> if ($this-&gt;helper('customer')-&gt;isLoggedIn()) { 
  // is logon 
 } 
</pre>
<p>在magento中判断用户的登录状态或是否登录</p>]]></description>
      <pubDate>Thu, 13 Aug 2015 13:49:16 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento通过sql删除magento产品数据]]></title>
      <link>https://www.360magento.com/blog/delete-all-products-with-sql/</link>
      <description><![CDATA[<p>删除magento所有数据最快的方法是直接使用SQL查询。记得把SET FOREIGN_KEY_CHECKS=0;放在开始，把SET FOREIGN_KEY_CHECKS=1;放最后。</p>
<h2>删除magento所有产品数据</h2>
<p>复制下面代码到phpmyadmin中的SQL查询执行</p>
<pre><code>
TRUNCATE TABLE `catalog_product_bundle_option`;
TRUNCATE TABLE `catalog_product_bundle_option_value`;
TRUNCATE TABLE `catalog_product_bundle_selection`;
TRUNCATE TABLE `catalog_product_entity_datetime`;
TRUNCATE TABLE `catalog_product_entity_decimal`;
TRUNCATE TABLE `catalog_product_entity_gallery`;
TRUNCATE TABLE `catalog_product_entity_int`;
TRUNCATE TABLE `catalog_product_entity_media_gallery`;
TRUNCATE TABLE `catalog_product_entity_media_gallery_value`;
TRUNCATE TABLE `catalog_product_entity_text`;
TRUNCATE TABLE `catalog_product_entity_tier_price`;
TRUNCATE TABLE `catalog_product_entity_varchar`;
TRUNCATE TABLE `catalog_product_link`;
TRUNCATE TABLE `catalog_product_link_attribute`;
TRUNCATE TABLE `catalog_product_link_attribute_decimal`;
TRUNCATE TABLE `catalog_product_link_attribute_int`;
TRUNCATE TABLE `catalog_product_link_attribute_varchar`;
TRUNCATE TABLE `catalog_product_link_type`;
TRUNCATE TABLE `catalog_product_option`;
TRUNCATE TABLE `catalog_product_option_price`;
TRUNCATE TABLE `catalog_product_option_title`;
TRUNCATE TABLE `catalog_product_option_type_price`;
TRUNCATE TABLE `catalog_product_option_type_title`;
TRUNCATE TABLE `catalog_product_option_type_value`;
TRUNCATE TABLE `catalog_product_super_attribute_label`;
TRUNCATE TABLE `catalog_product_super_attribute_pricing`;
TRUNCATE TABLE `catalog_product_super_attribute`;
TRUNCATE TABLE `catalog_product_super_link`;
TRUNCATE TABLE `catalog_product_enabled_index`;
TRUNCATE TABLE `catalog_product_website`;
TRUNCATE TABLE `catalog_category_product_index`;
TRUNCATE TABLE `catalog_category_product`;
TRUNCATE TABLE `cataloginventory_stock_item`;
TRUNCATE TABLE `cataloginventory_stock_status`;
TRUNCATE TABLE `cataloginventory_stock`;
TRUNCATE TABLE `rating_option_vote`; 
TRUNCATE TABLE `rating_option_vote_aggregated`;
TRUNCATE TABLE `review`; 
TRUNCATE TABLE `review_detail`; 
TRUNCATE TABLE `review_entity_summary`; 
TRUNCATE TABLE `review_store`;
INSERT  INTO `catalog_product_link_type`(`link_type_id`,`code`) VALUES (1,'relation'),(2,'bundle'),(3,'super'),(4,'up_sell'),(5,'cross_sell');
INSERT  INTO `catalog_product_link_attribute`(`product_link_attribute_id`,`link_type_id`,`product_link_attribute_code`,`data_type`) VALUES (1,2,'qty','decimal'),(2,1,'position','int'),(3,4,'position','int'),(4,5,'position','int'),(6,1,'qty','decimal'),(7,3,'position','int'),(8,3,'qty','decimal');
INSERT  INTO `cataloginventory_stock`(`stock_id`,`stock_name`) VALUES (1,'Default');
TRUNCATE TABLE `catalog_product_entity`;
</code>
</pre>
<h2>删除magento所有分类</h2>
<p>复制下面代码到phpmyadmin中的SQL查询执行</p>
<pre>TRUNCATE TABLE `catalog_category_entity`;
TRUNCATE TABLE `catalog_category_entity_datetime`;
TRUNCATE TABLE `catalog_category_entity_decimal`;
TRUNCATE TABLE `catalog_category_entity_int`;
TRUNCATE TABLE `catalog_category_entity_text`;
TRUNCATE TABLE `catalog_category_entity_varchar`;
TRUNCATE TABLE `catalog_category_product`;
TRUNCATE TABLE `catalog_category_product_index`;

INSERT  INTO `catalog_category_entity`(`entity_id`,`entity_type_id`,`attribute_set_id`,`parent_id`,`created_at`,`updated_at`,`path`,`POSITION`,`level`,`children_count`) VALUES (1,3,0,0,'0000-00-00 00:00:00','2009-02-20 00:25:34','1',1,0,1),(2,3,3,0,'2009-02-20 00:25:34','2009-02-20 00:25:34','1/2',1,1,0);
INSERT  INTO `catalog_category_entity_int`(`value_id`,`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`) VALUES (1,3,32,0,2,1),(2,3,32,1,2,1);
INSERT  INTO `catalog_category_entity_varchar`(`value_id`,`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`) VALUES (1,3,31,0,1,'Root Catalog'),(2,3,33,0,1,'root-catalog'),(3,3,31,0,2,'Default Category'),(4,3,39,0,2,'PRODUCTS'),(5,3,33,0,2,'default-category');

/**** Magento ver. 1.6.x.x ****/

TRUNCATE TABLE `catalog_category_entity`;
TRUNCATE TABLE `catalog_category_entity_datetime`;
TRUNCATE TABLE `catalog_category_entity_decimal`;
TRUNCATE TABLE `catalog_category_entity_int`;
TRUNCATE TABLE `catalog_category_entity_text`;
TRUNCATE TABLE `catalog_category_entity_varchar`;
TRUNCATE TABLE `catalog_category_product`;
TRUNCATE TABLE `catalog_category_product_index`;

INSERT  INTO `catalog_category_entity`(`entity_id`,`entity_type_id`,`attribute_set_id`,`parent_id`,`created_at`,`updated_at`,`path`,`POSITION`,`level`,`children_count`) VALUES (1,3,0,0,'0000-00-00 00:00:00','0000-00-00 00:00:00','1',1,0,1), (2,3,3,1,'0000-00-00 00:00:00','0000-00-00 00:00:00','1/2','1','1','0');
INSERT  INTO `catalog_category_entity_int`(`value_id`,`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`) VALUES (1,3,32,0,2,1),(2,3,36,0,2,1),(3,3,61,0,2,1),(4,3,44,0,2,NULL),(5,3,45,0,2,1),(6,3,62,0,2,1),(7,3,63,0,2,1),(8,3,64,0,2,NULL);
INSERT  INTO `catalog_category_entity_varchar`(`value_id`,`entity_type_id`,`attribute_id`,`store_id`,`entity_id`,`value`) VALUES (1,3,31,0,1,'Root Catalog'),(2,3,35,0,2,'Default Category'),(3,3,37,0,2,'default-category'),(4,3,40,0,2,NULL),(5,3,43,0,2,'PRODUCTS'),(6,3,52,0,2,NULL),(7,3,55,0,2,NULL);
</pre>
<h2>删除magento所有订单数据</h2>
<p>复制下面代码到phpmyadmin中的SQL查询执行</p>
<pre><code>
TRUNCATE `sales_order`;
  TRUNCATE `sales_order_datetime`;
  TRUNCATE `sales_order_decimal`;
  TRUNCATE `sales_order_entity`;
  TRUNCATE `sales_order_entity_datetime`;
  TRUNCATE `sales_order_entity_decimal`;
  TRUNCATE `sales_order_entity_int`;
  TRUNCATE `sales_order_entity_text`;
  TRUNCATE `sales_order_entity_varchar`;
  TRUNCATE `sales_order_int`;
  TRUNCATE `sales_order_text`;
  TRUNCATE `sales_order_varchar`;
  TRUNCATE `sales_flat_quote`;
  TRUNCATE `sales_flat_quote_address`;
  TRUNCATE `sales_flat_quote_address_item`;
  TRUNCATE `sales_flat_quote_item`;
  TRUNCATE `sales_flat_quote_item_option`;
  TRUNCATE `sales_flat_order_item`;
  TRUNCATE `sendfriend_log`;
  TRUNCATE `tag`;
  TRUNCATE `tag_relation`;
  TRUNCATE `tag_summary`;
  TRUNCATE `wishlist`;
  TRUNCATE `log_quote`;
  TRUNCATE `report_event`;

  ALTER TABLE `sales_order` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_int` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_text` AUTO_INCREMENT=1;
  ALTER TABLE `sales_order_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_address` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_address_item` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_item` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_quote_item_option` AUTO_INCREMENT=1;
  ALTER TABLE `sales_flat_order_item` AUTO_INCREMENT=1;
  ALTER TABLE `sendfriend_log` AUTO_INCREMENT=1;
  ALTER TABLE `tag` AUTO_INCREMENT=1;
  ALTER TABLE `tag_relation` AUTO_INCREMENT=1;
  ALTER TABLE `tag_summary` AUTO_INCREMENT=1;
  ALTER TABLE `wishlist` AUTO_INCREMENT=1;
  ALTER TABLE `log_quote` AUTO_INCREMENT=1;
  ALTER TABLE `report_event` AUTO_INCREMENT=1;
</code></pre>
<h2>删除magento所有客户数据</h2>
<p>复制下面代码到phpmyadmin中的SQL查询执行</p>
<pre><code>
TRUNCATE `customer_address_entity`;
  TRUNCATE `customer_address_entity_datetime`;
  TRUNCATE `customer_address_entity_decimal`;
  TRUNCATE `customer_address_entity_int`;
  TRUNCATE `customer_address_entity_text`;
  TRUNCATE `customer_address_entity_varchar`;
  TRUNCATE `customer_entity`;
  TRUNCATE `customer_entity_datetime`;
  TRUNCATE `customer_entity_decimal`;
  TRUNCATE `customer_entity_int`;
  TRUNCATE `customer_entity_text`;
  TRUNCATE `customer_entity_varchar`;
  TRUNCATE `log_customer`;
  TRUNCATE `log_visitor`;
  TRUNCATE `log_visitor_info`;

  ALTER TABLE `customer_address_entity` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `customer_address_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_datetime` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_decimal` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_int` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_text` AUTO_INCREMENT=1;
  ALTER TABLE `customer_entity_varchar` AUTO_INCREMENT=1;
  ALTER TABLE `log_customer` AUTO_INCREMENT=1;
  ALTER TABLE `log_visitor` AUTO_INCREMENT=1;
  ALTER TABLE `log_visitor_info` AUTO_INCREMENT=1;

  -- Now, lets Reset all ID counters
  TRUNCATE `eav_entity_store`;
  ALTER TABLE  `eav_entity_store` AUTO_INCREMENT=1;
</code></pre>
<p>删除产品图片，清空</p>
<pre>media/catalog/product</pre>
<p>目录</p>
<h2>通过写php脚本删除产品数据</h2>
<h3>Step 1. 创建skus.csv文件</h3>
<p>从magento后台导出所有产品的sku,导出文件为skus.csv</p>
<h3>Step 2. 创建php脚本文件delete-data.php</h3>
<p>在你的网站根目录创建一个php文件delete-data.php，然后复制以下代码</p>
<pre>require_once '../app/Mage.php';
Mage :: app("default") -&gt; setCurrentStore( Mage_Core_Model_App :: ADMIN_STORE_ID );
$skuAll =array();
$file_handle = fopen("skus.csv", "r");
 while (!feof($file_handle) ) {
    $line_of_text = fgetcsv($file_handle, 1024);
$allSku = $line_of_text[0];

}
$products = Mage::getResourceModel('catalog/product_collection')
    -&gt;addAttributeToSelect('*') 
    -&gt;addAttributeToFilter(
        'sku', array('in' =&gt; $allSku)
    )
    -&gt;load();

    if(is_array($products))
    {
        foreach ($products as $key =&gt; $pId)
        {
            try
            {
                $product = Mage::getModel('catalog/product')-&gt;load($pId)-&gt;delete();
                echo "successfully deleted product with ID: ". $pId ."<br />";
            } 
            catch (Exception $e) 
            {
                echo "Could not delete product with ID: ". $pId ."<br />";
            }
        }
    }</pre>]]></description>
      <pubDate>Thu, 13 Aug 2015 13:17:07 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento获取所有分类列表]]></title>
      <link>https://www.360magento.com/blog/get-all-category-listing-in-magento/</link>
      <description><![CDATA[<p>有的时候我们要显示网页所有类别或Magento的任何CMS页面。有许多不同的方式来获得的类别列表。我会告诉你如何得到所有类别您的Magento店的名单。</p>
<h2>1.显示所有的Magento分类列表(Active/Inactive)</h2>
<p>下面的代码将获取在你的magento商店里面的所有分类:</p>
<pre>$categories = Mage::getModel('catalog/category')-&gt;getCollection()-&gt;addAttributeToSelect('*');
</pre>
<h2>2. 显示所有激活的分类( Active Categories)</h2>
<p>下面的代码将获取你的magento商店里的所有激活的分类，过滤掉没有激活的分类</p>
<pre>$categories = Mage::getModel('catalog/category') -&gt;getCollection() -&gt;addAttributeToSelect('*') -&gt;addIsActiveFilter(); 
</pre>
<h2>3. 在magento中显示任意级别的并且是激活状态下的分类</h2>
<p>下面代码将获取所有特定级别的激活分类，在这里我选择了一级分类，并按照分类的name排序</p>
<pre>$categories = Mage::getModel('catalog/category') -&gt;getCollection() -&gt;addAttributeToSelect('*') -&gt;addIsActiveFilter() -&gt;addLevelFilter(1) -&gt;addOrderField('name'); 
</pre>
<h2>4. 在magento中显示特定分类存储类型</h2>
<p>下面的代码将获取所有激活的的存储特定分类</p>
<pre>getStoreCategories($sorted=false, $asCollection=false, $toLoad=true) 
$helper = Mage::helper('catalog/category'); 

// sorted by name, fetched as collection 
$categoriesCollection = $helper-&gt;getStoreCategories('name', true, false); 

// sorted by name, fetched as array 
$categoriesArray = $helper-&gt;getStoreCategories('name', false, false);</pre>
<h2>5. 在magento中只显示顶级分类</h2>
<p>下面的代码将获取所有magento顶级分类</p>
<pre>&lt;?php $_helper = Mage::helper('catalog/category') ?&gt; 
&lt;?php $_categories = $_helper-&gt;getStoreCategories() ?&gt; 
&lt;?php if (count($_categories) &gt; 0): ?&gt; 
&lt;ul&gt; 
&lt;?php foreach($_categories as $_category): ?&gt; 
&lt;li&gt; 
&lt;a href="<!--?php echo $_helper--->getCategoryUrl($_category) ?&gt;"&gt; 
&lt;?php echo $_category-&gt;getName() ?&gt; 
&lt;/a&gt; 
&lt;/li&gt; 
&lt;?php endforeach; ?&gt; 
&lt;/ul&gt; 
&lt;?php endif; ?&gt; 
</pre>
<h2>6. 在magento中显示所有顶级分类及其所有子分类</h2>
<p>下面的代码将获取所有的magento商店中顶级分类以及所有子分类</p>
<pre>&lt;?php $_helper = Mage::helper('catalog/category') ?&gt;
&lt;?php $_categories = $_helper-&gt;getStoreCategories() ?&gt;
&lt;?php $currentCategory = Mage::registry('current_category') ?&gt;
&lt;?php if (count($_categories) &gt; 0): ?&gt;
&lt;ul&gt;
&lt;?php foreach($_categories as $_category): ?&gt;
&lt;li&gt;
&lt;a href="&lt;?php echo $_helper-&gt;getCategoryUrl($_category) ?&gt;"&gt;
&lt;?php echo $_category-&gt;getName() ?&gt; //Top Level Category Listing
&lt;/a&gt;
&lt;?php $_category = Mage::getModel('catalog/category')-&gt;load($_category-&gt;getId()) ?&gt;
&lt;?php $_subcategories = $_category-&gt;getChildrenCategories() ?&gt;
&lt;?php if (count($_subcategories) &gt; 0): ?&gt;
&lt;ul&gt;
&lt;?php foreach($_subcategories as $_subcategory): ?&gt;
&lt;li&gt;
&lt;a href="&lt;?php echo $_helper-&gt;getCategoryUrl($_subcategory) ?&gt;"&gt; //Sub Category Listing
&lt;?php echo $_subcategory-&gt;getName() ?&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;?php endforeach; ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;
&lt;/li&gt;
&lt;?php endforeach; ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;
</pre>
<h2>7. 在magento中显示当前顶级分类的子分类</h2>
<p>下面的代码将获取当前顶级分类的所有子分类</p>
<pre>&lt;?php $_currentCategory = Mage::register('current_category') ?&gt;
&lt;?php $_helper = Mage::helper('catalog/category') ?&gt;
&lt;?php $_categories = $_helper-&gt;getStoreCategories() ?&gt;
&lt;?php if (count($_categories) &gt; 0): ?&gt;
&lt;ul&gt;
&lt;?php foreach($_categories as $_category): ?&gt;
&lt;li&gt;
&lt;a href="&lt;?php echo $_helper-&gt;getCategoryUrl($_category) ?&gt;" title="&lt;?php echo $_category-&gt;getName() ?&gt;"&gt;
&lt;?php echo $_category-&gt;getName() ?&gt;
&lt;/a&gt;
&lt;?php if ($_category-&gt;getId() == $_currentCategory-&gt;getId()): ?&gt;
&lt;?php $_subcategories = $_currentCategories-&gt;getChildrenCategories() ?&gt;
&lt;?php if (count($_subcategories) &gt; 0): ?&gt;
&lt;ul&gt;
&lt;?php foreach($_subcategories as $_subcategory): ?&gt;
&lt;li&gt;
&lt;a href="&lt;?php echo $_helper-&gt;getCategoryUrl($_subcategory) ?&gt;" title="&lt;?php echo $_subcategory-&gt;getName() ?&gt;"&gt;
&lt;?php echo $_subcategory-&gt;getName() ?&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;?php endforeach; ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;
&lt;?php endif; ?&gt;
&lt;/li&gt;
&lt;?php endforeach; ?&gt;
&lt;/ul&gt;
&lt;?php endif; ?&gt;
</pre>
<p>希望对你有帮助,Thanks</p>]]></description>
      <pubDate>Wed, 12 Aug 2015 09:43:43 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[论中国支付网关]]></title>
      <link>https://www.360magento.com/blog/chinese-payment-gateways/</link>
      <description><![CDATA[<p><a title="magento中国支付网关" href="http://www.360magento.com/blog/chinese-payment-gateways/"><img alt="magento中国支付网关" src="http://7xjryy.com1.z0.glb.clouddn.com/chinese_payment_gateways_insights.jpg" height="237" width="738" /></a></p>
<p>在中国的网络市场，贝宝几乎不见踪影（它主要被用于帮助中国商人向国外出口） ，因此，在中国需要依靠中国现有的主要支付网关：支付宝、财付通、中国银联等。</p>
<p>同时，通过信用卡支付的方式在中国市场也几乎不存在：中国的终端用户并不热衷于在电子商务网站上输入自己的信用卡信息。在他们的眼里，允许终端用户输入自己的信用卡信息看起来非常可疑，因此不建议在中国使用。</p>
<h2>从终端用户的角度分析，最流行的支付网关具有以下优点：</h2>
<h3>1 ）允许帐户充值和在线支付</h3>
<p>终端用户可以支付的金额为目前其支付网关帐户内的最高金额。这意味着，如果欲购买的产品高出其帐户余额，便无法完成付款。</p>
<p>另外，在中国，用户使用某种支付方式时对一次性支付的总额有一定限制，这一点非常重要。</p>
<h3>2 ）使用支付网关后被转向到银行页面</h3>
<p>在这种情况下，终端用户将被转向到他们的银行来完成支付，支付方式在此作为连通其银行账户页面的桥梁。</p>
<p>主要的支付网关都能访问大多数中国的银行。</p>
<p>对于中国的终端用户，这种付款方式尽管在付款流程优化方面不是很有效率，也同样非常受欢迎。</p>
<h3>3 ）快捷支付：支付网关直接链接到银行帐户</h3>
<p>快捷支付对于中国的终端用户是一个非常新颖的支付系统。它于2011年年底通过支付宝的快捷支付功能，在市场上首次亮相。</p>
<p>这种支付网关简化了支付过程，因为终端用户在注册支付网关的过程中已将其银行账户链接到该支付网关。随后，购买金额会从他的相应银行帐户中自动扣除。</p>
<p>支付宝、财付通和银联已经提供这种类型的支付方式。</p>
<h2>如何选择支付网关呢？</h2>
<p>如果您不知道该为您的电子商务网站选择哪种支付网关，你需要重视的第一点便是它们的受欢迎程度：</p>
<p>- 支付宝：市场占有率45％</p>
<p>- 财付通：市场占有率21％</p>
<p>- 银联：市场占有率11％</p>
<p>支付宝显然是最流行的支付网关系统，因为淘宝和天猫只使用这种支付网关。</p>
<p>另一个要考虑的标准是每个支付网关收取与交易量相应的佣金。在中国将遇到的难题是，这里并不采取固定的佣金率。因此，作为电商，您将不得不根据你的交易水平与付款网关供应商直接谈判。</p>
<p>由于与任何中国的支付网关供应商打交道都需要繁琐的行政工作，我们的客户通常在中国只采用一种在线付款方式。</p>]]></description>
      <pubDate>Wed, 12 Aug 2015 09:13:22 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[如何安装Magento 2.0]]></title>
      <link>https://www.360magento.com/blog/install-magento2/</link>
      <description><![CDATA[<p>2014年12月的Magento的2.0测试版发布。我是如此渴望得到它，因为&ldquo;Magento2将标志着一个转折点，并会扩大其市场占有率上！&rdquo;（马克拉维尔，在eBay担任产品副总裁、中型市场和Magento总经理）。&nbsp;Wow, sound great!</p>
<p><br />在等待公测版本中，我们应该抓紧时间，并开始有一个alpha版，我认为它的安装步骤，不会有太大变化。该指南是有点长，但它肯定是值得你花时间阅读<img class="wp-smiley" style="padding: 0px !important; margin: 0px 0.07em !important; outline: none; list-style: none; border: none !important; display: inline !important; box-shadow: none !important; height: 1em; width: 1em !important; vertical-align: -0.1em !important; max-width: 100%; color: #333333; font-family: 'Open Sans', sans-serif; font-size: 13.5px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24.2999992370605px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 2.72000002861023px; -webkit-text-stroke-width: 0px; max-height: 1em; background-image: none !important; background-attachment: initial !important; background-color: #ffffff; background-size: initial !important; background-origin: initial !important; background-clip: initial !important; background-position: initial !important; background-repeat: initial !important;" alt=":)" src="http://blog.magestore.com/wp-includes/images/smilies/simple-smile.png" /></p>
<p>&nbsp;</p>
<h2>在本地安装magento2</h2>
<h3>1. 安装 xampp</h3>
<p>进入<a href="https://www.apachefriends.org/index.html" target="_blank" rel="nofollow">这里安装</a></p>
<p>编辑文件: php.ini 开启以下扩展:</p>
<pre>;extension=php_openssl.dll  &rArr;  extension=php_openssl.dll
;extension=php_intl.dll        &rArr;  extension=php_intl.dll</pre>
<h3>2. 安装 composer:</h3>
<p>通过<a href="https://getcomposer.org/doc/00-intro.md" target="_blank" rel="nofollow">这个链接</a>安装 composer</p>
<p>下载 <a href="https://getcomposer.org/Composer-Setup.exe" target="_blank" rel="nofollow">Composer-Setup.exe</a> 并在本地安装</p>
<p>运行文件<a href="https://getcomposer.org/Composer-Setup.exe" target="_blank" rel="nofollow">Composer-Setup.exe</a></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装" src="http://7xjryy.com1.z0.glb.clouddn.com/1.-magento2.0.png" height="405" width="517" /></p>
<p style="text-align: justify;">&rArr;&nbsp;选择 <strong>Next</strong>继续</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第2步" src="http://7xjryy.com1.z0.glb.clouddn.com/2.-magento2.0.png" height="405" width="519" /></p>
<p style="text-align: justify;">&rArr;&nbsp;选择 <strong>Next</strong>继续</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第3步" src="http://7xjryy.com1.z0.glb.clouddn.com/3.-magento2.0.png" height="349" width="517" /></p>
<p style="text-align: justify;">选择<strong>php.exe</strong>安装在xampp的路径是 <em>C:\xampp\php\php.exe</em> 并点击 <strong>Next</strong></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第4步" src="http://7xjryy.com1.z0.glb.clouddn.com/4.-magento2.0.png" height="345" width="523" /></p>
<p style="text-align: justify;">&rArr; 选择<strong>Install</strong></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第5步" src="http://7xjryy.com1.z0.glb.clouddn.com/5.-magento2.0.png" height="404" width="525" /></p>
<p style="text-align: justify;">接下来, 等待一会儿.</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第6步" src="http://7xjryy.com1.z0.glb.clouddn.com/6.-magento2.0.png" height="417" width="517" /></p>
<p style="text-align: justify;">如果发生错误, 你看一样 <strong>任务管理器</strong>选择关闭Window Explorer。 选择<strong>Retry</strong> to continue.</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第7步" src="http://7xjryy.com1.z0.glb.clouddn.com/7.-magento2.0.png" height="374" width="516" /></p>
<p style="text-align: justify;">这个composer 安装进程将会出现下面窗口表示结束 :</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第8步" src="http://7xjryy.com1.z0.glb.clouddn.com/8.-magento2.0.png" height="407" width="526" /></p>
<p style="text-align: justify;">再次运行 Window Explorer:</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第9步" src="http://7xjryy.com1.z0.glb.clouddn.com/9.-magento2.0.png" height="368" width="517" /></p>
<h3 style="text-align: justify;">3. Install Magento 2.0</h3>
<p style="text-align: justify;">在这篇文章中，我使用的Magento2.0代码是来自 <a href="https://github.com/magento/magento2" target="_blank" rel="nofollow">https://github.com/magento/magento2</a></p>
<p style="text-align: justify;">复制magento2源码到 <strong>htdocs</strong> 本地文件夹. 然后, 右键并选择 <strong>Composer Installation</strong>在这个文件上 <em>\setup\composer.json</em></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第10步" src="http://7xjryy.com1.z0.glb.clouddn.com/10.-magento2.0.png" height="289" width="516" /></p>
<p style="text-align: justify;">显示cmd界面,你要等待一会儿</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第11步" src="http://7xjryy.com1.z0.glb.clouddn.com/11.-magento2.0.png" height="391" width="516" /></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第12步" src="http://7xjryy.com1.z0.glb.clouddn.com/12.-magento2.0.png" height="348" width="516" /></p>
<p style="text-align: justify;">登录到 <strong>mysql</strong>的管理面板phpmyadmin 来创建database</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第13步" src="http://7xjryy.com1.z0.glb.clouddn.com/13.-magento2.0.png" height="434" width="490" /></p>
<p style="text-align: justify;">在浏览器运行链接: <em>localhost/magento20/</em> 开始安装 Magento 2.0</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第14步" src="http://7xjryy.com1.z0.glb.clouddn.com/14.-magento2.01.png" height="386" width="589" /></p>
<p style="text-align: justify;">接下来就是一步步进行安装magento 2.0:</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第15步" src="http://7xjryy.com1.z0.glb.clouddn.com/15.-magento2.01.png" height="190" width="525" /></p>
<p style="text-align: justify;">Step 1: 检查服务器环境</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第16步" src="http://7xjryy.com1.z0.glb.clouddn.com/16.-magento2.01.png" height="301" width="558" /></p>
<p style="text-align: justify;">当Readiness Check 步骤完成后, 选择 <strong>Next</strong></p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第17步" src="http://7xjryy.com1.z0.glb.clouddn.com/17.-magento2.01.png" height="273" width="564" /></p>
<p style="text-align: justify;">在step 2填写服务器信息和数据库信息. 然后点击 <strong>Next</strong>继续</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第18步" src="http://7xjryy.com1.z0.glb.clouddn.com/18.-magento2.01.png" height="194" width="553" /></p>
<p style="text-align: justify;">Step 3: 提供你的网站访问链接并继续</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第19步" src="http://7xjryy.com1.z0.glb.clouddn.com/19.-magento2.01.png" height="266" width="551" /></p>
<p style="text-align: justify;">step 4: 自定义你的商店. 在进行step 5之前你可以编辑你的time zone, currency 和 language.</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第20步" src="http://7xjryy.com1.z0.glb.clouddn.com/20.-magento2.01.png" height="234" width="551" /></p>
<p style="text-align: justify;">Step 5需要你 创建管理员账号. 填入信息, 知道最后一项</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第21步" src="http://7xjryy.com1.z0.glb.clouddn.com/21.-magento2.01.png" height="207" width="554" /></p>
<p style="text-align: justify;">选择<strong>Install</strong>. 在 step 6, 你将看到以下屏幕</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第22步" src="http://7xjryy.com1.z0.glb.clouddn.com/22.-magento2.01.png" height="295" width="557" /></p>
<p style="text-align: justify;">这将需要一些时间才能完成安装. 所有的完成之后，窗口将显示为</p>
<p style="text-align: center;"><img alt="Magento 2.0 - 如何安装magento 2.0 - Composer 设置安装第23步" src="http://7xjryy.com1.z0.glb.clouddn.com/23.-magento2.02.png" height="385" width="379" /></p>
<h2 style="text-align: justify;"><span style="color: #993300;">在线上服务器安装 Magento 2.0 </span></h2>
<h3 style="text-align: justify;"><strong>1.</strong> copy源代码到服务器</h3>
<h3 style="text-align: justify;"><strong>2.</strong> 运行 puty来安装 composer</h3>
<p style="text-align: justify;">i. 移动到安装文件</p>
<pre>Cd folder_magento/setup</pre>
<p style="text-align: justify;">ii. 下载 composer</p>
<pre>curl -sS https://getcomposer.org/installer | php</pre>
<p style="text-align: justify;">iii.&nbsp;Run composer</p>
<pre>php composer.phar install</pre>
<h3 style="text-align: justify;"><strong>3.</strong> 运行magento链接地址安装，和在本地安装一样的.</h3>]]></description>
      <pubDate>Tue, 11 Aug 2015 08:23:35 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento网站seo优化之Magento高级优化]]></title>
      <link>https://www.360magento.com/blog/optimize-your-magento-website03/</link>
      <description><![CDATA[<p>3. 高级的Magento SEO 和相同的内容<br /><br />完成了所有基础的设置后，剩下的事情就是一件简单的事：相同的内容。实际上是大量的相同的内容。商品里有相同的内容，至少，在下面的URLs有完全相同的内容：<br /><br />www.360magento.com/product.html<br /><br />www.360magento.com/category1/product.html<br /><br />www.360magento.com/catalog/product/view/id/1/<br /><br />www.360magento.com/catalog/product/view/id/1/category/1/<br />此外，商品回顾页面有几乎一样的内容。另一个问题是目录，你有大量相同的内容在层级导航中和索引选择中。最坏的情况是一个商品在这个页面显示之外，至少还会在这个页面以外的4个页面中显示。<br />我们将要去掉这些相同的内容，并允许它们被蜘蛛爬但不被索引，固定目录的索引选择和层级导航。<br />3.1. 无内容页面需设置成Noindex, follow<br />安装 Yoast robots meta module 可确保设置成防止索引所有的无内容页面，如下：<br /><br />现在搜索引擎将通过所有的链接来到这些页面上但不会再索引中显示这些页面。<br /><br />3.2. Nofollowing 非必需的链接<br /><br />另一简单的步骤来提高你的 Magento SEO 是停止链接到你的登录，付款，希望购买列表和所有其他没有内容的页面。对于RSS feeds,层级导航，增加商品到希望购买列表，增加商品到比较列表来说也是同样的设置。目前还没有插件来完成这些工作。你不得不进入你的模板文件中手工完成。<br /><br />3.3. 规范的URLs<br /><br />帮助搜索引擎理解你页面中的相同内容，你可以在每个页面使用你更喜欢的URL，使用新的 canonical URL tag （规范的URL标签），你可以安装这个 Canonical URL&rsquo;s for Magento 模块完成。<br /><br />3.4. XML 地图<br /><br />XML 地图是让搜索引擎知道你的内容在哪里的简单方法，它不会帮助你提高排名，但它可以帮助你更快得到索引。你可以手工建立一个XML地图，后台点击 Catalog =&gt; Google Sitemap =&gt; Add Sitemap, 选择一个文件名，路径和商店界面，然后点击 &ldquo;Save &amp; Generate&rdquo;。<br /><br />然后你可以简单的把下面的代码放到你的 robots.txt 文件中指引搜索引擎向你的 sitemap.xml 文件:<br /><br /># Website Sitemap<br />Sitemap: http://www.360magento.com/sitemap.xml</p>]]></description>
      <pubDate>Sat, 08 Aug 2015 11:27:03 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento网站seo优化之Magento模板优化]]></title>
      <link>https://www.360magento.com/blog/optimize-your-magento-website02/</link>
      <description><![CDATA[<p>2.Magento模板优化<br /><br />2.1. 优化了的空白模板<br /><br />默认的Magento皮肤如 &ldquo;Default Theme&rdquo;, &ldquo;Blue Skin&rdquo; 和 &ldquo;Modern Theme&rdquo; 在标题方面的工作做得不好，从SEO的角度来看，有很多的地方可以改进。为使它对你变得简单，这里有一款空白的Magento SEO模板，基于Magento的核心技术，空白模板合并了所有的东西，你可以在这里下载.<br /><br />2.2. 标题<br /><br />默认的 logo 是一个 h1标签, 应该只是出现在首页，在别的页面上它应该是一个h3标签. 最重要的事实让标题的内容置于 h1 标签之中，例如，在目录页它应是目录名在商品也应是商品名。<br /><br />下一步是清除过量的标题。一个好主意是清除侧栏的标题，或者做一个和商店相关的文字（包括关键字）。在h4标签中增加关键字到标题往往对seo 是不利的. 你可以把所有标题的 h4 标签换成 div ，在div中添加 strong 标签更好。接着优化你的内容，在目录页中把商品名放在 h3 里，把目录名放在 h1里。在商品页，你应该把商品名放在h1里.<br /><br />2.3. 优化你的代码<br /><br />保持你的模板清爽，把你的模板文件中的所有 javascript 和 CSS 移到外部的 javascripts 和css 文件中，因为它们对你的Magento SEO没有任何好处。这样做可以确保你的用户在首次读取文件的时候储存那些文件，搜索引擎不需要花费大量的时间来下载它们。<br /><br />2.4. 提升magento访问速度<br /><br />一个很重要的情况是搜索引擎每一天要在你的商店爬过多少页面，你的商店的读取速度有多快。<br /><br />你可以做两件事来增加你的Magento的速度：<br /><br />激活缓存。后台点击 System =&gt; Cache Management =&gt; enable all caching features (勾选复选框).<br /><br />一个域名的主机和服务器的设置也是很重要的。用 MySQL 和 PHP opcode 缓存你可以提高你的Mageto速度。<br /><br />另一件需要考虑的就是减少外部文件的数量。每一个你让人们下载的文件，他们的浏览器会建立另一个连接到网络服务器。所以非常好的主意就是减少外部文件的数量，合并几个文件为一个文件。默认的Magento已经合并了几乎所有的 javascript 文件到一个文件中。<br /><br />但 stylesheets 文件没有合并：默认模板有6个不同的stylesheet 文件。你可以把这些文件合并成一个新文件，除了print.css文件，或者你可以安装这个扩展 Fooman Speedster module. 除了合并文件外，这个模块能压缩和缓存你的 javascript 和 stylesheet 文件。 (请注意Speedster的使用条件： mod_rewrite 必须可用，你的服务器需要支持.htaccess。 如果你在Magento同时使用规范的URLs和 Fooman Speedster，你需要利用this download 重写Canonical module 。)<br /><br />3. 高级的Magento SEO 和相同的内容<br /><br />完成了所有基础的设置后，剩下的事情就是一件简单的事：相同的内容。实际上是大量的相同的内容。商品里有相同的内容，至少，在下面的URLs有完全相同的内容：<br /><br />www.360magento.com/product.html<br /><br />www.360magento.com/category1/product.html<br /><br />www.360magento.com/catalog/product/view/id/1/<br /><br />www.360magento.com/catalog/product/view/id/1/category/1/<br />此外，商品回顾页面有几乎一样的内容。另一个问题是目录，你有大量相同的内容在层级导航中和索引选择中。最坏的情况是一个商品在这个页面显示之外，至少还会在这个页面以外的4个页面中显示。<br />我们将要去掉这些相同的内容，并允许它们被蜘蛛爬但不被索引，固定目录的索引选择和层级导航。<br />3.1. 无内容页面需设置成Noindex, follow<br />安装 Yoast robots meta module 可确保设置成防止索引所有的无内容页面，如下：<br /><br />现在搜索引擎将通过所有的链接来到这些页面上但不会再索引中显示这些页面。</p>
<p><a title="magento网站seo优化之基本优化" href="http://www.360magento.com/blog/optimize-your-magento-website01/">magento网站seo优化之基本优化</a>&nbsp;&nbsp;&nbsp;</p>]]></description>
      <pubDate>Fri, 07 Aug 2015 10:03:13 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento网站seo优化之基本优化]]></title>
      <link>https://www.360magento.com/blog/optimize-your-magento-website01/</link>
      <description><![CDATA[<p>1. 基本的技术优化<br /><br />1.1. 普通优化设置<br /><br />Magento 是搜索引擎最友好的商用平台之一，但有几点需要关注以便优化你的 Magento SEO. 第一步是在使用<span class="t_tag">最新</span>的版本中激活 Server URL rewrites. 你可以在系统按钮下找到这个选项： System =&gt; Configuration =&gt; Web =&gt; Search Engines Optimization. 激活后，在这个页面上，另一个不错的选择是设置&ldquo;Url Options &rdquo;下的 &ldquo;Add store Code to Urls&rdquo; ，在大多数情况下，把这个开关设为&ldquo;No&rdquo;更好。<br /><br />1.1.1. WWW 和 non-WWW<br /><br />在 &ldquo;Unsecure&rdquo; 和 &ldquo;Secure&rdquo; 的下拉菜单里你可以找到 Base URL, 在那里你可以设置你更喜欢的域名。你可以选择WWW的URL或者没有WWW的URL。改变这些设置你不会从www到non-www或者从 non-www到www建立一个重定向。所以你必须通过 .htaccess 文件建立 一个301重定向。除此之外，解决了 WWW vs non-WWW 的问题，这个重定向可以有效防止你的Magento URLs被加入SID问题，像?SID=b9c95150f7f70d6e77ad070259afa15d. 确保 Base URL 和重定向是一样的。编辑 .htaccess 文件时，你可以在根目录下的 .htaccess 文件中加入下面的重定向代码。<br /><br />大约 119 行:<br /><br />RewriteBase / RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /index\.php\ HTTP/<br /><br />RewriteRule ^index\.php$ http://www.mydomain.com/ [R=301,L]<br /><br />也许，你的Magento不是安装在根目录而是在某个子目录下http://www.mydomain.com/<span class="t_tag">magento</span>/:<br /><br />RewriteBase /magento/ RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /magento/index\.php\ HTTP/<br /><br />RewriteRule ^index\.php$ http://www.mydomain.com/magento/ [R=301,L]<br /><br />1.2. 页眉优化设置<br /><br />安装Magento时默认的标题是 &ldquo;Magento Commerce&rdquo;。为了你的Magento商店得到它应得得流量，以下你必须了然于胸：<br /><br />搜索引擎着重于开头的词，所以如果你的关键字靠近页面标题的开头那你有更大的可能性让排名更好。<br /><br />人们扫视结果页面，一般看开头的几个词。如果你的关键字位于页面的的开始，那你被点击的可能性就大很多。<br /><br />首先你应该去掉默认的标题 &ldquo;Magento Commerce&rdquo;. 后台点击 System =&gt; Configuration =&gt; Design =&gt; HTML Head. 为你的网站选一个描述性好的标题，这个标题也会在几个没有内容的页面中使用，比如 &ldquo;Contact Us&rdquo; 和 &ldquo;Popular Search Terms&rdquo;.<br /><br />把页面标题加到你的店名中，包括目录和商品，把你的店名放在&ldquo;标题后缀&rdquo;中。保持前缀空白是个不错的选择，原因上面提到过。同时保持 &ldquo;Default Description&rdquo; 和 &ldquo;Default Keywords&rdquo; 空白。对于非产品展示页面，为防止整站索引，设置 &ldquo;Default Robots&rdquo; 为 &ldquo;NOINDEX, NOFOLLOW&rdquo; 会有所帮助，但对于别的页面来说要确保设置为 &ldquo;INDEX, FOLLOW&rdquo;.<br /><br />接下来优化你的网店页面的 ，最好的方法是加上 new canonical tag （新的规范标签）。你可以安装 Canonical URL&rsquo;s for Magento Module 这个扩展以便把它们加到你的head种来改进你的Magento SEO。<br /><br />因某些原因Magento把未设置的meta机器人转为一个meta标签，方式如下：</p>
<div class="blockcode">
<div id="code0"><ol>
<li>&lt;meta name=&rdquo;robots&rdquo; content=&rdquo;*&rdquo; /&gt;</li>
</ol></div>
</div>
<p>这种方式会造成搜索引擎一些奇怪的行为，所以我们要把它移除。要从代码中移除这些空白的meta你可以安装 Yoast MetaRobots Module.<br /><br />1.3. CMS 页面优化设置<br /><br />第一眼看上去Magento似乎缺少华丽的CMS功能，但对于大多数使用者来说这已经足够了。简单 的CMS的好处之一是你能够控制页面的每一个方面。一旦你赋予每一个CMS页面一些不错的内容，选一个友好的URL和页面标题，（同时记住1.2小节中的 要点），到Meta数据标签处为每个你想要给它排名的 CMS页面写上描述。<br /><br />你可以保持&rdquo;Keywords&rdquo;栏空白。描述有一个很重要的作用：引诱人们去点击，所以确 保它描述的确实是他们所要点击页面的内容，那样可以引起他们的注意。因此，唯一的好的描述就是自己手写的，如果你考虑用自动描述软件来写描述，那还不如什 么也不做，让搜索引擎自动完成。<br /><br />如果你不使用meta描述，搜索引擎会在你的文件里找到关键字，并自动选择一条，那样在结果页面里会有一到两个醒目的词。<br /><br />1.4. 商品目录优化<br /><br />Magento 可以自定义目录名，让你的目录指向产品的URL。因为Magento对建立相同的内容这个功能的支持不够，很好的方式就是禁用它。设置它，点击 System =&gt; Configuration =&gt; Catalog =&gt; Search Engine Optimization and set &ldquo;Use categories path for product URL&rsquo;s to &ldquo;no&rdquo;.<br /><br />接着设置每一个目录的细节。点击Catalog =&gt; Manage Categories. 最重要的区域是：<br /><br />Meta 描述: 在这里放上吸引人的描述；记住人们会在搜索引擎的结果列表页中看到这个描述。<br /><br />页面标题: 保持页面标题空白，使用目录名包括父目录。但你按照要求制作目录时，标题会象你所输入的一样，没有父目录。<br /><br />URL 要点: 尝试保持短的但是关键字丰富的URL。移除像&ldquo;the&rdquo;，&ldquo;and&rdquo;,&rdquo;for&rdquo;等等没用的词。要注意的是你只能在&ldquo;all store views&rdquo;下设置, 对于多语种的商店你应该保持语言的独立。<br /><br />对于每一个商店界面，你可以指定名字，描述，页面标题和Meta数据。对多语种商店来说这真的是一个很棒的功能。<br /><br />1.5. 商品优化<br /><br />商品页面的优化和目录优化有些相似。你可以设置Meta信息为 &ldquo;Default Values&rdquo; 并使用于每一个 &ldquo;Store View&rdquo;. 注意对于 &ldquo;Meta Title&rdquo;, 这个将写在完全的页面标题上，包括目录但不包括标题的前缀/后缀，而不仅仅是商品的名称。<br /><br />Magento SEO中一个经常忽略的方面是你怎么处理你的图片。通过给图片写标签和考虑给你的图片起怎样的名字，你会从不同的图片搜索引擎得到不错的额外流量。</p>]]></description>
      <pubDate>Fri, 07 Aug 2015 09:51:24 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento在命令行刷新索引]]></title>
      <link>https://www.360magento.com/blog/reindex-magento-command-line/</link>
      <description><![CDATA[<p>有时，你可能会发现，需要通过命令行来重新索引Magento。这可能原因一大堆，例如，如果该索引超时或是通过Web界面没有完成。 Magento包含索引脚本，你可以找到</p>
<pre>Shell</pre>
<p>文件夹<br /> 在这个文件夹，你可以执行一些命令</p>
<h2>检查所有索引的状态</h2>
<pre>php indexer.php --status</pre>
<p>应该会输出类似下面：</p>
<pre>Product Attributes:            Pending
Product Prices:                Pending
Stock Status:                  Pending
Tag Aggregation Data:          Pending
Default Values:                Pending
Catalog URL Rewrites:          Pending
Product Flat Data:             Require Reindex
Category Flat Data:            Pending
Category Products:             Pending
Catalog Search Index:          Pending
</pre>
<h2>重新索引单个索引</h2>
<p>每个索引都有自己的索引键，当magento需要重新索引时就需要引用它，要获得这些键，你可以使用一下命令</p>
<pre>php indexer.php --info
</pre>
<p>你将会得到：</p>
<pre>catalog_product_attribute     Product Attributes
catalog_product_price         Product Prices
cataloginventory_stock        Stock Status
tag_summary                   Tag Aggregation Data
mana_db_replicator            Default Values
catalog_url                   Catalog URL Rewrites
catalog_product_flat          Product Flat Data
catalog_category_flat         Category Flat Data
catalog_category_product      Category Products
catalogsearch_fulltext        Catalog Search Index
</pre>
<p>重新索引单个索引，运行一下命令:</p>
<pre>php indexer.php --reindex [Index Option Code]
</pre>
<p>可以用逗号来分离多个索引</p>
<pre>php indexer.php --reindex catalog_product_price,catalog_url,catalog_product_flat
</pre>
<h2>重新刷新所有索引</h2>
<p>下面的代码将通过每个索引循环，来重新建立索引</p>
<pre>php indexer.php --reindexall
</pre>]]></description>
      <pubDate>Tue, 04 Aug 2015 11:10:20 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento在首页显示最新产品]]></title>
      <link>https://www.360magento.com/blog/magento-template002/</link>
      <description><![CDATA[<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;">打开Magento后台管理面板</p>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;">Go to<span class="Apple-converted-space">&nbsp;</span><code style="margin: 0px; padding: 1px 5px; border: 0px; font-size: 13px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: pre-wrap; background-color: #eeeeee;">CMS &gt; Pages &gt; Home page</code></p>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;">切换到 content 栏</p>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;">插入下面代码:</p>
<pre class="default prettyprint prettyprinted" style="margin: 0px 0px 1em; padding: 5px; border: 0px; font-size: 13px; overflow: auto; width: auto; max-height: 600px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; display: block; color: #393318; word-wrap: normal; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #eeeeee;"><code style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: inherit; background-color: #eeeeee;"><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">{{</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">block  type</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"catalog/product_new"</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;"> column_count</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"6"</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">  products_count</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"12"</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;"> name</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"home.catalog.product.new"</span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #00008b;">alias</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"product_homepage"</span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #00008b;">template</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">=</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #800000;">"catalog/product/list.phtml"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; font-size: 13px; color: #000000;">}}</span></code></pre>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;">释义:</p>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;"><code style="margin: 0px; padding: 1px 5px; border: 0px; font-size: 13px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: pre-wrap; background-color: #eeeeee;">column_count="6"</code><span class="Apple-converted-space">&nbsp;</span>&ndash; 显示产品列的数量</p>
<p style="margin: 0px 0px 1em; padding: 0px; border: 0px; font-size: 15px; clear: both; color: #222222; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 19.5px; orphans: auto; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;"><code style="margin: 0px; padding: 1px 5px; border: 0px; font-size: 13px; font-family: Consolas, Menlo, Monaco, 'Lucida Console', 'Liberation Mono', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', monospace, sans-serif; white-space: pre-wrap; background-color: #eeeeee;">products_count="12"</code><span class="Apple-converted-space">&nbsp;</span>&ndash; 显示产品的数量</p>]]></description>
      <pubDate>Wed, 27 May 2015 13:57:58 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[magento中调用静态块的几种方法 ]]></title>
      <link>https://www.360magento.com/blog/magento-template001/</link>
      <description><![CDATA[<p>在后台创建一个order_form静态块<br />Block Title :Order Form<br />Identifier :order_form<br />Status :Enabled<br />Content :自定义内容</p>
<p>1.如果要在.phtml文件中直接调用这个静态块，那可以采用以下方法</p>
<pre>    &lt;?php  
    $block = Mage::getModel('cms/block')  
     -&gt;setStoreId(Mage::app()-&gt;getStore()-&gt;getId())  
     -&gt;load('order_form');  
    $content = $block-&gt;getContent(); // Block的原始内容已经获得  
      
    $processor = Mage::getModel('core/email_template_filter');  
    echo $html = $processor-&gt;filter($content);  
    ?&gt;  
</pre>
<p>Mage::getModel('core/email_template_filter')-&gt;filter()是必须的，因为Static Block里可能包含Magento的模板语言（如:https://www.360magento.com/），fiter将翻译成实际的值 Magento中调用静态Block主要有两个地方。 是否感觉这代码太长了呢，那你还可以这么写</p>
<pre>&lt;?php echo $this-&gt;getLayout()-&gt;createBlock(&lsquo;cms/block&rsquo;)-&gt;setBlockId('order_form')-&gt;toHtml() ?&gt;
</pre>
<p>2.如何在CMS页面的Content中调用这个静态块呢？你可以采用以下方法</p>
<pre><span>{</span>{block type="cms/block"  name="cms_test_block"  block_id="order_form" }}   
</pre>
<p>将里面order_form改成你的静态块对应的block_id则可</p>
<p>3.怎么样在layout中调用静态块呢？</p>
<pre>  
&lt;reference name="footer"&gt;  
    &lt;block type="cms/block" name="order_form" before="-"&gt;  
        &lt;action method="setBlockId"&gt;&lt;block_id&gt;order_form&lt;/block_id&gt;&lt;/action&gt;  
    &lt;/block&gt;      
&lt;/reference&gt;   
   </pre>
<p>到此，你应该能够灵活的运用magento中的静态块了吧！</p>]]></description>
      <pubDate>Wed, 27 May 2015 13:33:10 +0000</pubDate>
    </item>
    <item>
      <title><![CDATA[Magento产品价格设置]]></title>
      <link>https://www.360magento.com/blog/magento_product_price/</link>
      <description><![CDATA[<p>Magento为你的产品价格提供了很多选项。你可以设置特价，定时促销等等。要编辑你的产品价格，首先登录你的Magento后台，然后进入<strong>Catalog-&gt;Manage Products</strong>。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento catalog Ma" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_1.jpg" width="auto" /></div>
<p>现在定位你要修改价格的产品上，点击它边上的Edit链接。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento price tab" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_2.jpg" width="auto" /></div>
<p>这里你将看到许多用来修改产品的选项。在左侧菜单选择Prices标签。</p>
<div class="entry-thumbnail"><img class="attachment-full wp-post-image" alt="magento product price" src="http://7xjryy.com1.z0.glb.clouddn.com/magento_product_price_3.jpg" width="auto" /></div>
<p>在这里你可以修改产品的价格，下面是一些比较重要选项的说明：</p>
<ul>
<li>Price（价格）：你要出售产品的价格，必填项，最重要的信息</li>
<li>Cost（成本）：你购买产品的价格</li>
<li>Tier Price（阶梯价格）：可根据购买数量设定折扣</li>
<li>Special Price（特价）：可设置特价及特价的起止事件，此选项不受购买数量的限制</li>
</ul>
<p>360magento提供专业的基于magento系统的<a title="magento电商网站开发" href="https://www.360magento.com/">电商网站开发</a>服务，如有需求或相关咨询，<a title="magento开发" href="https://www.360magento.com/contacts/">请与我们联系</a>。</p>]]></description>
      <pubDate>Wed, 03 Sep 2014 13:00:00 +0000</pubDate>
    </item>
  </channel>
</rss>
