1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Help Me Understand This Code

Discussion in 'XenForo Development Discussions' started by TheBigK, Nov 10, 2014.

  1. TheBigK

    TheBigK Well-Known Member

    I'm currently referring to this tutorial: https://xenforo.com/community/resou...rofile-page-using-hooks.335/update?update=487

    class newProfileTabs_Extend_ControllerPublic_Member extends XFCP_newProfileTabs_Extend_ControllerPublic_Member
    //See? actionNameOfOurAction
    public function actionUsersLike()
    //Lets get the userID
    $userId $this->_input->filterSingle('user_id'XenForo_Input::UINT);
    $user $this->getHelper('UserProfile')->assertUserProfileValidAndViewable($userId);
    //Lets get all the likes that this user gave to anothers
    //We are using our function here and our model! getAllGivenLikesByUser()
    $users_likes $this->getModelFromCache('newProfileTabs_Model_newProfileModel')->getAllGivenLikesByUser($userId'10');
    //Returning all the values to our template newProfileTab_ourTab_content
    //With the variable $users_likes, and the variable $user.
    return $this->responseView(
    'user' => $user'users_likes' => $users_likes)
    I could follow the entire tutorial until I stumbled upon this code snippet from the tutorial. My questions are very basic:-

    1. How would a new programmer know that I need to use functions / arrays such as -

    $userId = $this->_input->filterSingle('user_id', XenForo_Input::UINT);$user = $this->getHelper('UserProfile')->assertUserProfileValidAndViewable($userId); 

    Is there any pattern I need to know? I found out that the code snippet has been taken from /library/XenForo/ControllerPublic/Member.php --->>actionFollowers().

    2. getModelFromCache : Why has this been used? And how would I know that I need to use getModelFromCache and not something else?
  2. rainmotorsports

    rainmotorsports Well-Known Member

    For number 1 you always want to make sure your input is valid to prevent unecessary errors. As well as increasing security. If the input is going to be passed to model code that is going to be performing a database lookup you want to make sure you sanitize it. The method is is of course framework specific but any experienced developer know's they want to do it somehow.

    After that they are checking to make sure the input is actually an existing profile id. It is to prevent errors related to deleted members. The same thing is done with a thread before code is executed to display the thread. If you are passing an id to be used to display information about a user (or in the other example I have thread) you want to make sure it exists. Xenforo provides methods for this, I found this out looking at the thread display code. But on any platform even if the function doesn't exist you would query the database to see if the id is valid. Then display an error or continue on about your work.

    I don't know the answer to number 2 myself yet. One of those things I need answered. But my assumption is if there is a cache in play we have 2 options. We can bypass the cache with a direct call to the database or we can call a method that will hit the cache if available, direct if not.
    TheBigK likes this.
  3. TheBigK

    TheBigK Well-Known Member

    Thanks, @rainmotorsports . Do you have any suggestions on how a new programmer should approach the same code? For example, I'd have no clue that XF offers functions for filtering the inputs. I'd also like to know what's the best way of discovering all the methods already available to achieve something within the existing code.

    Would really appreciate if someone can help understand the 'getModelFromCache' thingy. It's seems to appear in the code out of nowhere.
  4. rainmotorsports

    rainmotorsports Well-Known Member

    I should mention I'm sick and pretty drugged up at the moment. So I forgot to mention that the area of concentration for input filtering is most often when the input is external. From a user. So for example if the ID is part of a URL or being posted from a form you ALWAYS want to make sure to filter it as valid, expected content. Whereas if the data is coming from a core function let's say we are responding to a user upgrade event, don't have to worry as much about it.

    The addons by ragtek and dbtech for who is viewing and who read a thread errored out if the thread was a redirect because they didn't check if the thread id existed. But my initial solution was to use the xenforo function that asserts if a thread is valid and viewable. You have to be careful because this adds an extra query and it wasn't needed because in that scenario all I had to do was check if it was an instance of a thread view. Something I learned by looking at another plugin. So when possible look for queryless methods of what you're doing.

    The best way is annoyingly stated as look at the xenforo source. I will also say look at plugins that do similar things. Lucky for me its my learning style. Documentation is a little thin. But for example I wanted to make a birthday bot. So I looked at the source code to Xenforos RSS feeder that posts threads and the code that generates today's birthdays on the members page.
    TheBigK likes this.
  5. Xon

    Xon Well-Known Member

    'getModelFromCache' is an important performance optimization in the XenForo codebase to allow the addon system to work nicely.

    Looking up models requires XenForo to resolve the class name, and then inject and build all the addons. Using the built model, is obviously much cheaper than doing this all the time.
    Last edited: Nov 10, 2014
  6. TheBigK

    TheBigK Well-Known Member

    Okay, I spent some more time understanding this and have a new question :-

    $userId $this->_input->filterSingle('user_id'XenForo_Input::UINT);
    This one filters the input aka $userID before it's fed to -> assertUserProfileValidAndViewable.

    What if the userId isn't valid? What would get stored in $userID then?

     $user $this->getHelper('UserProfile')->assertUserProfileValidAndViewable($userId); 
    ...and if the userID isn't valid, what will be the outcome of this specific code?
  7. Mr. Goodie2Shoes

    Mr. Goodie2Shoes Well-Known Member

    If the input 'user_id' is not a valid unsigned integer (the filter XenForo_Input::UINT is being used here) 0 (zero) is returned.

    And if the userId that is being returned is in the database the details of the following user is returned, else a response error is thrown.
  8. TheBigK

    TheBigK Well-Known Member

    Thanks @Mr. Goodie2Shoes . But isn't that response error is being assigned to $user?

    PS: Yet to understand Helpers, so I must be missing out on something important.
  9. Mr. Goodie2Shoes

    Mr. Goodie2Shoes Well-Known Member

    nopes... because it is being 'thrown'... that way, the FrontController gets the error response directly without any further execution of the controller helper or the controller.
    TheBigK likes this.
  10. TheBigK

    TheBigK Well-Known Member

    I see. Gotta explore this further. Thanks!
  11. rainmotorsports

    rainmotorsports Well-Known Member

    Something else to add. If you know what a functions return is for invalid data you can wrap the rest of your code in an if statement. So let's say the filter statement returns a 0 for not valid. Instead of happily skipping along to the next line of code we mind as well skip on to throwing an error.

    The check to see if a user Id is valid after that generates a database query. Why bother when we already know its coming back as not. In the code your looking at you might not see it done that way because its not a big deal. But its something to keep in mind.
    TheBigK likes this.

Share This Page