Jump to content

Coding practices for large scale projects?


cyllo

Recommended Posts

Hello all. I'm looking to build a website in php that will be large in scope and I'm looking for some direction as to how to go about coding it. What I'm referring to exactly is the programming model. I'm new to the language, but not to programming, and I've read up on it and familiarized myself with the syntax over the past few days. Normally when I go about building a project I like to plan ahead how I'm going to build It so I don't run into tedious issues later on and this is what I need help with.

 

My concerns: 

  1. I am looking to use the alternative syntax for control structures as to make the php code inside my html readable and easier to manage but in terms of OOP when is it best for me to use classes vs functions? 
  2. I am leaning towards using both classes and functions. Classes to handle polling data, sanitizing it and storing it while the functions will be used , with the alternative syntax, to display the data.
  3. How should I go about properly setting my project assuming I will have many concurrent users using the website at once?
  4. Is using xml / INI files as a directory to look up information a good practice? Is it better to declare constant variables instead?
  5. When working with multiple includes is there an easier way to include a file than having to explicity write "dirname( dirname(__FILE__) )" everytime?

 

I'm essentially looking for guidance / tips as to good programming practices with this language :) Advanced practices are welcomed as well.

 

 

Development Tools:

  1. XAMPP ( Windows 7 Pro )
  2. PHPStorm 

 

Current directory structure plan:

9d760588fa.jpg

 

Here is what I currently have:

 

 

The API class is a collection of functions that returns an object to be used at a later data.

<?php

/*
 * Development API Key
 * @since 1.0
 *
 * Rate Limit(s):
 * 10 request(s) every 10 second(s)
 * 500 request(s) every 10 minute(s)
 */
define( "__API_KEY__" , "---------------------------------" );

require_once dirname( dirname(__FILE__) ) . "\\settings.php";

class API
{

    // If successfull it returns an object from the url that's passed to this function.	
    private function api_call($url)
    {
	$result = null; // end result

        // Create a new curl handle.
        $ch = curl_init();

        curl_setopt($ch , CURLOPT_URL, "https://" . $url . "?api_key=" . __RIOT_API_KEY__); // set the URL
        curl_setopt($ch , CURLOPT_RETURNTRANSFER , true  ); // return the transfer as a string of the return value
        curl_setopt($ch , CURLOPT_SSL_VERIFYPEER , false ); // turn off ssl certificate verification

        // Execute the api call
        $response = curl_exec($ch);
        // Get info to analyze the result
        $ci = curl_getinfo($ch);

        $httpcode = $ci["http_code"];

        // If a curl error occured
        if(curl_errno($ch) || ($httpcode != "200"))
        {
            $die  = "Curl Error Code: "    . $httpcode       . "<br/>";
            $die .= "Curl Error Message: " . curl_errno($ch) . "<br/>";
            $die .= "Curl URL: "           . $ci["url"]      . "<br/>";
            die($die);
        } else {

            // Check if the api call we made was valid

            $response = json_decode($response, true);

            // If our response is an array check if it's an error response
            if(is_array($response))
            {
                $error_key = "status";
                if(array_key_exists($error_key, $response))
                {
                    $er = $response[$error_key];
                    $die  = "API Error Message: " . $er["message"]     . "<br/>";
                    $die .= "API Error Code: "    . $er["status_code"] . "<br/>";
                    die($die);
                }
            }

            // Our response is a valid object
            $result = $response;
    }

    private function sanitize_url($url)
    {
        // removes all whitespaces
        return trim(preg_replace( '/\s+/','',$url));
    }

    private function regional_endpoints()
    {
        static $regionini;

        if(is_null($regionini))
            $regionini = parse_ini_file(INI_REGIONAL_ENDPOINTS, true);

        return $regionini;
    }

    private function region_host($shortcode)
    {
        /*
         * regionalendpoints.ini
         * @since 1.0
         *
         * [SHORTCODE]
         * Description=<region_description>
         * Host=<host_url>
         */
        return $this->regional_endpoints()[strtoupper($shortcode)]["Host"];
    }

    public  function region_description($shortcode)
    {
        /*
        * regionalendpoints.ini
        * @since 1.0
        *
        * [SHORTCODE]
        * Description=<region_description>
        * Host=<host_url>
        */
        return $this->regional_endpoints()[strtoupper($shortcode)]["Description"];
    }

    public function api_object_by_name($name, $region)
    {
        /*
         * @Description: Get summoner objects mapped by standardized summoner name for a given list of summoner names.
         *
         *
         * @Returns: Map[string, SummonerDto]
         *
         * Object
         * ------------------------------------------------------------------------------------------------------
         * Name             Data Type          Description
         * ------------------------------------------------------------------------------------------------------
         * id	            long	           ID.
         * name	            string	           Name.
         * profileIconId    int                    ID of the summoner icon associated with the summoner.
         * revisionDate	    long	           Date summoner was last modified specified as epoch milliseconds.
         * Level            long	           Level associated with the summoner.
         */

         $api_url = "%s/api/col/%s/v1.4/obj/by-name/%s";

        return $this->api_call(sprintf($api_url,
            $this->region_host($region),
            strtolower($region),
            $this->sanitize_url($name)));
    }

}

Class that acts as the middle man between the api and the front end. Currently how it is set up it handles an internal queue.

<?php

include dirname(__FILE__) . "\\class-riotapi.php";

define( "SUMMONER_NAME" , 0 );
define( "SUMMONER_ID"   , 1 );

class Summoner
{

    private $riotapi        = null;

    private $summoner       = null;
    private $arr_summoners  = null;
    private $region         = null;


    public function __construct()
    {
        // Create our riot api object
        $this->riotapi = new RiotAPI();
    }


    public function summoner_exists($summoners, $region, $type = SUMMONER_NAME)
    {
        static $eoa; // end of array

        // If our array of summoners is empty or we have reached the end of the array.
        if( empty($this->arr_summoners) || $eoa )
        {
            // Get an array of summoner information from the riot api based on the type of information
            // supplied.
            switch($type)
            {
                case SUMMONER_NAME :
                    $this->arr_summoners = $this->riotapi->api_summoner_by_name($summoners, $this->region = $region);
                    break;

                case SUMMONER_ID :
                    $this->arr_summoners = $this->riotapi->api_summoner_by_id($summoners, $this->region = $region);
                    break;
            }

            // If our array of summoners isn't empty.
            if( !empty($this->arr_summoners) )
            {
                // Set our current summoner the first element in the array.
                $this->summoner = reset($this->arr_summoners);
            } else {
                // We failed to acquire any summoner information so return false.
                return false;
            }

            $eoa = false;

        } else {

            // If we have not reached the end of the summoners array set our current
            // summoner to the next element.
            $next = next($this->arr_summoners);

            // Have we reached the end of the array?
            if( $next ) {
                // No. Set our current summoner to the next element.
                $this->summoner = $next;
            } else {
                // Yes. Set our end of array variable to true.
                $eoa = true;
                // End the loop
                return false;
            }

        }

        return true;
    }


    public function summoner_id()
    {
        return $this->summoner["id"];
    }


    public function summoner_name()
    {
        return $this->summoner["name"];
    }


    public function summoner_profile_icon_id()
    {
        return $this->summoner["profileIconId"];
    }


    public function summoner_last_updated()
    {
        return $this->summoner["revisionDate"];
    }


    public function summoner_level()
    {
        return $this->summoner["summonerLevel"];
    }


    public function summoner_mastery_pages()
    {
        return $this->riotapi->api_summoner_masteries($this->summoner_id(),
            $this->region)[$this->summoner_id()]["pages"];
    }

}

Functions.php file that is a collection of functions that echo out information. 

<?php

require_once "settings.php";
include DIR_INCLUDE . "class-summoner.php";

function summoner_exists($summoners, $region = "NA", $type = SUMMONER_NAME)
{
    global $cs;
    if(!isset($cs)){
        $cs = new Summoner();
    }
    return $cs->summoner_exists($summoners, $region, $type);
}

function summoner_name()
{
    global $cs;
    if(isset($cs)){
        echo $cs->summoner_name();
    }
}

?>

index.php - Example of how I'm currently using the functions.php file.

<?php include "functions.php"; ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>

<?php while(summoner_exists("cyllo")) : ?>

