1
votes

I have a database that uses the Party analysis pattern to simplify associations (as it has to store info on both people and organisations, both of which have common attributes). Therefore my associated models can get quite deep. My question is what is the best way to save my data? Take for example saving an employee, the Employee table is not directly connected to Party table, however if I nest my models in an array like so:

array(
    'Party' => array(
        'Email' => array(...),
        'Address' => array(
            'Country' => array(...),
            'Location' => array(
                'State' => array(...)
            )
        ),
        'PhoneNumber' => array(...),
        'Person' => array(
            'Language' => array(...),
            'Skill' => array(...),
            'Employee' => array(
                'WorkHistory' => array(...),
                'Qualification' => array(...)
            )
        )
    )
)

I can use saveAll, and it will save everything. That means on my forms I have field names such as Party.Person.Employee.start_time for example. However I was told that doing it this way is not really following CakePHP conventions. The other alternative is to have my array like this:

array(
    'Party' => array(...)
    'Email' => array(...),
    'Address' => array(...),
    'Country' => array(...),
    'Location' => array(...),
    'PhoneNumber' => array(...),
    'Person' => array(...),
    'Language' => array(...),
    'Skill' => array(...),
    'Employee' => array(...),
    'WorkHistory' => array(...),
    'Qualification' => array(...)
)

However if I call saveAll on this, then not everything will be saved as some of the tables/models are not directly connected to Party. The only way to save such a structure, that I know of is, to use Transactions.

So I was wondering what the CakePHP experts think is the best way to approach a situation where you need to save very deep associated models?

Edit:

From what I can gather based on the responses I have had, for the model you are calling saveAll on, those other models that are directly associated to it do not need to be nested in that models array. However if you also want to save models that are not directly associated to it then you need to nest those inside a model that is directly associated to the model you are calling saveAll on. Sorry I know that's confusing so here is my revised array structure in light of this information:

array(
    'Party' => array(...),
    'Email' => array(...),
    'Address' => array(
        'Country' => 'attribute',
        'Location' => 'attribute',
        'State' => 'attribute'
    ),
    'PhoneNumber' => array(...),
    'Person' => array(
        'Language' => array(...),
        'Skill' => array(...),
        'Employee' => array(
            'WorkHistory' => array(...),
            'Qualification' => array(...)
        )
    )
)

Person is directly associated to Party and so does not need to be nested within Party. However Employee (a type of Person) is not directly associated to Party, and so for it to save the Employee data when calling saveAll on Party, it needs to be nested within Person because the Person model is directly associated to Party. (FYI: Party hasOne Person and Person hasOne Employee. This is the best way I could figure out to structure the inheritance in my database). By structuring it this way, the application is both conforming to CakePHP standards and saving the data with minimal effort.

1
Did the person(s) give you reasoning on why not to use the first way? If it works, I'd use it. - Dave
Here's the link to the question I asked about 'Containable' where I was trying to get an array formatted the way the form on my view likes: stackoverflow.com/questions/24604104/… The comment that was made was "why do you want to work against the CakePHP conventions in the first place, it will only cause trouble...". But no explanation. However the responder didn't really have the full story on why I was structuring my arrays like that. So thought I should check if it is ok, or if there is a reason why I should not do this. - nuutrino

1 Answers

0
votes

Well, the explanation kinda was there, it's simply the CakePHP conventions, and we all know what can happen when not following conventions, right?

As I said, following the conventions helps CakePHP to glue everything together automatically, and using the format shown in your question would require to manually restructure the data received by your Model::find() calls.

So while the structure shown in your question may work for saving (at least for now), it will at least cause you some extra work that isn't actually necessary.

I admit that I could have been a little more clear as you seem to have misunderstood me. I didn't wanted to say that the array should be flat altogether, it was just the Person entry that was wrongly placed, and so I only mentioned that one.

Of course in the end it all depends on the type of association, and there are examples for all that in the linked docs: Cookbook > Models > Saving Your Data

Generally you should be able to save as deep as you want using saveMany() or saveAssociated() as long as there aren't any HABTM associations where you create new records instead of assigning existing ones.

You can get started by referring to the structure returned by Model::find(), make sure you are saving on the main model (in this case Party), and depending on the associations/number of records use

  • save() (single record, no associations (except for HABTM))

  • saveAll() (wrapper for saveMany and saveAssociated)

  • saveMany() (multiple main model records, possible associations (require using the deep options))

  • or saveAssociated() (single main model record, including associations (may require using the deep option)

However this may not apply to all situations, as mentioned you may for example run into problems with HABTM associations, depending on whether you wan to create new records you may need to save them separately, but this isn't really the place to explain every possible situation, especially because the basics are already covered in the Cookbook.

I'd suggest that you study the docs, stick to the conventions, learn by trying, and check out the core source and tests, that's how everyone of us learned it. And when you have a problem with a specific situation that hasn't already been covered, just create a new question