cakePHP HABTM, am I getting it all wrong? - cakephp

I understood that every new row, causes the deletion of the rows that were there before?
What is the idea behind it? I don't believe that it is ..
So, what am i getting wrong?
Edit A
I have a form that adds a store to the Stores table. the store have a column named owner_id which is associated to the Users table through a belongsTo relationship.
There is also a table named stores_users that supposed to store the mangers for each store, using the HABTM relationship.
For this table there is a form with an email field, that connects the user to the store by saving the record directly to the stores_users table.
So, there is no full HABTM save anywhere, if I understand the term correctly.
So, my questions are:
Should I expect problems using it this way?
Can you advice me about how to it, if my method is not the proper way?
How can I use the stored data, using $this->User->find(...) to get all the stores that the user can manage?

yes, thats the default behavior of HABTM in cakephp
although this is not on "every row", but "every HABTM save".
this is working IF you always provide all HABTM values.
and with baked views according to the specifications for such HABTM this is all working out of the box.
if you change the default behavior (old ones get not deleted) you will need to make sure that there are no duplicates. there are behaviors out there, I think, which try to accomplish that.
but I would recommend for you to build your forms the way that the default behavior of cake can do its job.
Example:
IS: 1,3,6 (in DB for this key)
NEW: 2,3,6 (coming from form)
(cake deletes 1,3,6 and adds 2,3,6)
=> overall result (forgetting about different primary keys): "1" deleted, "2" added
so it might not be the most resource sparing way but its sure the easiest and fastest.

Related

There cannot be more than one relational path between any two tables in the graph

I'm building a database in Filemaker and I have a problem linking tables. Basically, I have a table "capture" showing an event where a photo will be taken. Someone will be dealing with "capture" meaning that there will be a responsible for "capture" to be recorded properly. The photo taken in "capture" will be recorded in a second table "photos". Another person could be responsible for the photo management. So I have a "Observers" table which will be my contact table. I want to be able to link the "Observers" table with the "capture" AND the "Photos" table so that the names in "Observers" populates both tables.
But if I do the link like in the image below:
I get this error:
"There cannot be more than one relational path between any two tables in the graph."
How can I like the 2 tables, if possible? I know it makes an "ambiguous" path, but there might be a way to reutilize the information in "Observers" to inform 2 different tables that are linked together.
I want to do something like this:
EDIT:
Use another occurrence of the Observers table.
See: https://fmhelp.filemaker.com/help/18/fmp/en/index.html#page/FMP_Help/adding-tables.html
Recommended reading:
http://www.nightwingenterprises.com/Resources/approaches_to_graph_modeling_en.pdf
-- Edit
Let's bring back to basics because when trying to define a model, the concept must have been well defined before.
Am i understand it well :
One or more observer are being assigned to work on a capture (evenement, place...).
The observer(s) take one or more Photo about the capture place.
And so one or more photo of a place can have been taken.
If that's true, we have the following relation
Here we are !
So what about the Logic Model of the database.
We can say that we have the following table :
CAPTURE(id_capture)
--> With id_capture being Primary Key of CAPTURE
OBSERVER(id_observer)
--> With id_observer being PK of OBSERVER
CAPTURE_OBSERVER(id_capture, id_observer)
--> With id_capture being FK of CAPTURE, and id_observer being FK of OBSERVER
PHOTO(id_photo, id_capture, id_observer)
--> With id_photo being PK of PHOTO, id_capture foreign key of CAPTURE, id_observer foreign key of OBSERVER
I hope i'm right, if not please correct me about the purpose of every entity in this model.
I think by adding this new table that i found (CAPTURE_OBSERVER) you'll be able to solve your problem AND to improve your model conception.

CakePHP model association based on field values?

