SitePoint Sponsor

User Tag List

Page 2 of 5 FirstFirst 12345 LastLast
Results 26 to 50 of 106
  1. #26
    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 dan7
    Thanks for your patience and a lot of responses. OK, distinct controller sounds good. But this way, the components list will grow bigger and bigger. I'm wondering if I should still create all component objects in index.php (or whatever script user requests) and pass ALL of them to the front controller like you suggested before.
    I'd create the subcontrollers in the main controller (As I also showed in the previous post, with getLoginBox method), as that's when I know that I need it. In PHP, you will generally want to create objects as late as possible.
    Shared objects (such as the db connection) are a bit more troublesome. If you use a registry, you need to create them all up-front in order to put them in the registry. You can upgrade the registry to a servicelocator. You basically add a factory, that creates the object on demand.
    Compare theese two implementations. The public interface is the same, but the second provides just-in-time creation of the shared object:
    PHP Code:
    class Registry {

        protected 
    $instances = Array();

        function 
    get($id) {
            return 
    $this->instances[$id];
        }

        function 
    set($id$instance) {
            
    $this->instances[$id] = $instance;
        }
    }
    // in index.php
    $registry = new Registry();
    $registry->set("db", new Database("localhost""root""secret"));
    // in page.php
    $db $registry->get("db"); 
    PHP Code:
    class ServiceLocator {

        protected 
    $instances = Array();
        protected 
    $factories = Array();

        function 
    get($id) {
            if (!isset(
    $this->instances[$id])) {
                
    $this->instances[$id] = call_user_func($this->factories[$id]);
            }
            return 
    $this->instances[$id];
        }

        function 
    registerFactory($id$callback) {
            
    $this->factories[$id] = $callback;
        }
    }
    // in index.php
    $registry = new ServiceLocator();
    $registry->set("db"create_function(
        
    '''return new Database("localhost", "root", "secret");'
    ));
    // in page.php
    $db $registry->get("db"); 

  2. #27
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks..

    Ok, it's looks great.
    I think I know enough to start working with actual code.

    Oh
    I have one more question
    Please correct me if I'm wrong. This is rather general question

    So far, I used PEAR package for form generation/validation. It's ok, but I feel I don't need those thousands lines for that functionality (generate html and apply a bunch of rules)
    For each form I always defined array with each field description. My wrapper around the pear class was just taking the array and returned to me html

    One of the advantages of that approach was that I could process the form (no output yet) and later decide, that some of the fields should be removed or some should be disabled.

    So I could just call several $element->updateAttribute() and similar methods before the form was parsed into html.

    This way I think I was creating the different view of the form and I started to think how I would do it now, after all great tips in these forums.

    Am I thinking in the right direction assuming, that I should switch the form output into different views depending on the controller assumptions?
    Let's say, that user can edit other users' privileges, but he can't edit his own. So, the controller determines, that the user is going to edit his own data and switches the standard view of the form (template) to some other, for example with disabled controls or static content instead of controls. Is that the way to handle this?

    Thank you kindly

  3. #28
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    I'd create the subcontrollers in the main controller (As I also showed in the previous post, with getLoginBox method), as that's when I know that I need it. In PHP, you will generally want to create objects as late as possible.
    Yes, that's all fine. I'm just asking myself, where I should include the classes then (assuming I'm using servicelocator'). Sorry if this sounds stupid. I just don't want to guess
    I have getLoginBox method in Page class - should I include my LoginBox controller file in exactly that method (same goes for the loginBox model, if it exists)? So it's used only when it's needed.
    Or maybe I should push everything (loginBox, db, cache, whatever else I'll use later) to serviceLocator and include files there? (on demand, if the given instance of the object does not exist yet)

    Thanks

  4. #29
    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 dan7
    Am I thinking in the right direction assuming, that I should switch the form output into different views depending on the controller assumptions?
    Let's say, that user can edit other users' privileges, but he can't edit his own. So, the controller determines, that the user is going to edit his own data and switches the standard view of the form (template) to some other, for example with disabled controls or static content instead of controls. Is that the way to handle this?
    Sounds reasonable to me.

    Quote Originally Posted by dan7
    Or maybe I should push everything (loginBox, db, cache, whatever else I'll use later) to serviceLocator and include files there? (on demand, if the given instance of the object does not exist yet)
    Yes, you might aswell relay the call to the service locator to keep all the creation in one place. I'm using PHP5 myself, so autoload makes inclusion a non-issue. I think it belongs with the factory though, so if you use a service locator, let it include aswell.

  5. #30
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, great.

    Thanks a lot for all your help.
    It's really invaluable.

    I'm starting the new branch of the project and I will try to catch the trunk ASAP

    P.S. Yes, I think I should consider switching to PHP5 but after I've seen a bug in 5.1.2 or 5.1.3 concerning form handling (and populating the $_POST array), I became more reserved... Maybe I'll install it side by side with php4 and play a bit. If I remember well, both can work together when one of them is working as the apache module while the other as cgi

    Cheers!

  6. #31
    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 dan7
    Yes, I think I should consider switching to PHP5 but after I've seen a bug in 5.1.2 or 5.1.3 concerning form handling (and populating the $_POST array), I became more reserved
    PHP5 is as stable as PHP4, if not more. The occasional bug pops up in all products. The only reason why you won't see a lot of bugs in the PHP4 branch is that it's not being developed much anymore.

    Quote Originally Posted by dan7
    Maybe I'll install it side by side with php4 and play a bit. If I remember well, both can work together when one of them is working as the apache module while the other as cgi
    Possibly ... The transition isn't that troublesome though. I switched about 6 months ago, and I had a rather large application in about a dozen installations. Most of the porting was done in less than a day.

  7. #32
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    The transition isn't that troublesome though. I switched about 6 months ago, and I had a rather large application in about a dozen installations. Most of the porting was done in less than a day.
    Alright then. I've just configured php5 to run concurrently with php4 and I will give it a shot. Actually the php is the oldest piece of software used in my projects, so maybe it's the high time to switch. I'll start a new branch along with php switch and I'll see how it works.. One of the benefits is that the examples you've given here won't have to be reverted to php4 hehe...

  8. #33
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK. I started to slowly write a new code and some other issues appeared.
    My questions will be more specific now and will refer to the actual code.
    I splitted my code into several components as explained by kyberfabrikken, so now, each of them can be developed indepedently. That's cool!

    But sharing resources came again.
    Here are relevant code snippets:
    main controller
    PHP Code:
    class Page {
        
        [...]

        function 
    getPageHeader() {
            
    $header = new Page_Header;
            return 
    $header->execute();
        }

        [...]

    }

    function 
    __autoload($class_name) {
        require 
    'class/'.strtolower($class_name) . '.php';

    header controller
    PHP Code:
    class Page_Header {

        function 
    execute() {
            
    ob_start();
            include(
    'tpl/head.tpl.php');
            return 
    ob_get_clean();
        }


    The questions
    1. Is that the 'correct' way of using __autoload? SO I don't have to put include... in each method that creates external objects
    2. For now, page header only grabs the html template, which is just echoed in the main template. But what I need to achieve is the following. Each page has main css file and additional files, that may overwrite some stuff from the main file. SOmetimes it gets even more complicated and some components require additional css (because they appear in different context, they have their own css stylesheet). Same story with javascript.

    My old solution was that main controller (main class actually) had css and js arrays and each 'component' (in my old way everything was in one class-tree) could append that array with needed data, so for example, login stuff could add 'login.css' and 'login.js, form.js' to these arrays.

    Those arrays were then iterated over in the head.tpl template.

    But now, each part of the page is closed in its own environment, having access (throu some kind of registrty probably) to commonly shared resorces like caches or db. The question is how I should handle the css and js in that new scenario? I don't want to load ALL files on each page, that's out of the question. The 'old way' output was OK. I just need a new implementation, appropriate for the code design...

    Thanks for the tips..

  9. #34
    SitePoint Member
    Join Date
    Aug 2006
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I am currently writing my own MVC. I strongly suggest you to read both:
    1. http://www.sitepoint.com/forums/showthread.php?t=184548
    2. Matt Zandstra: PHP 5 Objects, Patterns, and Practice ('PHP5 Obiekty, wzorce, narzedzia', Wyd. Helion - Polish edition).
    You will then start a great journey - mine is not finished yet :-)
    The book (2) is IMO the best php5 + design patterns book available on the market (in Poland). It includes the complete (working!) Front Controller solution explained step-by-step.
    The thread (1) includes few working and clearing-a-lot examples. Although Captain Proton's example is not perfect, it's so simple and self-explaining that I understood quite everything that was not clear for me both in MVC idea and the design patterns in the book (book is great - just I was too stupid to understand everything at first glance ).

  10. #35
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks
    Although I don't like 'polish editions' But maybe I'll buy the original one..
    First, I'll read the CP's thread once again. I remember reading it before, but now I know a bit more about the topic..

  11. #36
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've read the thread. I doesn't answer my question (or I missed the answer). And the book is not an option for this weekend, so I hope somebody (kyberfabrikken maybe? ) will give me some tips...

    Thanks

  12. #37
    SitePoint Member
    Join Date
    Aug 2006
    Posts
    2
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To be honest - the translation is not errorless, but the errors are not significant and should not influence the real value of the book. I strongly suggest that you buy polish edition (It's ~50 PLN).

    I'll will not help you with your problem because I think that you have come too far into low-leveling your application. I think that you are trying to think of every real aspect of your current system instead of re-designing it completely
    If you are rewriting it from the scratch you should re-think everything. Consider just one entry point (controller) for whole application (not including admin module - it's usually so different that it deserves to it's own entry point with a bit different rules of access, different model's objects interaction etc.).
    Consider whole site's 'meat' as the one big model. I mean for example that db class, user class, product class and so on being a part of the model - they are objects which interacts.
    The controller is using commands to make some operations on the model. In command you have firstly some basic operations and afterwards you initiate the view object and then pass to it the reference to some variables that you want to display.
    View class is managing displaying those variables. It has no knowledge of what they meaning is. So now when you decide to switch from Smarty to XML+XSLT, there will be no need at all to make changes in other places than View class and it's childs.
    When you decide, that new users while registering must include their age (to
    'eliminate' youngsters from being officially registered), you should only make two changes: in the view class - modification of the form; in the user class (or - better? - core user class child) - new user property, new 'CUser::addUser($login)' behaviour etc.
    In much fewer words:
    Controller is handling the request, creating a proper command object that will handle the request. The command object then is working with some model's objects to have some results. The results then are passed to view class. View is not aware of the model (It should not be, although there are some exceptions - especially while manipulating huge sets of data when you can reach memory limits. But do not concern of it - every rule has it's own exceptions ;-) ). It just have some variables to display.
    That's the basic idea of the layer separation.
    Of course I am not a so-called guru And I might be mistaken somewhere :-)
    Last edited by chesteroni; Aug 25, 2006 at 17:45.

  13. #38
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, but your explanation brings nothing to this discussion. No offence, really. I already know what is the theory behind MVC and code separation and that has been already cleared out. I can't go and buy the book right now, so this is not an option for at least the next few days...
    I'm not going to jump into XML+XSLT. Why would I? The tools I currently use are perfectly suited for the job and I'm familiar with them. I see no benefits for me with using XML + XSLT. I don't even use XML in my XMLHTTP operations.

    My main problem so far is specific components 'cooperation'. I've already separated my application and I think it's OK for now. But it's not so simple as gluing the output of each component into one and send it back to the browser. As I explained above with css/js example, some components have some 'influence' on the other components. While DB object may be needed by most of them and I can pass it as an argument or just register it with some additional class, I'm not too pleased to do the same with object like page_header.. It's just so different than typically shared object, then I'm sure using it the same way as DB is totally wrong.

    The CSS/JS issue is a specific example, because these files can be attached only in one place of the html output, so any component, that needs additional css/js file for presentation/additional behaviour needs some way to 'tell it' to the header component, which renders this part of the output.

    Of course, I could drop the header class and put css/js arrays in the front controller, so each of the component would have access to them
    Is that any good?

    It could look something like that
    main.tpl.php
    PHP Code:
    <?xml version="1.0" encoding="utf-8"?>
    <?php
    foreach ($this->css as $css) {
    echo 
    '<?xml-stylesheet href="/css/'.$css.'" type="text/css" media="screen, projection"?>';
    }
    ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    [...]
    <body>

    <h1><?php echo $this->__('header'); ?></h1> 

    [...]

    <?php echo $this->getLoginBox(); ?>

    [etc...]
    page.php
    PHP Code:
    class Page {

        (...)
        
        function 
    addCSS($css) {
            
    $this->css[] = $css;
        } 

        function 
    addJS($js) {
            
    $this->js[] = $js;
        } 

        protected function 
    getLoginBox() {
            
    $childcontroller = new LoginBox($this->translator);
            
    $this->addCSS($childcontroller->getCSS());
            
    $this->addJS($childcontroller->getJS());
            return 
    $childcontroller->execute();
        } 
    loginbox.php
    PHP Code:
    class LoginBox
    {
        protected 
    $translator;
        protected 
    $css 'login.css';
        protected 
    $js 'login.js';

        function 
    __construct($translator) {
            
    $this->translator $translator;
        }

        function 
    getCSS() {
            return 
    $this->css;
        }

        function 
    getJS() {
            return 
    $this->js;
        } 
    Does it make any sense at all?

  14. #39
    Non-Member
    Join Date
    Jan 2003
    Posts
    5,748
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You would be better of with the influence of the Composite pattern; I say this because of the following...

    > so any component, that needs additional css/js file for presentation/additional
    > behaviour needs some way to 'tell it' to the header component, which renders this
    > part of the output.

    The way I do it, the Iteration works from the bottom, upwards. So if you have one Composite that is lower down in the hierarchy, you can pass up an array towards the top most Composite during that Iteration.

    In doing so, each Composite can deposit (imagine an array merge for example) it's own payload; During said Iteration, each Composite takes a look at the merged array, and uses what it's interested in. That way, a lower down Composite that requires a specific CSS file, can deposit that to the shared array, and the top most Composite has said interest, and thus uses that shared data - which would have the CSS files as expected

    Does that make sense to you? I kind of started the ball rolling in regards to the Composite pattern on this forum, so there has been a lot of discussion on this pattern if you care to search.

    Any questions, I'll be around to answer them.

  15. #40
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    Does that make sense to you?
    Not as much as I'd expect.. I think that some sample code would tell 100x more than any words... That's why I ended up here, even though I hardly ever write to any forums. I found just too much theory and almost nothing really practical on the web.

    Quote Originally Posted by Dr Livingston
    I kind of started the ball rolling in regards to the Composite pattern on this forum, so there has been a lot of discussion on this pattern if you care to search.

    Any questions, I'll be around to answer them.
    OK, thanks for the help. First, I'll search and read the available data about Composite, then I'll surely ask the questions

  16. #41
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Dr Livingston
    The way I do it, the Iteration works from the bottom, upwards. So if you have one Composite that is lower down in the hierarchy, you can pass up an array towards the top most Composite during that Iteration.
    Hi, I 've read a bit about that pattern and got back to your post. One thing that strikes me is, that your Iteration goes from bottom to the top. It's OK for CSS/JS as they are used by the component at the top of the structure. But what if in the same time I need to pass something in the opposite direction?
    Maybe I don't really understand what you've written, but I don't see the solution right now.. If you could clear something up, it would be great.
    P.S. Is the solution I've given above crap in general?

    Thanks for help...

  17. #42
    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 dan7
    My main problem so far is specific components 'cooperation'. I've already separated my application and I think it's OK for now. But it's not so simple as gluing the output of each component into one and send it back to the browser. As I explained above with css/js example, some components have some 'influence' on the other components. While DB object may be needed by most of them and I can pass it as an argument or just register it with some additional class, I'm not too pleased to do the same with object like page_header.. It's just so different than typically shared object, then I'm sure using it the same way as DB is totally wrong.

    The CSS/JS issue is a specific example, because these files can be attached only in one place of the html output, so any component, that needs additional css/js file for presentation/additional behaviour needs some way to 'tell it' to the header component, which renders this part of the output.
    Yeah, that's a bit of a dilemma. On one hand you want to keep controllers isolated from each other, on the other hand, there are some things they need to share. You can solve this in different ways.
    The easiest (as you note) is to use a shared object for exchanging messages between views. It's a bit ugly in that it's basically semiglobal dump for all sorts of messages. To my experience, this can work because the amount of information they have to share is rather low - mostly stuff that goes in the <head> tags.
    A more solid solution is something like you are getting at with the code-example above. The main difference is that you send a message from child to parent controller, rather than using a global dump for piping the message. The child->parent route is more isolated, because the parent can intercept the message. You might want to make a more general message pipeline though, instead of one for js and one for css.

    Quote Originally Posted by dan7
    But what if in the same time I need to pass something in the opposite direction?
    I don't think you'll need that. I can't come up with a real-world case at least. If you really do, you could use some sort of two-step view mechanism.

  18. #43
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    A more solid solution is something like you are getting at with the code-example above. The main difference is that you send a message from child to parent controller, rather than using a global dump for piping the message. The child->parent route is more isolated, because the parent can intercept the message. You might want to make a more general message pipeline though, instead of one for js and one for css.
    Yes, after I posted it, I concluded, that having 2 methods for this job doesn't make sense. The only problem I see with this solution is that I can't have a Header component, because it'd be called first (from the main template) and thus couldn't grab the data from other components, which are invoked later.
    It's OK for now, when I only have css/js files. But I can imagine putting some additional stuff in the <head> section, like description or keywords (which can vary between pages) etc. It wouldn't be wise to glue this data in the front controller...

    I dumped registry/servicelocator for now and I'm going forward with your previous solutions, that is passing objects in constructors. I will decide later, if I really need a registry or not.

    I also changed MDB2 to PDO - I'm curious about the performance hit. Should be significant..

    Thanks

  19. #44
    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 dan7
    The only problem I see with this solution is that I can't have a Header component, because it'd be called first (from the main template) and thus couldn't grab the data from other components, which are invoked later.
    Rather than including a header and footer in your main view, you could have a separate controller for the html document, taking care of rendering everything, except the main content. Then call this as the last component, to wrap the contents of the primary controller(s). You can either make the main controller a child of this document controller, or vice versa.
    For example:
    PHP Code:
    class Controller
    {
        protected 
    $messages = Array();

        protected function 
    render($template) {
            
    ob_start();
            include(
    $template);
            return 
    ob_get_clean();
        }

        function 
    importMessages($messages) {
            
    $this->messages array_merge($this->messages$messages);
        }
        
        function 
    getMessages() {
            return 
    $this->messages;
        }

        abstract function 
    execute();

    PHP Code:
    class Document extends Controller
    {
        protected 
    $messages = Array(
            
    'css' => Array(),
            
    'js' => Array(),
            
    'title' => '',
        );

        protected 
    $body;

        function 
    __construct($body) {
            
    $this->body $body;
        }

        function 
    execute() {
            return 
    $this->render("document.tpl.php");
        }

    document.tpl.php
    PHP Code:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html>
    <head>
    <?php foreach ($this->messages['css'] as $css) : ?>
        <link rel="stylesheet" type="text/css" href="/css/<?php echo $css?>" media="screen, projection"></link>
    <?php endforech?>
    </head>
    <body>
    <?php echo $this->getChild('body'); ?>
    </body>
    </html>
    PHP Code:
    class Page extends Controller
    {
        protected function 
    getLoginBox() {
            
    $loginbox = new LoginBox($this->translator);
            
    $result $loginbox->execute();
            
    $this->importMessages($loginbox->getMessages());
            return 
    $result;
        }

        function 
    execute() {
            
    $result $this->render("main.tpl.php");
            
    $document = new Document($result);
            
    $document->importMessages($this->getMessages());
            return 
    $document->execute();
        }


  20. #45
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi. Thanks for the code. I need to think about it.
    In the meantime, I have a very small question to you. In some previous examples you created a function like
    PHP Code:
    (...)
        function 
    __($phrase) {
            return 
    $this->translator->getPhrase($phrase);
        } 
    Is the name of that function anything important?
    And the key question - why creating the function istead of calling $this->translator->getPhrase($phrase) directly in the template. I know it's longer etc. But I'm just asking why you're using it this way.

    If I'd follow your example, I'd have to create __($phrase) method in each component's class, that will make the use of a translator. It doesn't hurt, but I'm just curious...

    Thanks

  21. #46
    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 dan7
    Is the name of that function anything important?
    It's fast to write, and stands out. It's also a reference to the php function _() which is an alias for gettext() and essentially does the same, but in a global context.

    Quote Originally Posted by dan7
    And the key question - why creating the function istead of calling $this->translator->getPhrase($phrase) directly in the template. I know it's longer etc. But I'm just asking why you're using it this way.
    It's shorter, but it also makes the template know less about the controllers implementation. Rather than accessing properties of the controller from within the view, I prefer to call a method. Conceptually, they are two separate objects (even though that the view is a procedural file, and not an object).

    Quote Originally Posted by dan7
    If I'd follow your example, I'd have to create __($phrase) method in each component's class, that will make the use of a translator. It doesn't hurt, but I'm just curious...
    Use inheritance. Some helper methods are so common that you can just stick it in a base controller class.

  22. #47
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks for the answers

    Quote Originally Posted by kyberfabrikken
    Use inheritance. Some helper methods are so common that you can just stick it in a base controller class.
    Yeah. What a stupid question. Sorry

  23. #48
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by kyberfabrikken
    Rather than including a header and footer in your main view, you could have a separate controller for the html document, taking care of rendering everything, except the main content. Then call this as the last component, to wrap the contents of the primary controller(s). You can either make the main controller a child of this document controller, or vice versa.
    I had to sleep with this. Yes, that's the solution. I've already tried a few things after I realized, that it won't work without this separation you mentioned. Thanks for the tip!

  24. #49
    SitePoint Wizard REMIYA's Avatar
    Join Date
    May 2005
    Posts
    1,351
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    A very interesting thread, however here is my view. I am sorry, if it is not according to the mass idea of MVC. However.

    1) MVC is nothing more than a concept. It is an idea. Just like OOP is a concept, and idea. A programmer can easily code without bothering with OOP and MVC. However implementing these ideas, brings the code to the next level.

    2) MVC is nothing more than separation of logic. The Controller has nothing to do with View, nor View has to do with Model. If it does, then you are doing something wrong.

    3) MVC should closely follow the logic of the application. Making too many classes when not needed, gets the code over complicated, and hard to maintain in the future.

    So personally when I see a $this->retrieve_any_kind_of_data() in a Controller class it makes me shiver

  25. #50
    SitePoint Zealot
    Join Date
    Aug 2006
    Location
    Poland
    Posts
    108
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Remiya,
    I agree with you. I think the main problem is, that while you know what you want to achieve with the separation, the implementation is not so easy in some cases. Thanks to people at this forum I finally make some progress in rewriting my latest project, because I know that if I won't do it ASAP, it would be a pain to make any changes in the next few months. I tried some unit testing with the current code base and while it's possible to do, it took some time to establish all the code because of so many dependencies etc.

    So personally when I see a $this->retrieve_any_kind_of_data() in a Controller class it makes me shiver
    Please check my questions at the bottom. They refer to that...

    Based on the entries in this tread, I began to play a bit with sessions to finnaly bring my LoginBox to life

    So here are some general thoughts how I'd like to implement it.
    I have my custom session handler which manages sessions in the database.
    So, index.php could look similar to:
    PHP Code:
    require 'class/session.php';
    require 
    'class/db.php';
    require 
    'class/page.php';

    $page = new Page($db,new Translator($db), new Session($db)); 
    Now, the page.php is a the main controller.
    1. I think I should do session stuff here (start, check if expired, set some vars like is_logged)
    2. As I'm using some xmlhttp, I just send such requests with additional header, so I can easily check on the server side, if the request is xmlhttp or not without some fancy url vars. I'd like to check that in page.php too and set some variable like is_xmlhttp

    page.php
    PHP Code:
    class Page {
        (...)
        function 
    __construct($db,$translator,$session) {
            
    $this->db $db;
            
    $this->translator $translator;
            
    $this->session $session;

            
    // ok, so here I'd like to start the session
            
    $this->session->start();

            
    // get session data (id, some vars etc)
            // check if user is logged and set is_logged etc
            // is this the right place to do it?
            
    $this->getSessionData();

            
    // I need to check the request type, 
            // mainly if it was made through xmlhttprequest or not
            // method name is just an example
            
    $this->isAjax();
        }

        
    // I changed the loginBox to userBox, because if user is logged in, 
        // he can see some links instead of the login form
        // so here, I'd check if the user is logged 
        // and create proper child controller
        
    protected function getUserBox() {

            if (!
    $this->is_logged) {
                
    // I need to pass $db object and the session object
                
    $childcontroller = new LoginBox($this->db$this->sesison$this->is_xmlhttp);
            } else {
                
    $childcontroller = new UserLinks($this->translator);
            }

            return 
    $childcontroller->execute();
        } 
    OK, so if user is not logged in, we are passed to the loginBox controller
    The login component needs to talk with the database, but only if the login attempt appeared at all, so here is some code snippet and the specific questions wil follow
    PHP Code:
    class LoginBox {

        (...)
        function 
    __construct($db$session$xmlhttp) {
            
    $this->db $db;
            
    $this->session $session;
            
    $this->is_xmlhttp $xmlhttp;
        }

        function 
    execute() {
            
    // ok, so if the posted data contains
            // 'form_login_etc' (which will be a hidden input), then it means, that
            // user has attempted to log in (at least used THAT form)
            // I need to validate the data and do some actions when it's ok
            // Here I also need the model to talk to db, 
            // is it a good please to create an object??
            
    if (isset($_POST['form_login_etc'])) {
                
                
    $this->model = new Login_Model($this->db);
                
                
    // check the validation state and fire the proper action
                
    if ($this->validate($_POST)) {
                    
    // update session
                    
    $this->updateSessionData();
                    
    //update database
                    
    $this->model->updateLoginDate();
                    
    // if it's the xmlhttp, send some json string and exit
                    
    if ($this->is_xmlhttp) {
                        
    $this->sendJsonResponse();
                    }
                     
                    
    // if it's not xmlhttp, I should send header('Location 
                    // but it looks a bit dirty here.... - where to do it??
                
    }
            }

            return 
    $this->render('login.tpl.php');
        }

        
    // some example validation, it uses model to check some data!
        // errors are stored in an Array, so if the validation fails,
        // errors as just shown in the form in the proper place
        
    function validate($data) {

            if (
    trim($data['login']) == '' || trim($data['password']) == '') {
                
    $this->errors['login'] = $this->__('LOGIN_ERROR');
                return 
    false;
            }
            
            if (!
    $this->model->checkLogin($data['login'], $data['password'])) {
                
    $this->errors['login'] = $this->__('LOGIN_ERROR');
                return 
    false;
            }

            return 
    true;
        } 
    1. Where I should update the session data, in the controller or in the model? Can controller read any data (aside from validation) from the model at all?
    I think that the controller is the right place to do the job, but then, I'd need to grab the data (username, id, privileges etc) from the model...
    2. Is my use of model correct at all? What would be the better way of handling this stuff based on the code above?
    3. Is such validation OK? Or should I write additional class for that purpose etc? The example is quite simple, but if the form contains 30 fields, the validation would get much bigger
    4. Is my handling session/some checkings in the Page controller constructor OK? I know I need to check the session and request ASAP, because those things will be needed by other components. And I want to check that only once in my application.

    I will be grateful for any opinions and help.

    Cheers!
    Daniel


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
  •