“What’s SnailLife”, you say? Well I’m glad you asked! My snail simulation has gone through a couple of names…and even though I was never 100% happy with Gastropoda it was the best I could come up with - a name that was unique and didn’t allow the project to sound too “gamey” (because it’s not a game). All of the cooler names I could come up with weren’t suitable for various reasons (like domain name availability and such).

But recently I found out about the .life TLD! And I decided that nowadays we have such a varied domain name landscape that .com isn’t as important as it used to be, and definitely not for an obscure hobby project. So Gastropoda is now SnailLife! On to the messaging:

Messaging

I noticed when working on the simulation that it was tough to figure out who died and why when snails disappeared from a jar.

(Sidenote…I just realized…in real life a snail wouldn’t just disappear from a jar if it died. It would sit there and start decomposing until someone put it away. Maybe this should be the case with SnailLife, too).

Anyway, I wanted something to notify me immediately when something important happens, like a snail is born or dies. So I made a rudimentary messaging system to receive notifications from the simulation, which should be able to be pretty easily expanded into a user-to-user messaging system.

First I made a user_messages table with the following columns:

  • messageID
  • recipientID
  • senderID
  • subject
  • content
  • isRead
  • created_at
  • updated_at

Then I made a UserMessage model that looks like this for now:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;

class UserMessage extends Model {

    public static $rules = array(
        'recipientID'     => 'integer',
        'senderID'   => 'integer',
        'subject'    => 'alpha_num_spaces',
        'content'    => 'alpha_num_spaces',
        'isRead'     => 'boolean'
    );

    protected $primaryKey = 'messageID';

    protected $fillable = ['recipientID', 'senderID', 'subject', 'content', 'isRead', 'created_at', 'updated_at'];

    public function recipient() {
        $this->hasOne('App\User', 'userID', 'recipientID');
    }

    public function sender() {
        $this->hasOne('App\User', 'userID', 'senderID');
    }

    public function getSenderUserNameAttribute() {
        $username = 'SnailLife';
        if (isset($this->sender)) {
            $username = $this->sender->username;
        }
        return $username;
    }

    public function updateMessage($propertiesToUpdate) {
        $this->update($propertiesToUpdate);
        return true;
    }
}

{:lang=“php”}

When a snail is killed or born we create a new message for the user. For example:

if ($this->isEgg) {
    $notification = [
        'recipientID' => $this->ownerID,
        'subject'     => 'An egg has died!',
        'content'     => 'Egg ID ' . $this->snailID . ' has died. Cause of death: ' . $cod
    ];
}
else {
    $notification = [
        'recipientID' => $this->ownerID,
        'subject'     => 'A snail (' . $this->snailID . ') has died!',
        'content'     => 'SnailID ID ' . $this->snailID . ' has died. Cause of death: ' . $cod
    ];
}
$notification = new UserMessage($notification);
$notification->save();

{:lang=“php”}

(An egg is really just an instance of a snail, just one without a birthDate, so when an egg or snail dies it’s handled in the same model).

Then there’s the view. When logged in the user gets a notification of unread messages in the header:

<p>
    @if (count(Auth::user()->unreadMessages) > 0)
        <a href="/account/messages"><img src="{!! testurl::asset('assets/img/graphics/icons/envelope.png') !!}" alt="You have unread messages"></a> - You've got mail!
    @endif
</p>

{:lang=“html”}

Oh, we get unread messages in the User model using an Eloquent hasMany relationship:

public function unreadMessages() {
    return $this->hasMany('App\UserMessage', 'recipientID', 'userID')->where('isRead', '=', 0);
}

{:lang=“php”}

Once they click through they get taken to their message page (ignore the double-death messages. That’s being fixed right now…):

User messages

There they can click to view the individual message, delete messages, mark them as read, etc.

Pretty simple and gets the job done for now.