DB structure for site events timeline written on Laravel - php

I'm building timeline, that will show all things that users does, ( events ).
Example events:
User has joined site ( registration )
User has added post
User created public event
User joined some random group.
User has added a comment into forum or group.
Problem is that i don't know how to structure database, that will keep all events and show them in timeline.
Visual example:
I'm using Laravel with eloquent. I thought on all actions i could raise events, and them listen to them and add all events to database events table.
At example, when user registers, event is raised, and data is put to database, then script gets all events from database and structures them by date.
But problem is that all events has different content, at example, when user registers, I need to store only registered user foreign key that points to users table, but when user creates a post, I need to store his foreign key, and foreign key that points to created post.
So question is how, to structure database, that will keep all events for displaying them on timeline, assuming that event contents for each action can be different?

I would use polymorphic relationships:
http://laravel.com/docs/4.2/eloquent#polymorphic-relations
So your events table would look like this
Events
id
user_id
eventable_id
eventable_type
event_class
You would have a user relationship, and an eventable polymorphic relationship, which could point to a post, or back to a user (for registration).
I also added an event_class field, which could store the name of a class to handle how the event displays (you could have a class to handle New Post events, for example). I might even omit that and resolve the handler class somehow from the eventable_type column.
Depending on how you want it to work, you could also store the title and body in the database table, but I'd prefer to use a class to generate that on the fly.

Related

Database set up for multi-way relationships and form data collecting

I've posted a few questions on here and have gotten very great help and support. I'm still fairly new to programming and I'm putting together what I thought would be a simple website for the company I work at. I apologize in advance for my lengthy post/question, I just want to be thorough and clear in what I'm asking. My question is more of needing some help getting pointed in the right direction of how to get started and some best practices to be aware of. What I'm working on right now is to create a system where a user can submit a questionnaire/online form to inquire about a specific product (in this case it's a hard money loan product). The way I am planning on setting it up is to have a database with multiple tables (users, user_info, loan_app, property) and connect these together by referencing each other. I've read about table joins and I understand them conceptually but I have no idea how to implement in practice. I've had a hard time finding actual examples.
Specifically, this is what I am doing and how I am thinking it should work (correct me if I'm wrong or if there's a better way to do it):
1- the user (aka the borrower) signs in to the website. The user log in system references the user table where things like first name, last name, user name, password and user ID are stored. I have included an "active" column in this table so that when a user logs in the condition for them to get into the website is that the username and password match AND the user is activated. This way we can control on the back end certain user accounts access. I have this part working.
2- when the user registers, they only fill out the information that creates a new record in the "user" table. I have created a second table called "user_info" that will contain other data like home address, phone number email etc. But I need to be able to associate the correct record with right user. This is my first issue to wrap my head around. My thinking behind doing this instead of simply putting all this information in the user table is that for one, I might keep adding to that table and make it very big, and two for security reasons, I would like to keep the information separate. I don't know if this thought process has any merit to it though. Again, that's why I'm posting this here.
3- The user, once logged in, clicks on a button on their home screen/dashboard that will take them to the loan "pre-approval application" form, which is the questionnaire. On this form their basic information will be echoed/posted from the "user_info" table to pre-populate certain fields like first name, last name, email, phone number, address etc. So going back to #2 making sure I can associate the user with the correct record in the "user_info" table is critical. THEN, there are additional fields that the user has to fill out in order to submit the application/questionnaire. These form fields will create a new record in the "loan_app" table. This table will have a loanid column that is the primary key for that table, and an auto generated/randomized 6 or 7 digit loan number (loannum). The loanid will be a hidden value but the loan number will be like a reference number that is associated with the loan for the life of it and used for later accounting and recording purposes internally, whether or not it actually becomes a loan. The loanid, I'm assuming here, is the Foreign key in the "user" table and the userid is the Foreign key in the "loan_app" and "user_info" tables correct? If so, how do I incorporate being able to simultaneously associate all these records when the loan application/questionnaire is submitted? My thought would be write individual php scripts that does each of these things separately then have a "master" php that includes all of those individual ones that is placed as the form action associated with the submit button on the form.
Thanks for taking the time to read through this. I'd really appreciate any advice or reference material that I can read up on to learn more about this stuff. My job has a pretty crazy schedule and I travel a lot so I don't have the time to take actual classes to learn this stuff formally. I'm pretty much doing this as I go.
Also, I'm using MAMP with mysql, not sure if that helps any or not...
The user table's primary key userid can be the primary key of the user_info table as well, since each user will have only one user_info record, right? A foreign key constraint is good to ensure only valid userids get recorded in user_info.
The loan_app table can contain a denormalized relationship from loanid to userid so that each loan application is associated with a user. Again, use an FK constraint for integrity.
Don't include loanid in the user table - that would mean each user has a relationship to a single loan application. You already have the one-to-many relationship you need in the loan_app table.

Cakephp return true on findAll if record exists in another model

