Welcome Guest, Not a member yet? Register   Sign In
CXTags v1.0 - An awesome (but simple) taxonomy system
#11

[eluser]Xeoncross[/eluser]
Thanks, I needed a list of Non-standard chars to add to this - however - it is only in use on a US site so I just haven't gotten around to it yet. Thanks for your function. Also, if I remember right, I think we could encode the characters so that other langs like Mandarin would work also.
#12

[eluser]deadelvis[/eluser]
I have added another function. This one is a variation on your fetch_rows() function.

In your function, if you pass an array of safe tags the function will retrieve all rows/objects that contain at least ONE of the safe tags.

My function fetches all rows/objects that contain ALL safe_tags (a safe tags combo).

Cheers

Code:
/*
     *  Fetch all rows/objects that use ALL safe_tag(s)
     *
     * $data = array(
     *         'table' => 'posts',    // Name of the table row_id is from
     *         'tags' => 'safetag',// safe tag, or an array of safe tags
     *         'user_id' = > null,    // Optional only return rows for user_id
     *        'limit' => 10,        // Optional Max number of results
     *        'offset' => 0        // Optional Offset of results
     *    );
     * @param    array    data about the tag(s) we are fetching
     * @return    mixed (array of objects with ids)
     */
    function fetch_rows_combo($data) {
        //If there is no table
        if(!$data['table'] || !$data['tags']) {
            return;
        }

        //Add the WHERE clause for the tags
        $this->where_tags($data['tags']);

        //Select the Tag info
        //$this->db->select('tag, safe_tag, date, row_id, user_id');
        //Don't need tag/user info because the GROUP BY will only show 1
        //tag/user for each row (even if there are many)
        
        // We must adjust for duplicate normalized tags appearing multiple times in the join
        // by counting only the distinct tags.
        if(is_array($data['tags'])) {
            $uniques = count( $data['tags']);
        }else{
            $uniques = 1;
        }

        $this->db->select('row_id, COUNT(DISTINCT safe_tag) AS uniques',false);
        $this->db->having('uniques', $uniques);
        $this->db->group_by("row_id");
        $this->db->join($this->tags_ref,
            $this->tags_ref_prefix. '.tag_id = '. $this->tags_prefix. '.id', 'inner');
        $this->db->where('table', $data['table']);

        //If a limit is implied
        if(isset($data['limit']) && $data['limit']) {
            $this->db->limit($data['limit'],
            (isset($data['offset']) ? $data['offset'] : null)
            );
        }

        //If a user_id is given
        if(isset($data['user_id']) && $data['user_id']) {
            $this->db->where('user_id', $data['user_id']);
        }

        return $this->db->get($this->tags);

    }

PS: since only the sql statement changed, you can in practice still pass ids to the function as well, but this isn't of any use as all id's are unique. Maybe making this function independent from where_tags() would make more sense?
#13

[eluser]deadelvis[/eluser]
One more: fetch_similar_tags().
This one is a total ripoff from a freetag function I really missed. Outputs the same data format as fetch_popular_tags()

Code:
/*
    * Adapted from a freetag function by Myles Grant
    *
    * Finds tags that are "similar" or related to the given tags.
    * It does this by looking at the other tags on objects tagged with the tags specified.
    * Confusing? Think of it like e-commerce's "Other users who bought this also bought,"
    * as that's exactly how this works.
    *
    * It's important to note that the count passed back along with each tag
    * is a measure of the *strength of the relation* between the original tag
    * and the related tag. It measures the number of objects tagged with both
    * the original tag and its related tag.
    *
    * $data = array(
    *         'table' => 'posts',    // Name of the table row_id is from            
    *         'tags' => tag/array(),    // safe tag, or an array of safe tags
    *         'user_id' = > null,    // Optional only return rows for user_id
    *        'limit' => 10,        // Optional Max number of results
    *        'offset' => 0        // Optional Offset of results
    *    );
    *
    * @param    array    data about the tag(s) we are fetching
    * @return    mixed (mysql obj: tag / safe_tag / date / count)
    */

    function fetch_similar_tags($data) {
        
        //If there is no table
        if(!$data['table'] || !$data['tags']) {
            return;
        }

        // This query was written using a double join for PHP. If you're trying to eke
        // additional performance and are running MySQL 4.X, you might want to try a subselect
        // and compare perf numbers.
        $this->db->select('t1.tag, t1.safe_tag, t1.id, o1.date, COUNT( o1.row_id ) AS count');
        $this->db->from('tags_ref o1');
        
        if(!is_array($data['tags'])) { // convert to array is it is a single tag string
            $data['tags'] = array( $data['tags']);
        }
        
        foreach($data['tags'] as $key => $value){
            $t1 = (($key+1)*2)-1;     // 1, 3, 5, 7 ...
            $t2 = ($key+1)*2;         // 2, 4, 6, 8 ...
            $o2 = ($key+2);            // 2, 3, 4, 5 ...
            $this->db->join('tags t'.$t1, 't'.$t1.'.id = o1.tag_id', 'inner');
            $this->db->join('tags_ref o'.$o2, 'o1.row_id = o'.$o2.'.row_id', 'inner');
            $this->db->join('tags t'.$t2, 't'.$t2.'.id = o'.$o2.'.tag_id', 'inner');
            
            $t1 = (($key+1)*2)-1;     // 1, 3, 5, 7 ...
            $t2 = ($key+1)*2;         // 2, 4, 6, 8 ...
            $o2 = ($key+2);            // 2, 3, 4, 5 ...
            $this->db->where("t".$t2.".safe_tag", $value);
            $this->db->where("t".$t1.".safe_tag !=", $value);
        }
        
        $this->db->group_by("o1.tag_id");
        $this->db->orderby('count', 'desc');
        
        //If a limit is implied
        if(isset($data['limit']) && $data['limit']) {
            $this->db->limit($data['limit'],
            (isset($data['offset']) ? $data['offset'] : null)
            );
        }

        //If a user_id is given
        if(isset($data['user_id']) && $data['user_id']) {
            $this->db->where("o1.user_id", $data['user_id']);
            $this->db->where("o2.user_id", $data['user_id']);
        }
        
        return $this->db->get();
        
    }
#14

[eluser]port23user[/eluser]
Thanks for the model, xeoncross. I got it and after a little bit of sweat, it works great!
#15

[eluser]Xeoncross[/eluser]
Thanks for all the suggestions and functions posted. I just put them all into the new version 2.0 of CXTags. I also made some improvements to the code. I integrated a new "ALL" param to the fetch_rows() function that forces all rows returned to contain ALL tags given in order to be returned. I figured this would be a better step than building a whole new function like fetch_rows_combo() that deadelvis posted. Also checked into the internationalization features and you can turn them on or off per-function call. Thanks and let me know if something breaks. ;-)
#16

[eluser]JulianM[/eluser]
Where is the new version 2.0 for download?

Thanks.
#17

[eluser]JulianM[/eluser]
Ok, just found the download link:

http://code.google.com/p/cxtags/downloads/list

Thanks.
#18

[eluser]RS71[/eluser]
Quick question:

Does this library/system include the fetch similar function deadelvis posted? (with relational strength and whatnot)
#19

[eluser]Xeoncross[/eluser]
yes, though it might have been implemented into one of the existing functions (to save space). You'll just have to download it and find out. Wink
#20

[eluser]RS71[/eluser]
Ah found it. I didn't look beneath the support functions sections. Thanks mate.

I could be asking too much but could somebody explain me how the function works?




Theme © iAndrew 2016 - Forum software by © MyBB