Статьи

Пользовательский тип сообщения Помощник класса

В наши дни для многих проектов WordPress мы используем пользовательские типы записей. Команда разработчиков WordPress создала несколько удобных методов для их интеграции в ваши проекты. Но когда вы часто используете пользовательские типы записей, таксономии и мета-блоки, вполне вероятно, что вы будете повторяться. Вот почему мы собираемся использовать возможности этих функций WordPress для создания более мощного класса, который мы можем использовать для быстрой регистрации типов записей, таксономий и мета-блоков.


Вот как мы называем наш класс, когда это будет сделано.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
include(‘custom-post-type.php’);
 
$book = new Custom_Post_Type( ‘Book’ );
$book->add_taxonomy( ‘category’ );
$book->add_taxonomy( ‘author’ );
 
$book->add_meta_box(
    ‘Book Info’,
    array(
        ‘Year’ => ‘text’,
        ‘Genre’ => ‘text’
    )
);
 
$book->add_meta_box(
    ‘Author Info’,
    array(
        ‘Name’ => ‘text’,
        ‘Nationality’ => ‘text’,
        ‘Birthday’ => ‘text’
    )
);

Мы начнем с создания класса, основных свойств, конструктора и методов. В этом уроке мы наполним их нашей логикой программирования.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Custom_Post_Type
{
    public $post_type_name;
    public $post_type_args;
    public $post_type_labels;
     
    /* Class constructor */
    public function __construct()
    {
         
    }
     
    /* Method which registers the post type */
    public function register_post_type()
    {
         
    }
     
    /* Method to attach the taxonomy to the post type */
    public function add_taxonomy()
    {
         
    }
     
    /* Attaches meta boxes to the post type */
    public function add_meta_box()
    {
         
    }
     
    /* Listens for when the post type being saved */
    public function save()
    {
         
    }
}

Внутри конструктора мы создаем несколько важных переменных, которые используются внутри всего класса. Мы также вызываем add_action чтобы зарегистрировать тип записи, и мы прослушиваем, когда тип записи сохраняется, чтобы мы могли сохранить метаданные нашего сообщения. Если тип записи существует, add_action не вызывается, но $post_type_name установлено, поэтому мы можем добавить в него таксономии и мета-блоки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
public function __construct( $name, $args = array(), $labels = array() )
{
    // Set some important variables
    $this->post_type_name = strtolower( str_replace( ‘ ‘, ‘_’, $name ) );
    $this->post_type_args = $args;
    $this->post_type_labels = $labels;
     
    // Add action to register the post type, if the post type does not already exist
    if( ! post_type_exists( $this->post_type_name ) )
    {
        add_action( ‘init’, array( &$this, ‘register_post_type’ ) );
    }
     
    // Listen for the save post hook
    $this->save();
}

В методе register_post_type , который add_action в конструкторе, мы сначала определяем имя (с большой буквы) и множественное число. С этим именем и множественным числом мы создаем наши метки для типа записи и перезаписываем (и объединяем) их с заданными метками из переменной $this->post_type_labels . Затем мы создаем наши аргументы по тому же принципу.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public function register_post_type()
{
    //Capitilize the words and make it plural
    $name = ucwords( str_replace( ‘_’, ‘ ‘, $this->post_type_name ) );
    $plural = $name .
     
    // We set the default labels based on the post type name and plural.
    $labels = array_merge(
     
        // Default
        array(
            ‘name’ => _x( $plural, ‘post type general name’ ),
            ‘singular_name’ => _x( $name, ‘post type singular name’ ),
            ‘add_new’ => _x( ‘Add New’, strtolower( $name ) ),
            ‘add_new_item’ => __( ‘Add New ‘ . $name ),
            ‘edit_item’ => __( ‘Edit ‘ . $name ),
            ‘new_item’ => __( ‘New ‘ . $name ),
            ‘all_items’ => __( ‘All ‘ . $plural ),
            ‘view_item’ => __( ‘View ‘ . $name ),
            ‘search_items’ => __( ‘Search ‘ . $plural ),
            ‘not_found’ => __( ‘No ‘ . strtolower( $plural ) . ‘ found’),
            ‘not_found_in_trash’ => __( ‘No ‘ . strtolower( $plural ) . ‘ found in Trash’),
            ‘parent_item_colon’ => »,
            ‘menu_name’ => $plural
        ),
         
        // Given labels
        $this->post_type_labels
         
    );
     
    // Same principle as the labels.
    $args = array_merge(
     
        // Default
        array(
            ‘label’ => $plural,
            ‘labels’ => $labels,
            ‘public’ => true,
            ‘show_ui’ => true,
            ‘supports’ => array( ‘title’, ‘editor’ ),
            ‘show_in_nav_menus’ => true,
            ‘_builtin’ => false,
        ),
         
        // Given args
        $this->post_type_args
         
    );
     
    // Register the post type
    register_post_type( $this->post_type_name, $args );
}

Сначала мы проверяем, является ли параметр $name пустым. Когда это так, мы ничего не делаем. Когда это не так, мы создаем три переменные, в которых мы храним информацию для таксономии: $taxonomy_name , $taxonomy_labels и $taxonomy_args .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public function add_taxonomy( $name, $args = array(), $labels = array() )
{
    if( ! empty( $name ) )
    {
        // We need to know the post type name, so the new taxonomy can be attached to it.
        $post_type_name = $this->post_type_name;
 
        // Taxonomy properties
        $taxonomy_name = strtolower( str_replace( ‘ ‘, ‘_’, $name ) );
        $taxonomy_labels = $labels;
        $taxonomy_args = $args;
 
        /* More code coming */
    }
}

После того, как мы выполнили первые проверки и затем установили некоторые переменные, мы собираемся зарегистрировать тип записи. Но сначала мы проверим, существует ли таксономия.

1
2
3
4
5
6
7
8
if( ! taxonomy_exists( $taxonomy_name ) )
{
    /* Create taxonomy and attach it to the object type (post type) */
}
else
{
    /* The taxonomy already exists.
}

Если таксономия не существует, мы регистрируем ее. Мы используем add_action , но не обычным способом. Обычно вторым параметром add_action является имя функции, но поскольку мы каждый раз используем разные параметры, мы собираемся передать безымянную функцию ( Примечание: для этой функции требуется PHP 5.3+) и использовать функцию use() . С use() функции use() мы можем передавать переменные в безымянную функцию. На этот раз нам нужно передать $taxonomy_name , $post_type_name и $taxonomy_args для регистрации таксономии.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//Capitilize the words and make it plural
$name = ucwords( str_replace( ‘_’, ‘ ‘, $name ) );
$plural = $name .
 
// Default labels, overwrite them with the given labels.
$labels = array_merge(
 
    // Default
    array(
        ‘name’ => _x( $plural, ‘taxonomy general name’ ),
        ‘singular_name’ => _x( $name, ‘taxonomy singular name’ ),
        ‘search_items’ => __( ‘Search ‘ . $plural ),
        ‘all_items’ => __( ‘All ‘ . $plural ),
        ‘parent_item’ => __( ‘Parent ‘ . $name ),
        ‘parent_item_colon’ => __( ‘Parent ‘ . $name . ‘:’ ),
        ‘edit_item’ => __( ‘Edit ‘ . $name ),
        ‘update_item’ => __( ‘Update ‘ . $name ),
        ‘add_new_item’ => __( ‘Add New ‘ . $name ),
        ‘new_item_name’ => __( ‘New ‘ . $name . ‘ Name’ ),
        ‘menu_name’ => __( $name ),
    ),
 
    // Given labels
    $taxonomy_labels
 
);
 
// Default arguments, overwritten with the given arguments
$args = array_merge(
 
    // Default
    array(
        ‘label’ => $plural,
        ‘labels’ => $labels,
        ‘public’ => true,
        ‘show_ui’ => true,
        ‘show_in_nav_menus’ => true,
        ‘_builtin’ => false,
    ),
 
    // Given
    $taxonomy_args
 
);
 
// Add the taxonomy to the post type
add_action( ‘init’,
    function() use( $taxonomy_name, $post_type_name, $args )
    {
        register_taxonomy( $taxonomy_name, $post_type_name, $args );
    }
);

Когда таксономия не существует, мы прикрепляем ее только к нашему типу записи. Как и раньше, мы используем безымянную функцию и функцию use() . На этот раз нам нужно только передать $taxonomy_name и $post_type_name .

1
2
3
4
5
6
add_action( ‘init’,
    function() use( $taxonomy_name, $post_type_name )
    {
        register_taxonomy_for_object_type( $taxonomy_name, $post_type_name );
    }
);

Для регистрации мета-блоков нам нужно имя типа записи, поэтому сначала мы определим это. После этого нам понадобятся некоторые переменные для самого мета-блока, и мы сделаем пользовательские мета-поля глобальными, чтобы мы могли получить к ним доступ в хуке сохранения. Мы не будем здесь подробно рассказывать, потому что Тэмми Харт уже сделала очень полезное руководство по использованию мета-блоков многократного использования .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public function add_meta_box( $title, $fields = array(), $context = ‘normal’, $priority = ‘default’ )
{
    if( ! empty( $title ) )
    {
        // We need to know the Post Type name again
        $post_type_name = $this->post_type_name;
 
        // Meta variables
        $box_id = strtolower( str_replace( ‘ ‘, ‘_’, $title ) );
        $box_title = ucwords( str_replace( ‘_’, ‘ ‘, $title ) );
        $box_context = $context;
        $box_priority = $priority;
         
        // Make the fields global
        global $custom_fields;
        $custom_fields[$title] = $fields;
         
        /* More code coming */
    }
     
}

Когда мы устанавливаем переменные и глобальные переменные, мы регистрируем мета-поле с помощью add_action . Как и раньше, мы используем безымянную функцию. На этот раз нам нужны $box_id , $box_title , $post_type_name , $box_context , $box_priority и $fields .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
add_action( ‘admin_init’,
    function() use( $box_id, $box_title, $post_type_name, $box_context, $box_priority, $fields )
    {
        add_meta_box(
            $box_id,
            $box_title,
            function( $post, $data )
            {
                global $post;
                 
                // Nonce field for some validation
                wp_nonce_field( plugin_basename( __FILE__ ), ‘custom_post_type’ );
                 
                // Get all inputs from $data
                $custom_fields = $data[‘args’][0];
                 
                // Get the saved values
                $meta = get_post_custom( $post->ID );
                 
                // Check the array and loop through it
                if( ! empty( $custom_fields ) )
                {
                    /* Loop through $custom_fields */
                    foreach( $custom_fields as $label => $type )
                    {
                        $field_id_name = strtolower( str_replace( ‘ ‘, ‘_’, $data[‘id’] ) ) .
                         
                        echo ‘<label for=»‘ . $field_id_name . ‘»>’ .
                    }
                }
             
            },
            $post_type_name,
            $box_context,
            $box_priority,
            array( $fields )
        );
    }
);

Сохраните все метаданные поста. Мы перебираем их, используя глобальные $custom_fields . Это также быстрое освещение, см . Учебник Тэмми Харт о мета-блоках многократного использования .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public function save()
{
    // Need the post type name again
    $post_type_name = $this->post_type_name;
 
    add_action( ‘save_post’,
        function() use( $post_type_name )
        {
            // Deny the WordPress autosave function
            if( defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE ) return;
 
            if ( ! wp_verify_nonce( $_POST[‘custom_post_type’], plugin_basename(__FILE__) ) ) return;
         
            global $post;
             
            if( isset( $_POST ) && isset( $post->ID ) && get_post_type( $post->ID ) == $post_type_name )
            {
                global $custom_fields;
                 
                // Loop through each meta box
                foreach( $custom_fields as $title => $fields )
                {
                    // Loop through all fields
                    foreach( $fields as $label => $type )
                    {
                        $field_id_name = strtolower( str_replace( ‘ ‘, ‘_’, $title ) ) .
                         
                        update_post_meta( $post->ID, $field_id_name, $_POST[‘custom_meta’][$field_id_name] );
                    }
                 
                }
            }
        }
    );
}

Как видите, мы используем strtolower( str_replace( ' ', '_', $string ) ) и ucwords( str_replace( '_', ' ', $string ) ) несколько раз. Причина создания этого класса в том, что мы не повторяем себя, поэтому мы не хотим делать это и в этой части. Вот почему мы создаем несколько вспомогательных методов. Таким образом, мы можем сделать это: $name = self::beautify( $string ); вместо $name = strtolower( str_replace( ' ', '_', $title ) );

1
2
3
4
5
6
7
8
9
public static function beautify( $string )
{
    return ucwords( str_replace( ‘_’, ‘ ‘, $string ) );
}
 
public static function uglify( $string )
{
    return strtolower( str_replace( ‘ ‘, ‘_’, $string ) );
}

Другой момент — формы множественного числа, которые мы создаем. Мы просто создаем их, добавляя к слову «s». Но что происходит, когда слово оканчивается на «у»? По этой причине мы создаем вспомогательный метод для определения формы слова во множественном числе. Теперь мы можем легко сделать это: $plural = self::pluralize( $string ) и форма нашего слова во множественном числе будет определена.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
public static function pluralize( $string )
{
    $last = $string[strlen( $string ) — 1];
     
    if( $last == ‘y’ )
    {
        $cut = substr( $string, 0, -1 );
        //convert y to ies
        $plural = $cut .
    }
    else
    {
        // just attach an s
        $plural = $string .
    }
     
    return $plural;
}

И теперь мы закончили. Теперь вы можете использовать этот класс для простой регистрации типов записей, таксономий и мета-блоков. Если у вас есть предложения или вопросы, просто оставьте комментарий, чтобы мы могли поговорить об этом. Надеюсь увидеть вас в следующий раз!

Кроме того, я хотел бы отдать должное Джеффри Вей. Я использовал его урок как вдохновение для своего урока и для этого урока. Кроме того, я хотел бы поблагодарить Тэмми Харт за создание учебного пособия по использованию мета-блоков . Посмотрите на их работу.