I'm currently building a REST api for events with CakePHP. Right now I have an events table and an event_attendees table with columns event_id and user_id. Currently when I send back a list of all the events in response to a user request, each event has fields for its details and, through model linking with the users model, a list of all the users attending it. However, I want each event to also have the field "attending" which indicates whether the CURRENT user is attending the event (this can obviously be figured out by looking at the event_attendees table). So whenever I call findAll() on the Event model, I want each event to have the "attending" field as well.
Any help would be greatly appreciated.
If you want to stay away from globals, your best bet is to retrieve a list of events and a list of events for the current user. Two loops and you'll have your list of events with those the user is attending highlighted.
Example:
# In the user model
class User extends AppModel {
var $hasAndBelongsToMany = array('Event' => array('class' => 'Event'));
}
# In the controller
$allEvents = $this->Events->find('all');
$userAndEvents = $this->User->findForId($userId);
This assumes that you have a many-to-many relationship between your user and your event. In other words, one user can attend many events and an event can be attended by many users.

User's custom profile fields

I am currently working on a system that would allow users to add additional custom fields for the contacts that they add.
I wondered what is the best and most efficient approach to add such ability?
Right now what I was thinking was to have 1 table per users (with foreign keys to a "main" contacts table) and then adding a column for each custom fields that the user adds (since I don't expect to have more then 100-200 users per database shards [sharding is easy since every users never see each-other's content in this system]), although I am not 100% sure that this would be the right solution for such problems.
Maybe you could try to have one separated table to store a reference to the user, plus the field name and value, this way you will be able to have lots of custom fields.
If you go with Boyce-Codd, you separate the information and store them into a table.
Means one table for all users with a foreign key.
One table per user would lead to hundreds or more tables with possible repeated information.
You need to have one table named USERS that stores the id of a user and fixed info you might want. Then, you could have a CONTACT table, that stores the type of contact user might create, and one matching table USER_CONTACT that matches the user unique id with the id of the contact that was created.
With this, you could have advanced data mining on all the information stored, like nowing how many contacts each user created, who created more, etc...

Correct way to change user table relationship?

I am working on an event system that has two tables, EVENTS and EVENT_CREATORS. I have been linking events to creators by placing creator id in the events table as I thought I would only ever have one event creator.
I now need the ability for more than one creator to edit an event. Should I add simply add additional fields to EVENTS table, i.e ec_id, ec_id_2, ec_id_3, etc. Or does it make more sense to add a cross reference table to the database and a separate table for additional creators?
This is those cases, where it would be wise to use a cross reference table. I will explain it step by step. First
Create a new table. Call it "event_reference"
Give the following FIelds: Id, Ref_Id, Creator_ID.
I will omit the need of the EventId, because we are creating a table which is a reference to the event, so event's table will hold the Ref_Id to keep in track of all the references.
Next, Modify the events table and store Ref_ID instead of Creator
In such way, you can fetch all the creators of an events in the normalized way.
You should have 3 tables:
Event (with an ID field)
Creator (with an ID field)
EventCreator (2 fields: eventID and creatorID)
This should pretty much cover every possible relationship between events and creators. You can limit the relationships by creating indexes on the EventCreator table.
The simple say is to just add a cross reference table. This way you don't have to worry about how many creators someone will need in the future.
So, have a table like:
xref_Events_Creators
EventId
CreatorId

RestFul webService and Database Transactions

Lately i'm struggling with Rest architecture :p and i usualy raise a lot of problems with it.
Let's say that i have a resource named "user", and that user can have a list of cars.
Im trying to insert that user and his list of cars in the database at once. I know i have to do this with the POST HTTP verb. But how would i achieve this? Should i send only one URL with the user identification and the list of cars somehow encoded or should i use the "user" resource to insert the user, and then for each car, call a POST URL in a resource named "car"?
The second approach has a problem. This process must be implemented with a Database Transaction. If something goes wrong when inserting a car, i want the user to not be regitered in the database.
I know restFul architectures must be stateless, so how can i implement such a transaction using the database functionalities? I know i can implement myself some kind of transaction, but i wanted it to be more automaticaly.
Thanks in advance.
There are a number of ways you can do it depending on the languages you're using in the front and backend and how you plan to send this data. I would solve the problem like so, assuming you're using PHP and MySQL:
Get the data ready, so something like user=123&cars[]=1&cars[]=2&cars[]=3 (I'm using the var cars[] as this will send an array to PHP and you can achieve this by naming your input fields as cars[])
Post this to your backend
Your backend will then process the user and add them to the database if they're not there.
I would then have a table that illustrated the relationship between the user and the cars, something along the lines of:
CREATE TABLE box_to_category (
user_id int(11) NOT NULL,
car_id int(11) NOT NULL
);
In this table I'd clear all cars associated with that user and then add the new cars as POSTed to the backend (the user_id will be associated to a user in a users table and the car_id will be associated to a car in the cars table)
It's a simple set up.

Categories