SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 30
  1. #1
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    MVC and URL-logic

    I have been reading this thread (showthread (.) php?p=4248494 as I still can post links) and it gave me some great insight on some new ways of looking at things. A lot of like-minded people sharing usefull information..

    I am currently in the middle of designing my own MVC and I am encountering some approach-dillema's as well. I have one page that is a members-profile page and has arguments that need controller actions (video, blog, etc)

    Let me share some (probable) urls:

    Code HTML4Strict:
    domainname/member/(view)/1/
    domainname/member/(view)/1/video/10
    domainname/member/(view)/1/blog/7

    I could leave (view) out as i use it as the default state.
    Now let's try these, which will work fine, but the URL doens't really represent what it does.

    Code HTML4Strict:
    domainname/member/edit/1/
    domainname/member/edit/1/video/10
    domainname/member/add/1/video/
    domainname/member/edit/1/blog/7

    - member/add/1/video,
    Adds a new video to member 1's, but it reads as if it might add 1 video

    I am trying not the use a routing array or something like that. I would like to have the methods somehow to all belong to the members_controller.

    I am considering to have a members_controller (view states only, public) and a account_controller (view, add, edit, delete states), but I can't figure it out quite. I want the way to set it up to be as transparent as possible. A sortof WYSIWIC - What You See Is What It Controls

  2. #2
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about swap these two parts?
    Code:
    domainname/member/1/add/video/
    domainname/member/1/view/video/

  3. #3
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A nice suggestion, one I have come across as well, but it would mean (in an MVC approach) that the method would be '1' and not 'add'.

    I might need to elaborate on my URL's. There will also be:

    Code HTML4Strict:
    domain.com/video/
    domain.com/video/(view)/trance/

    Videos that belong to members would be something like:
    (translates: members/memberID/video/videoID)

    Code HTML4Strict:
    domain.com/members/1/video/1

    It would make for beautiful, representing URL's to have something like:

    Code HTML4Strict:
    domain.com/view/video/trance
    domain.com/view/members/1/
    domain.com/edit/members/1/video/7

    The downside, I can't have a custom 404 per controller. On member/viewx_typo (where a likely typo might occur) it would be easy to have a fallback error to the member_controller, if defined, so people stay on the page they were on (if there wasn't a controller specific 404 defined, it would default to the global 404).

    So, my url is either in need of a section action, or I should reconsider routing. The way I need it to be able to work is as a normal controller->action as well as being able to display a module within a controller called page.
    Last edited by mr.mstyle; May 8, 2009 at 13:26.

  4. #4
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    it would mean (in an MVC approach) that the method would be '1' and not 'add'
    I believe that MVC is not about routing specifics ... I've never heard about one and only mandatory order of route elements. Controller can be freely succeeded by argument, not method. E.g. http://docs.kohanaphp.com/general/routing

  5. #5
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    You could name the options then the method could go anywhere. You would need a map to do this though. The option name would map to a index on the url. The index could be defined by exploding the url via /.

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    domain.com/members/1/video/1

    URL Options
    1. 1
    2. video
    3. 1


    Controller Options
    1. memeber
    2. method
    3. video


    Mapping
    1. memeber => 1
    2. method => video
    3. video => 1


    Then use a object to access the option values by their name.

    PHP Code:
    echo $path->getOption('method'); // video 
    That is how my system works in a nutshell. However, everything is stored in the database.

    controllers
    • id
    • name
    • class
    • file
    • access_level


    controller_options
    • id
    • controller_id
    • position
    • name
    • required


    Any controller_option named method is special. When the controller is initialized if a method option exists it attempts to call that method on the given controller. This makes it possible to place that option anywhere after the first option which is by default the controller abstracted name.

    View and models then work much the same way and are linked to a controller through a relation table.

    views
    • id
    • class
    • file


    models
    • id
    • class
    • file


    modelazations
    • id
    • controller_id
    • model_id


    viewazations
    • id
    • controller_id
    • view_id


    This ultimately eliminates the need for any needless string manipulation, directory hierarchies or naming conventions.

  7. #7
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    It's good practise to let URLs identify resources, not actions. The following violates this:
    Code:
    domain.com/view/video/trance
    domain.com/view/members/1/
    domain.com/edit/members/1/video/7
    For a basic CRUD, I would recommend that you try to lean as much up of AtomPub as possible:

    Code:
    GET    /collection     -> list entries
    POST   /collection     -> create new entry
    GET    /collection/$id -> show full entry
    PUT    /collection/$id -> update entry
    DELETE /collection/$id -> delete entry
    You can't use PUT/DELETE in a browser application, so you will need to mimic it. The de-facto standard is to have a hidden field with the name _method, that overrides the http-method.

    Code:
    <input name="_method" type="hidden" value="put" />
    This schema doesn't give you any way to display forms for editing/creating entries. You can extend the schema in different ways. Ruby of Rails has some "magic" urls that are used for this. Eg.:

    Code:
    GET    /collection/new      -> new  (input-form)
    GET    /collection/$id/edit -> edit (input-form)
    Or you use the filename extension:

    Code:
    GET    /collection.form     -> new  (input-form)
    GET    /collection/$id.form -> edit (input-form)
    I like this style.

    You could also let a query-string parameter determine which sub-view to display. So your schema becomes:

    Code:
    GET    /collection?new      -> new  (input-form)
    GET    /collection/$id?edit -> edit (input-form)
    See also: http://microformats.org/wiki/rest/urls

  8. #8
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @oddz I have been looking into Kahona earlier as a viable option, but the documentation was lacking. It's something more people are saying. Also, I think I had decided on trying to write my own MVC allready.

    Code:
    $config['article/([0-9]+)'] = 'news/show/$1';
    I looked at the routing and it might surely be an option if all else fails.

    @kyberfabrikken I had read about REST allready a while ago, which also sounded logical. I did a site a while back, which used XMLRPC. Also leaning on clear identifiers to do things (GET only btw.).
    I had seen a ROR video a while back and knew about the way they did adding and editing in ROR, but never had the use for it, so I never really dove into it.

    I'll have a look at the Atompub video. I'm sure it'll will give me new insights to think about.

  9. #9
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @kyberfabrikken I have watched the Atompub intro.

    The pros: It would make a framework more flexible and it would be API orientated and API ready.

    the cons: I would need to build it completetly around this model, which would bring in extra code, since it would need constructing/deconstructing the Atom-XML structure.

    I found another way to implement a controller -> module. I was reading the mojavi (by Sean Kerr) site and it uses 'slots' which define (inside a view) what needs to be loaded for a page.
    What I find interessting is that you can basically have any module (or collections of modules) on a page.

    http://www.mojavi.org/category/mojavi-project/

    The questions that arise. What is the consensus of this approach? Is the view acting as a controller? Is it true to the MVC architecture? I do like the flexibility.

  10. #10
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mr.mstyle View Post
    I would need to build it completetly around this model, which would bring in extra code, since it would need constructing/deconstructing the Atom-XML structure.
    Yes, AtomPub consists of two parts; A schema for URLs + a specific content-type (Actually, three document types). I'm not overly interested in the last part, but the URL schema I think is reusable in other contexts; Even if you serve up different content-types.

    Quote Originally Posted by mr.mstyle View Post
    The questions that arise. What is the consensus of this approach? Is the view acting as a controller? Is it true to the MVC architecture? I do like the flexibility.
    I wouldn't concern my self too much about being "true" MVC or not. It's a very loosely defined concept and as such there is no canonical definition that you can go by. Even if there was one, it wouldn't necessarily be the best. I'm inclined to say that if it makes sense to you, then go with it. Keep in mind though that the view/controller separation can be cut in many ways. In my opinion, there is often no need for keeping these separate, and then you end up with a lot of bureaucratic cruft for no reason.

  11. #11
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    Keep in mind though that the view/controller separation can be cut in many ways...
    I know, that's exactly my point. I am trying to find some kind of solution , structure or even logic which can handle most (if not all) requests.

    I have just found the same kind of discussion on this topic over at Zend. An interessting read as well. http://devzone.zend.com/node/view/id/63

  12. #12
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A new thought on approach. Not to confuse things, but to evaluate. I'd like to know what others think of it. First off, don't hang me on naming conventions, I'm open to any naming that seems suitable.

    The Frontcontroller thread of Captain proton (which has been retracted as to the naming, I know!).
    So the Frontcontroller would become the Main-entrypoint (deciding the controller/action or fallback if one of both doesnt exists). What I like about the controller is that it is based around the methods 'add, edit, update, delete' upfront. So, we would have an 'add, edit, update, delete' switch (to function) per page (I had been doing this in general and it just doesnt make sense, since not every page will need it). We could then apply user-privilege-roles, based upon interception-filters (nested filters, loose filters).

    The flexibillity I am looking for in the end is being able to load a page (say 'members'), but also subpages or modules ('members/1/audio/') for a certain page. This could be the content for a page, as well as subcontent, let's say a poll, or a sidebar with ads, etc. (this is also why I mentioned the slots-approach earlier on. Being able to flexibily load more content per page). So, something like:

    Index/Entry: (entry point funtioning as switch, check/determine query->actions)
    Pagecontroller: (add, edit, update, delete. Based upon authentication/roles, filter)
    Modeller: perform the function(s) defined in the pagecontroller.
    Views: Load the corresponding views.

    or

    Index/Entry: (entry point funtioning as switch, check/determine query->actions)
    Pagecontroller: (add, edit, update, delete. Based upon authentication/roles, filter)
    Call View: Load the correspond view_index and let the page_controller scan for function(s)-slots.
    Modeller: perform the function(s) derived from the view-to-controller and sent back the data.
    Views: Show the resulting view.

    A Call view (as a slots model) might have a comment like <!-- slot('content','functionname','role') -->
    The view for content would be mostly html where an edit link could be a function: link('Edit content','viewname or form','role'); If the role is not allowed to edit the content, the link would not show.

    I'm just trying to point out where I would like to go with my approach and have some do's and dont's feedback.

  13. #13
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you have Front Controller, then Page Controller is superfluous (in most cases). By the way ...
    Pagecontroller: (add, edit, update, delete ...)
    These actions are usually results of POST request (page with form), so you should process them in POST front controller. They do not belong to any page, they are finished with redirect.

  14. #14
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    In my case I am building a community site. So I have the need for modules inside base_templates, say module 'audio'. So a profile page (handled by let's say profile_controller) can have add, edit, update and delete. How would I update the 'audio' content and not the profile, since the controller for that page is profile_controller.

  15. #15
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    It doesn't seem right to place destructive methods inside the same controller which is used for reading contents. I would factor those destructive tasks out of the public "access" into separate controllers which may only be accessed with the given access level.

    edit-audio => EditAudioController
    delete-audio => DeleteAudioController
    add-audio => AddAudioController

    However, that's just me.

    I might also opt for one management controller and have add,edit and delete as actions.

    PHP Code:
    AudioManagementController extends Controller {

       public function 
    add() { }
       public function 
    delete() { }
       public function 
    edit() { }

    }

    BlogManagementController extends Controller {

       public function 
    add() { }
       public function 
    delete() { }
       public function 
    edit() { }

    }

    VideoManagementController extends Controller {

       public function 
    add() { }
       public function 
    delete() { }
       public function 
    edit() { }


    You could get even fancier and create a abse class which you extend and override.

    PHP Code:

    class CRUDController extends Controller {

        public function 
    create() { }
        public function 
    update() { }
        public function 
    read() { }
        public function 
    delete() { }

    }

    AudioController extends CRUDController {

       public function 
    add() { }

    }

    BlogController extends CRUDController {

       public function 
    delete() { }

    }

    VideoController extends CRUDController {

       public function 
    add() { }
       public function 
    delete() { }


    If you want to manage CRUD specific responsibilities using one class per item.

  16. #16
    SitePoint Addict Mastodont's Avatar
    Join Date
    Mar 2007
    Location
    Czech Republic
    Posts
    375
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    How would I update the 'audio' content and not the profile
    Try forms with hidden fields or write extra classes for form manipulations.
    Code:
    <input TYPE="hidden" NAME="module" VALUE="audio">

  17. #17
    SitePoint Addict
    Join Date
    Feb 2006
    Posts
    281
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Forget this just stick with the ISO standarnd url writing.

    The only thing I use for MVC urls is:

    index.php?route=folder/class/method&product_id=1

    there is no advantage in url rewriting. Even googles blog say it does not give a higher posisiton for changing urls.

  18. #18
    SitePoint Evangelist
    Join Date
    Mar 2006
    Location
    Sweden
    Posts
    451
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by blueyon View Post
    there is no advantage in url rewriting. Even googles blog say it does not give a higher posisiton for changing urls.
    For me, friendly urls isn't about google. It's about the visitor. If i give them friendly, descriptive, hierarchical urls, they will get a better experience on the site.

  19. #19
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,147
    Mentioned
    16 Post(s)
    Tagged
    3 Thread(s)
    The information pertaining to a page accessible only through a query string can't be indexed. So inaccessible URLs do adversely affect SEO.

  20. #20
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by oddz View Post
    The information pertaining to a page accessible only through a query string can't be indexed.
    I believe you're wrong. As far as I am aware, all spiders will use the URL (which includes the query string) to identify pages. They won't follow forms (get or post) though.

    Quote Originally Posted by blueyon View Post
    Forget this just stick with the ISO standarnd url writing.
    Which ISO standard are you referring to?

  21. #21
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Some great and interessting ways to go. I'm pondering myself on what will be a felxible way to go. I was just watching Rasmus Lerdorf giving a talk at Drupalcon2008 and discussing a lot of PHP stuff, but also some notes on frameworks. He concluded some stuff that I have been dealing with as well.. frameworks can be nice, but can become bloated and loose transparency fairly quickly. So, I'm looking for the advantages of MVC, which to me is seperation of layers and on the other hand sticking to native PHP as much as possible. This will mean it won't be a low-entry-level access kind of framework, but since most developers know a fair share of PHP, they should be able to make it work. My current thought on approach:

    Entrypoint
    - Handle the incoming request based on nice-urls and get one controller->method with the vars that come along with it.
    - At this point I am really thinking of having an Error-handler that would go to a default 404 if the controller hasn't one, or wasn't found. Otherwise a page-specific error handler could be called if one was set up. (so users would land of the right page, yet no action could be called, so we could have a page specific view to get maybe point them in the right direction.
    - Set up the enviroment variables outside the global scope. Most likely a registry kind of file
    - Have a pagecontroller for each page that can be programmed to handle request based on the variables it has to work with.
    - Have all stuff being processed by the modeler and passed to the view(s).

    The views is still one I am not sure about. I think in the end templating is the slowest way to go and I am thinking of using (template-kind of) vars that get substituted once the included view gets called
    Code HTML4Strict:
    (e.g. <h2><?php $display->get('page_heading');?></h2>)

    Any thoughts on this approach? Let me know.

  22. #22
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mr.mstyle View Post
    - Have a pagecontroller for each page that can be programmed to handle request based on the variables it has to work with.
    If you have a front controller (as you described), then the individual handlers aren't called page controllers. Page controller is when you don't have a front controller, but simply address a separate file. Eg. plain vanilla php.
    A better name to use would be handler, or just controller. If you have a tight coupling between view and controller, you could also call it a component or a widget.

    Quote Originally Posted by mr.mstyle View Post
    - Have all stuff being processed by the modeler and passed to the view(s).
    I don't know what a modeler is. The most commonly used design has a controller do any updates to the model, and then select relevant data from the model and pass to the view. The update part is optional. The view can be a template or a procedural style php file. Some people prefer a better separation between view and controller, which can be achieved by not allowing the controller to pass data to the view - instead letting the view query the model it self. This is usually a bit harder to implement, and arguably not worth the effort.

  23. #23
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    If you have a front controller (as you described), then the individual handlers aren't called page controllers. Page controller is when you don't have a front controller, but simply address a separate file. Eg. plain vanilla php.
    A better name to use would be handler, or just controller. If you have a tight coupling between view and controller, you could also call it a component or a widget.
    Right, I didn't name the things right. Basically my frontcontroller (or better named 'entrypoint/routing') will only do the routing after checking if the needed file(s) exists. If not, it will fallback to a page-specific errorpage or a default errorpage.

    The vars for the template will be replaced from vars that got set before the calling of the view file, so the view just calls an object that holds the defined variables.

  24. #24
    SitePoint Enthusiast
    Join Date
    May 2009
    Posts
    29
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I have been busy with all kinds of stuff and this also gave me time to let all of this MVC sink in. There are many good frameworks, but I am still looking for something slim, extendable and easy, hence this post. Things might have been mentioned before, but this thread is also for me as a scratchpad.

    The 4 states slowly sank in. Use a CRUD kind of model on the controller because it is logic in its approach. You won't need to have it in every controller, but if.. those are the 4 that form the backbone of the approach.

    Code HTML4Strict:
    index.php (the router which uses a $_GET for the specific section)
    -Controllers
      - index.controller.php
      - members.controller.php
      - member.controller.php
    - Models
      - index.model.php
      - members.model.php
      - member.model.php
    - Views
      - index
        - index.view.php
        - 404.view.php
      - members
        - members.view.php
      - member
        - member.view.php
        - member.profile.php
    - Includes
    - Libs
      - db.class.php
      - session.class.php
      - template.class.php

    This way, adding new section should be fairly easy. And with logic names, sections can be edited/debugged etc. fairly quick.
    On the index you could handle SESSIONS, apply (pre)filters and a typical request could be:

    http://www.domain.com/
    http://www.domain.com/members/
    http://www.domain.com/member/14591/profile/

  25. #25
    SitePoint Member
    Join Date
    Sep 2009
    Posts
    12
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken View Post
    It's good practise to let URLs identify resources, not actions.
    Why? What advantages does it have? Also, how would you handle things like logging in or digging an article?


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •