Skip to content

Remove extra structs for objects with properties#1992

Merged
alcaeus merged 3 commits intomongodb:v2.xfrom
alcaeus:phpc-2699-remove-extra-structs
Apr 16, 2026
Merged

Remove extra structs for objects with properties#1992
alcaeus merged 3 commits intomongodb:v2.xfrom
alcaeus:phpc-2699-remove-extra-structs

Conversation

@alcaeus
Copy link
Copy Markdown
Member

@alcaeus alcaeus commented Apr 16, 2026

With many classes storing internal properties in zend_object, we're now storing data twice in multiple classes: once in the struct fields, and once in the property. The struct fields are only used for the getters, which strictly speaking isn't necessary. To be clear, we were doing this before already once get_properties_hash was invoked and we populated our own properties table.

This PR does away with that duplicate data handling for everything that returns static information (i.e. where we don't need to keep a reference to an underlying libmongoc structure):

  • The new PHONGO_PROPERTY_GETTER macro is used to declare the boilerplate for getters, consisting of parameter parsing and reading the property value into the return_value zval
  • For classes affected by this, we remove the class helpers and the struct

Not only does this remove duplicate data handling, but it greatly simplifies those value object classes by doing away with class handlers, allocations, etc.

@alcaeus

This comment was marked as resolved.

@alcaeus alcaeus force-pushed the phpc-2699-remove-extra-structs branch from d9948b0 to 3e2cfd8 Compare April 16, 2026 12:54
@alcaeus alcaeus marked this pull request as ready for review April 16, 2026 12:55
@alcaeus alcaeus requested a review from a team as a code owner April 16, 2026 12:55
@alcaeus alcaeus requested review from Copilot and paulinevos and removed request for a team April 16, 2026 12:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors several “value object” classes in the PHP extension to stop duplicating state in both custom C structs and PHP object properties, relying solely on properties for getters and dropping now-unnecessary structs/handlers.

Changes:

  • Introduces PHONGO_PROPERTY_GETTER (and related) macros to standardize boilerplate getters that return stored properties.
  • Removes a number of per-class internal structs and custom object handlers for objects that only expose static/stored information.
  • Updates WriteError/WriteConcernError and multiple APM Monitoring event classes to initialize readonly properties directly and have getters read from those properties.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/phongo_structs.h Removes internal C structs for several value-object style classes/events.
src/phongo_classes.h Adds property-getter/object-init macros; adjusts class declarations for removed structs.
src/MongoDB/WriteError.c Drops custom struct/handlers; stores values in properties and uses property-based getters.
src/MongoDB/WriteConcernError.c Drops custom struct/handlers; stores values in properties and uses property-based getters.
src/MongoDB/Monitoring/TopologyOpeningEvent.c Uses property-based getter and initializes properties directly.
src/MongoDB/Monitoring/TopologyClosedEvent.c Uses property-based getter and initializes properties directly.
src/MongoDB/Monitoring/ServerOpeningEvent.c Uses property-based getters and initializes properties directly.
src/MongoDB/Monitoring/ServerHeartbeatSucceededEvent.c Uses property-based getters and initializes properties directly (including reply conversion).
src/MongoDB/Monitoring/ServerHeartbeatStartedEvent.c Uses property-based getters and initializes properties directly.
src/MongoDB/Monitoring/ServerHeartbeatFailedEvent.c Uses property-based getters and initializes properties directly (including error object).
src/MongoDB/Monitoring/ServerClosedEvent.c Uses property-based getters and initializes properties directly.
src/MongoDB/Monitoring/CommandSucceededEvent.c Uses property-based getters and initializes properties directly.
src/MongoDB/Monitoring/CommandStartedEvent.c Uses property-based getters and initializes properties directly.
src/MongoDB/Monitoring/CommandFailedEvent.c Uses property-based getters and initializes properties directly.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 96 to 101
/* TODO: Use MONGOC_NO_SERVER_CONNECTION_ID once it is added to libmongoc's public API (CDRIVER-4176) */
if (intern->server_connection_id == -1) {
zend_update_property_null(phongo_commandfailedevent_ce, &intern->std, ZEND_STRL("serverConnectionId"));
if (mongoc_apm_command_failed_get_server_connection_id_int64(event) == -1) {
zend_update_property_null(phongo_commandfailedevent_ce, object, ZEND_STRL("serverConnectionId"));
} else {
zend_update_property_long(phongo_commandfailedevent_ce, &intern->std, ZEND_STRL("serverConnectionId"), intern->server_connection_id);
zend_update_property_long(phongo_commandfailedevent_ce, object, ZEND_STRL("serverConnectionId"), mongoc_apm_command_failed_get_server_connection_id_int64(event));
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On 32-bit builds, serverConnectionId is an int64 from libmongoc but is stored into a zend_long here without any range check. The previous getter warned when truncating a 64-bit value; after this change, large values can be silently truncated when assigning the "serverConnectionId" property. Consider restoring the SIZEOF_ZEND_LONG == 4 warning/handling before calling zend_update_property_long.

Copilot uses AI. Check for mistakes.
Comment on lines 80 to 85
/* TODO: Use MONGOC_NO_SERVER_CONNECTION_ID once it is added to libmongoc's public API (CDRIVER-4176) */
if (intern->server_connection_id == -1) {
zend_update_property_null(phongo_commandsucceededevent_ce, &intern->std, ZEND_STRL("serverConnectionId"));
if (mongoc_apm_command_succeeded_get_server_connection_id_int64(event) == -1) {
zend_update_property_null(phongo_commandsucceededevent_ce, object, ZEND_STRL("serverConnectionId"));
} else {
zend_update_property_long(phongo_commandsucceededevent_ce, &intern->std, ZEND_STRL("serverConnectionId"), intern->server_connection_id);
zend_update_property_long(phongo_commandsucceededevent_ce, object, ZEND_STRL("serverConnectionId"), mongoc_apm_command_succeeded_get_server_connection_id_int64(event));
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation warned on 32-bit builds when a 64-bit serverConnectionId would be truncated. This refactor stores the int64 directly into a zend_long without any SIZEOF_ZEND_LONG == 4 range check, which can silently truncate large values. Consider restoring the warning (and/or clamping/using string) before updating the "serverConnectionId" property when sizeof(zend_long) == 4.

Copilot uses AI. Check for mistakes.
Comment on lines 78 to 83
/* TODO: Use MONGOC_NO_SERVER_CONNECTION_ID once it is added to libmongoc's public API (CDRIVER-4176) */
if (intern->server_connection_id == -1) {
zend_update_property_null(phongo_commandstartedevent_ce, &intern->std, ZEND_STRL("serverConnectionId"));
if (mongoc_apm_command_started_get_server_connection_id_int64(event) == -1) {
zend_update_property_null(phongo_commandstartedevent_ce, object, ZEND_STRL("serverConnectionId"));
} else {
zend_update_property_long(phongo_commandstartedevent_ce, &intern->std, ZEND_STRL("serverConnectionId"), intern->server_connection_id);
zend_update_property_long(phongo_commandstartedevent_ce, object, ZEND_STRL("serverConnectionId"), mongoc_apm_command_started_get_server_connection_id_int64(event));
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old getServerConnectionId() implementation emitted a warning on 32-bit builds when a 64-bit serverConnectionId would be truncated. This code now writes the int64 directly into the "serverConnectionId" property via zend_update_property_long without a SIZEOF_ZEND_LONG == 4 bounds check, which can silently truncate. Suggest reinstating the warning (or another non-truncating representation) before storing the value.

Copilot uses AI. Check for mistakes.

PHONGO_RETURN_PROPERTY(commandfailedevent, "serverConnectionId");
}
PHONGO_PROPERTY_GETTER(MongoDB_Driver_Monitoring_CommandFailedEvent, getCommandName, commandfailedevent, "commandName")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very satisfying

Copy link
Copy Markdown
Contributor

@paulinevos paulinevos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but is the thing Copilot mentioned worth looking into, also in terms of test coverage?

@alcaeus
Copy link
Copy Markdown
Member Author

alcaeus commented Apr 16, 2026

LGTM, but is the thing Copilot mentioned worth looking into, also in terms of test coverage?

I didn't want to include it, but common sense prevailed and I added the warnings back in for 32-bit platforms. We should really get rid of that at some point in time (or lobby for PHP's zend_long becoming an int64_t regardless of platform int size)

@alcaeus alcaeus merged commit 770c1b9 into mongodb:v2.x Apr 16, 2026
43 checks passed
@alcaeus alcaeus deleted the phpc-2699-remove-extra-structs branch April 16, 2026 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants