Proles and Statuses [ 142 ] require_once( FRAMEWORK_PATH . 'controllers/profile/ profilestatusescontroller.php' ); $sc = new Profilestatusescontroller( $this->registry, true, $user ); } If the user tried to access a sub-controller that doesn't exist, we would display an error. /** * Display an error - you cannot access profiles simply by visiting /profile/ ! * @return void */ private function profileError() { $this->registry->errorPage( 'Sorry, an error has occured', 'The link you followed was invalid, please try again'); } } ?> Core shared information Although the user's prole is going to be broken down into different areas, which are accessed through different links showing different pages, there will be some information that should be common throughout all of these aspects, such as: • The name of the user whose prole we are viewing • Their photograph • A sample of their friends This core shared information is something we can generate from within the prole controller, which is called regardless of which sub controller control is subsequently delegated to. This information can be generated and sent to the template handler ready for when the page is outputted to the user's browser. Name, ID, and photograph To get the name, ID, and photograph of a user, we are going to require a prole model to access and manage the data from a user's prole. We are also going to need to add a new eld to our prole table, one for a user's prole picture (as we didn't consider that when the user signed up to Dino Space). While we are creating this model, we should also create a eld in the database for the users' biography information, for them to tell everyone about themselves. Download from Wow! eBook <www.wowebook.com> Chapter 5 [ 143 ] Prole model We need to create a prole model (models/profile.php), which we will need to do the following things: • Populate its elds based on a user's prole in the database • Update its elds based on changes to a user's prole • Update the corresponding database record for the prole, provided the user updating the prole is either an administrator or the user themselves • Generate template tags for the data within • Return certain information on demand—for us, we want to get the user's name and the user's photograph The code for such a model is as follows: <?php /** * Profile model */ class Profile{ /** * The registry */ private $registry; /** * Profile ID */ private $id; /** * Fields which can be saved by the save() method */ private $savable_profile_fields = array( 'name', 'dino_name', 'dino_dob', 'dino_breed', 'dino_gender', 'photo', 'bio' ); /** * Users ID */ private $user_id; /** Download from Wow! eBook <www.wowebook.com> Proles and Statuses [ 144 ] * Users name */ private $name; /** * Dinosaurs name */ private $dino_name; /** * Dinosaurs Date of Birth */ private $dino_dob; /** * Dinosaurs breed */ private $dino_breed; /** * Dinosaurs gender */ private $dino_gender; /** * Users bio */ private $bio; /** * Users photograph */ private $photo; Upon construction, if an ID has been passed, the database should be queried, and the elds of the object populated with the result from the query. /** * Profile constructor * @param Registry $registry the registry * @param int $id the profile ID * @return void */ public function __construct( Registry $registry, $id=0 ) { $this->registry = $registry; Download from Wow! eBook <www.wowebook.com> Chapter 5 [ 145 ] if( $id != 0 ) { $this->id = $id; // if an ID is passed, populate based off that $sql = "SELECT * FROM profile WHERE user_id=" . $this->id; $this->registry->getObject('db')->executeQuery( $sql ); if( $this->registry->getObject('db')->numRows() == 1 ) { $data = $this->registry->getObject('db')->getRows(); // populate our fields foreach( $data as $key => $value ) { $this->$key = $value; } } } } As usual, we have a number of setter methods: /** * Sets the users name * @param String $name * @return void */ public function setName( $name ) { $this->name = $name; } /** * Sets the dinosaurs name * @param String $name the name * @return void */ public function setDinoName( $name ) { $this->dino_name = $name; } /** * Sets the users bio * @param String $bio the bio * @return void Download from Wow! eBook <www.wowebook.com> Proles and Statuses [ 146 ] */ public function setBio( $bio ) { $this->bio = $bio; } The dinosaur date of birth setter method also accepts a formatted parameter, which indicates that the date being passed has already been formatted appropriately, or that it hasn't and additional processing is necessary. /** * Set the dinosaurs data of birth * @param String $dob the date of birth * @param boolean $formatted - indicates if the controller has formatted the dob, or if we need to do it here */ public function setDinoDOB( $dob, $formatted=true ) { if( $formatted == true ) { $this->dino_dob = $dob; } else { $temp = explode('/', $dob ); $this->dob = $temp[2].'-'.$temp[1].'-'.$temp[0]; } } /** * Sets the breed of the users dinosaur * @param String $breed * return void */ public function setDinoBreed( $breed ) { $this->dino_breed = $breed; } /** * Set the gender of the users dinosaur * @param String $gender the gender * @param boolean $checked - indicates if the controller has validated the gender, or if we need to do it * @return void Download from Wow! eBook <www.wowebook.com> Chapter 5 [ 147 ] */ public function setDinoGender( $gender, $checked=true ) { if( $checked == true ) { $this->dino_gender = $gender; } else { $genders = array(); if( in_array( $gender, $genders ) ) { $this->dino_gender = $gender; } } } /** * Sets the users profile picture * @param String photo name * @return void */ public function setPhoto( $photo ) { $this->photo = $photo; } If the user or administrator saves the prole, we take each of the values from the savable prole elds, add them to an update array, and then pass this to the database object's updateRecords method to save the prole, provided that the user is either the administrator or changing their own prole. /** * Save the user profile * @return bool */ public function save() { // handle the updating of a profile if( $registry->getObject('authenticate')->isLoggedIn() && ( $registry->getObject('authenticate')->getUser()- >getUserID() == $this->id || $registry- >getObject('authenticate')->getUser()->isAdmin() == true ) ) { // we are either the user whose profile this is, or we are the administrator Download from Wow! eBook <www.wowebook.com> Proles and Statuses [ 148 ] $changes = array(); foreach( $this->saveable_profile_fields as $field ) { $changes[ $field ] = $this->$field; } $this->registry->getObject('db')->updateRecords( 'profile', $changes, 'user_id=' . $this->id ); if( $this->registry->getObject('db')->affectedRows() == 1 ) { return true; } else { return false; } } else { return false; } } Next, we have a method to convert the data from the model into template tags to make it easy to populate the view: /** * Convert the users profile data to template tags * @param String $prefix prefix for the template tags * @return void */ public function toTags( $prefix='' ) { foreach( $this as $field => $data ) { if( ! is_object( $data ) && ! is_array( $data ) ) { $this->registry->getObject('template')->getPage()- >addTag( $prefix.$field, $data ); } } } Download from Wow! eBook <www.wowebook.com> Chapter 5 [ 149 ] Finally, we have a number of getter methods to retrieve data from the model: /** * Get the users name * @return String */ public function getName() { return $this->name; } /** * Get the users photograph * @return String */ public function getPhoto() { return $this->photo; } /** * Get the users ID * @return int */ public function getID() { return $this->user_id; } } ?> Sample of friends Our relationships model (models/relationships.php) contains a method to return a cached query of a user's friends and contacts. We can extend this method to, if we request, return a random sample of these friends. We can do this by adding two additional parameters to the method, one to indicate if the results should be random, and another to limit the result set, and by checking the values of these parameters and modifying the query appropriately, as highlighted in the code below: /** * Get relationships by user * @param int $user the user whose relationships we wish to list * @param boolean $obr should we randomly order the results? * @param int $limit should we limit the results? ( 0 means no, > 0 means limit to $limit ) * @return int the query cache ID Download from Wow! eBook <www.wowebook.com> Proles and Statuses [ 150 ] */ public function getByUser( $user, $obr=false, $limit=0 ) { // the standard get by user query $sql = "SELECT t.plural_name, p.name as users_name, u.ID FROM users u, profile p, relationships r, relationship_types t WHERE t.ID=r. type AND r.accepted=1 AND (r.usera={$user} OR r.userb={$user}) AND IF( r.usera={$user},u.ID=r.userb,u.ID=r.usera) AND p.user_id=u.ID"; // if we are ordering by random if( $obr == true ) { $sql .= " ORDER BY RAND() "; } // if we are limiting if( $limit != 0 ) { $sql .= " LIMIT " . $limit; } // cache and return $cache = $this->registry->getObject('db')->cacheQuery( $sql ); return $cache; } Currently, this query will give us a list of friend's names and the type of relationship the user has with them. We may wish to extend this in the future to pull in prole pictures and other information to make the sample of friends more interesting to the user viewing the prole. Pulling the core shared information together By using the relationships model and the prole model, we can get the core shared information we need. We now need a method in our prole controller (controllers/profile/controller.php) to get the data, and assign it to appropriate template variables. /** * Set common template tags for all profile aspects * @param int $user the user id * @return void */ private function commonTemplateTags( $user ) { // get a random sample of 6 friends. require_once( FRAMEWORK_PATH . 'models/relationships.php' ); $relationships = new Relationships( $this->registry ); Download from Wow! eBook <www.wowebook.com> Chapter 5 [ 151 ] $cache = $relationships->getByUser( $user, true, 6 ); $this->registry->getObject('template')->getPage()->addTag( 'profile_friends_sample', array( 'SQL', $cache ) ); // get the name and photo of the user require_once( FRAMEWORK_PATH . 'models/profile.php' ); $profile = new Profile( $this->registry, $user ); $name = $profile->getName(); $uid = $profile->getID(); $photo = $profile->getPhoto(); $this->registry->getObject('template')->getPage()->addTag( 'profile_name', $name ); $this->registry->getObject('template')->getPage()->addTag( 'profile_photo', $photo ); $this->registry->getObject('template')->getPage()->addTag( 'profile_ user_id', $uid ); // clear the profile $profile = ""; } This method should be called before we pass control to the various other controllers. Static prole Let us now look at providing functionality for the user's "static prole", that is, the information about them, interests, hobbies, facts, and other information that is unlikely to change on a regular basis. Our prole model that we created earlier in the chapter should make accessing and displaying prole information much easier. Viewing the prole What do we need to do to facilitate viewing a user's prole: • We need to put a prole link in the members list, and the member's search results pages, so users can actually get to these proles! • We need to create a prole information controller, which: ° Gets prole data from the prole model, and sends it to the template engine • We need to create a template, which includes provisions for both prole information, and the common prole information Download from Wow! eBook <www.wowebook.com> . $this->id; $this->registry->getObject('db' )-& gt;executeQuery( $sql ); if( $this->registry->getObject('db' )-& gt;numRows() == 1 ) { $data = $this->registry->getObject('db' )-& gt;getRows(); . $registry->getObject('authenticate' )-& gt;isLoggedIn() && ( $registry->getObject('authenticate' )-& gt;getUser( )- >getUserID() == $this->id || $registry- . 'models/profile .php& apos; ); $profile = new Profile( $this->registry, $user ); $name = $profile->getName(); $uid = $profile->getID(); $photo = $profile->getPhoto(); $this->registry->getObject('template' )-& gt;getPage( )-& gt;addTag(