প্রশ্নগুলি বাছাই করার সময় প্রাথমিক নিবন্ধগুলি (যেমন 'এ', 'এ' বা '') উপেক্ষা করছেন?


13

আমি বর্তমানে সংগীতের শিরোনামগুলির একটি তালিকা আউটপুট দেওয়ার চেষ্টা করছি এবং শিরোনামের প্রাথমিক নিবন্ধটি বাছাই করা উপেক্ষা করতে চাই (তবে এখনও প্রদর্শিত)।

উদাহরণস্বরূপ, যদি আমার কাছে ব্যান্ডগুলির একটি তালিকা থাকে তবে এটি বর্ণমালা অনুসারে ওয়ার্ডপ্রেসে প্রদর্শিত হবে:

  • ব্ল্যাক সাবাথ
  • নেতৃত্বে জেপেলিন
  • গোলাপী ফ্লয়েড
  • দ্য বিট্লস
  • দ্য কিঙ্কস
  • ঘূর্ণায়মান পাথর
  • পাতলা লিজি

পরিবর্তে আমি প্রাথমিক আর্টিকেল 'দ্য' উপেক্ষা করার সময় এটি বর্ণানুক্রমিকভাবে প্রদর্শন করতে চাই:

  • দ্য বিট্লস
  • ব্ল্যাক সাবাথ
  • দ্য কিঙ্কস
  • নেতৃত্বে জেপেলিন
  • গোলাপী ফ্লয়েড
  • ঘূর্ণায়মান পাথর
  • পাতলা লিজি

আমি গত বছর থেকে একটি ব্লগ এন্ট্রি একটি সমাধান জুড়ে এসেছি , যা নিম্নলিখিত কোডের পরামর্শ দেয় functions.php:

function wpcf_create_temp_column($fields) {
  global $wpdb;
  $matches = 'The';
  $has_the = " CASE 
      WHEN $wpdb->posts.post_title regexp( '^($matches)[[:space:]]' )
        THEN trim(substr($wpdb->posts.post_title from 4)) 
      ELSE $wpdb->posts.post_title 
        END AS title2";
  if ($has_the) {
    $fields .= ( preg_match( '/^(\s+)?,/', $has_the ) ) ? $has_the : ", $has_the";
  }
  return $fields;
}

function wpcf_sort_by_temp_column ($orderby) {
  $custom_orderby = " UPPER(title2) ASC";
  if ($custom_orderby) {
    $orderby = $custom_orderby;
  }
  return $orderby;
}

এবং তারপরে add_filterআগে এবং remove_filterপরে কোয়েরিটি মোড়ানো ।

আমি এটি চেষ্টা করেছি, তবে আমি আমার সাইটে নিম্নলিখিত ত্রুটিটি পেয়ে যাচ্ছি:

ওয়ার্ডপ্রেস ডাটাবেস ত্রুটি: [অজানা কলাম 'শিরোনাম 2' 'ক্রম ধারা']

Wp_posts নির্বাচন করুন। * Wp_posts থেকে যেখানে 1 = 1 এবং wp_posts.post_type = 'রিলিজ' এবং (wp_posts.post_status = 'প্রকাশ' বা 'wp_posts.post_status =' প্রাইভেট ') অর্ডার বা শিরোনাম 2 দ্বারা ASC

আমি মিথ্যা বলব না, আমি ওয়ার্ডপ্রেসের পিএইচপি অংশে বেশ নতুন, তাই কেন আমি এই ত্রুটি পাচ্ছি তা সম্পর্কে আমি নিশ্চিত নই। আমি দেখতে পাচ্ছি যে এটি 'শিরোনাম 2' কলামটির সাথে কিছু করার ছিল, তবে এটি আমার বোঝা ছিল যে প্রথম ফাংশনটি এটির যত্ন নেওয়া উচিত। এছাড়াও, যদি এটি করার কোনও স্মার্ট উপায় থাকে তবে আমি সকলেই কান। আমি এই সাইটটি প্রায় ঘুরে বেড়াচ্ছি এবং অনুসন্ধান করে যাচ্ছি, তবে সত্যিকার অর্থে আমি খুব বেশি সমাধান খুঁজে পাইনি।

ফিল্টারগুলি ব্যবহার করে আমার কোডটি কোনওরকম সহায়তা হলে এটি দেখতে এমন দেখাচ্ছে:

<?php 
    $args_post = array('post_type' => 'release', 'orderby' => 'title', 'order' => 'ASC', 'posts_per_page' => -1, );

    add_filter('post_fields', 'wpcf_create_temp_column'); /* remove initial 'The' from post titles */
    add_filter('posts_orderby', 'wpcf_sort_by_temp_column');

    $loop = new WP_Query($args_post);

    remove_filter('post_fields', 'wpcf_create_temp_column');
    remove_filter('posts_orderby', 'wpcf_sort_by_temp_column');

        while ($loop->have_posts() ) : $loop->the_post();
?>

1
বিকল্প সমাধান হ'ল আপনি যে শিরোনামটি পোষ্ট মেটা ডেটা হিসাবে বাছাই করতে চান তা শিরোনামের পরিবর্তে সেই ক্ষেত্রটিতে অর্ডার করতে পারেন।
মিলো

কীভাবে তা চালানো যায় সে সম্পর্কে আমি কিছুটা অনিশ্চিত। একটি নতুন কলামের ফলাফলটিতে বর্তমানে যেটি পাচ্ছি তার অনুরূপ একটি ত্রুটিযুক্তটি এটি সংরক্ষণ করে রাখবে না?
আরপিবিটিজ

1
আপনি এই কোডটির কোনও ব্যবহার করবেন না, আপনি মেটা ক্যোয়ারী প্যারামিটারগুলির সাথে পোস্ট মেটাতে কোয়েরি করতে পারেন এবং বাছাই করতে পারেন ।
মিলো

উত্তর:


8

সমস্যাটি

আমি মনে করি সেখানে একটি টাইপো আছে:

ফিল্টারটির নাম posts_fieldsনেই post_fields

title2ক্ষেত্রটি কেন অজানা তা এটি ব্যাখ্যা করতে পারে কারণ উত্পাদিত এসকিউএল স্ট্রিংয়ে এর সংজ্ঞা সংযুক্ত করা হয়নি।

বিকল্প - একক ফিল্টার

আমরা এটি কেবল একটি একক ফিল্টার ব্যবহার করতে আবার লিখতে পারি:

add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    // Do nothing
    if( '_custom' !== $q->get( 'orderby' ) )
        return $orderby;

    global $wpdb;

    $matches = 'The';   // REGEXP is not case sensitive here

    // Custom ordering (SQL)
    return sprintf( 
        " 
        CASE 
            WHEN {$wpdb->posts}.post_title REGEXP( '^($matches)[[:space:]]+' )
                THEN TRIM( SUBSTR( {$wpdb->posts}.post_title FROM %d )) 
            ELSE {$wpdb->posts}.post_title 
        END %s
        ",
        strlen( $matches ) + 1,
        'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'     
    );

}, 10, 2 );

যেখানে এখন আপনি _customঅর্ডারবাই প্যারামিটার দিয়ে কাস্টম অর্ডারিং সক্রিয় করতে পারেন :

$args_post = array
    'post_type'      => 'release', 
    'orderby'        => '_custom',    // Activate the custom ordering 
    'order'          => 'ASC', 
    'posts_per_page' => -1, 
);

$loop = new WP_Query($args_post);

while ($loop->have_posts() ) : $loop->the_post();

বিকল্প - পুনরাবৃত্তি TRIM()

আসুন পাস্কাল বার্চলারের পুনরাবৃত্ত ধারণাটি বাস্তবায়ন করি , এখানে মন্তব্য করেছেন :

add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    if( '_custom' !== $q->get( 'orderby' ) )
        return $orderby;

    global $wpdb;

    // Adjust this to your needs:
    $matches = [ 'the ', 'an ', 'a ' ];

    return sprintf( 
        " %s %s ",
        wpse_sql( $matches, " LOWER( {$wpdb->posts}.post_title) " ),
        'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'     
    );

}, 10, 2 );

যেখানে আমরা উদাহরণস্বরূপ পুনরাবৃত্ত ফাংশনটি এটি তৈরি করতে পারি:

function wpse_sql( &$matches, $sql )
{
    if( empty( $matches ) || ! is_array( $matches ) )
        return $sql;

    $sql = sprintf( " TRIM( LEADING '%s' FROM ( %s ) ) ", $matches[0], $sql );
    array_shift( $matches );    
    return wpse_sql( $matches, $sql );
}

এই যে মানে

$matches = [ 'the ', 'an ', 'a ' ];
echo wpse_sql( $matches, " LOWER( {$wpdb->posts}.post_title) " );

উত্পন্ন হবে:

TRIM( LEADING 'a ' FROM ( 
    TRIM( LEADING 'an ' FROM ( 
        TRIM( LEADING 'the ' FROM ( 
            LOWER( wp_posts.post_title) 
        ) )
    ) )
) )

বিকল্প - মারিয়াডিবি

সাধারণভাবে আমি মাইএসকিউএল এর পরিবর্তে মারিয়াডিবি ব্যবহার করতে চাই । তারপরে এটি অনেক সহজ কারণ মারিয়াডিবি 10.0.5 সমর্থন করে : REGEXP_REPLACE

/**
 * Ignore (the,an,a) in post title ordering
 *
 * @uses MariaDB 10.0.5+
 */
add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
    if( '_custom' !== $q->get( 'orderby' ) )
        return $orderby;

    global $wpdb;
    return sprintf( 
        " REGEXP_REPLACE( {$wpdb->posts}.post_title, '^(the|a|an)[[:space:]]+', '' ) %s",
        'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'     
    );
}, 10, 2 );

আমি মনে করি এটি আমার সমাধানের চেয়ে ইস্যুটি আরও ভাল সমাধান করা উচিত
পিটার গুসেন

আপনি একেবারে সঠিক ছিলেন - পোস্ট_ফিল্ডগুলি পোস্ট_ফিল্ডে পরিবর্তন করা সমস্যার সমাধান করেছে এবং এটি এখন আমার ঠিক এটির মতো সাজান। ধন্যবাদ! আমি এখন দেখে কিছুটা বোকা বোধ করছি যেহেতু বিষয়টি ছিল। 4am এ কোডিংয়ের জন্য যা পাই তা অনুমান করুন। আমি একক ফিল্টার সমাধানও সন্ধান করব। সত্যিই ভাল ধারণা মত মনে হচ্ছে। আবার ধন্যবাদ.
আরপিবিটিজ

আমি এটিকে সঠিক উত্তর হিসাবে চিহ্নিত করব কারণ এটি আমার প্রাথমিক প্রশ্নের সাথে সর্বাধিক ঘনিষ্ঠভাবে জড়িত, যদিও আমি অন্য উত্তরগুলি বলতে পারি বৈধ সমাধানও।
আরপিবিটিজ

একক ফিল্টার বিকল্পটিও কবজির মতো কাজ করেছে worked আমি এখন ফিল্টার কোডটি ভিতরে রাখতে পারি functions.phpএবং orderbyযখন আমার প্রয়োজন হয় তখনই এটি কল করতে পারি। দুর্দান্ত সমাধান - আপনাকে ধন্যবাদ :-)
rpbtz

1
এটি আপনার জন্য কাজ করে শুনে খুব ভাল লাগল - আমি পুনরাবৃত্তির পদ্ধতিটি যুক্ত করেছি। @rpbtz
বার্জায়ার

12

একটি সহজ উপায় হতে পারে। যে পোস্টগুলিতে এটির প্রয়োজন (writing পোস্ট লেখার পর্দার শিরোনামের অধীনে) এর Permalink স্লাগ পরিবর্তন করা এবং তারপরে কেবল শিরোনামের পরিবর্তে অর্ডার দেওয়ার জন্য এটি ব্যবহার করা।

অর্থাত। বাছাইয়ের জন্য ব্যবহার করবেন post_nameনা post_title...

এর অর্থ হ'ল আপনার পারমালিংকটি আলাদা হতে পারে যদি আপনি আপনার পারমালিঙ্ক কাঠামোয়% পোস্টনাম% ব্যবহার করেন যা একটি অতিরিক্ত বোনাস হতে পারে।

যেমন। দেয় http://example.com/rolling-stones/ নাhttp://example.com/the-rolling-stones/

সম্পাদনা : বিদ্যমান স্লাগগুলি আপডেট করার কোড, post_nameকলাম থেকে অযাচিত উপসর্গগুলি সরিয়ে ...

global $wpdb;
$posttype = 'release';
$stripprefixes = array('a-','an-','the-');

$results = $wpdb->get_results("SELECT ID, post_name FROM ".$wpdb->prefix."posts" WHERE post_type = '".$posttype."' AND post_status = 'publish');
if (count($results) > 0) {
    foreach ($results as $result) {
        $postid = $result->ID;
        $postslug = $result->post_name;
        foreach ($stripprefixes as $stripprefix) {
            $checkprefix = strtolower(substr($postslug,0,strlen($stripprefix));
            if ($checkprefix == $stripprefix) {
                $newslug = substr($postslug,strlen($stripprefix),strlen($postslug));
                // echo $newslug; // debug point
                $query = $wpdb->prepare("UPDATE ".$wpdb->prefix."posts SET post_name = '%s' WHERE ID = '%d'", $newslug, $postid);
                $wpdb->query($query);
            }
        }
    }
}

দুর্দান্ত সমাধান - বাছাইয়ের জন্য খুব সহজ এবং দক্ষ।
বিলেকে

@ বিবিরগায়ার থেকে টাইপো সমাধান একটি কবজির মতো কাজ করেছে তবে এটি একটি শালীন বিকল্প বলে মনে হচ্ছে। আমি এখনই অন্যটির সাথে যাব কারণ প্রাথমিক নিবন্ধের সাথে বেশ কয়েকটি অনুসন্ধানী পোস্ট রয়েছে এবং সমস্ত পারমিলিং স্লাগ পরিবর্তন করতে কিছুটা সময় লাগতে পারে। যদিও আমি এই সমাধানটির সরলতা পছন্দ করি। ধন্যবাদ :-)
আরপিবিটিজ

1
যেহেতু আপনি পছন্দ করেছেন, এমন কিছু কোড যুক্ত করেছেন যা চাইলে / প্রয়োজনে সমস্ত স্লাগগুলি পরিবর্তন করা উচিত। :-)
মজিক

6

সম্পাদনা

আমি কোডটি কিছুটা উন্নত করেছি। সমস্ত কোড ব্লক সেই অনুযায়ী আপডেট করা হয়। মূল উত্তরটিতে আপডেটগুলিতে ঝাঁপ দেওয়ার আগে কেবল একটি নোট , নীচের সাথে কাজ করার জন্য কোডটি সেট আপ করেছি

  • কাস্টম পোস্টের ধরণ -> release

  • কাস্টম বিভাগে -> game

আপনার প্রয়োজন অনুযায়ী এটি সেট করতে ভুলবেন না

মূল উত্তর

অন্যান্য উত্তরগুলি এবং টাইপোটি @ বিবারগায়ার দ্বারা নির্দেশিত ছাড়াও, এখানে অন্য পদ্ধতি রয়েছে।

প্রথমত, আমরা শিরোনামটি একটি গোপন কাস্টম ক্ষেত্র হিসাবে সেট করব, তবে আমরা প্রথমে এই শব্দটি theবাদ দিতে চাইব। আমরা এটি করার আগে, প্রথমে নিষিদ্ধ শব্দগুলির নাম এবং পদ শিরোনাম থেকে নিষিদ্ধ শব্দগুলি সরাতে আমাদের প্রথমে একটি সহায়ক ফাংশন তৈরি করতে হবে

/**
 * Function get_name_banned_removed()
 *
 * A helper function to handle removing banned words
 * 
 * @param string $tring  String to remove banned words from
 * @param array  $banned Array of banned words to remove
 * @return string $string
 */
function get_name_banned_removed( $string = '', $banned = [] )
{
    // Make sure we have a $string to handle
    if ( !$string )
        return $string;

    // Sanitize the string
    $string = filter_var( $string, FILTER_SANITIZE_STRING );

    // Make sure we have an array of banned words
    if (    !$banned
         || !is_array( $banned )
    )
        return $string; 

    // Make sure that all banned words is lowercase
    $banned = array_map( 'strtolower', $banned );

    // Trim the string and explode into an array, remove banned words and implode
    $text          = trim( $string );
    $text          = strtolower( $text );
    $text_exploded = explode( ' ', $text );

    if ( in_array( $text_exploded[0], $banned ) )
        unset( $text_exploded[0] );

    $text_as_string = implode( ' ', $text_exploded );

    return $string = $text_as_string;
}

এখন আমরা এটি কভার করেছি, আমাদের কাস্টম ক্ষেত্রটি সেট করার জন্য কোডের টুকরো তাকান। আপনি একবারে কোনও পৃষ্ঠা লোড করার সাথে সাথে আপনাকে অবশ্যই এই কোডটি পুরোপুরি সরিয়ে ফেলতে হবে । আপনার যদি এক টন পোস্ট সহ বিশাল সাইট থাকে তবে আপনি সমস্ত পোস্টে কাস্টম ফিল্ডটি সমস্ত পোস্টে সেট না করা অবধি কয়েকবার স্ক্রিপ্টগুলিতে সেট posts_per_pageকরে 100চালাতে পারেন

add_action( 'wp', function ()
{
    add_filter( 'posts_fields', function ( $fields, \WP_Query $q ) 
    {
        global $wpdb;

        remove_filter( current_filter(), __FUNCTION__ );

        // Only target a query where the new custom_query parameter is set with a value of custom_meta_1
        if ( 'custom_meta_1' === $q->get( 'custom_query' ) ) {
            // Only get the ID and post title fields to reduce server load
            $fields = "$wpdb->posts.ID, $wpdb->posts.post_title";
        }

        return $fields;
    }, 10, 2);

    $args = [
        'post_type'        => 'release',       // Set according to needs
        'posts_per_page'   => -1,              // Set to execute smaller chucks per page load if necessary
        'suppress_filters' => false,           // Allow the posts_fields filter
        'custom_query'     => 'custom_meta_1', // New parameter to allow that our filter only target this query
        'meta_query'       => [
            [
                'key'      => '_custom_sort_post_title', // Make it a hidden custom field
                'compare'  => 'NOT EXISTS'
            ]
        ]
    ];
    $q = get_posts( $args );

    // Make sure we have posts before we continue, if not, bail
    if ( !$q ) 
        return;

    foreach ( $q as $p ) {
        $new_post_title = strtolower( $p->post_title );

        if ( function_exists( 'get_name_banned_removed' ) )
            $new_post_title = get_name_banned_removed( $new_post_title, ['the'] );

        // Set our custom field value
        add_post_meta( 
            $p->ID,                    // Post ID
            '_custom_sort_post_title', // Custom field name
            $new_post_title            // Custom field value
        );  
    } //endforeach $q
});

এখন যেহেতু কাস্টম ক্ষেত্রগুলি সমস্ত পোস্টে সেট করা আছে এবং উপরের কোডটি সরিয়ে দেওয়া হয়েছে, আমাদের অবশ্যই এটি নিশ্চিত করতে হবে যে আমরা এই কাস্টম ফিল্ডটি সমস্ত নতুন পোস্টে সেট করেছি বা যখনই আমরা পোস্টের শিরোনাম আপডেট করি। এর জন্য আমরা transition_post_statusহুক ব্যবহার করব । নিম্নলিখিত কোডটি একটি প্লাগইন ( যা আমি প্রস্তাব করি ) বা আপনার মধ্যে যেতে পারেfunctions.php

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
    // Make sure we only run this for the release post type
    if ( 'release' !== $post->post_type )
        return;

    $text = strtolower( $post->post_title );   

    if ( function_exists( 'get_name_banned_removed' ) )
        $text = get_name_banned_removed( $text, ['the'] );

    // Set our custom field value
    update_post_meta( 
        $post->ID,                 // Post ID
        '_custom_sort_post_title', // Custom field name
        $text                      // Custom field value
    );
}, 10, 3 );

আপনার পোস্টগুলিতে অনুসন্ধান করা

কোনও কাস্টম ফিল্টার ছাড়াই আপনি আপনার প্রশ্নগুলি স্বাভাবিক হিসাবে চালাতে পারেন। আপনি আপনার পোস্টগুলি নিম্নলিখিত হিসাবে ক্যোয়ারী বাছাই করতে পারেন

$args_post = [
    'post_type'      => 'release', 
    'orderby'        => 'meta_value', 
    'meta_key'       => '_custom_sort_post_title',
    'order'          => 'ASC', 
    'posts_per_page' => -1, 
];
$loop = new WP_Query( $args );

আমি এই পদ্ধতির পছন্দ করি (শিরোনামের শুরু থেকে নিষিদ্ধ শব্দটি মুছে ফেলার পক্ষে এটি যথেষ্ট)
বার্গিরে

@ বিবিরগায়ার আমি কেবল এটিই নিয়েছিলাম কারণ আমার এসকিউএল জ্ঞান যেমন গির্জার মাউস হিসাবে দুর্বল, হাহাহাহা।
টাইপোর

1
মজাদার মাউস হার্ডকোডযুক্ত এসকিউএল হাতির তুলনায় অনেক বেশি
চটচটে

0

শুধুমাত্র এই ক্ষেত্রটি দ্বারা অর্ডার দেওয়ার সময় বার্গিরের উত্তরগুলি ভাল কাজ করে। একাধিক ক্ষেত্রের অর্ডার দেওয়ার সময় এটি কার্যকর করার জন্য আমি কিছু সংশোধন করেছি (আমি নিশ্চিত নই যে শিরোনাম ক্রম যখন প্রাথমিক হয় তখন এটি সঠিকভাবে কাজ করে):

add_filter( 'posts_orderby', function( $orderby, \WP_Query $q )
{
// Do nothing
if( '_custom' !== $q->get( 'orderby' ) && !isset($q->get( 'orderby' )['_custom']) )
    return $orderby;

global $wpdb;

$matches = 'The';   // REGEXP is not case sensitive here

// Custom ordering (SQL)
if (is_array($q->get( 'orderby' ))) {
    return sprintf( 
        " $orderby, 
        CASE 
            WHEN {$wpdb->posts}.post_title REGEXP( '^($matches)[[:space:]]+' )
                THEN TRIM( SUBSTR( {$wpdb->posts}.post_title FROM %d )) 
            ELSE {$wpdb->posts}.post_title 
        END %s
        ",
        strlen( $matches ) + 1,
        'ASC' === strtoupper( $q->get( 'orderby' )['_custom'] ) ? 'ASC' : 'DESC'     
    );
}
else {
    return sprintf( 
        "
        CASE 
            WHEN {$wpdb->posts}.post_title REGEXP( '^($matches)[[:space:]]+' )
                THEN TRIM( SUBSTR( {$wpdb->posts}.post_title FROM %d )) 
            ELSE {$wpdb->posts}.post_title 
        END %s
        ",
        strlen( $matches ) + 1,
        'ASC' === strtoupper( $q->get( 'order' ) ) ? 'ASC' : 'DESC'     
    );
}

}, 10, 2 );
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.