How to create 450 categories in wp
I am having trouble to find a way for how to add categories for all the products.
I have Apple, Samsung, Sony, Xiaomi, Huawei categories and each of there needs subcategories which will stand for models, and also specific part.
example of category tree:
Apple>Iphone 6s>Iphone 6s battery
Apple>Iphone 6s>Iphone 6s replacement screen>
Apple>Iphone 8>Iphone 8 battery
etc
All the products needs to be in separated category so I can show correct item under correct menu item and no other Iphone stuff, only the battery for example.
How do I create 500+ categories which will represent all the items we have got?
I was thinking to export existing database and edit in text editor and write all the categories there as it would be simpler then using category manager inside WordPress cpanel which is very bad for this, as I am getting lost of what is in there and what isn't.
Do you think it will work this way? Or what do you suggest?
Thanks!
categories mysql
add a comment |
I am having trouble to find a way for how to add categories for all the products.
I have Apple, Samsung, Sony, Xiaomi, Huawei categories and each of there needs subcategories which will stand for models, and also specific part.
example of category tree:
Apple>Iphone 6s>Iphone 6s battery
Apple>Iphone 6s>Iphone 6s replacement screen>
Apple>Iphone 8>Iphone 8 battery
etc
All the products needs to be in separated category so I can show correct item under correct menu item and no other Iphone stuff, only the battery for example.
How do I create 500+ categories which will represent all the items we have got?
I was thinking to export existing database and edit in text editor and write all the categories there as it would be simpler then using category manager inside WordPress cpanel which is very bad for this, as I am getting lost of what is in there and what isn't.
Do you think it will work this way? Or what do you suggest?
Thanks!
categories mysql
add a comment |
I am having trouble to find a way for how to add categories for all the products.
I have Apple, Samsung, Sony, Xiaomi, Huawei categories and each of there needs subcategories which will stand for models, and also specific part.
example of category tree:
Apple>Iphone 6s>Iphone 6s battery
Apple>Iphone 6s>Iphone 6s replacement screen>
Apple>Iphone 8>Iphone 8 battery
etc
All the products needs to be in separated category so I can show correct item under correct menu item and no other Iphone stuff, only the battery for example.
How do I create 500+ categories which will represent all the items we have got?
I was thinking to export existing database and edit in text editor and write all the categories there as it would be simpler then using category manager inside WordPress cpanel which is very bad for this, as I am getting lost of what is in there and what isn't.
Do you think it will work this way? Or what do you suggest?
Thanks!
categories mysql
I am having trouble to find a way for how to add categories for all the products.
I have Apple, Samsung, Sony, Xiaomi, Huawei categories and each of there needs subcategories which will stand for models, and also specific part.
example of category tree:
Apple>Iphone 6s>Iphone 6s battery
Apple>Iphone 6s>Iphone 6s replacement screen>
Apple>Iphone 8>Iphone 8 battery
etc
All the products needs to be in separated category so I can show correct item under correct menu item and no other Iphone stuff, only the battery for example.
How do I create 500+ categories which will represent all the items we have got?
I was thinking to export existing database and edit in text editor and write all the categories there as it would be simpler then using category manager inside WordPress cpanel which is very bad for this, as I am getting lost of what is in there and what isn't.
Do you think it will work this way? Or what do you suggest?
Thanks!
categories mysql
categories mysql
asked Dec 29 '18 at 11:32
Martin ValihoraMartin Valihora
134
134
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
You can try using BulkPress. It allows you to create hundreds of categories very easily. Follow these steps:
- Install and activate the plugin.
- In the left side bar, hover your cursor on Bulkpress. Then click
on Terms. - A new page will appear. In Taxonomy field, choose Category.
- Insert your Categories in the Terms field.
- Choose your desired Parent, if required.
- Finally, click on the Add Terms button.
add a comment |
Wouldn't it be handy if we could write our category hierarchy that we wish to import as:
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
with each row as:
term slug|term name|term description
and the hierarchy defined by the indentation.
Example #1
An example using a space for indentation and |
as a column delimiter:
$import = '
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
';
wpse324129_bulk_terms_importer( $import, 'category', '|', PHP_EOL );
that would import the terms as:
Example #2
Another example using a tab for indentation and comma as a column delimiter:
$import = '
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
';
wpse324129_bulk_terms_importer( $import, 'category', ',', PHP_EOL );
importing terms as:
Implementation
Here's a first draft for such a function to bulk import terms from a string:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default 'category'.
* @param string $col_delimiter Column delimiter. Default '|'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = 'category', $col_delimiter = '|', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( 'Incorrect number of columns', 'wpse' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
'description' => $term_desc,
'slug' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( 'term_id', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term['term_id'] ) ) {
$args['parent'] = $parent_term['term_id'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( 'slug', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term['term_id'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( 'Could not insert term!', 'wpse' ) );
}
$prev_term_id = $result['term_id'];
} else {
$prev_term_id = $term['term_id'];
}
}
}
When we insert a term, we need to know about it's parent. So we need to collect the direct term ancestors when we traverse the hierarchy. The stack is a suitable data structure, where the last item in is the first item out (LIFO). In PHP 5.3+ we can use SplStack
that already implements methods like pop()
, push()
, top()
and count()
.
By comparing the current level to the number of current ancestors, we can determine if we are going inner (right) or outer (left) and adjust the stack accordingly. Reducing the stack when we go left and push to the stack when we go right.
For large import, one could run it through the wp-cli
to avoid timeout.
Hope you can extend this further to your needs, e.g. with a format validator and what to do with existing terms (we currently leave them unaffected here).
Please backup before testing!
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "110"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fwordpress.stackexchange.com%2fquestions%2f324129%2fhow-to-create-450-categories-in-wp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can try using BulkPress. It allows you to create hundreds of categories very easily. Follow these steps:
- Install and activate the plugin.
- In the left side bar, hover your cursor on Bulkpress. Then click
on Terms. - A new page will appear. In Taxonomy field, choose Category.
- Insert your Categories in the Terms field.
- Choose your desired Parent, if required.
- Finally, click on the Add Terms button.
add a comment |
You can try using BulkPress. It allows you to create hundreds of categories very easily. Follow these steps:
- Install and activate the plugin.
- In the left side bar, hover your cursor on Bulkpress. Then click
on Terms. - A new page will appear. In Taxonomy field, choose Category.
- Insert your Categories in the Terms field.
- Choose your desired Parent, if required.
- Finally, click on the Add Terms button.
add a comment |
You can try using BulkPress. It allows you to create hundreds of categories very easily. Follow these steps:
- Install and activate the plugin.
- In the left side bar, hover your cursor on Bulkpress. Then click
on Terms. - A new page will appear. In Taxonomy field, choose Category.
- Insert your Categories in the Terms field.
- Choose your desired Parent, if required.
- Finally, click on the Add Terms button.
You can try using BulkPress. It allows you to create hundreds of categories very easily. Follow these steps:
- Install and activate the plugin.
- In the left side bar, hover your cursor on Bulkpress. Then click
on Terms. - A new page will appear. In Taxonomy field, choose Category.
- Insert your Categories in the Terms field.
- Choose your desired Parent, if required.
- Finally, click on the Add Terms button.
edited Dec 29 '18 at 13:37
answered Dec 29 '18 at 12:06
Md. Ehsanul Haque KananMd. Ehsanul Haque Kanan
31226
31226
add a comment |
add a comment |
Wouldn't it be handy if we could write our category hierarchy that we wish to import as:
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
with each row as:
term slug|term name|term description
and the hierarchy defined by the indentation.
Example #1
An example using a space for indentation and |
as a column delimiter:
$import = '
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
';
wpse324129_bulk_terms_importer( $import, 'category', '|', PHP_EOL );
that would import the terms as:
Example #2
Another example using a tab for indentation and comma as a column delimiter:
$import = '
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
';
wpse324129_bulk_terms_importer( $import, 'category', ',', PHP_EOL );
importing terms as:
Implementation
Here's a first draft for such a function to bulk import terms from a string:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default 'category'.
* @param string $col_delimiter Column delimiter. Default '|'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = 'category', $col_delimiter = '|', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( 'Incorrect number of columns', 'wpse' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
'description' => $term_desc,
'slug' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( 'term_id', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term['term_id'] ) ) {
$args['parent'] = $parent_term['term_id'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( 'slug', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term['term_id'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( 'Could not insert term!', 'wpse' ) );
}
$prev_term_id = $result['term_id'];
} else {
$prev_term_id = $term['term_id'];
}
}
}
When we insert a term, we need to know about it's parent. So we need to collect the direct term ancestors when we traverse the hierarchy. The stack is a suitable data structure, where the last item in is the first item out (LIFO). In PHP 5.3+ we can use SplStack
that already implements methods like pop()
, push()
, top()
and count()
.
By comparing the current level to the number of current ancestors, we can determine if we are going inner (right) or outer (left) and adjust the stack accordingly. Reducing the stack when we go left and push to the stack when we go right.
For large import, one could run it through the wp-cli
to avoid timeout.
Hope you can extend this further to your needs, e.g. with a format validator and what to do with existing terms (we currently leave them unaffected here).
Please backup before testing!
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
add a comment |
Wouldn't it be handy if we could write our category hierarchy that we wish to import as:
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
with each row as:
term slug|term name|term description
and the hierarchy defined by the indentation.
Example #1
An example using a space for indentation and |
as a column delimiter:
$import = '
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
';
wpse324129_bulk_terms_importer( $import, 'category', '|', PHP_EOL );
that would import the terms as:
Example #2
Another example using a tab for indentation and comma as a column delimiter:
$import = '
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
';
wpse324129_bulk_terms_importer( $import, 'category', ',', PHP_EOL );
importing terms as:
Implementation
Here's a first draft for such a function to bulk import terms from a string:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default 'category'.
* @param string $col_delimiter Column delimiter. Default '|'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = 'category', $col_delimiter = '|', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( 'Incorrect number of columns', 'wpse' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
'description' => $term_desc,
'slug' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( 'term_id', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term['term_id'] ) ) {
$args['parent'] = $parent_term['term_id'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( 'slug', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term['term_id'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( 'Could not insert term!', 'wpse' ) );
}
$prev_term_id = $result['term_id'];
} else {
$prev_term_id = $term['term_id'];
}
}
}
When we insert a term, we need to know about it's parent. So we need to collect the direct term ancestors when we traverse the hierarchy. The stack is a suitable data structure, where the last item in is the first item out (LIFO). In PHP 5.3+ we can use SplStack
that already implements methods like pop()
, push()
, top()
and count()
.
By comparing the current level to the number of current ancestors, we can determine if we are going inner (right) or outer (left) and adjust the stack accordingly. Reducing the stack when we go left and push to the stack when we go right.
For large import, one could run it through the wp-cli
to avoid timeout.
Hope you can extend this further to your needs, e.g. with a format validator and what to do with existing terms (we currently leave them unaffected here).
Please backup before testing!
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
add a comment |
Wouldn't it be handy if we could write our category hierarchy that we wish to import as:
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
with each row as:
term slug|term name|term description
and the hierarchy defined by the indentation.
Example #1
An example using a space for indentation and |
as a column delimiter:
$import = '
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
';
wpse324129_bulk_terms_importer( $import, 'category', '|', PHP_EOL );
that would import the terms as:
Example #2
Another example using a tab for indentation and comma as a column delimiter:
$import = '
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
';
wpse324129_bulk_terms_importer( $import, 'category', ',', PHP_EOL );
importing terms as:
Implementation
Here's a first draft for such a function to bulk import terms from a string:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default 'category'.
* @param string $col_delimiter Column delimiter. Default '|'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = 'category', $col_delimiter = '|', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( 'Incorrect number of columns', 'wpse' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
'description' => $term_desc,
'slug' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( 'term_id', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term['term_id'] ) ) {
$args['parent'] = $parent_term['term_id'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( 'slug', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term['term_id'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( 'Could not insert term!', 'wpse' ) );
}
$prev_term_id = $result['term_id'];
} else {
$prev_term_id = $term['term_id'];
}
}
}
When we insert a term, we need to know about it's parent. So we need to collect the direct term ancestors when we traverse the hierarchy. The stack is a suitable data structure, where the last item in is the first item out (LIFO). In PHP 5.3+ we can use SplStack
that already implements methods like pop()
, push()
, top()
and count()
.
By comparing the current level to the number of current ancestors, we can determine if we are going inner (right) or outer (left) and adjust the stack accordingly. Reducing the stack when we go left and push to the stack when we go right.
For large import, one could run it through the wp-cli
to avoid timeout.
Hope you can extend this further to your needs, e.g. with a format validator and what to do with existing terms (we currently leave them unaffected here).
Please backup before testing!
Wouldn't it be handy if we could write our category hierarchy that we wish to import as:
apple|Apple|Apple products
iphone-6s|Iphone 6s|Apple Iphone 6s
iphone-6s-battery|Iphone 6s battery|Apple Iphone 6s battery
iphone-8-battery|Iphone 8 battery|Apple Iphone 8 battery
with each row as:
term slug|term name|term description
and the hierarchy defined by the indentation.
Example #1
An example using a space for indentation and |
as a column delimiter:
$import = '
a1|A1|Term description
a11|A11|Term description
a111|A111|Term description
a112|A112|Term description
a12|A12|Term description
';
wpse324129_bulk_terms_importer( $import, 'category', '|', PHP_EOL );
that would import the terms as:
Example #2
Another example using a tab for indentation and comma as a column delimiter:
$import = '
a1,A1,"Term description, including column delimiter"
a11,A11, "Term description, including column delimiter"
a111,A111,"Term description, including column delimiter"
a112,A112,"Term description, including column delimiter"
a12,A12,"Term description, including column delimiter"
';
wpse324129_bulk_terms_importer( $import, 'category', ',', PHP_EOL );
importing terms as:
Implementation
Here's a first draft for such a function to bulk import terms from a string:
/**
* Bulk Term Importer
*
* Bulk import terms with a given hierarchy, defined by indentation (tab or space).
*
* @version 0.1.3
*
* @see https://wordpress.stackexchange.com/a/324157/26350
*
* @param string $import Terms to import
* @param string $tax Taxonomy. Default 'category'.
* @param string $col_delimiter Column delimiter. Default '|'.
* @param string $row_delimiter Row delimiter. Default PHP_EOL.
*/
function wpse324129_bulk_term_importer( $import, $tax = 'category', $col_delimiter = '|', $row_delimiter = PHP_EOL ) {
$rows = explode( $row_delimiter, trim( $import ) );
$level = 0;
$prev_term_id = 0;
$ancestors = new SplStack(); // Last-In First-Out.
foreach( $rows as $row ) {
$cols = str_getcsv( $row, $col_delimiter );
if ( 3 !== count( $cols ) ) {
throw new Exception( __( 'Incorrect number of columns', 'wpse' ) );
}
$term_slug = $cols[0];
$term_name = $cols[1];
$term_desc = $cols[2];
// Hierarchy traversal level (non negative).
$level = strlen( $term_slug ) - strlen( ltrim( $term_slug ) );
// Push the previous term to the ancestors stack if we go inner (right).
if ( $level > $ancestors->count() ) {
$ancestors->push( $prev_term_id );
} // After: level === ancestors count
// Reduce the ancestors' stack when we go outer (left).
while ( $level < $ancestors->count() ) {
$ancestors->pop();
} // After: level === ancestors count
// Arguments for term creation.
$args = [
'description' => $term_desc,
'slug' => $term_slug,
];
// Check parent term and add to the term creation arguments if needed.
if ( $prev_term_id > 0 && $ancestors->count() > 0 ) {
$parent_id = $ancestors->top(); // The parent is the one on the top.
$parent_term = get_term_by( 'term_id', $parent_id, $tax, ARRAY_A );
if ( isset( $parent_term['term_id'] ) ) {
$args['parent'] = $parent_term['term_id'];
}
}
// Check if current term slug exists and insert if needed.
$term = get_term_by( 'slug', $term_slug, $tax, ARRAY_A );
if ( ! isset( $term['term_id'] ) ) {
$result = wp_insert_term( $term_name, $tax, $args );
if ( is_wp_error( $result ) ) {
throw new Exception( __( 'Could not insert term!', 'wpse' ) );
}
$prev_term_id = $result['term_id'];
} else {
$prev_term_id = $term['term_id'];
}
}
}
When we insert a term, we need to know about it's parent. So we need to collect the direct term ancestors when we traverse the hierarchy. The stack is a suitable data structure, where the last item in is the first item out (LIFO). In PHP 5.3+ we can use SplStack
that already implements methods like pop()
, push()
, top()
and count()
.
By comparing the current level to the number of current ancestors, we can determine if we are going inner (right) or outer (left) and adjust the stack accordingly. Reducing the stack when we go left and push to the stack when we go right.
For large import, one could run it through the wp-cli
to avoid timeout.
Hope you can extend this further to your needs, e.g. with a format validator and what to do with existing terms (we currently leave them unaffected here).
Please backup before testing!
edited Dec 31 '18 at 7:43
answered Dec 29 '18 at 16:09
birgirebirgire
53.6k463142
53.6k463142
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
add a comment |
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
ps: alternative format could be to use numbers instead of indentation (thanks Egill for the suggestion)
– birgire
Dec 30 '18 at 12:31
add a comment |
Thanks for contributing an answer to WordPress Development Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fwordpress.stackexchange.com%2fquestions%2f324129%2fhow-to-create-450-categories-in-wp%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown