This is how I finally decided to solve this in the PHP client.
I decided to just keep the membership in the category_items table and use dynamic queries at the time of submission to update this table.
This is a function in my script that is called to update the categories of items during submit or update. It accepts a list of categories selected by the user (which can be selected only from categories that do not have dynamic queries), and using this and dynamic queries, he determines the difference between the categories in which the element is located and those it should be included and insert / delete if necessary to synchronize them. (Please note that the actual table names in my database do not match, as in my question, I used several common terms.)
function update_item_categories($dbh, $id, $requested_cats) { $data = mysql_check($dbh, mysqli_query($dbh, "select id, query from t_ld_categories where query is not null"), 'getting dynamic categories'); $clauses = array(); while ($row = mysqli_fetch_object($data)) $clauses[] = sprintf('select %d cat_id, (%d in (%s)) should_be_in', $row->id, $id, $row->query); if (!$requested_cats) $requested_cats[] = -1; // Dummy entry that never matches cat_id $requested_cat_string = implode(', ', $requested_cats); $clauses[] = "select c.id cat_id, (c.id in ($requested_cat_string)) should_be_in from t_ld_categories c where member_type = 'lessons' and query is null"; $subquery = implode("\nunion all\n", $clauses); $query = "select c.cat_id cat_id, should_be_in, (member_id is not null) is_in from ($subquery) c left outer join t_ld_cat_members m on c.cat_id = m.cat_id and m.member_id = $id"; // printf("<pre>$query</pre>"); $data = mysql_check($dbh, mysqli_query($dbh, $query), 'getting current category membership'); $adds = array(); $deletes = array(); while ($row = mysqli_fetch_object($data)) { if ($row->should_be_in && !$row->is_in) $adds[] = "({$row->cat_id}, $id)"; elseif (!$row->should_be_in && $row->is_in) $deletes[] = "(cat_id = {$row->cat_id} and member_id = $id)"; } if ($deletes) { $delete_string = implode(' or ', $deletes); mysql_check($dbh, mysqli_query($dbh, "delete from t_ld_cat_members where $delete_string"), 'deleting old categories'); } if ($adds) { $add_string = implode(', ', $adds); mysql_check($dbh, mysqli_query($dbh, "insert into t_ld_cat_members (cat_id, member_id) values $add_string"), "adding new categories"); } }
Barmar
source share