Skip to main content

Forums

  • This topic is empty.
Viewing 12 posts - 1 through 12 (of 12 total)
  • Author
    Posts
  • #195488
    bearhead
    Participant

    Hi, I am in the process of updating a website with nearly 400 separate page. I have read that using your index.php file as a single point of entry for the site is a good way to vastly improve maintainability on large sites.

    However I’m not very experienced with php, and I’m not quite sure what that means or how to implement it. Does the index.php contain a script that loads in content, based on what url the user is viewing? If so what would such a script look like? I have searched a bit, but I can’t really find any explanations that I could understand.

    Thanks for the clarification.

    #195493
    __
    Participant

    This reply has been reported for inappropriate content.

    Single-point of entry is good. “how to implement” depends a lot on your situation. Are you using a database? Do your pages all have a similar structure/layout?

    Basically, you’re talking about a “front controller.” Yes, that’s all it needs to do: decide what the user wants to view, and load it. Simples.

    decide what user wants
        (typ. by looking at URL/PATH_INFO/query string)
    do "domain" work:
        DB access
        process user input
        further decision-making
        build info needed for content
        etc.
    prepare the "response":
        get the HTML template you want
        use the info from the domain to build the content
        set http status and headers
        send response
    all done
    
    #195495
    Anonymous
    Inactive

    I’m not quite sure what that means or how to implement it. Does the index.php contain a script that loads in content, based on what url the user is viewing? If so what would such a script look like?

    Before coding anything, think through what those 400 pages have in common. The point of a single point of entry is not that it is good in itself, but that you are trying to separate content / data from how it is presented. For example, a blog site might have 400 posts, but each post would be essentially the same. They each have a title, a date, an author, and some content.

    An important first question – have you used databases before and are you currently using one?

    #195498
    bearhead
    Participant

    This reply has been reported for inappropriate content.

    The things that every page will have in common are a (basic)stylesheet, jquery libray, header, footer, and a php doc with list of employee names assigned to a vraible (generated by a database).

    Would it maybe be better to place these into a file like config.php, and then just require config.php on every page?

    I originally planned to do it like that, and just automate the process by prepending the file in php.ini, but the website is on a shared sever, and we can’t edit the php.ini file.

    #195502
    __
    Participant

    This reply has been reported for inappropriate content.

    How much is different about each page?

    From what you’re describing so far, it sounds like a single point of entry would work very well, probably with only a single template for displaying content.

    Where is the actual page content stored? in a DB? flat files? Or is this yet to be determined?

    edit

    To answer your question, no: including a config file on every page would be a less-than-great solution.

    I mean, it would probably be better than what you have now, but it would still have all them same problems of being difficult to implement, maintain, etc., and you’d still have code duplicated and spread out over 400+ files.

    #195503
    __
    Participant

    This reply has been reported for inappropriate content.

    Also, I would highly recommend that you consider taking the opportunity to leave shared hosting. Virtual Private Servers have tremendous advantages, are readily available, and have costs comparable to (in some cases, lower than) shared hosting.

    Just my 2¢

    #195505
    bearhead
    Participant

    This reply has been reported for inappropriate content.

    There is some variance in the page layouts. I would need probably 3-4 separate templates.

    Currently the page content is just in the actual web pages, its a static site and there isn’t any templating going on, save that the header.php and footer.php files are included on every page on the site, individually (yes it is a monstrosity).

    I definitely agree that a private server would be better… unfortunately that isn’t a decision I can make, and my company’s administration has a very “bargain” mind-set when it comes to our internet presence. To make matters more difficult, our website’s back end is handled by our IT department, so I need to go through them to access it, and they care more about the company intranet than the website.

    I’m actually supposed to be just the front-end developer, and even that was something I took on myself because the website is so laughably implemented. -I don’t mind learning php though, its a valuable skill.

    #195524
    bearhead
    Participant

    This reply has been reported for inappropriate content.

    Here is where I’m at: (may be doing ti totally wrong)

    I have my index.php set up like so:

    <?php 
    
    if ($_SERVER['REQUEST_URI'] == '/project1/') {
        include '../template1.php';
    }elseif ($_SERVER['REQUEST_URI'] == '/project2/') {
        include '../template2.php';
    }else {
        include 'notfound.php';
    }
    
    ?>
    

    So basically I’m trying to get it to see what directory the user is at, and then include the correct template – which is working.

    However, as I understand it, this file is going to have to be in every directory, right? Is there any way I could just have one instance of it in the root directory, which users are directed to by default? Am I missing something? I feel like I’m doing it wrong.

    #195530
    __
    Participant

    This reply has been reported for inappropriate content.

    You need only one front controller (that’s the whole point). You should have no other directories/files on the publicly accessible portion of your server (your document root; “/user/yourname/public_html” or whatever your host calls it), with the possible exception of static resources (css, js, images, etc.).

    Instead of a big if/elseif/elseif… list of every possible file, put all of the valid “routes” (urls that can be requested) into an array, and check the user’s request against that. For example:

    index.php

    <?php
    
    // define acceptable routes
    $routes = [
        "/home",
        "/contact",
        "/projects/project1",
        // etc. …
    ];
    
    // get user's request 
    // (here, from PATH_INFO, but this is up to you)
    // (if there is no request, default to homepage)
    $request = $_SERVER["PATH_INFO"]?:
        "/home";
    
    // in case of errors
    try{
    
        // the "model" is a script which handles 
        //  all of the logic and work of 
        //  retrieving/building the info 
        //  we need to create the response.
    
        // if the user's request is routable,
        //  we get a model for that "action";
        // if not, we will get a model for a 404 action.
        $model = in_array( $request,$routes )?
            "./models/{$request}.php":
            "./models/not-found.php";
    
        // once we have the model,
        //  get the template and hand it over.
        echo response( "./templates/{$request}.php",$model );
    
        // all done.
        exit;
    }
    catch( Exception $E ){
        // log the exception so you can troubleshoot it.
        // during dev you may print the error message,
        //   but DO NOT do so on a "live" site.
    
        // return an error page.
        http_response_status( 500 );
        echo "Sorry, an internal error occurred.";
        exit( 500 );
    }
    

    I’m sure you have an idea what “template” files are, and you might guess what all of the “model” files do (they do the logic+processing+etc. and return info the template will need to render the page’s content).

    I’ve got two functions in there: model and response. They’re actually very simple:

    function/response.php

    <?php
    
    function response( $template,array $model ){
        // first, look for the template file.
        if( ! is_readable( $template ) ){
            throw new InvalidArgumentException( "template is not readable" );
        }
    
        // we expect $model to be an assoc. array of data for the template to use.
        // we'll turn this array into variables here in the local scope.
        extract( $model,EXTR_SKIP );
    
        // turn on output buffering (no accidental output)
        ob_start();
    
        // run the template
        require $template;
    
        // get and return the contents of the output buffer
        //  (the response body).
        return ob_get_clean();
    }
    

    Similarly, the model function is not very complex either. Your model scripts can do anything you might normally do in your php files, with two exceptions:

    1. They must not produce any output (no echo, no headers, etc.).
    2. They must `return` an associative array of data for the template to use.

    function/model.php

    <?php
    
    function model( $action ){
        // first, look for the action file.
        if( ! is_readable( $action ) ){
            throw new InvalidArgumentException( "action is not readable" );
        }
    
        // run the action.
        $model = require $action;
    
        // make sure the action returned an array like it was supposed to
        if( ! is_array( $model ) ){
            throw new UnexpectedValueException( "action did not return a model" );
        }
    
        // otherwise, return the model.
        return $model;
    }
    

    Here’s some examples to go with those functions:

    models/home.php

    <?php
    
    // maybe info to build a special slideshow for the homepage
    $banner = [
        "heading" => "Welcome!",
        "slides" => [
            ["/imgs/slide1.png","Look at that!"],
            ["/imgs/slide2.png","Much Wow"],
            // etc. …
        ]
    ];
    
    // maybe getContent queries the DB
    //  for articles that go on the "homepage"
    $content = getContent( "homepage" );
    
    // more stuff, etc.
    
    // at the end, pack it all up and return it
    // (remember array keys must be valid var names)
    return [
        "banner"  => $banner,
        "content" => $content,
        "etc"     => $etc
    ];
    

    templates/home.php

    <!doctype html>
    <html>
        <?php require "./html_head.php" ?>
        <body>
            <!--  blah blah blah  -->
            <h1>This is Our Home Page</h1>
            <header>
                <?php require "./html_site_nav.php" ?>
                <div id="slideshow">
                    <h2><?= $banner["heading"]; ?></h2>
    <?php foreach( $banner["slide"] as $slide ){ >
                    <img src="<?= $slide[0] ?>" alt="<?= $slide[1] ?>">
    <?php } /* end foreach banner[slide] */ ?>
                </div>
            </header>
            <main>
                <?= $content ?>
                <?= $etc ?>
            </main>
            <footer>
                <?php require "./html_site_footer.php" ?>
            </footer>
        </body>
    </html>
    

    …Whew.

    Simples, right !?

    #195639
    bearhead
    Participant

    This reply has been reported for inappropriate content.

    yeah, totally simple o.O

    seriously though, thanks for the detailed explanation of how a front controller should work… I think I am beginning to understand what is going on.

    The big thing that I wasn’t getting before is that the actual navigation links need to be setup like so

    <a href="index.php/project1">
    

    I was stuck thinking that the links would still be pointing to specific files and was like- how the hell is code on index.php going to matter when the user clicks a link and goes to a different page!?

    d’oh!

    #195710
    __
    Participant

    This reply has been reported for inappropriate content.

    the actual navigation links need to be setup like …`index.php/project1`

    Well, I said “typically” and “it depends.” I like using path_info. Using the query string is probably a more common practice. Then, there are all kinds of options introduced by URL rewriting. And it can depend on other things too (for example, $_SERVER["PATH_INFO"] isn’t always available on all servers).

    I was stuck thinking that the links would still be pointing to specific files and was like- how the hell

    Yeah : )

    That’s something to get over. It’s a major mental stumbling block for a lot of people. URLs don’t have to point at actual files. It’s not even the “natural” thing to do; it’s only the default thing that Apache does. Things got a lot easier for me when I stopped thinking in terms of “pages.”

    Also note, of course, that my description above is only one of many possible strategies.

    #198592
    Taufik Nurrohman
    Participant

    I was stuck thinking that the links would still be pointing to specific files and was like- how the hell is code on index.php going to matter when the user clicks a link and goes to a different page!?

    Use .htaccess to remove the index.php part in URL. Query string will be used as the fake URL path. When you click on a link, you are not going to any different pages. It’s just the same index.php page with different query strings.

    # Rewrite `http://my_website.com/index.php?foo/bar` to `http://my_website.com/foo/bar'
    &lt;IfModule mod_rewrite.c&gt;
    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?$1 [L,QSA]
    &lt;/IfModule&gt;
    

    Here you can use the query string for loading different template to the index.php using PHP include or require.

    Something like this:

    <?php
    
    $q = str_replace('?', "", $_SERVER['QUERY_STRING']);
    
    if (strpos($q, 'path/to/file-1') === 0) {
        include '../template-1.php';
    } elseif (strpos($q, 'path/to/file-2') === 0) {
        include '../template-2.php';
    } else {
        include '404.php';
    }
    

    This barebones should be able to help you to understand: https://github.com/tovic/cms-starter

Viewing 12 posts - 1 through 12 (of 12 total)
  • You must be logged in to reply to this topic.