I've got three tables (there's actually several more, but I only need the three for this problem). Applications, Appattrs and Appcats. In CakePHP parlance (as best as I can since I'm still learning the framenwork) Applications hasMany Appattrs and Appattrs belongsTo Applications. Easy.
The problem comes when I want to associate Appattrs and Appcat - the association is predicated on a field value and a corresponding foreign key in Appattrs. For instance:
If appattrs.type = 'appcatid' then appattrs.value would point to a record in the Appcat table.
The appattrs table holds static data appattrs.type='dateadded' and value='201201011300' as well as foreign key references. I'd rather not get into a discussion as to why data is stored this way, I just want to figure out how to create associations that will let me pull an application record, the associated attr records and then an attr record with its associated row from the appropriate table. Dynamically.
It seems to me that I should be able to create a model based on a query and then associate that model - I just can't seem to figure out how to do that.
--
If I need to post schema for the three tables, I can. I can also post my current model code, but honestly, right now it's just association variables so I don't think it'll get anyone anywhere.
Thow I do not understand the logic behind this design, I thing what you are looking for
is Creating and Destroying associations on the fly.
On this section of CakePHP Docs, it describes how you can associate models from within the corresponding controller.
So, for example, when you want to save specific data to Appattr model you can do some data checking and create your association using bind() method.
A very abstract approach to the above would be something like this
public function yourmethod() {
...
if ($this->request->data['Appattr']['type'] == 'sometype') {
$this->Appattr->bindModel(
array(/*Your association*/ => array(/* Your attributes...*/)
);
/* Rest of the logic follows */
}
}
This way you get your job done, but it's very possible to end up having very complicated
data in your database and thus having very complicated code.
I hope this helps

How would you model a table to record changes in other tables' records' values?

I am writing a model to record the changes that are made to other models so that there is a record of every attribute change. I'm looking for input on how best to structure the change record table.
For instance, I have a User model with a name attribute. I want to save a Change record to the database when that user has its name changed from Bob to Ted.
Furthermore, if a user updates multiple attributes on the User at the same time I would like to record these as being a single Change. For instance, a User changes both the name and email attributes from Bob and bob#bobsdomain.com to Ted and ted#teddy.com, respectively.
The set of attributes on a given object that are being changed are arbitrary. How would you structure the table?
Currently, I am doing something like the following (simplified):
Changes:
user_id:integer
changed_fields:string
old_values:text
new_values:text
In the above examples these records would look like the following:
:changed_fields => "name",
:old_values => "Bob",
:new_values => "Ted"
and
:changed_fields => "name,email",
:old_values => "Bob,bob#bobsdomain.com",
:new_values => "Ted,ted#teddy.com"
On the Change model I have special getter/setter methods that parse the input/output to map to specific formatting.
Is there a better way to model this kind of thing?
If not, what is the best way to format the values for the database to make parsing the input/output work best, given that the values can be arbitrary.
I am using Postgres as my DB and ActiveRecord as the ORM.
Storing both the old and new value is redundant. You could instead store just the new value at the time of the change, and make sure you also add a change record when a new row is created. If a row has been changed N times, it will have N+1 records in the change table, and you can find the differences between them retrospectively if you need to.
In fact, one approach is to have only one table containing all versions of the data. Instead of updating any rows in-place, make edits by inserting new rows. I've taken this approach while either using a boolean "latest" field, or using a foreign key from another table, to refer to the current version of each row.
These days though I'm using the django-reversion package to implement revision tracking for me. It uses a single table to record all versions of all tracked tables, storing a JSON representation of the state of each object at each version. It uses an additional table to track whole change-sets, so it can version changes that span multiple objects.
The solution that's best for you will depend on which operations you need to be able to do efficiently on your tables, and on what your ORM makes easy for you to work with. I hope this answer has been helpful at pointing out some approaches that have worked in other settings.

Saving corresponding data in a hasOne relation

As I read in other postings, the id of the table, which has a relation to the frist model has to be set by an hidden field in the form.
echo $form->input('Gallery.id', array('type'=>'hidden', 'value'=>$showcase['Gallery']['id']));
(see question at Update hasone relation behaves strangely (cakephp))
But isn't that risky, because anyone could edit this hidden field value and another dataset would be updated.
What is the best option to avoid such security issues when trying to update a whole dataset with 2 models associated together with a hasOne / belongsTo relation?
Thx
Best
Stefan
1st option is to have multiple queries and checks on save
2nd option is http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#form-tampering-prevention
So whatever method works best in your particular case...
You can switch to using UUIDs. Just need to change your primary key and foreign key to char(36) and cake will do the rest.

Deleting association from HABTM table

I have a Users and a Reports table, connected with HABTM relationship.
I can save a report that creates a correct record in reports_users table, I can view the relationship table by using $this->User->ReportsUser->.., and so on.
Now I want to delete a specific row in reports_users table, but I can't seem to do it.
I have tried the following:
$this->User->ReportsUser->deleteAll(array(
'ReportsUser.report_id' => $this->data['Report']['report_id'],
'ReportsUser.user_id' => $this->data['Report']['user_id']
));
..but it deletes all the rows with the given user_id, with this query:
What am I doing wrong here. Is it a bad data in the deleteAll call?
I don't want to delete any users or reports, only the relationship between them.
I can confirm that the table names are correct, and that the variables exist and are set.
It seems no error with your code. Either your $this->data['ReportUser']['report_id'] is having some problem. The best way is to first try to print your $this->data. And check whether it exists?
For the safety reasons, use the second argument $cascade = false and also unbind all the ReportUser model Associationship using $this->ReportUser->unbindModel() method.
The other reason seems to be deleting data through
$this->User->ReportUser. Try to use $this->ReportUser->deleteAll('your conditions', false); directly.
Please ask if it not worked for you.

Resources