标签: wordpress

  • WordPress获取文章内的第一张图片

    <?php
    // 获取文章第一张图片
    
    function catch_that_image() {
        global $post, $posts;
        $first_img = '';
        ob_start();
        ob_end_clean();
        $output = preg_match_all('/<img.+?src=[\'"]([^\'"]+)[\'"].*?>/i', $post->post_content, $matches);
        $first_img = $matches[1][0];
        if (empty($first_img)) {
            $first_img = "/path/to/default.png";
        }
        return $first_img;
    }

    改进版,增加了默认图片的显示,以及文章中没有图片时的判断:

    <?php
    // 获取文章第一张图片
    function catch_that_image() {
        global $post, $posts;
        $first_img = '';
        ob_start();
        ob_end_clean();
        $output = preg_match_all('/<img.+?src=[\'"]([^\'"]+)[\'"].*?>/i', $post->post_content, $matches);
        if ($output) {
            $first_img = $matches[1][0];
        }
    
        if (empty($first_img)) {
            $first_img = bloginfo('template_url') . "/assets/images/default_image.jpeg";
        }
        return $first_img;
    }

    默认图片:default_image.jpeg,需要自己找一张。

  • WordPress分页改不了分页URL的问题,并且分页 页面提示“找不到页面”

    一个分页问题搞了一晚上和一上午,分页函数`paginate_links`生成的链接一直是`/page/2`这种,并且打不开,提示找不到页面。

    google+baidu 几乎找遍了也没找到解决方案。最后在看`paginate_links`参数时,发现第一个参数`base`的意思是”Base of the paginated url”,翻译过来就是“分页URL的基础”,忽然意识到是不是这个参数的原因。

    由于之前分页代码是在网上随便找的,`base`参数是

    $big = 999999999;
    'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),

    打印了一下它的值是https://lwbj.cn/case/page/%#%,也就是说生成的分页链接就是/case/page/%#%这种格式的。

    那么到此就可以确定是该参数的问题,解决办法就是不使用该参数,或者使用它的默认值%_%,即可把分页URL改成https://lwbj.cn/case?page=2这种默认样式。

    至于为什么只有默认URL样式才能访问,而page/2这样样式会找不到页面,就不得而知了。

    最终改过之后的代码如下:

    global $wp_query;
    echo paginate_links( array(
         'base' => '%_%',
         'format' => '?page=%#%',
         'current' => max( 1, get_query_var('page') ),
         'total' => $wp_query->max_num_pages
     ) );

    附一个兼容boostrap4的分页样式:

    // 兼容bootstrap4的分页
    function bootstrap_pagination(\WP_Query $wp_query = null, $echo = true) {
        if (null === $wp_query) {
            global $wp_query;
        }
    
        $pages = paginate_links(
            [
                //'base'         => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
                'format'       => '?page=%#%',
                'current'      => max(1, get_query_var('paged')),
                'total'        => $wp_query->max_num_pages,
                'type'         => 'array',
                'show_all'     => false,
                'end_size'     => 3,
                'mid_size'     => 1,
                'prev_next'    => true,
                'prev_text'    => __('« 上一页'),
                'next_text'    => __('下一页 »'),
                'add_args'     => false,
                'add_fragment' => ''
            ]
        );
    
        if (is_array($pages)) {
            //$paged = ( get_query_var( 'paged' ) == 0 ) ? 1 : get_query_var( 'paged' );
            $pagination = '<div class="pagination"><ul class="pagination">';
            foreach ($pages as $page) {
                $pagination .= '<li class="page-item' . (strpos($page, 'current') !== false ? ' active' : '') . '"> ' . str_replace('page-numbers', 'page-link', $page) . '</li>';
            }
            $pagination .= '</ul></div>';
            if ($echo) {
                echo $pagination;
            } else {
                return $pagination;
            }
        }
        return null;
    }

    经验教训:复制网上的代码时,要弄懂每一行在干什么,不要随意粘贴到自己的项目中。

  • WordPress创建自定义文章类型 CPT (custom post type)

    注册自定义文章类型,代码如下:

    add_action('init', 'my_custom_post_product');
    function my_custom_post_product() {
        $labels = array(
            'name'               => _x('产品中心', 'post type 名称'),
            'singular_name'      => _x('产品', 'post type 单个 item 时的名称,因为英文有复数'),
            'add_new'            => _x('添加产品', '添加新内容的链接名称'),
            'add_new_item'       => __('添加新产品'),
            'edit_item'          => __('编辑产品'),
            'new_item'           => __('新产品'),
            'all_items'          => __('产品列表'),
            'view_item'          => __('查看产品'),
            'search_items'       => __('搜索产品'),
            'not_found'          => __('没有找到有关产品'),
            'not_found_in_trash' => __('回收站里面没有相关产品'),
            'parent_item_colon'  => '',
            'menu_name'          => '产品管理'
        );
    
        $args = array(
            'labels'        => $labels,
            'description'   => '我们网站的产品信息',
            'public'        => true,
            'menu_position' => 5,
            'menu_icon'     => 'dashicons-money-alt',
            // 支持的功能,还可以添加:'excerpt', ,  'comments'
            'supports'      => array('title', 'editor', 'thumbnail'),
            /*这个设置为true,
            才能在前台 single-[post_type].php 和 archive-[post_type].php 显示列表*/
            'has_archive'   => true
    
        );
        // 注册文章类型,第一个参数为类型名称,即post type name
        register_post_type('product', $args);
    }
    
    为新注册的类型,添加分类功能,代码如下:
    
    /**
     * 为产品 post type 添加分类功能
     */
    add_action('init', 'my_taxonomies_product', 0);
    function my_taxonomies_product() {
        $labels = array(
            'name'              => _x('产品分类', 'taxonomy 名称'),
            'singular_name'     => _x('产品分类', 'taxonomy 单数名称'),
            'search_items'      => __('搜索产品分类'),
            'all_items'         => __('所有产品分类'),
            'parent_item'       => __('该产品分类的上级分类'),
            'parent_item_colon' => __('该产品分类的上级分类:'),
            'edit_item'         => __('编辑产品分类'),
            'update_item'       => __('更新产品分类'),
            'add_new_item'      => __('添加新的产品分类'),
            'new_item_name'     => __('新产品分类'),
            'menu_name'         => __('产品分类'),
        );
    
        $args = array(
            'labels' => $labels,
            'hierarchical' => true,
        );
        /** 注册分类,第一个参数为分类法的名字,即taxonomy
        第二个参数为该分类属于哪个文章类型 */
        register_taxonomy('product_category', 'product', $args);
    }
    
    
    为新注册的文章类型添加额外的输入框,即 meta box
    
    /**
     * 为产品发布类型 添加自定义 Meta Box
     * 功能特征 meta box
     */
    add_action('add_meta_boxes', 'product_gongneng');
    function product_gongneng() {
        // add_meta_box( $id, $title, $callback, $post_type, $context,$priority, $callback_args );
        add_meta_box(
            'product_gongneng',                 // id
            '功能特征',                          // title        
            'product_gongneng_meta_box',        // callback
            'product',                          // post_type
            'normal',                           // context
            'low'                               // priority
        );
    }
    
    /**
     * 为meta box 添加html表单
     */
    function product_gongneng_meta_box($post) {
        // 创建临时隐藏表单,为了安全
        wp_nonce_field('product_gongneng_meta_box', 'product_gongneng_meta_box_nonce');
    
        // 获取之前存储的值
        $field_value = get_post_meta($post->ID, '_product_gongneng', false);
    ?>
        <p>
            <label for="_product_gongneng"></label>
            <?php
            $settings = array(
                'quicktags' => array('buttons' => 'em,strong,link',),
                'quicktags' => true,
                'tinymce' => true,
                'editor_height' => 100, // In pixels, takes precedence and has no default value
                'textarea_rows' => 20,  // Has no visible effect if editor_height is set, default is 20
            );
    
            wp_editor(html_entity_decode($field_value[0]), '_product_gongneng', $settings);
            ?>
        </p>
    <?php
    
    }
    
    
    // 保存meta_box
    add_action('save_post', 'product_gongneng_save_meta_box');
    function product_gongneng_save_meta_box($post_id) {
        // 安全检查
        // 检查是否发送了一次性隐藏表单内容(判断是否为第三者模拟提交)
        if (!isset($_POST['product_gongneng_meta_box_nonce'])) {
            echo 'a11111';
            exit();
            return;
        }
    
        // 判断隐藏表单的值与之前是否相同
        if (!wp_verify_nonce($_POST['product_gongneng_meta_box_nonce'], 'product_gongneng_meta_box')) {
            echo '222';
            exit();
            return;
        }
    
        // 判断该用户是否有权限
        if (!current_user_can('edit_post', $post_id)) {
            echo '333';
            exit();
            return;
        }
    
    
        // 判断 Meta Box 是否为空
        if (!isset($_POST['_product_gongneng'])) {
            echo '444';
            exit();
            return;
        }
    
        // 使用 wpautop 函数,是因为表单中 使用了富文本编辑器,要对文本进行处理
        $gongeng = htmlentities(wpautop($_POST['_product_gongneng']));
        $_product_gongneng = sanitize_text_field($gongeng);
        // 把字段值保存到数据库
        update_post_meta($post_id, '_product_gongneng', $_product_gongneng);
    }
  • wordpress获取某个分类下文章的标签列表

    WordPress 提供了函数来获取某个分类下文章的标签列表。可以使用 get_terms()wp_get_post_tags() 函数来实现该功能。

    // 获取特定分类下的标签
    $category_id = 1; // 替换为你想要查询的分类ID
    $tags = get_terms( array(
        'taxonomy' => 'post_tag', // 标签的 taxonomy 名称
        'object_ids' => get_posts( array(
            'posts_per_page' => -1,
            'post_type' => 'post',
            'post_status' => 'publish',
            'category' => $category_id, // 指定分类ID
            'fields' => 'ids',
        ) ),
        'hide_empty' => false, // 设置为 false 以包括没有文章的标签
    ) );
    
    // 输出标签
    if ( ! is_wp_error( $tags ) && ! empty( $tags ) ) {
        foreach ( $tags as $tag ) {
            echo $tag->name . '<br>';
        }
    } else {
        echo '没有标签';
    }
    
  • wordpress获取某一篇文章所在分类的子分类

    要获取某篇文章所在分类的子分类,可以首先通过 get_the_category() 获取文章的分类 ID,然后再根据该分类的 ID 获取子分类。

    以下是一个示例代码:

    $post_id = 123; // 文章的 ID
    $categories = get_the_category($post_id);
    
    if (!empty($categories)) {
        $parent_category_id = $categories[0]->term_id; // 获取文章的第一个分类的 ID
        $taxonomy = 'category'; // 分类的 taxonomy,通常是 'category'
    
        $args = array(
            'taxonomy'     => $taxonomy,
            'parent'        => $parent_category_id,
            'hide_empty'    => false, // 是否排除没有文章的分类
        );
    
        $subcategories = get_terms($args);
    
        if (!empty($subcategories) && !is_wp_error($subcategories)) {
            foreach ($subcategories as $subcategory) {
                echo '子分类名称: ' . $subcategory->name . '<br>';
                echo '子分类链接: ' . get_term_link($subcategory) . '<br>';
            }
        } else {
            echo '没有找到子分类。';
        }
    } else {
        echo '文章没有分类。';
    }
    

    说明:

    • get_the_category($post_id) 获取文章所属的分类。如果文章属于多个分类,它会返回一个分类数组,这里我们使用了第一个分类的 ID($categories[0]->term_id)。
    • 然后,使用该分类 ID 查询其子分类,get_terms() 返回该分类下的子分类列表。

    这段代码假设文章有至少一个分类,并且你希望基于第一个分类获取子分类。如果文章有多个分类,你可以根据需求修改代码,选择不同的分类来获取子分类。

  • wordPress 取某个分类的子分类

    在 WordPress 中,可以通过 get_terms() 函数来获取某个分类的子分类。假设你已经知道父分类的 ID,可以使用如下代码来获取该父分类的子分类:

    $parent_category_id = 123; // 父分类的 ID
    $taxonomy = 'category'; // 分类的 taxonomy,通常是 'category'
    
    $args = array(
        'taxonomy'     => $taxonomy,
        'parent'        => $parent_category_id,
        'hide_empty'    => false, // 是否排除没有文章的分类
    );
    
    $subcategories = get_terms($args);
    
    if (!empty($subcategories) && !is_wp_error($subcategories)) {
        foreach ($subcategories as $subcategory) {
            echo '子分类名称: ' . $subcategory->name . '<br>';
            echo '子分类链接: ' . get_term_link($subcategory) . '<br>';
        }
    } else {
        echo '没有找到子分类。';
    }
    

    说明:

    • parent:传入父分类的 ID 来获取其子分类。
    • taxonomy:指定要查询的分类法(通常是 category)。
    • hide_empty:设置为 false 以确保获取所有子分类,包括没有文章的分类。

    你可以根据需要调整查询参数,获取不同的分类或更复杂的分类数据。

  • WordPress 修改附件元数据

    今天修改了一张图片的名字,以为在数据库里同步修改就行了,结果不是那么回事,在wp_postmeta表中有个meta_key字段保存了一个附件的元数据,meta_key的值是_wp_attachment_metadata,对应的meta_value是附件的元数据,如下图所示:

    这个元数据是不能直接编辑的,要用代码生成,代码如下:

    // 获取附件ID
    $attachment_id = 3261; // 请根据实际的附件ID修改
    
    // 获取附件元数据
    $metadata = wp_get_attachment_metadata( $attachment_id );
    
    // 修改文件路径和文件名
    $new_file = '2023/08/zaochencongzhongwukaishi.jpeg'; // 新的文件路径
    $metadata['file'] = $new_file;
    
    // 修改各个尺寸的路径(如果有需要)
    foreach ( $metadata['sizes'] as $size => $size_data ) {
        $metadata['sizes'][$size]['file'] = str_replace('zaochenchongzhongwukaishi', 'zaochencongzhongwukaishi', $size_data['file']);
    }
    
    // 更新附件元数据
    wp_update_attachment_metadata( $attachment_id, $metadata );

    注意在执行这段代码前,不要动原来的元数据。

    可以把这面代码放在functions.php里执行,或者放到某个插件代码文件里执行都行。执行完了记得删除。

    补充:附件ID需要到wp_posts表找。

  • 给wordpress添加归档页面

    今天给另一个网站增加一个文章归档功能,步骤如下:

    1、复制page.php,改名为archive.php,并在最顶部添加以下代码,告诉wordpress这是一个模板

    /*
    Template Name: Archives
    */

    2、把page.php中间输出内容的部分换成我们的归档代码。

    完整代码如下:

    <?php
    /*
    Template Name: Archives
    */
    get_header(); ?>
    
    <style>
    	.monthly-posts {
    		list-style-type: none;
    		/* 去掉默认的列表样式 */
    		padding-left: 0;
    		/* 去掉外边距 */
    	}
    
    	.monthly-posts li {
    		margin-left: 20px;
    		/* 为每个文章项添加左侧缩进 */
    		line-height: 1.8;
    		/* 增加行高让显示更清晰 */
    
    		margin-left: 20px;
    		line-height: 1.6;
    		margin-bottom: 5px;
    		/* 增加每个列表项之间的间距 */
    	}
    
    	.monthly-posts li a {
    		font-weight: bold;
    		/* 强调文章标题 */
    	}
    
    
    	.monthly-posts li span.post-date {
    		font-size: 0.9em;
    		color: #666;
    		/* 设置日期的颜色 */
    		margin-left: 10px;
    	}
    
    	/* 针对 <p> 标签样式进行调整 */
    	.monthly-posts p.post-excerpt {
    		font-size: 1em;
    		color: #444;
    		/* 设置摘要文本颜色 */
    		margin-top: 5px;
    		line-height: 1.6;
    		margin-left: 40px;
    		/* 添加左侧缩进 */
    	}
    
    	h3 {
    		font-size: 1.2em;
    		color: #333;
    		margin-top: 20px;
    		margin-bottom: 10px;
    	}
    
    	.post-count {
    		margin-top: 30px;
    		font-size: 1.2em;
    		font-weight: bold;
    		color: #333;
    		text-align: center;
    	}
    </style>
    
    
    <div id="primary" class="site-content">
    	<div id="content" role="main">
    
    		<?php
    		// 获取按月归档的日期
    		$archives = $wpdb->get_results("
        SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month
        FROM $wpdb->posts
        WHERE post_status = 'publish'
        ORDER BY post_date DESC
    ");
    
    		// 遍历每个月的归档
    		if ($archives) :
    			foreach ($archives as $archive) :
    				// 获取当前月份的文章
    				$year_month = $archive->year . '-' . str_pad($archive->month, 2, '0', STR_PAD_LEFT);
    
    				// 设置自定义查询来列出该月的文章
    				$query = new WP_Query(array(
    					'year'  => $archive->year,
    					'monthnum' => $archive->month,
    					'posts_per_page' => -1 // -1 表示列出该月所有文章
    				));
    
    				// 如果该月有文章,显示月份和文章列表
    				if ($query->have_posts()) :
    					echo '<h3>' . $archive->year . '年' . $archive->month . '月</h3>';
    					echo '<ul class="monthly-posts">';
    					while ($query->have_posts()) : $query->the_post();
    						// 获取文章的发布日期
    						$post_date = get_the_date('Y年m月d日'); // 修改为你想要的日期格式
    						echo '<li><a href="' . get_permalink() . '" title="' . get_the_title() . '">' . get_the_title() . '</a>  <span class="post-date">- ' . $post_date . '</span></li>';
    						// 输出文章摘要
    						echo '<p class="post-excerpt">' . get_the_excerpt() . '</p>';
    					endwhile;
    					echo '</ul>';
    				endif;
    
    				// 重置查询
    				wp_reset_postdata();
    			endforeach;
    		else :
    			echo '<p>没有按月归档的文章。</p>';
    		endif;
    		?>
    
    		<?php
    		// 获取已发布文章的数量
    		$post_count = wp_count_posts()->publish;
    		?>
    
    		<div class="post-count">
    			<p>总共写了 <?php echo $post_count; ?> 篇文章。</p>
    		</div>
    
    
    	</div><!-- #content -->
    </div><!-- #primary -->
    
    <?php get_sidebar(); ?>
    <?php get_footer(); ?>

    3、把archive.php传到服务器主题目录下,并新建一个页面,在该新建页面里面选择模板,选择Archives,保存即可。

  • WordPress 禁止更新大版本,只允许小版本更新

    如果不希望 WordPress 自动更新大版本,同时也不想在后台更新页看到新版本的更新提醒,可以在主题的functions.php里面添加如下代码:

    // 允许自动更新小版本,但禁止大版本更新
    add_filter( 'allow_major_auto_update', '__return_false' );
    add_filter( 'allow_minor_auto_update', '__return_true' );
    
    // 禁止后台更新页面显示新版本更新提示
    add_filter( 'site_transient_update_core', function( $value ) {
        if ( is_object( $value ) && isset( $value->updates ) ) {
            foreach ( $value->updates as $key => $update ) {
                // 移除新版本更新提示
                if ( version_compare( $update->current, get_bloginfo( 'version' ), '>' ) ) {
                    unset( $value->updates[ $key ] );
                }
            }
        }
        return $value;
    } );

    加上这段代码后,如果有新的小版本,那么 WordPress 会默默地自动更新,不管是大版本还是小版本,都不会在后台更新页进行提示,以免干扰用户。

    科普一下WordPress的版本规则,例如版本6.6.2,6.6是一个大版本,.2是一个小版本,禁止大版本更新就是禁止从6.6升级到6.7或7.x;允许小版本更新,就是允许从6.6.2升级到6.6.3这样的。

    参考链接:https://make.wordpress.org/core/handbook/about/release-cycle/version-numbering/

  • 给 WordPress 添加文章浏览量统计功能

    前几天给网站添加了文章的浏览量统计功能,但统计了几天后发现,统计了个寂寞,来访的除了蜘蛛就是自己,意义不大,索性删除了罢。想要统计,后面可以接入专门的网站统计系统,比如Google Analytics。下面把wordpress文章统计代码分享出来。

    下面的代码我是加到functions.php里面的,当然,也可以做成插件。

    /**
     * 获取文章阅读量
     *
     * @since 2024.10.25
     *
     */
    function getPostViews($postID){
        $count_key = 'post_views_count';
        $count = get_post_meta($postID, $count_key, true);
        if($count==''){
            delete_post_meta($postID, $count_key);
            add_post_meta($postID, $count_key, '0');
            return "0";
        }
        return $count;
    }
    
    /**
     * 更新文章阅读量
     *
     * @since 2024.10.25
     *
     */
    function setPostViews($postID) {
        // 检查用户是否已登录
        if (is_user_logged_in()) {
            return; // 已登录用户,不执行统计
        }
        $count_key = 'post_views_count';
        $count = get_post_meta($postID, $count_key, true);
        if($count==''){
            $count = 0;
            delete_post_meta($postID, $count_key);
            add_post_meta($postID, $count_key, '0');
        }else{
            $count++;
            update_post_meta($postID, $count_key, $count);
        }
    }
    // Remove issues with prefetching adding extra views
    remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0);

    使用方法:

    setPostViews函数加到single.php里面,如果有访问就会调用该函数实现文章阅读统计。然后在适当的地方调用getPostViews函数用于获取文章的阅读量。

    当然,也可以完善setPostViews函数,使之不统计蜘蛛的流量,要实现也不难,通过useragent来判断即可。但既然觉得这事没有意义,也就懒得去做了。

    补充:

    既然去掉了该功能,那么数据库里产生的统计数据就要删除掉:

    DELETE FROM wp_postmeta WHERE meta_key = 'post_views_count';