* @return void */ private function profileError { $this->registry->errorPage 'Sorry, an error has occured', 'The link you followed was invalid, please try again'; } } ?> Core shar
Trang 1require_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 profile 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 profile we are viewing
• Their photograph
• A sample of their friends
This core shared information is something we can generate from within the profile
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 profile
model to access and manage the data from a user's profile We are also going to
need to add a new field to our profile table, one for a user's profile 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 field in the database for the users' biography
information, for them to tell everyone about themselves.
Trang 2Profile model
We need to create a profile model (models/profile.php), which we will need to do
the following things:
• Populate its fields based on a user's profile in the database
• Update its fields based on changes to a user's profile
• Update the corresponding database record for the profile, provided the user
updating the profile 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;
/**
Trang 3* 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
fields 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;
Trang 4if( $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
Trang 5*/
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
Trang 6*/
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 profile, we take each of the values from the
savable profile fields, add them to an update array, and then pass this to the database
object's updateRecords method to save the profile, provided that the user is either
the administrator or changing their own profile.
/**
* 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
Trang 7$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 );
}
}
}
Trang 8Finally, 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
Trang 9*/
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 profile
pictures and other information to make the sample of friends more interesting to the
user viewing the profile.
Pulling the core shared information together
By using the relationships model and the profile model, we can get the core
shared information we need We now need a method in our profile 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 );
Trang 10$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 profile
Let us now look at providing functionality for the user's "static profile", that is,
the information about them, interests, hobbies, facts, and other information that
is unlikely to change on a regular basis.
Our profile model that we created earlier in the chapter should make accessing
and displaying profile information much easier
Viewing the profile
What do we need to do to facilitate viewing a user's profile:
• We need to put a profile link in the members list, and the member's search
results pages, so users can actually get to these profiles!
• We need to create a profile information controller, which:
° Gets profile data from the profile model, and sends it to the
template engine
• We need to create a template, which includes provisions for both profile
information, and the common profile information