





















































Create a powerful and dynamic Social Networking website in PHP by building a flexible framework
Throughout the course of this article we will be using a social networking site for keepers of pet dinosaurs (of course nobody owns a real pet dinosaur, but for the sake of this article, let's pretend!), which we will call DinoSpace.
The status stream fully supports public messages and streaming them to the Dino Space members. What we don't yet have, however, is support for users to post messages on the profiles of other users, so, let's add that in now.
A user should only be able to post a message on another user's profile if they are connected. The post message form should only be displayed if the users are connected. Similarly, a public message post should only be processed if the two users are connected. The controller also needs to display messages that have been posted on a user's profile too.
If we look at our Profilestatusescontroller (controllers/profile/ profilestatusescontroller.php), in the listRecentStatuses method, we have our query for listing recent profile statuses:
$sql = "SELECT t.type_reference, t.type_name, s.*, p.name as
poster_name FROM statuses s, status_types t, profile p
WHERE t.ID=s.type AND p.user_id=s.poster AND p.user_id={$user}
ORDER BY s.ID DESC LIMIT 20";
At the moment, this query pulls in any posts on a user's profile by the user whose profile it is. If that user has made a post on someone else's profile, the message instead shows on the user's own profile, which we don't want.
We need to change this to pull in the profiles table twice, once for the user who made the post, and again for the user whose profile is being viewed. We will also want to only pull in posts made on the user's profile, and not posts made by the user on another user's profile (though this is something we can expand on in the future, perhaps to indicate that a user has made a post on the profile of another user). The following query should meet our requirements nicely:
$sql = "SELECT t.type_reference, t.type_name, s.*, pa.name as
poster_name FROM statuses s, status_types t, profile p,
profile pa WHERE t.ID=s.type AND p.user_id=s.profile
AND pa.user_id=s.poster AND p.user_id={$user}
ORDER BY s.ID DESC LIMIT 20";
Now, if we view a user's profile, we see their own status updates, and messages posted on their profile by other users, as shown in the following screenshot:
The listRecentStatuses method we were just editing is the method we need to edit to display the post message box. This box should only be displayed if the user is logged in, and is connected to the user. If the user is viewing their own profile, then they should see a box to update their own status:
// post status / public message box
if( $this->registry->getObject('authenticate')->isLoggedIn() == true )
{
$loggedInUser = $this->registry->getObject('authenticate')-
>getUser()->getUserID();
If the logged in user is viewing their own profile, then we add the update template to the view, so they can update their status:
if( $loggedInUser == $user )
{
$this->registry->getObject('template')->addTemplateBit('status_
update', 'profile/statuses/update.tpl.php' );
}
else
{
If the user isn't viewing their own profile, but is logged in, we get any connections the user has:
require_once( FRAMEWORK_PATH . 'models/relationships.php' );
$relationships = new Relationships( $this->registry );
$connections = $relationships->getNetwork( $user, false );
if( in_array( $loggedInUser, $connections ) )
{
If the user is connected to the user whose profile they are viewing, then we allow them to post a message on the users profile with the post template:
$this->registry->getObject('template')->addTemplateBit(
'status_update', 'profile/statuses/post.tpl.php' );
}
else
{
If the user isn't connected to the user, or isn't logged in, then we simply remove the template tag from the view so they don't see any update or post box on the page:
$this->registry->getObject('template')->getPage()-
>addTag( 'status_update', '' );
}
}
}
else
{
$this->registry->getObject('template')->getPage()-
>addTag( 'status_update', '' );
}
Now, we need to process status updates and profile posts, and create the templates that make up the final aspect of our view.
The same logic that we used to determine whether the user should see a post form is what we need to use to determine if we should process a status update, or public message submission.
Status model
To save the status update or public profile post in the database, we will need a status model; as with our previous models, this simply needs to represent the fields from the database, with setter methods for these fields, and a save method to insert a new record into the database. In the future, we may wish to extend this to pull in statuses from the database, and save changes to them, as well as deleting statuses, perhaps if the owner of the message or the owner of the profile the message was posted on wishes to edit or delete it.
The following is suitable code for our status model (models/status.php):
<?php
/**
* Status model
*/
class Status {
/**
* The registry object
*/
private $registry;
/**
* Statuses ID
*/
private $id;
/**
* Poster of the status update / profile message
*/
private $poster;
/**
* The profile the status update / profile message was posted on
*/
sprivate $profile;
/**
* Type of status
*/
private $type;
/**
* The update / profile message itself
*/
private $update;
/**
* Reference for the type of status
*/
private $typeReference = 'update';
/**
* Constructor
* @param Registry $registry the registry object
* @param int $id ID of the status update / profile message
* @return void
*/
public function __construct( Registry $registry, $id=0 )
{
$this->registry = $registry;
$this->id = 0;
}
/**
* Set the poster of the status / profile message
* @param int $poster the id of the poster
* @return void
*/
public function setPoster( $poster )
{
$this->poster = $poster;
}
/**
* Set the profile that the message / status is posted on
* @param int $profile the profile ID
* @return void
*/
public function setProfile( $profile )
{
$this->profile = $profile;
}
/**
* Set the status / profile message itself
* @param String $status
* @return void
*/
public function setStatus( $status )
{
$this->status = $status;
}
/**
* Set the type of status / profile message
* @param int $type
* @return void
*/
public function setType( $type )
{
$this->type = $type;
}
/**
* Set the type reference, so we can get the type ID from the
database
* @param String $typeReference the reference of the type
* @return void
*/
public function setTypeReference( $typeReference )
{
$this->type = $typeReference;
}
/**
* Generate the type of status based of the type reference
* @return void
*/
public function generateType()
{
$sql = "SELECT * FROM status_types WHERE
type_reference='{$this->typeReference}'";
$this->registry->getObject('db')->executeQuery( $sql );
$data = $this->registry->getObject('db')->getRows();
$this->type = $data['ID'];
}
/**
* Save the status / profile message
* @return void
*/
public function save()
{
if( $this->id == 0 )
{
$insert = array();
$insert['update'] = $this->status;
$insert['type'] = $this->type;
$insert['poster'] = $this->poster;
$insert['profile'] = $this->profile;
$this->registry->getObject('db')-
>insertRecords( 'statuses', $insert );
$this->id = $this->registry->getObject('db')->lastInsertID();
}
}
}
?>
Now that we have some functionality to easily insert the status into the database, we need to update our profile controller to process the new status update.