Actuellement, j'utilise le plug-in "Admin Columns Pro" pour Wordpress pour modifier certaines des colonnes du backend. Le plugin contient des fonctionnalités permettant d'afficher l'auteur de l'article (ou dans mon cas, le produit) sous forme de colonne.
Cependant, je suis dans une position où j'ai besoin de voir qui est l'éditeur le plus récent du produit. Fondamentalement, ce que nous avons maintenant, c'est qu'un individu crée un brouillon de produit, puis quelqu'un le termine, et j'ai besoin de voir ces deux noms (un créateur et un the_modified_author).
Le plugin contient la documentation pour créer des colonnes personnalisées , et j'ai essayé de la suivre, mais je n'arrive pas à obtenir le passage "the_modified_author" .
Des pensées?
Changer de colonne admin appartient à un plugin , pas à un fichier de thème, car les thèmes ne devraient jamais changer autre chose que la sortie frontale. Vous pouvez obtenir le plugin complet ici:Editeur de produit de plugin Column.
En regardant les documents que vous avez liés, je vois que l'auteur du plug-in a besoin d'une classe enfant qui mélange plusieurs tâches distinctes. Ce n'est pas bon. Nous verrons dans une minute pourquoi.
Par contre, nous ne sommes pas dans le support de plugin de toute façon. Nous sommes dans le Trouvez votre propre entreprise de solutions. Ignorons donc ce plugin et examinons les fonctions principales.
"manage_{$post_type}_posts_columns"
. Pour une publication, tapez product
, ce serait "manage_product_posts_columns"
."manage_{$post_type}_posts_custom_column"
.Ce sont des noms très pauvres: ils ne nous disent pas vraiment ce qui se passe ici.
Les deux points d'ancrage sont appelés lorsque le fichier wp-admin/edit.php
est chargé. Nous attendons donc que l'action 'load-edit.php'
se déclenche.
Sur la page d'édition, nous examinons l'objet renvoyé par get_current_screen()
: si sa propriété id
correspond à "edit-$post_type"
, nous enregistrons nos rappels.
Le filtre "manage_{$post_type}_posts_columns"
nous donne un tableau des en-têtes de colonnes existants. Nous ajoutons simplement une entrée et retournons le tableau:
function add_column( Array $columns )
{
$columns[ 'modified_author' ] = 'Last modified by';
return $columns;
}
L'action "manage_{$post_type}_posts_custom_column"
nous donne le $column_name
et le $post_id
. Nous comparons le nom de la colonne avec notre nom enregistré antérieur, 'modified_author'
, car il peut y avoir d’autres colonnes personnalisées et nous ne souhaitons pas les toucher. Si le nom de colonne indiqué est le nôtre, nous utilisons le $post_id
pour obtenir l'ID du dernier auteur ayant modifié le message:
$last_id = get_post_meta( $post_id, '_edit_last', TRUE );
$last_user = get_userdata( $last_id );
print esc_html( $last_user->display_name );
La version courte de notre code pourrait ressembler à ceci:
add_action( 'load-edit.php', function() {
$post_type = 'product';
$col_name = 'modified_author';
$screen = get_current_screen();
if ( ! isset ( $screen->id ) )
return;
if ( "edit-$post_type" !== $screen->id )
return;
add_filter(
"manage_{$post_type}_posts_columns",
function( $posts_columns ) use ( $col_name ) {
$posts_columns[ $col_name ] = 'Last modified by';
return $posts_columns;
}
);
add_action(
"manage_{$post_type}_posts_custom_column",
function( $column_name, $post_id ) use ( $col_name ) {
if ( $col_name !== $column_name )
return;
$last_id = get_post_meta( $post_id, '_edit_last', TRUE );
if ( ! $last_id ) {
print '<i>Unknown</i>';
return;
}
$last_user = get_userdata( $last_id );
print esc_html( $last_user->display_name );
},
10, 2
);
});
Cela fonctionne, mais ce n’est pas bon.
Améliorons notre code!
L'enregistrement des rappels doit être effectué par un contrôleur. Il n’est pas nécessaire de savoir où nous obtenons nos données et comment nous les imprimons à l’écran de l’utilisateur; transmettez-les donc comme - dépendances abstraites :
class Controller
{
/**
* @var Column_Data
*/
private $data;
/**
* @var Column_View
*/
private $view;
/**
* @param Column_Data $data
* @param Column_View $view
*/
public function __construct( Column_Data $data, Column_View $view ) {
$this->data = $data;
$this->view = $view;
}
/**
* @return void
*/
public function setup()
{
$screen = get_current_screen();
$post_type = $this->data->get_post_type();
if ( ! isset ( $screen->id ) )
return;
if ( "edit-$post_type" !== $screen->id )
return;
add_filter(
"manage_{$post_type}_posts_columns",
[ $this->data, 'add_column' ]
);
add_action(
"manage_{$post_type}_posts_custom_column",
[ $this->view, 'render_column' ],
10, 2
);
}
}
Column_Data
et Column_View
sont interfaces , pas des classes concrètes, nous pouvons donc réutiliser ce contrôleur avec différents fournisseurs de données ou gestionnaires de sortie. Construisons ces interfaces.
L’interface pour les données a besoin de méthodes pour
interface Column_Data
{
/**
* @param array $columns
* @return array
*/
public function add_column( Array $columns );
/**
* @param int $post_id
* @return string
*/
public function get_column_content( $post_id );
/**
* @return string
*/
public function get_post_type();
/**
* @param $column_name
* @return bool
*/
public function is_valid_column( $column_name );
}
L'objet de sortie/vue n'a besoin que d'une méthode:
interface Column_View
{
/**
* @param string $column_name
* @param int $post_id
* @return void
*/
public function render_column( $column_name, $post_id );
}
La vue doit extraire des informations du modèle de données, passez donc une instance au constructeur de la classe concrète:
class Last_Mod_Author_Column_Output implements Column_View
{
/**
* @var Column_Data
*/
private $data;
/**
* @param Column_Data $data
*/
public function __construct( Column_Data $data )
{
$this->data = $data;
}
/**
* @param string $column_name
* @param int $post_id
* @return void
*/
public function render_column( $column_name, $post_id )
{
if ( ! $this->data->is_valid_column( $column_name ) )
return;
$content = $this->data->get_column_content( $post_id );
if ( '' === $content )
print '<i>Unknown</i>';
else
print esc_html( $content );
}
}
Le modèle de données doit connaître le type de publication. Nous le transmettons donc au constructeur de la classe Concrete:
class Last_Mod_Author_Column_Data implements Column_Data
{
/**
* @var string
*/
private $post_type;
/**
* @var string
*/
private $column_name = 'modified_author';
/**
* @param string $post_type
*/
public function __construct( $post_type )
{
$this->post_type = $post_type;
}
/**
* @param array $columns
* @return array
*/
public function add_column( Array $columns )
{
$columns[ $this->column_name ] = 'Last modified by';
return $columns;
}
/**
* @param int $post_id
* @return string
*/
public function get_column_content( $post_id )
{
$last_id = get_post_meta( $post_id, '_edit_last', TRUE );
if ( ! $last_id ) {
return '';
}
$last_user = get_userdata( $last_id );
return $last_user->display_name;
}
/**
* @return string
*/
public function get_post_type()
{
return $this->post_type;
}
/**
* @param $column_name
* @return bool
*/
public function is_valid_column( $column_name )
{
return $this->column_name === $column_name;
}
}
Et maintenant, nous pouvons utiliser ces classes:
add_action( 'load-edit.php', function() {
$model = new Last_Mod_Author_Column_Data( 'product' );
$view = new Last_Mod_Author_Column_Output( $model );
$controller = new Controller( $model, $view );
$controller->setup();
});
Nous pouvons utiliser le même code pour les pages avec juste un changement minime:
add_action( 'load-edit.php', function() {
$model = new Last_Mod_Author_Column_Data( 'page' );
$view = new Last_Mod_Author_Column_Output( $model );
$controller = new Controller( $model, $view );
$controller->setup();
});
Pourquoi ce code plutôt long est-il meilleur?
Nous pourrions implémenter l'interface de données dans une classe qui extrait la valeur d'une autre table, d'un fichier texte ou d'une API externe, sans modifier le contrôleur ni la vue.
Nous pourrions utiliser une vue qui met le nom de l'auteur en gras ou utilise un repli différent, sans changer le contrôleur ou le modèle de données.
Nous pouvons tester toutes les méthodes publiques de toutes les classes en fournissant des objets factices pour les dépendances (stubs).
Nous évitons le problème de classe de base fragile , car nous n’utilisons pas l’héritage comme celui du plugin que vous avez mentionné.