Please upgrade here. These earlier versions are no longer being updated and have security issues.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Confused with database and models

AviramAviram
edited December 2013 in Vanilla 2.0 - 2.8

Hello, sorry for posting it here but I'm not able to post in developer so I hope someone moves it if he can
I'm creating my own plugin for my forums and I have few questions regarding using the database.
I want to get a column from all comments in a specific discussion id
I almsot figured it out but I'm not sure yet. When I use $CommentsModel->Get(DiscussionId) I get a dataset, but do I need to first use ->FirstRow or I can just loop from the start with NextRow? Also can I access the column by "NextRow->ColumnsName" to retrieve value?
Here's how I'm planning on doing it but I'm not sure if it's valid or if there's any better way:


$Discussion = GetValue('Discussion', $Sender->EventArguments);
$sum = 0;
$CommentsModel = new CommentModel();
$CommentsModel->Get($Discussion);
while ($CommentsModel->NextRow)
$sum += $CommentsModel->Karma;

Thanks in advance.

«13

Comments

  • R_JR_J Ex-Fanboy Munich Admin
    edited December 2013
    $CommentModel = new CommentModel();
    $Comments = $CommentModel->Get($DiscussionID)
    foreach ($Comments as $Comment) {
       $sum += $Comment->Karma;
    }
    
  • R_JR_J Ex-Fanboy Munich Admin

    You should try to copy the names of common used variables. Models are always called the same as the classes are named. So it is not "Commentsmodel" but "CommentModel".
    If you use a function that requires the "DiscussionID", try to call it with a parameter called "DiscussionID". "Discussion" is the name for a discussion object.
    For the same reason "CommentModel->Get()" returns "Comments" and you loop through that objects and working on single objects called "Comment".

    If you follow that conventions it will be easier for others to read what you write and, even more important, you can copy someone elses code more easily ;)

  • AviramAviram
    edited December 2013

    Thanks.
    For some reason my plugin causes page to be blank, isn't there any error log file I can use to find out why?

    This is my code BTW:
    http://pastebin.com/bq3HK9iE
    I used voting plugin as a skeleton

  • Comments don't have Karma. What are you trying to do?

    grep is your friend.

  • R_JR_J Ex-Fanboy Munich Admin

    This could not work: $Comments = $CommentModel->Get($Discussion);
    You have to pass in a DiscussionID, not the object itself. $Comments = $CommentModel->Get($Discussion->DiscussionID);

    By the way: you are hooking the DiscussionController, so the parameter "$Sender" is already the Discussion object you were looking for. It took me very long to understand "$Sender"...
    $Comments = $CommentModel->Get($Sender->DiscussionID);

  • Ok I see you are creating you own meta. However what you are trying to do is really inefficient.

    What you are basically saying is every discussion in the the discussion list I will query its comments, and add up the comment count for that one discussion. But typically there are 30-50 discussion displayed on a page an any one time. So that is a lot of unnecessary queries.

    This is not not how comment counts are done, they are denormalized. You need the to update the sum when incremented, for ease or retrieval. So you could store the denormalised count with the discussions. You will need to track any event that would update karma so you can update the related count.

    You will need to debug you plugin anyway, However I'd work more on the design a bit more.

    grep is your friend.

  • Thanks for the notes guys!

    @x00 Yeah I had that idea in mind that maybe I need to go that approach.

    Maybe I should make my own event and fire it each time a karma is changed? (So it'll update thread's karma).

    @R_J Thanks for the fixes!

  • hgtonighthgtonight ∞ · New Moderator

    @R_J said:
    By the way: you are hooking the DiscussionController, so the parameter "$Sender" is already the Discussion object you were looking for. It took me very long to understand "$Sender"...
    $Comments = $CommentModel->Get($Sender->DiscussionID);

    $Sender is a generic term that is used for the sending object. I sometimes find it helpful to name the object the type it is. In this case, $DiscussionController. Once you understand this, you can do away with some difficult debugging and find what you are looking for in the calling class.

    What @x00 is saying is you should hook into the comment model after a meta change and increment/decrement the karma count in the discussion field. This way you don't recalculate it every time the discussion is requested.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • R_JR_J Ex-Fanboy Munich Admin

    @hgtonight said:
    $Sender is a generic term that is used for the sending object. I sometimes find it helpful to name the object the type it is.

    I think that is the most useful hint I've ever read! "$Sender" really gave me the creeps. I've almost always dumped it to the screen at the beginning and I'm still doing that a lot. Simply not calling it Sender but someController is simple, but helps a ton for me to understand what's going on when I'm looking at source code.

    Bye, bye $Sender!

  • AviramAviram
    edited December 2013


    Yeah that's what I thought.

    I have another problem now, not related to my plugin. Every plugin I try to activate using the Dashboard gives me a blank page, every plugin! I've enabled debug but still blank page..

  • Well the problem mentioned above is fixed.

    Now I have another concern - How do I create my own events handle them? I tried the documents but they didn't have answers.

  • R_JR_J Ex-Fanboy Munich Admin

    Could you describe what you try to achieve? Normally you don't create events by yourself but hook the events of the framework. If you want to add an event to a plugin and hook that event from another plugin you will have to use FireEvent. Just search the source of Vanilla to find numerous examples.

  • I want to create a plugin that's similar to KarmaBank but without the karma as a currency.

    People can receive karma for comments and discussions and they level up as they receive karma.

    Each user has limit on how much karma (based on his level) he can send everyday and everyday the limit is reset.

    Now that I think about it I don't need to fire events as my plugin controls the karma receive so I can just call the function to calculate balances etc.

    In order to track all transactions and make sure that each karma is related to a discussion id and post id I guess I'd have to hook to Post delete ,discussion delete etc.

    So my current question is if I hook Comment delete and discussion delete, will it trigger the comment delete twice? As when I delete a discussion I guess it deletes comments also?

    Sorry if I confused you, hehe.

  • R_JR_J Ex-Fanboy Munich Admin

    Look into function Delete of the discussioncontroller (/applications/vanilla/controller/class.discussioncontroller.php). There you'll see that no comment function is called, only DiscussionModel->Delete. When you now look at the delete function of the discussionmodel, you'll see that there is no call to comment model.
    You might want to hook "DeleteDiscussion".

  • @R_J
    Can't find in Doxygen DeleteDiscussion.. :\

  • R_JR_J Ex-Fanboy Munich Admin

    DeleteDiscussion is not a function, it is an event. Search in the wiki for that. You can also look at the source for "FireEvent". If you look at the discussion model, function delete, you'll find that piece of code:

    1385 $this->EventArguments['DiscussionID'] = $DiscussionID;
    1386 $this->FireEvent('DeleteDiscussion');

    Because it is in the DiscussionModel, you would have to create a public function DiscussionModel_DeleteDiscussion_Handler($Sender) {} in your plugin and that will be called when the above lines are executed.
    But instead of calling the parameter plain and simple $Sender, you might consider that:
    public function DiscussionModel_DeleteDiscussion_Handler ($DiscussionController) {}

    $DiscussionController->DiscussionID will be the ID of the discussion that is deleted right now and you can perform actions on the discussion and/or its comments in your function

  • hgtonighthgtonight ∞ · New Moderator

    @R_J said:
    But instead of calling the parameter plain and simple $Sender, you might consider that:
    public function DiscussionModel_DeleteDiscussion_Handler ($DiscussionController) {}

    The sender in this case would be a DiscussionModel, not a DiscussionController.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • AviramAviram
    edited December 2013

    Great! Thanks! :D

    I didn't know a wiki existed btw.

  • R_JR_J Ex-Fanboy Munich Admin

    @hgtonight said:
    The sender in this case would be a DiscussionModel, not a DiscussionController.

    Leaving $Sender won't be easy... :\

  • hgtonighthgtonight ∞ · New Moderator

    @Aviram said:
    I didn't know a wiki existed btw.

    :(

    Check out my signature for more information.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

Sign In or Register to comment.