TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
User Relations. where to place business logic
  • Hi all! at first a little example. I have 2 users and I need to get there relations(not logged user, stranger, friend and etc.) everywhere. I've placed business logic in Model_User:

    class Model_User extends ORM {

    //model functions

    ...

    //RELATIONS
    //
    // 0 - Not logged
    // 1 - Stranger
    // 2 - Owner
    // 3 - Incoming request
    // 4 - Outcoming request to user
    // 5 - Friend
    
    public function relations(){
                $suspect = Auth::instance()->get_user();
    
        //here is checking $suspect and setting $relations
    
        return $relations;
    }
    

    }

    in controller I get relations and use where I need it(for example checking permissions...I'm not sure about it too..Permissions is my next question =) ).

    What do u think? Is it good solution? I think about adding class "Relations" and use it like this: Relations::factory('object_name')->get();

  • Is 'relations' the right term? To me, a relation suggests that it's a User -> {Another_Model} relationship? Especially with something like 'Friend'?

    I don't fully understand the issue, but I can say that if I was going to check a relationship between 2 models, I would have a separate class (edit: Or a static function in the model), as you have said, and I'd have it work like this:

    NOTE: I haven't used ORM in AGES, and I can't remember how it all works, but I've had a quick go.

    Database Table (User_Relationships): http://i.imgur.com/mCqwxWj.png (The idea being that user_id is the person who has SENT the friend request (therefore, accepted the friendship by sending the request) and friend_id is the person who needs to accept it.

    Not production code (likely to be errors)

    <?php defined('SYSPATH') or die('No direct script access.');
    
    class Model_User_Relationship extends ORM {
    
        const NOT_LOGGED       = 0;
        const STRANGER         = 1;
        const OWNER            = 2;
        const INCOMING_REQUEST = 3;
        const OUTGOING_REQUEST = 4;
        const FRIEND           = 5;
    
        public static function check(Model_User $user_1, Model_User $user_2)
        {
            $relationship = ORM::factory('user_relationship');
    
            // User 1 is friends with User 2?
            $relationship->where_open()->where('user_id', '=', $user_1->pk())->and_where('friend_id', '=', $user_2->pk())->where_close();
    
            // User 2 is friends with User 1?
            $relationship->or_where_open()->where('user_id', '=', $user_2->pk())->and_where('friend_id', '=', $user_1->pk())->or_where_close();
    
            $friendship = $relationship->find();
    
            // Check to see if friendship is found?
            if ($friendship)
            {
                return $friendship;
            }
    
            // Return false (representing that relationship doesn't exist?)
            return FALSE;
        }
    
        public function is_friend()
        {
            if ($this->type == Model_User_Relationship::FRIEND)
            {
                return TRUE;
            }
    
            return FALSE;
        }
    }
    

    and then you'd call it like this:

    $user_1 = ORM::factory('user', 1);
    $user_2 = ORM::factory('user', 2);
    
    $relationship = Model_User_Relationship::check($user_1, $user_2);
    
    if ($relationship->is_friend())
    {
    // Display form to write on their wall or w/e?
    }
    

    I haven't tested any of this, so there's probably tons of bugs, but I hope it may help in some way?

  • good...the second example I have a photo and 3 types of authors(user, community, page). And I need to:

    1. Check relations with post author
    2. Check permissions using relations
    3. Get array $permissions.

    where should I do that? How I see a solution

    Controller:

    class Controller_Photo_Photo extends Controller_Photo_Album { public $owner_type; public $owner_id; public $owner; public $permissions;

       //class code
    
    private function permissions(){
    
        $permissions = array('edit' => FALSE, 'watch' => TRUE);
    
        switch($this->owner_type){ //owner_type, owner_id and owner are set in method 'before'
    
            //User
            case "0":
                //check relations and rewrite $permissions default array
                }
                break;
            //Community
            case "1":
                //check relations and rewrite $permissions default array
                break;
            //Page
            case "3":
                //check relations and rewrite $permissions default array
                break;
        }
    
        return $permissions;
    

    }

    Or I should use factory Permissions and set there object and id like this: Permissions::factory('photo', 1)->get();

  • I personally wouldn't do it that way.

    I assume you have a method on your Photo Controller (such as action_view) and it passes through a $this->request->param('id') ? And then you load the photo by id?

    In my opinion, the permissions should be stored in the model. So I'd implement it like this:

    <?php defined('SYSPATH') or die('No direct script access.');
    
    class Controller_Photo_Photo extends Controller_Photo_Album {
    
        //public $owner_type; public $owner_id; public $owner; public $permissions;
    
        public function action_view()
        {
            $photo_id = $this->request->param('id');
    
            $photo = ORM::factory('photo', $photo_id);
    
            $user = Auth::instance()->get_user();
    
            // Load photo view
            $view = View::factory('photo/album/photo');
    
            // Create a get_permissions() method on the photo model, and then work out if the user is able to edit it.
            // Maybe you'd pass the user's role into this? I'm not sure how you've structured it.
            $view->set('permissions', $photo->get_permissions($user));
    
            $this->response->body($view);
        }
    
        public function action_save()
        {
            if ($this->request->method() === POST)
            {
                $photo_id = $this->request->param('id');
    
                $photo = ORM::factory('photo', $photo_id);
    
                $user = Auth::instance()->get_user();
    
                // Attempt to save it as user
                // This function could then check if $user has access to do it, rather than checking the permissions in the controller
                $photo->save_as_user($user);
            }
        }
    
    }
    

    Then the save_as_user() method would check the permissions of the user again.

    This feels really foreign to me because I've been separating the persistence from the models for ages now. To me, it makes more sense to have something like Photo::save($photo_model, $user_model), but oh well. One thing I am confident on is that you should definitely have a 'higher level' than the controller to check if the user has permission to edit the photo.

  • I set $permissions in parent controller and then check it in children. For example: if $permissions['edit'] in parent class Album is TRUE then I don't check it in controller Photo, because if I can edit album I can edit photos there. But if I need extra checking for photo I can do that in Photo class and rewrite $permissions['edit'].

  • @Jack Ellis your version have problem with pagination, need add access terms in find query

  • @WinterSilence My code was only loading single models :P

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion