Saving to a model related to another instance of this model in CakePHP 1.3 - models

I'm relatively new to cake, and once again I'm having to work around how it does things to get what I want. I'd really love to find out the "correct" way of doing what I need.
I'm building a "performance" system, that's used each month to review how someone did against their goals from last month.
This month's review sets new goals, and also records the result against last month.
I have a Review model, which hasMany Goals.
In the edit view for this months Review I display some data from last month's Review & some fields from the Goals related to last month's Review.
I need to save the result for each of last months Goals, as well as to be able to set this months Goals too - so I'm saving data to Goals related to the current Review, as well as another one.
When I try to save the "unrelated" Goals, CakePHP forces the review_id to be the id of the current one - I even tried looping in the Review::afterSave callback and checking each review_id - although I can send the right review_id value to Goal->save, the database still gets updated with the current Review id, rather than the one I set.
Can anyone tell me the "cake" way to save to models related to another instance of the current model? Is this even possible?

Ok, this may not be the most efficient way of doing it - but I'm on a deadline.
So, instead of retrieving last month's Review, I created another "hasMany" relationship, using a finderQuery that has a subselect to find the ID of the last months query, and use that to select the Goals with that review_id. It uses {$__cakeID__$} to find the ID of the current Review as explained here:
http://book.cakephp.org/view/1039/Associations-Linking-Models-Together#hasMany-1043
Because everything's related to each other in a way that Cake understands, things just update automatically on saveAll.
It means I have a ridiculous subselect query relating the last months Goals to this months Review, but it works.
One day I'll figure out how to optimise it so it doesn't make my database cry....

Related

GraphQL query for only unseen content - Schema Advice

I'm building a graphql schema through AWS AppSync and have a question regarding schema structure. My app will show users new posts and have them either join or pass on them. I'm trying to build in a way that I will only show users new posts and not repeat or at least not repeat for a certain amount of time. It's similar to swiping on tinder, they don't show you somebody again if you've already swiped on them. Does anybody have any ideas how to structure this in my schema. Do I need to store references to all of the seen posts in the user model or should I store each swipe as its own model and how should I structure the querying? I'd appreciate any advice on this.
Thanks!
Assuming a post has a creation time, you could keep track of the last (max created time) post they've seen, then display anything after that.
But think about what happens if they've been off the app for 5 minutes, or 5 days, or 5 weeks... depending on the volume of posts you anticipate they could quickly get behind and have to wade through too many older posts.
One thought would be to show the next oldest post, based derived from the creation time of the most recent post they viewed. Unless N number of posts were created since the last time they were online (a threshold you'd have to decide). Then start with displaying the N - Xth post (where X is 5, or 500, again depending on volume) until they're all caught up.
There are lots of ways you could program it, it all depends on your use case, you may want to take "popular" posts into account for example, those might be weighted above/before the other posts in their backlog.
Hope this helped.

Database schema for rewarding users for their activities

I would like to provide users with points when they do a certain thing. For example:
adding article
adding question
answering question
liking article
etc.
Some of them can have conditions like there are only points for first 3 articles a day, but I think I will handle this directly in my code base.
The problem is what would be a good database design to handle this? I think of 3 tables.
user_activities - in this table I will store event types (I use
laravel so it would probably be the event class name) and points for
specific event.
activity_user - pivot table between user_activities and users.
and of course users table
It is very simple so I am worrying that there are some conditions I haven't thought of, and it would come and bite me in the future.
I think you'll need a forth table that is simply "activities" that is simply a list of the kinds of activities to track. This will have an ID column, and then in your user_activities table include an 'activity_id' to link to that. You'll no doubt have unique information for each kind, for example an activities table may have columns like
ID : unique ID per laravel
ACTIVITY_CODE : short code to use as part of application/business logic
ACTIVITY_NAME : longer name that is for display name like "answered a question"
EVENT : what does the user have to do to trigger the activity award
POINT_VALUE: how many points for this event
etc
If you think that points may change in the future (eg. to encourage certain user activities) then you'll want to track the actual point awarded at the time in the user activities table, or some way to track what the points were at any one time.
While I'm suggesting fourth table, what you really need is more carefully worded list of features to be implemented before doing any design work. My example of allowing for points awarded to change over time is such a feature that you don't mention but you'll need to design for if this feature is needed.
Well I have found this https://laracasts.com/lessons/build-an-activity-feed-in-laravel as very good solution. Hope it helps someone :)

How to sort posts to keep new top rated posts at top

Lets say we have a website with posts.
The information we can get is:
post_time (from site launch)(doesn't change)
post_rating (changes over time)
number_of_comments (changes over time)
what would be a good formula in order for the website to keep fresh and good posts at the top without seeing the same post at the top again.
I figured I should give "weights" to each of the fields above, where
post_time will have the heaviest weight.
What kind of sorting does 9gag use for instance?
the difference between post_time can vary between 1 second and minutes/hours
edit:
Clarification:
I have a database where I keep all of this information, what I need
is a formula that will keep the posts page up to date and a user that logs now and in 20 minutes will see different posts.
Ok so the simplest way I found is as follows:
Add an additional DATE field to the Posts SQL table that is called top_date
Select from the posts table all highest ratings that has top_date NULL
update top_date of a wanted post with current time stamp
now the posts page will use DESC by top_date.
also there can be a function that will be called every few minutes that will
gather the top rating (RATING ONLY) posts without top_date and randomly choose
one to be updated.
If i was unclear feel free to ask any question here or in private message.

MVC (codeigniter) design question

users want to see some reports from stored data in the db
for example:
all sales in a time interval (user submits a just a time interval),
all the sales in the selected city in a time interval (same with above but this time extra city select dropdown),
top selling 20 shops (another report , no form submission and different db tables involved ),
etc
My problem is
how can i accomplish these task without writing a separate model, controller and view for each report
or
each report has a method in a single controller and model and two views (one for form submission 1 for results).
i must tell my background is procedural programming and i am confused. everything seems like writing basic "switch case" in a really complicated way.
thank you.
This depends on how you structure your db. Although having lots of models might seem like overkill I would suggest that if you approach it in the right way you will find it makes your life easier. For example you could have a model that deals with sales. Within that model there could be a function to retrieve all sales by date or time. This function could have an optional parameter to allow you to filter by city. You might then have another function in the same model to retrieve the top 20.
From the controller you would have one function. This would be one big if statement based on whether or not the user had submitted the form. If not then display the form view (it is best to have separate views for specific things or at least fragments of views). If data has been submitted then simply test the data to find out which report is required, query the relevant method in your model and send the results to another results view.
This way, one controller, one model, 2 views ( or more if you're using a template kind of thing).
I deliberately haven't written the code for you, but I hope this points you in the right direction. Please comment if ive misunderstood the question or you need clarification.

How do I restrict a users access to an object?

Hi Sitepoint wizard people,
Say we have an admin application that has multiple users and various objects. What I'd like to do is control access within the object itself - that is, it will behave one way for one type of user, and another way for other users. For example...
Director Mike can override Reception user Sally's registration date. One would assume that Mike could set any date both in the past or in the future. Then we have Payroll user Steve who can also modify Sally's registration date, but only for dates in the past up until (for example) one year ago. To spice things up, then we have the HR Manager Mary who can also amend Sally's registration date, but only for dates from precisely 23rd June 2007 up until one month from now...
How can I program the access restrictions so that on the front end, the form control is restricted with a min and max date, and in the backend, the validator checks the entered date to make sure it falls between those dates? I'd obviously need to be able to tweak the min and max dates for each user type. Other objects might have different parameters - maximum amount on a discount field or days of the week for overtime, for example.
I've asked this question in different ways, but each time I get bogged down by the implementation. I'm currently developing it as a php/MySQL web-based application, but thoughts and comments from other platforms very welcome! This time I'm looking at first principles, so it doesn't matter what your background is, if you have any ideas, please let me know! What do you even call this type of access control...?
Depending of how you application is based, you could ask for credentials at the start of the application and depending on who is requiring access, you could load a different xml file containing different settings.
As for security issue, make sure that the different xml files can't be reached by the users.
Edit:
Since you are using MySQL you could do something like this.
Let's say you have a table of users that has those fields : UserId, UserName, RestrictionId.
And with a Restriction table that looks like : RestrictionId, FieldName, FieldCondition.
This way, in your php app, when a user is authenticated, you can go fetch the correct "Restrictions" on the field and apply them in your code. If it happens that you have multiple fields that require different rules then you can simply add them with the correct RestrictionId.
This DB design is far from perfect, I'm pretty sure you can do better
Since, you are already using MySql db. You can maintain the UserRole Master table details in DB itself. Load the user role data based on login, then you can easily validate the changes made by the user accordingly.

Resources