View Full Version : problem with Category_FindNext_Parent() M4
This is in Miva 4.
I have a script that is supposed to pick up a category id and then retrieve all the child categories of that category. I'm using Category_FindFirst_Parent() and Category_FindNext_Parent() to retrieve the child categories. This works fine as long as the child categories are stored next to each other in the database (actual database not the list in Miva). If there are other records separating some of the child categories, all the child categories that are not next to the others are not returned. Anybody know if this is a bug in Miva or am i the one screwing up somehow. If possible, i'd like to salvage this code instead of re-writing it and manually retrieving the records.
Kent Multer
04-19-06, 07:59 PM
Most likely there is a bug in your code. The Miva DB functions are quite reliable, although just to cover all the bases, I should ask: 4.what? If it's an early version, you might conceivably have encountered a Merchant bug.
If you post some of your code, I'll take a look at it.
MM: v4.24 / MVM: v4.1400
I have to mention that this function is recursive, as you can probably tell, if that makes a difference.
<MvFUNCTION NAME="show_cat" PARAMETERS="" STANDARDOUTPUTLEVEL="text,html,compresswhitespace">
<MvCOMMENT> *** only list the active categories *** </MvCOMMENT>
<MvIF EXPR="{Categories.d.Active}">
<MvEVAL EXPR="{Categories.d.name}">
</MvIF>
<MvASSIGN NAME="l.theid" VALUE="{Categories.d.ID}">
<MvDO FILE="{g.Module_Library_DB}" NAME="l.done" VALUE="{Category_FindFirst_Parent(l.theid)}">
<MvASSIGN NAME="l.childid" VALUE="{Categories.d.Id}">
<MvIF EXPR="{l.done}">
<MvWHILE EXPR="{l.done}">
<MvASSIGN NAME="l.add_it" VALUE="{show_cat()}">
<MvDO FILE="{g.Module_Library_DB}" NAME="l.done" VALUE="{Category_Find_Id(l.childid)}">
<MvDO FILE="{g.Module_Library_DB}" NAME="l.done" VALUE="{Category_FindNext_Parent(l.theid)}">
<MvASSIGN NAME="l.childid" VALUE="{Categories.d.ID}">
</MvWHILE>
</MvIF>
</MvFUNCTION>
obviously some unrelated code is taken out. The function is first called with the Categories db pointing to a main category and it is supposed to list all the subs and their subs. This works as long as the subs a sequentially listed in the database but as soon as you encounter a situation where the next sub is not directly next to the current sub, it terminates as if it did not find it.
Thanks for the help
Kent Multer
04-19-06, 09:04 PM
You seem to have misunderstood how the DB functions work -- not your fault, the documentation sucks, and Miva stopped publishing the source code several years ago. Basically, Category_FindFirst_Parent() and Category_FindNext_Parent() have to be used in a closely-matched way. If you put other Category_Find-something functions inside the loop, you'll have trouble.
Here's a function I wrote for a custom project. It doesn't display anything, just collects the data into an array.
<MvFUNCTION NAME="CatList" PARAMETERS="parent, level" STANDARDOUTPUTLEVEL="">
<MvDO FILE="{ g.Module_Library_DB }" NAME="l.fc"
VALUE="{ Customer_Category_FindFirst_Parent(BasketList.d.cu st_id, l.parent) }">
<MvWHILE EXPR="{ l.fc }">
<MvASSIGN NAME="l.n" VALUE="{ l.n + 1 }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="id" VALUE="{ Categories.d.id }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="code" VALUE="{ Categories.d.code }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="name" VALUE="{ Categories.d.name }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="active" VALUE="{ Categories.d.active }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="level" VALUE="{ l.level }">
<MvDO FILE="{ g.Module_Library_DB }" NAME="l.fp"
VALUE="{ Customer_Product_FindFirst_Category(BasketList.d.c ust_id, l.cat[l.n]:id) }">
<MvASSIGN NAME="l.cat" INDEX="{ l.n }" MEMBER="prod" VALUE="{ l.fp }">
<MvDO FILE="{ g.Module_Library_DB }" NAME="l.fc"
VALUE="{ Customer_Category_FindNext_Parent(BasketList.d.cus t_id, l.parent) }">
</MvWHILE>
<MvFUNCRETURN VALUE="{ l.cat }">
</MvFUNCTION>
The "level" parameter is included for display purposes; it can be used to select indentation, fonts, etc. The recursive part is handled by a separate function that calls this one. I found this to be the best approach: collect one set of subcats at a time, and store them in arrays, rather than try to jump around the database.
Kent Multer
04-19-06, 09:06 PM
Oops, a couple of extra bits of explanation about that last code sample:
1. It uses Customer_Category_Find instead of Category_Find. But the logic is the same.
2. The loop also checks to see whether each category has any products. That may not be relevant to your project.
Oops, a couple of extra bits of explanation about that last code sample:
1. It uses Customer_Category_Find instead of Category_Find. But the logic is the same.
2. The loop also checks to see whether each category has any products. That may not be relevant to your project.
Thanks Kent. I put in the Category_Find_Id() to sort-of reset the pointer to the current category so that when you run Category_FindNext_Parent() you don't risk having the pointer at .d.eof.(found out the hard way). i thought that would give the _FindNext_ function the right position to start from when looking for the next sub-category.
I'll re-do it the way you suggested and go with the arrays for storage.
And thanks for the products part, that part was working fine for me.
Bruce - PhosphorMedia
04-22-06, 07:22 AM
most of the time i add NOT(database.d.eof) to the while loop to stop at the end of the record.
Kent Multer
04-22-06, 09:45 AM
Thanks Kent. I put in the Category_Find_Id() to sort-of reset the pointer to the current category so that when you run Category_FindNext_Parent() you don't risk having the pointer at .d.eof.(found out the hard way). i thought that would give the _FindNext_ function the right position to start from when looking for the next sub-category.
This kind of manual resetting will work in some cases. But sometimes there's more than one database involved in the Find_ function; and if any of the databases have more than one index, you have to figure out which ones were used, and use MvPRIMARY to adjust them if necessary. Again, all this wasn't too hard to do, back when we had the source code. Nowadays, all you have is guesswork and trial-and-error. Even at their best, the Miva docs never had this level of detail.
vBulletin® v3.7.4, Copyright ©2000-2008, Jelsoft Enterprises Ltd.