Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
11 posts Page 1 of 2
Hi,

I have a product/catalog pages and a user page. We like the ability for a user to edit the relation between the product/catalog and the user page. In the user page we have the relation set like:

<cms:editable type='relation' label='Products' name='user_products' masterpage='catalog.php' />

This gives us on the admin page a way to turn the relation on and of, but I can't find a way to let the user at the front-end do the same thing except if I load the whole list from the relation on the catalog page :

<cms:form masterpage='users.php' mode='edit' page_id=my_user_id method='post'>
<cms:if k_success >
<cms:db_persist_form />
</cms:if>

<cms:input id="user_products" name="user_products" type="bound"/>
<cms:input name="submit" type="submit" value="Send" />

</cms:form>

But I need only the current catalog page as an option in the form, is there a way to filter this ?

Thanks
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
Hi Tom,

While I can see what you are trying to do, I don't think there is an easy way of setting a many-to-many relation's value without using its GUI (setting a single value e.g. the current catalog will remove all other related items).

I haven't tried this but I think one workaround could be to use CSS to hide all items from the relation's list except the current catalog (we can use the 'value' selector holding the catalog ids e.g. input[value="234"] { display: block; }​ ).

Please try and see if this works.

Thanks.
Hi KK,

Thanks you pointed me to a solution ... I wasn't able to use the value selector this only applied to the check-box the regenerated label was still displayed. I had to edit the couch/addons relation.php to provide a css selector (added on line 136 at the label tag rel='.$key.') then used the following code:

<style>
#hide label { display: none; }
#hide label[rel="<cms:show k_page_id/>"] { display: inline; }
</style>


<div id="hide">
<cms:form masterpage='users.php' mode='edit' page_id=my_user_id method='post'>
<cms:if k_success >
<cms:db_persist_form />
</cms:if>


<cms:input id="user_products" name="user_products" type="bound"/>
<cms:input name="submit" type="submit" class="button small" value="Send" />

</cms:form>

</div>

This is giving me the desired result but... I suppose it's not the correct solution by editing the relation.php and I'm a little worried about the loading speed of the page since i have ± 10.000 catalog pages to handle. (this way the not needed hidden ones are still loading to the page)

If someone has a better idea to solve this I really like to know.

Thanks
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
± 10.000 catalog pages to handle.
Whew!

Anyways, can you please explain to us the use case a bit?
I mean, What are the catalog items?
How (and why) do the users have to choose the catalog items? etc.
If you could post a few screenshots that'd be great.

As I said before, there is no easy way of setting M:M relations sans its GUI but, I am sure, there would be a way, nevertheless, once the problem domain is understood.

Thanks.
Hi KK,

Yes, I know the amount of catalog items is the problem throughout the whole project.
Catalog items are products we sell.

We have a site running on magento (http://www.e-tukku.fi) although magento can handle the large amount, it's slow and way to much time consuming to maintain, upgrade and update products. So the idea was to leave large scaled cart systems and to use a fast easy to use simple cms to present our products (we are a B2B supplier so we don't need a full blown shopping cart).

We tested many,many cms products and came to the conclusion CouchCms is the best option for us. So we decided to go for a minimalistic approach in design and site structure but still offer the visitors a easy to navigate presentation (due to the amount and diversity this is quite something) . The structure we have until now is:

- index page (home)
- catalog.php (products)
- products.php (landing pages for categories of the catalog)
- about-us.php (company info)
- news.php (news items)
- wishlist.php (cookie based wishlist)
- users.php (cheesypoof user login + those files)

Cheesypoof user login project gave us the idea to give clients(users), that order every time the same products a list on there user page of those products, this to spare them the process of going trough all the lists of the catalog items to find those.

We did use the <cms:editable type='relation' label='Products' name='user_products' masterpage='catalog.php' /> for this as stated above. Now we can edit the users page and link the items for them. Next we created a Quick order form for them so they can choose these catalog items with a small text area for extra info and on submit we receive a mail from that form with the selected item and the info text.

As you can understand maintaining users is not really an option for us (we have to manage a large amount of product pages) the solution should be that the user would maintain his own list. We where thinking that we could do this with a button or check-box on the catalog page so when a user is logged in he/she can ad or remove the corresponding item by using the relation and the data bound form.

I hope this is a better explanation of what I try to do. Catalog page of the development site is here.http://www.e-products.eu.com/fin/catalog/tyovaatteet/t-paidat-tyokayttoon/russell-010m-heavy-duty-t-paita.html
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
Thanks for the detailed description.
I think I get it now (hopefully :) ).

So the use-case goes like this -
a. A registered user visits a product page.
b. If the product is not in the list of products related to her, she sees a button saying 'Add this product'. Clicking the button adds the product to her list.
c. If the product is already in the list of products related to her, she sees a button saying 'Remove this product'. Clicking the button removes the product from her list.

Is that fine?
If so, I'll detail one possible solution below.

The solution revolves around the fact that we can set related-pages by specifying a comma-separated list of page ids. For example -
Code: Select all
<cms:if k_success > 
    <cms:db_persist_form
        user_products='324, 456, 709'
    />   
</cms:if>
notice how in the code above we are providing a list of ids as values of the 'relation' field named 'user_products'.

Now, when a user is visiting a product page, the id of the product is well known (k_page_id).
If we were to set this id as follows
Code: Select all
<cms:db_persist_form 
      user_products=k_page_id
/>
..it would work but it would remove *all other* previously related pages while making the current page the only related page.

That was the problem I had alluded to.

So, for our solution,
a. we need to first get a list of all pages (products) related to the user.
b. if the current page is already in the list, remove it from the list
c. if it is not in the list, add it to list
d. Now we can safely supply this list to cms:db_persist_form.

Following is a complete working code that does just this.
IMP:
1. You need to place this code in the page_view of products.php
2. the code assumes that 'my_user_id' contains the id of the logged-in user.


Code: Select all
<cms:if k_is_page>
   
    <!-- save the id of the current product in a variable -->
    <cms:set my_current_product=k_page_id 'global' />

    <!-- get the list of ids of products related to this user -->
    <cms:pages masterpage='users.php' id=my_user_id limit='1'>
        <cms:set my_related_products="<cms:related_pages 'user_products' ids_only='1' />" 'global' />
    </cms:pages>

    <!-- use PHP to manipulate the list got above to include/exclude current page (i.e. product) -->
    <cms:php>
        global $CTX;
       
        $my_current_product = $CTX->get( 'my_current_product' );
        $my_related_products = $CTX->get( 'my_related_products' );
       
        // is the current product (the page we are on) in the list of related products?
        $arr_products = explode( ',', $my_related_products );
        $key = array_search( $my_current_product, $arr_products );
        if( $key !== false ){
            // product already related.. remove it from list
            unset( $arr_products[$key] );
            $CTX->set( 'is_already_related', '1', 'global' );
        }
        else{
            // not yet related.. add product to list
            $arr_products[] = $my_current_product;
            $CTX->set( 'is_already_related', '0', 'global' );
        }
       
        // set the revised list of ids in context
        $my_related_products = trim( implode(',', $arr_products) );
        $CTX->set( 'my_related_products', $my_related_products, 'global' );

    </cms:php>

    <!-- use databound form to persist the new list of related pages -->
    <cms:form masterpage='users.php' mode='edit' page_id=my_user_id method='post' anchor='0'>
        <cms:if k_success >
            <cms:db_persist_form
                user_products=my_related_products
            />
            <cms:redirect k_page_link />
        </cms:if>

        <cms:if is_already_related >
            <cms:input name="submit" type="submit" value="Remove product from my list" />
        <cms:else />
            <cms:input name="submit" type="submit" value="Add product to my list" />
        </cms:if>   
    </cms:form>
   
</cms:if>

Please test out the code first as it is - modify it once you're sure everything is working fine.

Hope this helps.
Do let us know.

Thanks.
Yes....!!! This works super ! exactly what I needed !

I was almost a the point of leaving this feature out. I'm to limited in my PHP knowledge I suppose.

Don't know how to thank you. I owe you one.

Thanks again...
I load frameworks and write bugs on top of them, after that I rearrange the code so that it looks like a cool product.
You are welcome :)
How about this one?
I have relation in the same template, but i dont know how to put the relation in db_persist_form.
Here's the relation code:
Code: Select all
<cms:editable 
label = "Followers'"         
name="rev_relation_<cms:show k_template_id />"
desc = "Followers"
type = 'reverse_relation'
masterpage = 'users/index.php'
anchor_text = 'View'
field = "relation_<cms:show k_template_id />"
order='12'
/>

<!--establish relations within template-->
<cms:editable label = "Relation with '<cms:show k_template_title />'"   
name = "relation_<cms:show k_template_id />"
desc = "FOLLOWING"
type = 'relation'
masterpage = "<cms:show k_template_name />"
has='many'
no_gui = '0'
order='13'
/>

The form code in frontend:
Code: Select all
<!-- save the id of the current product in a variable -->
    <cms:set my_current_product=k_page_id 'global' />
    <cms:set my_user_id=k_user_id 'global' />

    <!-- get the list of ids of products related to this user -->
    <cms:pages masterpage='users/index.php' id=my_user_id limit='1'>
        <cms:set my_related_products="<cms:related_pages 'rev_relation_<cms:show k_template_id />' field="relation_<cms:show k_template_id />" ids_only='1'/>" 'global' />
    </cms:pages>

    <!-- use PHP to manipulate the list got above to include/exclude current page (i.e. product) -->
    <cms:php>
        global $CTX;
       
        $my_current_product = $CTX->get( 'my_current_product' );
        $my_related_products = $CTX->get( 'my_related_products' );
       
        // is the current product (the page we are on) in the list of related products?
        $arr_products = explode( ',', $my_related_products );
        $key = array_search( $my_current_product, $arr_products );
        if( $key !== false ){
            // product already related.. remove it from list
            unset( $arr_products[$key] );
            $CTX->set( 'is_already_related', '1', 'global' );
        }
        else{
            // not yet related.. add product to list
            $arr_products[] = $my_current_product;
            $CTX->set( 'is_already_related', '0', 'global' );
        }
       
        // set the revised list of ids in context
        $my_related_products = trim( implode(',', $arr_products) );
        $CTX->set( 'my_related_products', $my_related_products, 'global' );

    </cms:php>
   
    <!-- use databound form to persist the new list of related pages -->
    <cms:form
    masterpage='users/index.php'
    mode='edit'
    page_id=my_user_id
    method='post'
    anchor='0'>
        <cms:if k_success >
            <cms:db_persist_form
                rev_relation_<cms:show k_template_id />=my_related_products
            />
        </cms:if>
      
      <cms:if k_logged_in>
        <cms:if is_already_related >
            <cms:input class="sh-btn-red sh-btn-small" name="submit" type="submit" value="Unfollow" />
        <cms:else />
            <cms:input class="sh-btn sh-btn-small" name="submit" type="submit" value="Follow" />
        </cms:if> 
      <cms:else/>
      <a href="<cms:show k_login_link />" class="sh-btn sh-btn-small">Follow</a>
      </cms:if>
       
    </cms:form>

When i register it via admin it was fine, the PHP manipulated is also works. But i can't make it works to Follow and Unfollow in frontend.
Please help.

Thankyou.
I think the problem lies here -
<cms:db_persist_form
rev_relation_<cms:show k_template_id />=my_related_products
/>

You can't use Couch tag on the left-side of '='.
Please use explicitly the correct name of the relation field (e.g. "rev_relation_24" where24 is the template id).

That said, I have my doubts about your decision to use <cms:show k_template_id /> or <cms:show k_template_name /> to set the names of editable regions - it will only make things difficult, as you are seeing with the current problem.
11 posts Page 1 of 2
cron