Skip to main content

Migrating to GravityView 3.0

GravityView 3.0 is a structural refactor. The plugin's class library has been consolidated under the GravityKit\GravityView\* namespace with PSR-4 autoloading, the minimum WordPress version has moved up, and a long-standing assumption that certain files must exist on disk has been removed.

This guide is for developers who build on top of GravityView: custom templates, add-ons, extensions, theme overrides, and integration layers. It covers what changed, what you need to do before upgrading, and how to resolve the most common migration errors.

Mostly structural, with two caveats

3.0 is structural. Legacy class names, file-based template overrides, and hook callbacks continue to work through compatibility bridges. You can migrate on your own schedule; the deprecation window stays open.

Two caveats worth knowing up front: get_class() now returns the canonical PSR-4 name, so string comparisons against old class names will fail (see "Use is_a() or instanceof"), and some operations no longer assume a physical file is on disk (see "File system changes").

Overview of what's changing

  • Every class from includes/ (convention: GravityView_*) and future/ (namespace: \GV\*) has moved to src/ under GravityKit\GravityView\*.
  • The includes/ and future/ directories were removed entirely. Over 200 legacy files and 83 namespaced files were relocated and renamed to match PSR-4 conventions.
  • Composer autoload now targets src/ with an optimized classmap.
  • Legacy names resolve through lazy SPL autoloaders in src/Aliases/gv-aliases.php and src/Aliases/legacy-aliases.php that call class_alias() on demand.
  • The minimum WordPress version has been raised — see below.
  • Certain operations no longer require a physical file on disk. This is a new architectural direction in 3.0 and has implications for custom templates and integrations — see "File system changes" below.
  • A set of formal interfaces was added under GravityKit\GravityView\Contracts.
  • Over 40 legacy hooks deprecated in 2.55 continue to emit deprecation notices.
  • Search, which moved to the Query Filters pipeline in 2.x, stays on that pipeline in 3.0. A handful of legacy search hooks deprecated in 2.56 remain in the compatibility layer.

New minimum WordPress version

GravityView 3.0 raises the minimum supported WordPress version to 5.5.

DependencyMinimumRecommended
PHP7.4.08.1+
WordPress5.56.0+
Gravity Forms2.6.02.7+

Why 5.5?

  • WordPress 5.2 added the libsodium polyfill and the site health tooling. That's the floor we need for any modern crypto or diagnostic code.
  • WordPress 5.5 added the https_local_ssl_verify filter and improved REST and cron internals. Supporting anything older forced us to keep shims in place for behaviors that shipped over five years ago.
  • WordPress 6.0+ is recommended. Block editor work and newer Gravity Forms features assume it.

If your add-on also targets GravityView, update your own Requires at least header to 5.5 and audit any conditional code that branched on pre-5.5 WordPress versions. You can drop those branches.

The future-minimum constants in gravityview.php have been updated accordingly:

GV_MIN_WP_VERSION           // '5.5'
GV_FUTURE_MIN_WP_VERSION // '6.0'
GV_MIN_GF_VERSION // '2.6.0'
GV_FUTURE_MIN_GF_VERSION // '2.7.0'
GV_FUTURE_MIN_PHP_VERSION // '8.0.0'

If your add-on checks GV_MIN_WP_VERSION to decide whether to bail, you're fine — the constant still exists. If you hard-coded 4.7.0 anywhere, update it.

Query Filters

A common question during the 3.0 beta: did Query Filters ship with 3.0?

No — Query Filters shipped in 2.x. The search pipeline was rebuilt on top of the Query Filters library in 2.56, and the legacy GF_Query-based search hooks were deprecated at the same time. 3.0 doesn't change the pipeline. It continues to route View searches through Query Filters and keeps the 2.56 deprecation notices active for any code still wired to the old hooks.

If you were already using the modern gk/gravityview/search/request/* and gk/query-filters/condition/* filters in 2.x, nothing changes for you in 3.0. If you're still on a legacy search hook, the replacement has existed since 2.56:

Deprecated in 2.56Replacement
gravityview_fe_search_criteriagk/gravityview/search/request/filters
gravityview/widgets/search/created_by/user_meta_fieldsgk/query-filters/condition/created-by/user-meta-fields
gravityview/widgets/search/created_by/user_fieldsgk/query-filters/condition/created-by/user-fields
GravityView_Widget_Search_Author_GF_Query_ConditionQuery Filters Created_By_Condition class

If you previously extended GravityView_Widget_Search_Author_GF_Query_Condition or wrote a custom GF_Query_Condition subclass for GravityView searches, port your logic to a Query Filters condition class. The library's Created_By_Condition is a reference implementation.

File system changes

3.0 beta: verify in your environment

This section describes an architectural change we're still hardening during the 3.0 beta. Some error paths have not yet been exercised at scale — please test in staging and report anything unexpected to support before relying on this behavior in production.

In 2.x and earlier, several GravityView operations assumed a physical file existed on disk — template includes, field-type registrations, and some admin view resolutions all resolved by calling file_exists() or require_once on a concrete path. 3.0 breaks that assumption.

What changed

  • Class resolution runs through the PSR-4 autoloader and Composer's optimized classmap. No code path explicitly requires a legacy file to be present by name.
  • Template resolution continues to support file-based overrides in your theme or plugin (see "Template overrides" below), but core template loading no longer depends on a physical file at the canonical includes/ or future/ path.
  • Registered field types and widgets can be contributed entirely in-memory via their class, without a supporting field-types/*.php or widgets/*.php file.

Errors you might see during the beta

Because the file-existence assumption is baked into some third-party add-ons and into older custom code, you may hit errors of the form:

  • include(): Failed opening '.../includes/class-gravityview-*.php' — an add-on is trying to require_once a file that was moved to src/.
  • Call to undefined function gravityview_*() — a global helper is defined inline in a file that is no longer auto-included. Most globals moved to src/Utils/helper-functions.php, which Composer loads via files autoload. If you replaced the autoloader or bootstrapped GravityView manually in a test harness, re-include it.
  • Class 'GravityView_*' not found thrown during spl_autoload_call() — the alias autoloader hasn't been registered yet because GRAVITYVIEW_DIR wasn't defined when vendor/autoload.php ran. Define the plugin constants before loading the autoloader, or let gravityview.php bootstrap normally.

How to handle them

  1. Replace any require_once WP_PLUGIN_DIR . '/gravityview/includes/...' (or future/...) in your add-on with a namespaced class reference. The PSR-4 autoloader will find it.
  2. If you maintain a plugin that inlined a helper function expecting a certain GravityView file to be loaded, replace the inline with a call to the canonical helper in src/Utils/helper-functions.php.
  3. Avoid file_exists() gates against GravityView internal paths in your own code. Check class existence with class_exists(...) instead — it respects aliases.
  4. If you ship a test bootstrap that loads vendor/autoload.php before GravityView's constants are defined, the alias files short-circuit. That's intentional. Re-include them after constants are set, or simply let gravityview.php handle the sequence.
Reporting edge cases

If you hit a file-not-found or class-not-found error that doesn't match the patterns above, email [email protected] with a stack trace and your GravityView version. We'd rather catch these during beta than after.

Plugin bootstrap order

Understanding the load sequence helps diagnose "class not found" and alias timing issues. gravityview.php executes in this order:

  1. Foundation preflight check
  2. GravityKit\GravityView\Foundation\should_load() and meets_min_php_version_requirement() gates
  3. Plugin constants (GV_PLUGIN_VERSION, GRAVITYVIEW_DIR, etc.)
  4. Composer autoload: vendor/autoload.php, then vendor_prefixed/autoload.php
  5. Alias includes: src/Aliases/gv-aliases.php and src/Aliases/legacy-aliases.php
  6. GravityKit\GravityView\Foundation\Core::register( GRAVITYVIEW_FILE )
  7. _mocks.php for deprecated global functions
  8. GravityView_Deprecated_Hook_Notices::init()
  9. \GV\Core::bootstrap()

The alias files are also listed in Composer's files autoload. They register once via a GRAVITYVIEW_LEGACY_ALIASES_REGISTERED / GRAVITYVIEW_GV_ALIASES_REGISTERED sentinel, so double inclusion is safe.

Autoload strategy

GravityView 3.0 uses a two-layer autoload approach.

Layer 1: PSR-4 with optimized classmap

composer.json maps the PSR-4 root to src/:

"autoload": {
"psr-4": {
"GravityKit\\GravityView\\": "src/"
},
"exclude-from-classmap": [
"src/Gutenberg/node_modules/",
"src/Gutenberg/Blocks/*/block.php",
"src/Admin/Rendering/field-types/",
"src/GravityForms/QueryExtensions/_mocks.php",
"src/Widget/Search/class-search-widget.php",
"src/Utils/class-common.php",
"src/API/class-api.php"
],
"files": [
"src/Aliases/gv-aliases.php",
"src/Aliases/legacy-aliases.php",
"src/Utils/helper-functions.php",
"src/Utils/connector-functions.php",
"src/Utils/import-functions.php"
]
}

composer dump-autoload -o is run in post-install-cmd and post-update-cmd. Class lookups hit the optimized classmap before falling back to PSR-4 path resolution.

Layer 2: Lazy SPL autoloaders for legacy names

Both alias files register SPL autoloaders that intercept legacy class references. When PHP encounters a legacy name (\GV\View or GravityView_Admin), the autoloader:

  1. Looks up the legacy → PSR-4 name in a static map.
  2. Triggers the Composer PSR-4 autoloader to load the canonical class.
  3. Calls class_alias( $psr4_class, $legacy_class ) so the legacy name resolves.

Lazy resolution avoids the circular-dependency problems that class_alias() batches at load time would introduce — for example, aliasing a child before its parent.

Vendor prefixing with Strauss

Foundation and Query Filters are vendor-prefixed during composer install:

  • GravityKit\Foundation\*GravityKit\GravityView\Foundation\*
  • GravityKit\QueryFilters\*GravityKit\GravityView\QueryFilters\*
  • Third-party dependencies (Gettext, Illuminate, Monolog, Psr, TrustedLogin) move under GravityKit\GravityView\Foundation\ThirdParty\*

If your add-on depends on Foundation or Query Filters, reference GravityView's prefixed copies by their prefixed names.

Namespace mapping

The full tables live below. The complete mapping also lives in src/Aliases/gv-aliases.php (372 lines, \GV\* mappings) and src/Aliases/legacy-aliases.php (819 lines, GravityView_* mappings). Read those files when you can't find a class in these tables.

Core infrastructure

Old nameNew PSR-4 name
\GV\CoreGravityKit\GravityView\Core\Core
\GV\PluginGravityKit\GravityView\Core\Plugin
\GV\PermalinksGravityKit\GravityView\Core\Permalinks
\GV\SettingsGravityKit\GravityView\Settings\Settings
\GV\Plugin_SettingsGravityKit\GravityView\Settings\PluginSettings
\GV\View_SettingsGravityKit\GravityView\Settings\ViewSettings
\GV\LoggerGravityKit\GravityView\Logging\Logger
\GV\LogLevelGravityKit\GravityView\Logging\LogLevel
\GV\WP_Action_LoggerGravityKit\GravityView\Logging\LoggerWpAction
\GV\CollectionGravityKit\GravityView\Data\Collection
\GV\SourceGravityKit\GravityView\Form\Source
\GV\ContextGravityKit\GravityView\Template\Context
\GV\Template_ContextGravityKit\GravityView\Template\TemplateContext
\GV\UtilsGravityKit\GravityView\Utils\Utils
\GV\ExtensionGravityKit\GravityView\Extension\Extension
\GV\oEmbedGravityKit\GravityView\Media\oEmbed
\GV\Wrappers\viewsGravityKit\GravityView\Wrappers\Views
\GV\Collection_Position_AwareGravityKit\GravityView\Contracts\CollectionPositionAwareInterface
\GV\Field_Renderer_TraitGravityKit\GravityView\Renderer\FieldRendererTrait

View domain

Old nameNew PSR-4 name
\GV\ViewGravityKit\GravityView\View\View
\GV\View_CollectionGravityKit\GravityView\View\ViewCollection
\GV\JoinGravityKit\GravityView\View\Join
GravityView_ViewGravityKit\GravityView\View\ViewLegacy
GravityView_View_DataGravityKit\GravityView\Data\ViewData

Entry domain

Old nameNew PSR-4 name
\GV\EntryGravityKit\GravityView\Entry\Entry
\GV\GF_EntryGravityKit\GravityView\Entry\EntryGravityForms
\GV\Entry_CollectionGravityKit\GravityView\Entry\EntryCollection
\GV\Entry_FilterGravityKit\GravityView\Entry\EntryFilter
\GV\GF_Entry_FilterGravityKit\GravityView\Entry\EntryFilterGravityForms
GravityView_Entry_ApprovalGravityKit\GravityView\Entry\Approval
GravityView_Entry_Approval_StatusGravityKit\GravityView\Entry\ApprovalStatus
GravityView_Entry_Approval_Merge_TagsGravityKit\GravityView\Entry\ApprovalMergeTags

Form and field domains

Old nameNew PSR-4 name
\GV\FormGravityKit\GravityView\Form\Form
\GV\GF_FormGravityKit\GravityView\Form\FormGravityForms
\GV\Form_CollectionGravityKit\GravityView\Form\FormCollection
\GV\FieldGravityKit\GravityView\Field\Field
\GV\GF_FieldGravityKit\GravityView\Field\FieldGravityForms
\GV\Internal_FieldGravityKit\GravityView\Field\InternalField
\GV\Internal_SourceGravityKit\GravityView\Field\InternalSource
\GV\Field_CollectionGravityKit\GravityView\Field\FieldCollection
GravityView_FieldGravityKit\GravityView\Field\Types\GravityViewField

Widget, template, and renderer

Old nameNew PSR-4 name
\GV\WidgetGravityKit\GravityView\Widget\Widget
\GV\Widget_CollectionGravityKit\GravityView\Widget\WidgetCollection
\GV\TemplateGravityKit\GravityView\Template\Template
\GV\View_TemplateGravityKit\GravityView\Template\TemplateView
\GV\Entry_TemplateGravityKit\GravityView\Template\TemplateEntry
\GV\Field_TemplateGravityKit\GravityView\Template\TemplateField
\GV\View_Table_TemplateGravityKit\GravityView\Template\View\Table
\GV\View_List_TemplateGravityKit\GravityView\Template\View\ListTemplate
\GV\Entry_Table_TemplateGravityKit\GravityView\Template\Entry\Table
\GV\Entry_List_TemplateGravityKit\GravityView\Template\Entry\ListTemplate
\GV\RendererGravityKit\GravityView\Renderer\Renderer
\GV\View_RendererGravityKit\GravityView\Renderer\ViewRenderer
\GV\Entry_RendererGravityKit\GravityView\Renderer\EntryRenderer
\GV\Field_RendererGravityKit\GravityView\Renderer\FieldRenderer
GravityView_TemplateGravityKit\GravityView\Template\LegacyTemplate
GravityView_Merge_TagsGravityKit\GravityView\Renderer\MergeTags

Request, shortcode, REST, and admin

Old nameNew PSR-4 name
\GV\RequestGravityKit\GravityView\Request\Request
\GV\Frontend_RequestGravityKit\GravityView\Request\FrontendRequest
\GV\Admin_RequestGravityKit\GravityView\Request\AdminRequest
\GV\ShortcodeGravityKit\GravityView\Shortcode\Shortcode
\GV\Shortcodes\gravityviewGravityKit\GravityView\Shortcode\GravityViewShortcode
\GV\REST\CoreGravityKit\GravityView\REST\Core
\GV\REST\RouteGravityKit\GravityView\REST\Route
\GV\REST\Views_RouteGravityKit\GravityView\REST\ViewsRoute
GravityView_AdminGravityKit\GravityView\Admin\Admin
GravityView_Admin_ViewsGravityKit\GravityView\Admin\AdminViews
GravityView_Admin_MetaboxesGravityKit\GravityView\Admin\Metaboxes\AdminMetaboxes
GravityView_frontendGravityKit\GravityView\Frontend\Frontend

Extensions and utilities

Old nameNew PSR-4 name
GravityView_Edit_EntryGravityKit\GravityView\Extension\EditEntry\EditEntry
GravityView_Delete_EntryGravityKit\GravityView\Extension\DeleteEntry\DeleteEntry
GravityView_Duplicate_EntryGravityKit\GravityView\Extension\DuplicateEntry\DuplicateEntry
GravityView_APIGravityKit\GravityView\API\API
GVCommonGravityKit\GravityView\Legacy\Utility\Common
GravityView_CacheGravityKit\GravityView\Data\Cache
GravityView_ImageGravityKit\GravityView\Frontend\Image
GravityView_CompatibilityGravityKit\GravityView\Utils\Compatibility
GravityView_GF_CompatGravityKit\GravityView\GravityForms\Compat
GravityView_LoggingGravityKit\GravityView\Logging\Logging
GravityView_NotificationsGravityKit\GravityView\Core\Notifications
GravityView_Powered_ByGravityKit\GravityView\Frontend\PoweredBy
GravityView_Error_MessagesGravityKit\GravityView\Utils\ErrorMessages
GravityView_Post_TypesGravityKit\GravityView\Core\PostTypes
GravityView_HTML_ElementsGravityKit\GravityView\Utils\HtmlElements
GravityView_UninstallGravityKit\GravityView\Core\Uninstall
GravityView_AjaxGravityKit\GravityView\AJAX\AJAX
GravityView_SettingsGravityKit\GravityView\Settings\GravityViewSettings
GravityView_Roles_CapabilitiesGravityKit\GravityView\Permissions\RolesCapabilities
GravityView_Deprecated_Hook_NoticesGravityKit\GravityView\Deprecation\DeprecatedHookNotices
GravityView_oEmbedGravityKit\GravityView\Media\LegacyOEmbed
GVCommon is classified as legacy

GVCommon is intentionally parked under Legacy\Utility. The class aggregates unrelated responsibilities (data access, view configuration, HTML, email/encryption) and will be split into focused helpers in a future release. The alias keeps all GVCommon::method() calls working.

New Contracts interfaces

src/Contracts/ introduces formal interfaces that document the expected contract of core domain types. Custom implementations can target these interfaces for type safety and future-proofing:

InterfaceDescribes
GravityKit\GravityView\Contracts\ViewInterfaceA configured display of form entries, backed by the gravityview post type.
GravityKit\GravityView\Contracts\EntryInterfaceA single form submission rendered inside a View.
GravityKit\GravityView\Contracts\FieldInterfaceA data point inside a View — form field value, custom content, computed value.
GravityKit\GravityView\Contracts\FormInterfaceA data source (Gravity Forms form or internal source) that provides entries.
GravityKit\GravityView\Contracts\WidgetInterfaceSupplementary UI such as pagination, search, or custom content areas.
GravityKit\GravityView\Contracts\CollectionPositionAwareInterfaceCollections filterable by position (fields, widgets, search fields).

These are new in 3.0. Core classes implement them, and \GV\Collection_Position_Aware now aliases the new interface. If you implement a custom Field, Widget, or Source, consider implementing the matching Contracts\*Interface alongside extending the base class.

Migrating your code

Update use statements

// Before:
use GV\View;
use GV\Entry;
use GV\GF_Entry;
use GV\Template_Context;

// After:
use GravityKit\GravityView\View\View;
use GravityKit\GravityView\Entry\Entry;
use GravityKit\GravityView\Entry\EntryGravityForms;
use GravityKit\GravityView\Template\TemplateContext;

Update fully-qualified class references

// Before:
$view = \GV\View::by_id( $view_id );
$entry = \GV\GF_Entry::by_id( $entry_id );
$admin = new GravityView_Admin();

// After:
$view = \GravityKit\GravityView\View\View::by_id( $view_id );
$entry = \GravityKit\GravityView\Entry\EntryGravityForms::by_id( $entry_id );
$admin = new \GravityKit\GravityView\Admin\Admin();

Use is_a() or instanceof, not get_class() string comparisons

Legacy class names continue to work with type operators. Both old and new names resolve to the same object:

// Both of these return true for the same object:
if ( $object instanceof \GV\View ) { /* ... */ }
if ( $object instanceof \GravityKit\GravityView\View\View ) { /* ... */ }

// Both of these return true:
if ( is_a( $object, 'GV\View' ) ) { /* ... */ }
if ( is_a( $object, 'GravityKit\GravityView\View\View' ) ) { /* ... */ }
warning
get_class() returns the canonical name

get_class() returns the canonical (PSR-4) class name, not the alias. String equality against the old class name will fail in 3.0.

// Breaks in 3.0 — get_class() returns 'GravityKit\GravityView\View\View':
if ( get_class( $object ) === 'GV\View' ) { /* ... */ }

// Use instead:
if ( is_a( $object, 'GV\View' ) ) { /* ... */ }

This is the single most common break in downstream integrations. Audit your codebase for get_class( and replace any string comparisons with is_a() or instanceof.

The same applies to serialization keys, array lookups keyed by class name, and any reflective code that reads class strings. If you persist class names to storage (options, meta, cache), re-key them using is_a() lookups or store the alias explicitly.

Update extends declarations

If you subclass GravityView template or renderer classes, update the parent:

// Before:
class My_Custom_Table_Template extends \GV\View_Table_Template { /* ... */ }

// After:
use GravityKit\GravityView\Template\View\Table;

class My_Custom_Table_Template extends Table { /* ... */ }

Template overrides

File-based template overrides are unchanged. The GravityKit\GravityView\Template\LegacyOverride class extends the Gamajo Template Loader and continues to resolve templates from both theme and plugin locations:

LocationPurpose
wp-content/themes/your-theme/gravityview/Theme-level overrides
wp-content/plugins/your-plugin/templates/Plugin-level overrides

Filenames and directory structure are identical to 2.x. If you copied list-body.php, list-header.php, table-body.php, table-header.php, single-entry.php, or any other partial into your theme, those files continue to render without modification.

The gravityview_theme_template_directory and gravityview_plugin_template_directory filters still fire during path resolution if you need to inject custom lookup directories.

Deprecations and breaking changes

Deprecated 1.x hooks

Over 40 legacy gravityview_* hooks were deprecated in 2.55 and continue to emit deprecation notices in 3.0. All deprecations are routed through the GravityView_Deprecated_Hook_Notices wrapper:

$default_areas = \GravityView_Deprecated_Hook_Notices::apply_filters(
'gravityview_widget_active_areas',
[ $default_areas ],
'2.55', // Deprecated since version
'gravityview/widget/active_areas' // Replacement hook
);

The wrapper calls WordPress's apply_filters_deprecated() / do_action_deprecated() under the hood. Internal GravityKit callbacks are suppressed from the PHP trigger_error so staging logs stay quiet when our own code is still wired to the legacy hook. External callbacks produce a deprecation notice and a Foundation-stored admin notice pointing to the offending file and line.

note
Deprecation notices only surface with WP_DEBUG

Admin notices for deprecated hooks are only rendered when WP_DEBUG is enabled (or when the gk/gravityview/deprecated-hook-notices/register filter returns true). Production sites stay quiet.

Template and rendering hooks

Deprecated (1.x, @since ≤2.x)Replacement (2.0+)
gravityview_beforegravityview/template/before
gravityview_headergravityview/template/header
gravityview_footergravityview/template/footer
gravityview_aftergravityview/template/after
gravityview_field_outputgravityview/field_output/html
gravityview/field_output/argsgravityview/template/field_output/context
gravityview_entry_classgravityview/template/{template}/entry/class
gravityview_default_argsgravityview/view/settings/defaults
gravityview_go_back_urlgravityview/template/links/back/url
gravityview_go_back_labelgravityview/template/links/back/label
gravityview_empty_valuegravityview/field/value/empty
gravitview_no_entries_text (sic)gravityview/template/text/no_entries
gravityview_directory_linkgravityview/view/links/directory
gravityview/template/field_labelgravityview/template/field/label

Table template hooks

DeprecatedReplacement
gravityview_table_cellsgravityview/template/table/fields
gravityview_table_cells_beforegravityview/template/table/cells/before
gravityview_table_cells_aftergravityview/template/table/cells/after
gravityview_table_body_beforegravityview/template/table/body/before
gravityview_table_body_aftergravityview/template/table/body/after
gravityview_table_tr_beforegravityview/template/table/tr/before
gravityview_table_tr_aftergravityview/template/table/tr/after

List template hooks

DeprecatedReplacement
gravityview_list_body_beforegravityview/template/list/body/before
gravityview_list_body_aftergravityview/template/list/body/after
gravityview_list_entry_{zone}_beforegravityview/template/list/entry/{zone}/before
gravityview_list_entry_{zone}_aftergravityview/template/list/entry/{zone}/after

Field and entry hooks

DeprecatedReplacement
gravityview_field_entry_linkgravityview/template/field/entry_link
gravityview_field_entry_valuegravityview/template/field/{type}/output
gravityview_field_entry_value_{type}gravityview/template/field/{type}/output
gravityview_field_entry_value_{type}_pre_linkgravityview/template/field/{type}/output
gravityview_template_{field_type}_optionsgk/gravityview/template/options
gravityview_template_{input_type}_optionsgk/gravityview/template/options

View, widget, and lifecycle hooks

DeprecatedReplacement
gravityview_direct_accessgravityview/view/output/direct
gravityview_widget_active_areasgravityview/widget/active_areas
gravityview_register_directory_widgetsgravityview/widgets/register
gravityview_include_frontend_actionsgravityview/loaded
gravityview_view_entriesgravityview/view/entries
gravityview_before_get_entriesgravityview/view/entries
gravityview/configuration/fieldsgravityview/view/configuration/fields
gravityview/data/parse/meta_keysgravityview/view_collection/from_post/meta_keys
gravityview/widget/hide_until_searched/whitelistgravityview/widget/hide_until_searched/allowlist (since 2.14)
gravityview/edit_entry/field_blacklistgravityview/edit_entry/field_blocklist (since 2.14)
gravityview_blacklist_field_typesgravityview_blocklist_field_types (since 2.14)
gravityview/sortable/field_blacklistgravityview/sortable/field_blocklist (since 2.14)

Extension hooks

Delete Entry hooks were renamed to the gk/ namespace in 2.55:

DeprecatedReplacement
gravityview/delete-entry/modegk/gravityview/delete-entry/mode
gravityview/delete-entry/deletedgk/gravityview/delete-entry/deleted
gravityview/delete-entry/trashedgk/gravityview/delete-entry/trashed
gravityview/delete-entry/delete-connected-postgk/gravityview/delete-entry/delete-connected-post

Search hooks (deprecated in 2.56)

See the Query Filters section above. These were deprecated when the Query Filters pipeline replaced the GF_Query-based search logic in 2.56 — they remain in the compatibility layer in 3.0.

Removed files

  • Legacy REST route shim files (src/REST/class-gv-rest-route.php, src/REST/class-gv-rest-views-route.php).
  • Legacy Admin stubs; gravityview_is_admin_page() moved to src/API/class-api.php.

New hooks in 3.0

The 3.0 release cycle added roughly 80 new gk/gravityview/* hooks. A non-exhaustive list of the most useful ones:

Search and query

  • gk/gravityview/search/request/filters — modify search filters before the query runs.
  • gk/gravityview/search/request/method — change the search method (any vs all).
  • gk/gravityview/search/request/search-arguments — modify parsed search arguments before processing.
  • gk/query-filters/condition/created-by/user-meta-fields — extend created_by searches to custom user meta fields.
  • gk/query-filters/condition/created-by/user-fields — extend created_by searches to custom user table columns.

Template rendering

  • gk/gravityview/template/options — field options filter; receives $field_options, $template_id, $field_id, $context, $input_type, $form_id.
  • gk/gravityview/admin-views/view/template/active-areas — per-template active area definitions.
  • gk/gravityview/admin-views/row/before and row/after — inject markup around View Editor rows.
  • gk/gravityview/admin-views/area/actions and rows-actions — contribute actions to the View Editor UI.

Entry management

  • gk/gravityview/delete-entry/mode, deleted, trashed, delete-connected-post, can-delete, show-delete-button — full set of Delete Entry extension points.
  • gk/gravityview/edit-entry/init/data — modify Edit Entry render data.
  • gk/gravityview/edit-entry/lock-granted-stale, lock-stale-threshold — tune entry-lock behavior.
  • gk/gravityview/edit-entry/user-can-edit-field — per-field edit permission.
  • gk/gravityview/entry-approval/choices — extend approval status choices.
  • gk/gravityview/entry/approval-link/params — modify approval-link query parameters.

Compatibility and admin

  • gk/gravityview/compatibility/block-assets-on-demand — toggle asset loading strategy.
  • gk/gravityview/admin/can_duplicate_field — per-field duplication control.
  • gk/gravityview/deprecated-hook-notices/register — force registration of deprecation notices.
  • gk/gravityview/deprecated-hook-notices/is-internal — classify a callback as internal (suppresses notice).
  • gk/gravityview/feature/upgrade/disabled — disable specific upgrade-gated features.

Deprecation notices infrastructure

GravityKit\GravityView\Deprecation\DeprecatedHookNotices exposes three public static methods:

DeprecatedHookNotices::apply_filters(
string $hook,
array $args,
string $version,
string $replacement = '',
string $message = ''
);

DeprecatedHookNotices::do_action(
string $hook,
array $args,
string $version,
string $replacement = '',
string $message = ''
);

DeprecatedHookNotices::deprecated_hook(
string $hook,
string $version,
string $replacement = '',
string $message = ''
);

If you maintain add-ons with their own deprecation wave, you can reuse this infrastructure — it's a candidate for migration to Foundation in the future so all GravityKit products share the same notice handling.

Before you upgrade

Run through this checklist on a staging site before upgrading production:

  1. Confirm your WordPress version is 5.5 or newer. If you're below that, upgrade WordPress first.
  2. Scan your codebase for use GV\ and use GravityView_; replace each with the PSR-4 equivalent.
  3. Replace \GV\* and bare GravityView_* references in new, static calls, return types, and parameter types.
  4. Search for get_class( and replace string comparisons against old class names with is_a() or instanceof.
  5. Search for implements \GV\Collection_Position_Aware and update to GravityKit\GravityView\Contracts\CollectionPositionAwareInterface.
  6. Update extends declarations on subclasses of GravityView template, renderer, or field classes.
  7. Review any code that persists class names to storage (options, meta, cache). Migrate stored values if they must match get_class().
  8. Check your composer.json if your add-on depends on gravitykit/foundation or gravitykit/query-filters directly — GravityView ships its own prefixed copies under vendor_prefixed/.
  9. Remove any require_once against files in includes/ or future/. The directories are gone. Rely on the PSR-4 autoloader and alias autoloaders.
  10. Turn on WP_DEBUG and WP_DEBUG_LOG in staging. Exercise your add-on's critical paths and review debug.log for deprecation notices.
  11. Run your existing test suite. Because 3.0 is structural, most failures point to a missed rename rather than a logic regression.

Troubleshooting common migration errors

Fatal error: Class 'GravityView_Foo' not found

Cause: Either (a) the alias autoloader was not registered before the class was referenced, or (b) the class name doesn't map to anything in src/Aliases/legacy-aliases.php.

Fix:

  • Verify GRAVITYVIEW_DIR was defined before vendor/autoload.php ran. If you bootstrap GravityView manually (e.g. in a test harness), let gravityview.php bootstrap normally, or define constants before autoload.
  • Check src/Aliases/legacy-aliases.php and src/Aliases/gv-aliases.php for the mapping. If the class name truly isn't mapped, the class was either removed or renamed and not aliased — email [email protected] with the class name and caller.

PHP Warning: include(): Failed opening '.../includes/class-gravityview-*.php'

Cause: An add-on or theme is trying to require_once a file that was moved to src/ under a new name.

Fix: Remove the require_once and reference the class through the PSR-4 autoloader. If the file was a global-helper include, replace it with a call to the canonical helper in src/Utils/helper-functions.php.

if ( get_class( $view ) === '\GV\View' ) branches stop matching

Cause: get_class() returns the canonical PSR-4 name.

Fix: Replace with if ( $view instanceof \GV\View ) or if ( is_a( $view, 'GV\View' ) ). Both the legacy and the canonical name resolve via the alias, so is_a() matches in either direction.

Deprecation notices flooding debug.log

Cause: An active add-on still uses 1.x hooks deprecated in 2.55.

Fix: Audit the add-on against the replacement tables above and update to the 2.0+ replacement hooks. If the add-on is a third-party plugin you don't maintain, file an issue with the author — the replacement hooks have been available since 2.0 in most cases, and since 2.55 at the latest.

Cause: The search pipeline moved to Query Filters in 2.56. Your subclass never ran in production after that release.

Fix: Port the condition to a Query Filters condition class. Created_By_Condition in the Query Filters library is a reference.

Child classes erroring during autoload

Cause: Rare, but possible if you instantiate a subclass of a legacy-aliased parent during early bootstrap.

Fix: The lazy autoloader resolves the child first, then the parent. If both are aliases, two autoloader passes run. This is expected and works — but make sure you're not calling it before step 5 of the bootstrap order (the alias includes). If you need classes earlier, include src/Aliases/gv-aliases.php and src/Aliases/legacy-aliases.php explicitly after defining GRAVITYVIEW_DIR.

Known edge cases

  • Test bootstraps that load vendor/autoload.php before constants are defined will still work. The alias files short-circuit when GRAVITYVIEW_DIR is not defined and are re-included by gravityview.php after constants are set.
  • Namespaced use statements that import from \GV\*. PHP records the import at compile time but doesn't resolve the class until usage. First use triggers the alias autoloader, which creates the alias. Subsequent uses are cached.
  • Reflection. ReflectionClass::getName() returns the canonical PSR-4 name. If you compare reflection output against legacy strings, normalize with is_a().
  • Some legacy compatibility files remain where deeper refactors are pending: src/API/class-api.php (global helper functions), src/Utils/class-common.php (GVCommon implementation), and src/Widget/Search/class-search-widget.php.

Getting help

Email [email protected] with the class or hook name, the version of your add-on, the GravityView version, and a minimal reproduction. If you maintain a commercial extension, we'll help you plan the migration and coordinate release timing.