Fields, like most other things, are configuration (entities) now.
That means you don't have to write code to create them, you can simply create them in the UI, then export them through the Configuration management UI and put the relevant files into your
config/install folder. Drupal will automatically import all your configuration from that folder.
Note that a field commonly consists of 4 parts:
- The field storage, a file named
field.storage.user.yourfieldname.yml (or node, comment,... for other entity types). This defines the field and storage relevant configuration.
- The field, a file named
field.field.user.user.yourfieldname.yml (user is special because there is only one bundle, for nodes, it would e.g. be node.article). This defines that a field is available on a specific bundle and includes configuration like the label.
- One or multiple form displays, for example named
core.entity_form_display.user.default.yml. User by default has two form modes, default and register. Node by default has only one. This stores the widget configuration for the field.
- One or multiple view displays, for example
core.entity_view_display.user.default.yml. This stores the formatter information for a specific view mode.
The first two files can just be copied to your
config/install folder. The other two are bit more complicated, because they contain the widget/formatter configuration for all fields of that entity type, bundle and form/view display combination. So in the case of user for example, you do need a bit of code to add the configuration to the existing form/view display. See node_add_body_field() for example code. You can get the exact settings from the exported files.
If you own the bundle, for example, if your module defines a node type with a numer of fields, you can also just add those form/view displays to the configuration folder.