    <div>Summoner Name: <?php summoner_name(); ?></div>
    <div>Summoner ID: <?php summoner_id(); ?></div>
    <div>Summoner Profile icon ID: <?php summoner_profile_icon_id(); ?></div>
    <div>Last Updated: <?php summoner_last_updated(); ?></div>
    <div>Summoner Level: <?php summoner_level(); ?></div>

    <div>
        <?php mastery_pages(); ?>
    </div>

<?php endwhile; ?>
</body>
</html>
Link to comment
Share on other sites

I have problems with this statement:

 

  1. I am looking to use the alternative syntax for control structures as to make the php code inside my html readable and easier to manage but in terms of OOP when is it best for me to use classes vs functions? 

a)  you should not be considering how your php code looks inside your html code.  It should not even Be There!!

 

b)  and whatever does 'alternative syntax' have to do with design considerations?  IMHO - using the alternative syntax is a surefire method of confusing the next person who looks at this code.  What's wrong with the 'recommended' or 'non-alternative' syntax?  Why do you want to use the one that few use?  (Isn't that why it's called alternative?)

Link to comment
Share on other sites

All of your question have already been answered by most of the popular modern frameworks available for php.

 

I'd recommend you take a look at one of them. Symfony or Laravel are my preferred options.

 

I will surely look into those, thank you :)

 

 

I have problems with this statement:

 

  1. I am looking to use the alternative syntax for control structures as to make the php code inside my html readable and easier to manage but in terms of OOP when is it best for me to use classes vs functions? 

a)  you should not be considering how your php code looks inside your html code.  It should not even Be There!!

 

b)  and whatever does 'alternative syntax' have to do with design considerations?  IMHO - using the alternative syntax is a surefire method of confusing the next person who looks at this code.  What's wrong with the 'recommended' or 'non-alternative' syntax?  Why do you want to use the one that few use?  (Isn't that why it's called alternative?)

 

Feel free to correct me if I'm wrong since I'm still reading up on this as I go along. As far as my understanding goes the alternative syntax to

<?php
if( $a == 5 ){
echo "5";
}
?>

is

<?php if( $a == 5 ): ?>

5

<?php endif; ?>

What I want to do in create html templates and then use php code to populate it. I want to avoid having to use a lot of echo statements as well as keep my php code inside classes and out of the html code. As I am new to the language if I'm using the terminology wrong please let me know. 

Edited by cyllo
Link to comment
Share on other sites

Yes you do - so why did you state just the opposite in your item #1?  Writing chunks of html code and populating it with php vars is the way to go.  Leave the php logic out of the end result.

 

Your ex. of the two syntaxes is meaningless since you can achieve the same outcome in either syntax without an echo.  It's just that the alt. syntax is so rarely seen and therefore rarely used.  Of course it may have had more usage years ago - I wasn't around then.  But again - your example is a poor one if you truly intend to separate your php code and html code.

 

It sounds like your attempt to pre-plan your standards for your upcoming large project may be poorly thought out.  Without significant experience in writing some heavy duty code you will surely end up making mistakes and using unsound practices.  Not a criticism - merely preparing you for the day you look thru your efforts and (with increased awareness) discover that you didn't fully understand things back then.  :)  If this large project is something you are doing on your own, I suggest that you continue to grow on some smaller stuff  first.  Having only been using php for a little over 3 years I marvel at some of my earliest scripts (just simple single modules) and the way I wrote things back then. Whatever was I thinking??

Link to comment
Share on other sites

I think you're missing the point, ginerjm.

 

cyllo wants to use PHP as a template engine, that is, he wants an HTML document with embedded control structures (loops, if statements etc.) for the dynamic parts. This is perfectly valid. PHP is a rather lousy template language compared to Twig or Smarty, but the concept is just fine and very common. In fact, I wonder what you do you instead. You're talking about chunks of HTML with PHP values, but some pages are more complex than that and need actual control structures. How do you generate markup with a loop, for example?

 

The verbose PHP syntax is not “rarely seen” or “rarely used”. You use it in exactly this scenario: In a template, curly braces don't work very well, because you just can't see which one belongs to which statement. This doesn't happen with an explicit “endfor” or “endif”.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.