PHP 5 Social Networking: Implementing Public Messages

PHP 5 Social Networking


October 2010

$26.99

Create a powerful and dynamic Social Networking website in PHP by building a flexible framework

PHP 5 Social Networking

PHP 5 Social Networking

Create a powerful and dynamic Social Networking website in PHP by building a flexible framework

 
  • Build a flexible Social Networking framework using PHP which can be extended to fit the needs of any Social Networking site
  • Develop a suitable structure for our framework, with MVC to structure the architecture and a Registry to store core Objects
  • Allow users to connect and communicate with each other using communication with friends list, flexible user profiles, messages, discussions, and much more
  • Plan marketing and scaling strategies, to entice more users and ensure the site can cope with the demand
  • Packed with real-world code and clear explanation, this book uses an ongoing case study for creating a Social Networking framework
        Read more about this book      

(For more resources on PHP, see here.)

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.

Public messages

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.

Controller

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.

Displaying profile messages

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:

Displaying the post message box

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.

Process a new message

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.

        Read more about this book      

(For more resources on PHP, see here.)

Controller additions

As we discussed earlier, we need to take the same logic we used for displaying the status form, to determine whether we should process a status submission. We can then combine our new status model to insert the status.

Within the listRecentStatuses method in the profilestatusescontroller, under the authentication check line, we can check for any $_POST data being submitted, and if there is, we can call a new method to process the submission:

// post status / public message box
if( $this->registry->getObject('authenticate')->isLoggedIn() == true )
{
if( isset( $_POST ) && count( $_POST ) > 0 )
{
$this->addStatus( $user );
}

Since we have placed this within our listRecentStatuses method, once any processing has been done, the user is presented with the list of statuses and public profile messages for that user.

The addStatus method only inserts the status into the database if the user is posting the status either to their own profile, or the profile of one of their contacts:

/**
* Process a new status submission / profile message
* @param int $user the profile the message is being posted on
* @return void
*/
private function addStatus( $user )
{
$loggedInUser = $this->registry->getObject('authenticate')-
>getUser()->getUserID();
if( $loggedInUser == $user )
{
require_once( FRAMEWORK_PATH . 'models/status.php' );
$status = new Status( $this->registry, 0 );
$status->setProfile( $user );
$status->setPoster( $loggedInUser );
$status->setStatus( $this->registry->getObject('db')-
>sanitizeData( $_POST['status'] ) );
$status->generateType();
$status->save();
// success message display
}
else
{
require_once( FRAMEWORK_PATH . 'models/relationships.php' );
$relationships = new Relationships( $this->registry );
$connections = $relationships->getNetwork( $user, false );
if( in_array( $loggedInUser, $connections ) )
{
require_once( FRAMEWORK_PATH . 'models/status.php' );
$status = new Status( $this->registry, 0 );
$status->setProfile( $user );
$status->setPoster( $loggedInUser );
$status->setStatus( $this->registry->getObject('db')-
>sanitizeData( $_POST['status'] ) );
$status->generateType();
$status->save();
// success message display
}
else
{
// error message display
}
}
}

Displaying a confirmation message

Once the user has posted their message on another user's profile, they are redirected to the profile. Although the profile now has their message on it, there isn't a direct confirmation message to the user, so let's look at adding a notification to confirm to the user that their post was successful.

As we won't always wish to display a message, such as if the user hasn't submitted the form, then we either need to clear the template tag, or simply place it within some HTML comments, for example:

<!-{status_update_message} -->

If we do this, we simply need to start the contents of the message template with --> and end it with <!-- to ensure the message itself isn't commented out. Since we have used the same logic to process the form as we used to display the form, we can also customize the message based on the context of the submission, for example, You have updated your status, or You have posted on John's wall.

We can then add the message to the view, like so:

$this->registry->getObject('template')->addTemplateBit( 'status_
update_message', 'profile/statuses/update_confirm.tpl.php' );

View

We need to add two template tags to our statuses list file (views/default/ templates/profile/statuses/list.tpl.php), one for the status update/profile message submit form, and the other (wrapped in HTML comments) for the success or error message to use:

{status_update}
<!-- {status_update_message} -->

Five small new templates are required, for:

  • Form to update your own status
  • Form to post a message on someone else's profile
  • Success confirmation message when your own status is updated
  • Success confirmation message when you post on someone else's profile
  • Error message, if you try to post on the profile of someone you are not connected to (although the lack of a form for this should prevent this happening)

Updating your own status: views/default/templates/profile/statuses/ update.tpl.php.

<p>Tell your network what you are up to</p>
<form action="profile/statuses/{profile_user_id}" method="post">
<textarea id="status" name="status"></textarea>
<br />
<input type="submit" id="updatestatus" name="updatestatus"
value="Update" />
</form>

Posting on someone else's profile: views/default/templates/profile/statuses/ post.tpl.php.

<p>Post a message on {profile_name}'s profile</p>
<form action="profile/statuses/{profile_user_id}" method="post">
<textarea id="status" name="status"></textarea>
<br />
<input type="submit" id="postmessage" name="postmessage"
value="Update" />
</form>

Success message after updating your own status: views/default/templates/ profile/statuses/update_confirm.tpl.php.

-->
<p style="border: 1px solid #000; padding: 5px;">Your status
has been saved</p>
<!--

Success message after posting on someone else's profile: views/default/ templates/profile/statuses/post_confirm.tpl.php.

-->
<p style="border: 1px solid #000; padding: 5px;">Your message
has been posted on {profile_name}'s profile</p>
<!--

Error message after trying to post on the profile of an unconnected user: views/ default/templates/profile/statuses/error.tpl.php.

-->
<p style="border: 1px solid #000; padding: 5px;">You are not
connected to {profile_name}, so your message was not saved.</p>
<!--

In action

With the new logic and templates in place, let's try updating our own status. We now have a form to allow us to update our status as shown in the following screenshot:

After submitting the form, we have a new status in our updates stream, and a confirmation message is displayed as shown in the following screenshot:

Summary

In this article, we have taken extended statuses on our users' profiles to support public messages between users. These public messages can use the comments system we have in place to form public conversations.

In the next article we will learn how to allow users to post private messages to each other.


Further resources on this subject:


Books to Consider

Object-Oriented Programming with PHP5
$ 14.40
AJAX and PHP: Building Modern Web Applications 2nd Edition
$ 23.99
comments powered by Disqus
X

An Introduction to 3D Printing

Explore the future of manufacturing and design  - read our guide to 3d printing for free