#[AllowDynamicProperties], and when it is honest

The attribute opts a class out of the deprecation, which is occasionally correct and is usually a way of deferring a rename.

#[AllowDynamicProperties]
class LegacyBag
{
    // a class whose whole purpose is arbitrary attributes,
    // written before stdClass was idiomatic
}

// it is inherited by subclasses, which is convenient and
// makes the exemption wider than the annotation suggests.

// the honest alternatives:
//   declare the properties
//   extend stdClass
//   hold an array and expose it through __get

Inheritance of the attribute is the part that makes it dangerous as a quick fix: applying it to a base model exempts every model in the application, which is exactly what somebody under deadline pressure will do. Where it is legitimate — a genuine property bag from before stdClass was conventional — it deserves a comment explaining why, because the next reader will assume it was applied to make a build pass.