0

I have a base entity "Organization" that represents an organization (be it a business entity, a baseball team, or a podcast). It is quite generic.

Each of these organizations can have multiple staff, and each staff can be of a different type. We want this to be generic and variable, so that we can have one or many of differnt types of staff (CEO, Waitress, Coach, Personal Trainer, Manager, Board Member). Is there an established way to handle this?

IF not, any feedback on my solution woud be greatly appreciated:

So, I want to represent this by having a "staff" member on the organization. Staff will be a collection of "StaffMember" objects, which in turn are:

StaffMember:
    person(a Person object)
    organization(an Organization object)(this may not be necessary if StaffMember is only used on an org)
    staffType

StaffType:
    title(string)
    significance(int)

Does this seem okay? The staff type are objects we can create as needed that represent a staff type (Host, CEO, CFO, Board Member, Coach, etc). So a Staff Member knows the person and the type. We are using MongoDB so the "staff" property would likely be an embedded collection of StaffMembers.

I just want to make sure I am not overlooking anything, so any feedback would be greatly appreciated!

Chris Tickner
  • 2,008
  • 2
  • 20
  • 24

2 Answers2

1

One thing you should consider is the expected number of staff members in an organization. If this number is very large, or larger than what you'd like to have in memory at any given moment, then you may consider implementing this association with a repository instead of a direct reference. This means that the Organization class would not reference the staff collection directly, instead the staff collection would have to be retrieved with a repository. Take a look here for more details on this.

Also, take care with bi-directional associations such as the one between StaffMember and Organization. They are cheap to model but more expensive to implement. Basically, try to design the system in such a way that the reverse relationship isn't needed.

eulerfx
  • 36,769
  • 7
  • 61
  • 83
1

We have a similar structure in our product. This is how we have accomplished it.

/** @MongoDB\Document(collection="companies") */
class Company
{
    // Properties

    /** @MongoDB\Id */
    protected $id;

    /** @MongoDB\String */
    protected $name;

    /** @MongoDB\ReferenceMany(targetDocument="Employee", mappedBy="company", cascade={"remove"}) */
    protected $employees;

    /** @MongoDB\ReferenceMany(targetDocument="Role", mappedBy="company", cascade={"remove"}) */
    protected $roles;
}

/**
 * @MongoDB\Document(collection="roles")
 * @MongoDB\UniqueIndex(keys={"title"="asc", "company"="asc"})
 */
class Role
{

    /** @MongoDB\Id */
    protected $id;

    /** @MongoDB\String */
    protected $title;

    /** @MongoDB\String */
    protected $description;

    /** @MongoDB\ReferenceMany(targetDocument="Employee", mappedBy="role") */
    protected $employees;

    /** @MongoDB\ReferenceOne(targetDocument="Company", inversedBy="roles") */
    protected $company;
}

/**
 * @MongoDB\Document
 * @MongoDB\DiscriminatorField(fieldName="type")
 * @MongoDB\DiscriminatorMap({"person"="Person", "employee"="Employee"})
 */
class Employee extends Person
{
    // Properties

    /** @MongoDB\String */
    protected $employeeId;

    /** @MongoDB\ReferenceOne(targetDocument="Role", inversedBy="employees") */
    protected $role;

    /** @MongoDB\ReferenceOne(targetDocument="Company", inversedBy="roles") */
    protected $company;
}

This allows a large volume of employees within a company with a large volume of roles. It's handy because you can easily get the list of roles/employees via the company references and you don't need to store the details inside the company document.

Jamie Sutherland
  • 2,760
  • 18
  • 19