我扩展了 woocommerce 的产品帖子类型,使其具有一个名为“expired”的自定义 post_status。
期望的行为是将产品发布到商店并将其设置为在特定时间跨度后过期。
只有已发布的产品应该在商店中可见,但在 post_status 设置为过期后产品的永久链接应该仍然有效,但显示不同的模板。
默认情况下,Woocommerce 本身仅显示带有“发布”post_status 的产品(在商店和单一产品 View 中),所以我最初的想法是简单地连接到 pre_get_posts 和将“expired”添加到 post_status 查询变量。
一点补充是对帖子、产品和页面使用相同的 slug。
http://example.com/product-name
为了完成这一切,我想出了以下代码:
add_action(
'pre_get_posts',
'custom_pre_get_posts'
);
function custom_pre_get_posts($query) {
global $wpdb;
if( !is_admin() && $query->is_main_query() && $post_name = $query->get('name')) {
$result = $wpdb->get_row(
$wpdb->prepare(
'SELECT post_type, ID, post_status FROM '.$wpdb->posts.' WHERE post_name = %s LIMIT 1',
$post_name
)
);
if(!empty($result) && $result->post_type == 'product'){
$query->set('name', $post_name);
$query->set('product', $post_name);
$query->set('post_type', $result->post_type);
$query->set('post_status', $result->post_status);
}
}
}
只是手动检查具有给定名称的帖子是否存在以及它的 post_status 是什么。之后,相应地设置查询变量。
并包含过期产品的自定义模板:
add_filter(
'template_include',
'custom_expired_templates',
99
);
function custom_expired_templates($template){
global $wp_query;
$status = $wp_query->get('post_status');
$type = $wp_query->get('post_type');
if($status === 'expired' && $type ==='product'){
$template = locate_template( array( 'woocommerce/expired-single-product.php' ) );
}
return $template;
}
woocommerce/expired-single-product.php 只是我主题目录中 woocmmerce/single-product.php 的普通副本。
上面的代码有效...但是这样做似乎有点老套,因为自定义模板得到了显示,但是 wordpress 发送了一个 404 header 并且标题被设置为“找不到页面”,所以我基本上是覆盖了404 模板。
副作用是 woocommerce 样式和脚本不会加载。我真的试图深入研究 woocommerce 的文档,但我无法找出错误。
关于实现所需行为的正确方法有什么建议吗?
更新
通过添加验证生成的 SQL 查询
add_action('the_posts','test_sql_request');
function test_sql_request($posts){
echo $GLOBALS['wp_query']->request;
var_dump($posts);
return $posts;
}
过期产品有SQL请求:
SELECT wp_posts.* FROM wp_posts WHERE 1=1 AND wp_posts.post_name = 'expired-product' AND wp_posts.post_type = 'product' AND ((wp_posts.post_status = 'expired')) ORDER BY wp_posts.post_date DESC
但它返回一个空数组。在 phpmyadmin 中运行确切的查询返回了正确的帖子。除了 post_status 和 name(不言自明)之外,发布产品的查询看起来完全相同......但返回数组中的正确帖子。
最佳答案
好的,所以失败不在上面发布的代码中,而是在 post_status 本身的注册中:
function my_custom_post_status(){
register_post_status( 'expired', array(
'label' => _x( 'expired', 'product' ),
'public' => false,
'exclude_from_search' => true,
'show_in_admin_all_list' => true,
'show_in_admin_status_list' => true,
'label_count' => _n_noop( 'Expired <span class="count">(%s)</span>', 'Expired <span class="count">(%s)</span>' ),
) );
}
add_action( 'init', 'my_custom_post_status' );
有问题的部分是
'public' => false
并且必须更改为
'public' => true
我不知道 public 属性影响查询,即使你查询 ID。过期产品的 ID 为 103,$post = new WP_Query('p=103'); 不会返回单个帖子,其中 $post = get_post(103); 确实返回了正确的帖子。
也许这可以防止将来遇到类似情况的人头疼。
关于php - woocommerce 过期产品自定义 post_status,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31450231/
是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
rails中是否有任何规定允许站点的所有AJAXPOST请求在没有authenticity_token的情况下通过?我有一个调用Controller方法的JqueryPOSTajax调用,但我没有在其中放置任何真实性代码,但调用成功。我的ApplicationController确实有'request_forgery_protection'并且我已经改变了config.action_controller.consider_all_requests_local在我的environments/development.rb中为false我还搜索了我的代码以确保我没有重载ajaxSend来发送
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty