Resource defaults are dynamically scoped (they one of the few remaining things that are). That means your example will work, in that the defaults declared in class
profiles::phpwebserver will apply in class
::apache.
In general, dynamic scoping is a tricky beast, and I would warn that the defaults applicable when the first declaration of class
::apache is processed are the (only) ones that apply. In this case, however, because you use a resource-like class declaration for class
::apache, if it ever is not the first processed then catalog building will fail. I ordinarily cast that as a serious problem with the resource-like class declaration style, and recommend not using that style. Inasmuch as you might actually
want your catalog compilations to fail if the desired package installation options are not set, though, it might work for you.
Putting resource defaults at top scope or node scope instead of some class scope would work around the issue of ensuring the defaults are in scope for all declarations of a given class, but that cannot work for you (or at least, it does not afford a complete solution) because you want *different* defaults to apply to different classes.
Also, resource defaults are only
defaults. If alternative values are expressed for the parameters involved then the assigned defaults are completely ignored. That could render your resource defaults moot in unfavorable circumstances.
I suggest an alternative approach: resource overrides. You can perform overrides via collectors and tags to set an appropriate scope for the defaults, and to combine your installation options with any others that might be set on the packages. For example,
class profiles::phpwebserver {
# ... no package defaults here ...