Created
October 16, 2010 22:01
-
-
Save chrismeller/630321 to your computer and use it in GitHub Desktop.
Habari Taxonomy Structure Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Term extends QueryRecord { | |
protected $vocabulary; // set by child classes to indicate which vocabulary your term relates to | |
// these two would be emulated by __get() and __set() so that they're actually stored in $this->fields | |
// for QueryRecord to work but this would be the public API | |
public $term; // the slugified version of the term name | |
public $display; // the raw term name for display | |
// these wrap around their QueryRecord parents | |
function insert () {} | |
function delete () {} | |
function update () {} | |
function attach_to_object ( $object_id, $object_type ) { | |
// attach $this->id (no need to pass in one) to the object of $object_type with id $object_id | |
// $object_type would default to the type of object a vocabulary is set to link against, if it is limited to a particular type | |
// otherwise, presumably it would default to 'post' for convenience | |
} | |
function detach_from_object ( $object_id, $object_type ) {} | |
function rename ( $new_name ) { | |
// rename $this->term to $new_name. should handle making sure it's available in the given $vocabulary | |
// as well as merging it with an existing tag of the same name | |
// just like deleting terms (see note in Vocabulary), you do this on a single term, not on a group of terms | |
// which means it goes in Term, not Vocabulary | |
} | |
function next () { | |
// get the next Term in the tree, if Vocabulary is heirarchical | |
// similar methods for working up and down the tree, getting children, etc. would be needed | |
} | |
// note that there is no get() method. you don't directly fetch a term, you fetch terms from a vocabulary | |
} | |
class Vocabulary extends QueryRecord { | |
protected $term = 'Term'; // overridden by child classes to indicate which class we use to represent terms. ie: which class should Vocabulary tell PDO to return results as? | |
protected $vocabulary; // set by child classes to indicate the name of this vocabulary (matches up with Term::$vocabulary) | |
// these wrap around their QueryRecord parents | |
function insert () {} | |
function delete () {} | |
function update () {} | |
static function create ( $params = array() ) { | |
// a factory method that returns a newly-created Vocabulary object after calling ->insert() on it | |
// this would really only be useful if you're creating some kind of dynamicly named vocabulary and can't create | |
// a separate class that extends Vocabulary like you normally would | |
} | |
function get_terms ( $params = array() ) { | |
// works the same as Posts::get(), parsing out the parameters from the array | |
// and returning all matching terms for vocabulary $this->vocabulary (so you don't have to | |
// pass in 'vocabulary' => 'tags', like you do 'content_type' => 'entry' for Posts calls) | |
// this would replace get_all(), get_by_id(), get_by_name(), etc. | |
// we would then return a simple array of $term objects - either the generic Term class or any other class specified in self::$term | |
// since we only return an array(), which is really all that the current Tags class is once its methods are moved into | |
// this generic Vocabulary class, there's no need for a "container" class anymore. | |
// $post->tags is an array, not a Tags object emulating an array | |
} | |
// note there are no other term-modifying methods (like delete_term()). | |
// you get terms and perform operations on individual term objects instead, just like we do with posts | |
// we would also add handling for the different vocabulary features (heirarchical, etc.) in here, | |
// as well as getting and managing the tree of terms, if applicable | |
// also note there is not necessarily an $object_type parameter. a vocabulary could be linked to any type of object | |
// so limiting it always to a single type is not appropriate. that's why you always pass an $object_type to Term::attach_to_object(). | |
// there should, however, be the option to specifically link a vocabulary to a single type of object | |
} | |
// now we set up our default Tags structure! | |
class Tag extends Term { | |
protected $vocabulary = 'tags'; | |
// that's it, there is nothing special about a Tag object, it behaves just like any other term, | |
// so all the methods for dealing with tags are actually in Term | |
} | |
class Tags extends Vocabulary { | |
protected $term = 'Tag'; // our Terms are the Tag class, return that type of object for all terms | |
protected $vocabulary = 'tags'; // the name of our vocabulary is 'tags' - linked with Tag::$vocabulary | |
// again, there is nothing special about tags, any functions we might need or actions to be performed on them are in | |
// the base Vocabulary class. getting tags works just like getting any other type of term, no modifications are | |
// required to Vocabulary::get_terms(). | |
} | |
// and finally, examples of using the classes | |
// in the Post class, you load tags for the post: | |
$post->tags = Tags::get_terms( array( 'object_type' => 'post', 'object_id' => $post->id ) ); | |
// $posts->tags would be set to array( $tag1 instanceOf Tag, $tag2 instanceOf Tag, ... ) | |
// a better structure, however, would be more generic. every time a post is loaded, we would retrieve all its related | |
// terms, regardless of vocabulary, and set $post->vocabulary->%vocabulary_name% = array( %vocabulary_terms% ) | |
// so instead of $post->tags we would access them at $post->vocabulary->tags instead. | |
// delete the 'foo' tag entirely, including associations with any objects | |
$tag = Tags::get_terms( array( 'name' => 'foo' ) ); | |
// similar to Posts::get(), if it's a single tag i would return simply a single tag object, not an array with a single entry | |
$tag->delete(); | |
// boom, it's gone and works just like deleting a post | |
// say i'm dynamically determining the name of a vocabulary - maybe i let the user create any type of vocabulary they want | |
// in that case i don't know the name of the vocabulary and can't create a class to extend Vocabulary. no big deal, it's convenient | |
// but not required: | |
$tags = Vocabulary::create( array( 'vocabulary' => 'tags' ) ); | |
// the vocabulary is created because create() calls ->insert() before it returns the Vocabulary object | |
// from now on i can get the vocabulary: | |
$tags = Vocabulary::get( array( 'vocabulary' => 'tags' ) ); | |
// or: | |
$tags = new Vocabulary( array( 'vocabulary' => 'tags' ) ); | |
// and get some terms from it: | |
$terms = $tags->get_terms( array( 'name' => 'foo' ) ); | |
// or all of them for a given post: | |
$terms = $tags->get_terms( array( 'object_id' => 123, 'object_type' => 'post' ) ); | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment