mehrshaddarzi / wp-cli-fixtures
Easily generate fake data for WordPress
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 19
Type:wp-cli-package
pkg:composer/mehrshaddarzi/wp-cli-fixtures
Requires
- fzaninotto/faker: ^1.9
- nelmio/alice: ~3.2.2
- symfony/yaml: ^2.8
Requires (Dev)
- wp-cli/wp-cli-bundle: ^2.4
- wp-cli/wp-cli-tests: ^2.1
This package is auto-updated.
Last update: 2025-09-29 02:39:15 UTC
README
Inspired by Faker, this package provides an easy way to create massive and custom fake data for your WordPress installation. This package is based on nelmio/alice and fzaninotto/Faker. Please refer to these packages docs for advanced usage.
WARNING: This package is mostly intented to be used for development purposes. Use it at your own risk, don't run it on a production database or make sure to back it up first.
Quick links: Install | Usage | Contribute
Install
wp package install https://github.com/mehrshaddarzi/wp-cli-fixtures/archive/refs/heads/master.zip
Requires PHP ^7.3.
Usage
Create fixtures
At the root of your project, create a fixtures.yml file (you can download it here):
# # USERS # Hellonico\Fixtures\Entity\User: user{1..10}: user_login (unique): <username()> # '(unique)' is required user_pass: 123 user_email: <freeEmail()> user_url: <url()> user_registered: <dateTimeThisDecade()> first_name: <firstName()> last_name: <lastName()> description: <sentence()> role: <randomElement(['subscriber', 'editor'])> meta: show_admin_bar_front: 'false' billing_phone: <phoneNumber()> billing_country: 'IR' billing_state: <randomElement(['ABZ','ADL','EAZ','WAZ','BHR','CHB','FRS','GIL','GLS','HDN','HRZ','ILM','ESF','KRN','KRH','NKH','RKH','SKH','KHZ','KBD','KRD','LRS','MKZ','MZN','GZN','QHM','SMN','SBN','THR','YZD','ZJN'])> billing_city: <city()> billing_address_1: <streetAddress()> billing_postcode: <postcode()> billing_email: '@self->user_email' billing_first_name: '@self->first_name' billing_last_name: '@self->last_name' acf: facebook_url: <url()> twitter_url: <url()> # # ATTACHMENTS # Hellonico\Fixtures\Entity\Attachment: default (template): post_title: <words(2, true)> post_date: <dateTimeThisDecade()> post_content: <paragraphs(5, true)> pics{1..3} (extends default): file: <picsum(<uploadDir()>, 400, 400)> documents{1..2} (extends default): file: <fileIn('C:\Users\xxx\Desktop\document', <uploadDir()>)> custom_images{1..4} (extends default): file: <fileIn('C:\Users\xxx\Desktop\wallpaper', <uploadDir()>)> # # TERMS # Hellonico\Fixtures\Entity\Term: category{1..10}: name (unique): <words(2, true)> # '(unique)' is required description: <sentence()> parent: '50%? <termId(childless=1)>' # 50% of created categories will have a top level parent category taxonomy: 'category' # could be skipped, default to 'category' tag{1..5}: name (unique): <words(2, true)> # '(unique)' is required description: <sentence()> taxonomy: 'post_tag' product_cat{1..5}: # custom taxonomy name (unique): <words(2, true)> # '(unique)' is required description: <sentences(3, true)> taxonomy: 'product_cat' acf: address: <streetAddress> zip: <postcode()> city: <city()> image: '@custom_images*->ID' # # POSTS # Hellonico\Fixtures\Entity\Post: # TEMPLATE defaultpost (template): post_title: <words(5, true)> post_date: <dateTimeThisDecade()> post_content: <paragraphs(5, true)> post_excerpt: <paragraphs(1, true)> # POSTS post{1..30} (extends defaultpost): meta: _thumbnail_id: '@custom_images*->ID' meta_input: _extra_field: <paragraphs(1, true)> post_category: '3x @category*->term_id' # post_category only accepts IDs tax_input: post_tag: '2x @tag*->term_id' # post_tag: '5x <words(2, true)> # Or tags can be dynamically created # PAGES page{contact, privacy} (extends defaultpost): post_title: <current()> post_type: page # CUSTOM POST TYPE product{1..15} (extends defaultpost): post_type: product meta: _thumbnail_id: '@custom_images*->ID' meta_input: _sku: <numberBetween(1000, 2000)> _price: <numberBetween(10000, 20000)> _stock_status: 'instock' _manage_stock: 'yes' _stock: <numberBetween(1, 10)> # # COMMENTS # Hellonico\Fixtures\Entity\Comment: comment{1..50}: comment_post_ID: '@post*->ID' user_id: '@user*->ID' comment_date: <dateTimeThisDecade()> comment_author: <username()> comment_author_email: <safeEmail()> comment_author_url: <url()> comment_content: <paragraphs(2, true)> comment_agent: <userAgent()> comment_author_IP: <ipv4()> comment_approved: 1 comment_karma: <numberBetween(1, 100)> # 'meta' and 'comment_meta' are basically the same, you can use one or both, # they will be merged, just don't provide the same keys in each definition comment_meta: some_key: <sentence()> meta: another_key: <sentence()> # # NAV MENUS # Hellonico\Fixtures\Entity\NavMenu: header: name: header locations: - header - footer # # NAV MENUS ITEMS # Hellonico\Fixtures\Entity\NavMenuItem: custom_menu: menu_item_url: <url()> menu_item_title: <words(4, true)> menu_id: '@header->term_id' categories{1..3}: menu_item_object: '@category*' menu_id: '@header->term_id' posts{1..3}: menu_item_object: '@post*' menu_id: '@header->term_id' page: menu_item_object: '@page*' menu_id: '@header->term_id'
The example above will generate:
- 10 users
- 15 attachments
- 10 categories
- 40 tags
- 30 posts with a thumbnail, 3 categories and 5 tags
- 10 pages
- 15 custom post types named 'product'
- 50 comments associated with post and user
- 1 nav menu
- 6 nav menu items
IMPORTANT: Make sure referenced IDs are placed BEFORE they are used.
Example: Term or Attachment objects must be placed before Post if you're referencing them in your fixtures.
Load fixtures
wp fixtures load
You can also specify a custom file by using the --file argument:
wp fixtures load --file=data.yml
Delete fixtures
wp fixtures delete
You also can delete a single fixture type:
wp fixtures delete post
Valid types are post, attachment, comment, term, user.
Add fake data to existing content
wp-cli-fixtures allows you to add/update content to existing entities by passing the ID as a constructor argument.
Add/update data to post ID 1:
Hellonico\Fixtures\Entity\Post: my_post: __construct: [1] # Pass your post ID as the constructor argument post_title: '<sentence()>' post_content: '<paragraphs(5, true)>' post_excerpt: '<paragraphs(1, true)>'
Add/update data to 10 random existing posts:
Hellonico\Fixtures\Entity\Post: post{1..10}: __construct: [<postId()>] # Use a custom formatters to return a random post ID as the constructor argument post_title: '<sentence()>' post_content: '<paragraphs(5, true)>' post_excerpt: '<paragraphs(1, true)>'
Entities
Post
Hellonico\Fixtures\Entity\Post can take any parameters available in wp_insert_post + meta and acf key.
Note: post_date_gmt and post_modified_gmt have been disabled, there are set from post_date and post_modified.
Attachment
Hellonico\Fixtures\Entity\Attachment can take any parameters available in wp_insert_attachment + meta, file and acf custom keys.
Note: parent must be passed with post_parent key.
Term
Hellonico\Fixtures\Entity\Term can take any parameters available in wp_insert_term + meta and acf custom keys.
Note: term and taxonomy must be respectively passed with name and taxonomy key.
User
Hellonico\Fixtures\Entity\User can take any parameters available in wp_insert_user + meta and acf custom keys.
Comment
Hellonico\Fixtures\Entity\Comment can take any parameters available in wp_insert_comment + meta custom key.
comment_date_gmt has been disabled, it is set from comment_date.
Nav menu
Hellonico\Fixtures\Entity\NavMenu is a term just like Hellonico\Fixtures\Entity\Term. It takes an addiotional locations parameter to set the menu location.
Hellonico\Fixtures\Entity\NavMenu: header: name: header locations: - header
Nav menu item
Hellonico\Fixtures\Entity\NavMenuItem takes the same parameters as $menu_item_data in wp_update_nav_menu_item
Note 1: replace dashes with underscore in keys (e.g. menu-item-object becomes menu_item_object).
Note 2: menu-item-object can also accept an entity object, if so, menu-item-type and menu-item-object-id will be filled automatically with appropriate values
ACF Support
Each ACF supported entity (post, term, user) can have an acf key, which works just like meta.
Hellonico\Fixtures\Entity\Post: post{1..30}: post_title: <words(3, true)> post_date: <dateTimeThisDecade()> acf: # number field number: <numberBetween(10, 200)> # repeater field features: - label: <words(2, true)> value: <sentence() - label: <words(2, true)> value: <sentence()> - label: <words(2, true)> value: <sentence()>
Be careful with duplicate field keys, if you have multiple field with the same key, prefer using ACF field key (field_948d1qj5mn4d3).
Custom formatters
In addition to formatters provided by fzaninotto/Faker, you can use custom formatters below.
postId($args)
Returns a random existing post ID.
$args is optional and can take any arguments from get_posts
Example:
<postId(category=1,2,3)>
attachmentId($args)
Returns a random existing attachment ID.
$args is optional and can take any arguments from get_posts
Example:
<attachmentId(year=2016)>
termId($args)
Returns a random existing term ID.
$args is optional and can take any arguments from get_terms
Example:
<termId(taxonomy=post_tag)>
userId($args)
Returns a random existing user ID.
$args is optional and can take any arguments from get_users
Example:
<userId(role=subscriber)>
fileContent($file)
Returns the content of a file.
Example:
<fileContent('path/to/file.html')>
fileIn($src, $target, false)
Wrapper around file provider because some Faker providers conflicts with PHP native . Returns file path or file name in a directory ($src relative to fixtures.yml).
Default target is the WordPress uploads.
Example:
<fileIn('my/set/of/images')>
Tips
While playing with fixtures, the database command package can be useful to reset database faster than wp fixtures delete and start over.
Contribute
This package follows PSR2 coding standards and is tested with Behat. Execute composer run test to ensure your PR passes.
You will need to run
composer run prepare-testsbefore your first run.