6
\$\begingroup\$

I have written out the following code in the head section of my document, which should load 3 separate style sheets for each page based on the URL/URI that the user is visiting. It is working as intended as tested with the comment in the code but I am wondering if there is a more efficient way to do this. I initially started writing out a switch statement, but chose to try if else statements before.

Also I have added this part:

 || $_SERVER['PHP_URL_PATH']

to each statement in case there is an error of some kind with the first expression. It seems to be working whether I use just ['PHP_URL_PATH'] or the full $_SERVER['PHP_URL_PATH'].

My questions are:

  1. Which out of the two would be more efficient (switch or if else)?
  2. Is the second declaration of $_SERVER actually necessary, or will it work without this specificity?

Any improvements that people could point me to would be greatly appreciated.

PS: I have removed all the echo's for including the actually <link>'s to the CSS files.

This has been tested and is showing to work in Firefox Developer Edition so guessing it's ok, but could be improved maybe; what about scalability, or any security concerns? I am new so please advise or help.

// Create Logic here to include various different style sheets. 

if($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH']  === "/mainHubV8.1.php"){
    echo "Loading Styles for MainHubV8.1.php";

    }
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/advSearchV8.1.php"){
    echo "Loading Styles for advSearchV8.1.php";

    }
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/loginOrSignUpV8.1.php"){
    echo "Loading Styles for loginOrSignUpV8.1.php";

    }
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/profilePageV8.1.php"){
    echo "Loading Styles for profilePageV8.1.php";

    }                            
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/chatApllicationV8.1.php"){
    echo "Loading Styles for chatApllicationV8.1.php";

    }                            
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/onlineUsersV8.1.php"){
    echo "Loading Styles for onlineUsersV8.1.php";

    }                            
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/index.php"){
    echo "Loading Styles for index.php";

    }                            
else if ($_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/404"){
    echo "Loading Styles for error page";

    }

Is there a better alternative to achieving the same goal? If so could you please provide reference or articles/Question & answers anywhere on Stack Exchange or some other resource. Plus I do not want to use Javascript or JQuery really as these can be turned off and disabled. So PHP seems more appropriate.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ What would you want the code to do if $_SERVER['PHP_SELF'] matched one case while $_SERVER['PHP_URL_PATH'] matched a different one? \$\endgroup\$
    – Nat
    Commented Jun 1, 2019 at 15:24
  • 2
    \$\begingroup\$ Also, isn't this what maps are for? \$\endgroup\$ Commented Jun 1, 2019 at 18:33
  • \$\begingroup\$ @Mooing Duck can you elaborate? \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 18:40
  • 1
    \$\begingroup\$ @RyanStone: php.net/manual/en/language.types.array.php \$\endgroup\$ Commented Jun 1, 2019 at 18:43

4 Answers 4

8
\$\begingroup\$

Most of questions you are asking are not fit for this site and your code does not work as intended but this is an interesting case to review

The grave mistake

Adding anything to your code just in case there would be some imaginary "error of some kind" is the worst thing a programmer could do ever. You effectively ruined your code with adding that || $_SERVER['PHP_URL_PATH'] stuff:

  • there is no such thing $_SERVER['PHP_URL_PATH'] for starter: such a variable just doesn't exist
  • of course ['PHP_URL_PATH'] without the $_SERVER part makes no sense
  • neither the whole condition returns anything sensible due to PHP syntax rules you are yet to learn.

Yet this code works somehow, albeit not the way you expect.

The operator precedence

The way this code executes is a very interesting matter, once I wrote an article that explains it in detail, Operator precedence or how does 'or die()' work. Given you only started learning it could be too complex for you for the moment to wrap your head around, but in time you will find it very interesting to read.

$_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/mainHubV8.1.php" doesn't mean "if either PHP_SELF or PHP_URL_PATH equal to /mainHubV8.1.php". It means "if PHP_SELF contains any value OR PHP_URL_PATH is equal to /mainHubV8.1.php".

In short, an expression $_SERVER['PHP_SELF'] || $_SERVER['PHP_URL_PATH'] === "/mainHubV8.1.php" evaluates to true when $_SERVER['PHP_SELF'] contains any value. Which means always.

Given PHP already has it's answer, it ceases to execute the further condition. This is why you can write either $_SERVER['PHP_URL_PATH'] or ['PHP_URL_PATH'] or don't even get a notice for the non-existent array index - this code is just never executed.

As a result, this code will always output just "Loading Styles for MainHubV8.1.php" no matter which page it is called on.

The right way

To elaborate on the Neoan's answer, given you have 3 styles to load, here is the proposed array structure

$stylesheets = [
    '/mainHubV8.1.php' => [
        'style1.css',
        'style2.css',
        'style3.css',
    ],
    '/advSearchV8.1.php' => [
        'style4.css',
        'style5.css',
        'style6.css',
    ],
    // and so on
];

given this structure, you will be able to get the correct styles right from $_SERVER['PHP_SELF']:

foreach($stylesheets[$_SERVER['PHP_SELF']] as $file) {
    echo "<link rel='stylesheet' type='text/css' href='$file'>\n";
}
\$\endgroup\$
9
  • \$\begingroup\$ Thank you for your reply, I will read through it carefully.. How does $_SERVER['PHP_URL_PATH'] not exist when I have clearly found documentation to support that it does? & also I have only asked 2 questions so far so that is a bit of an unfair statement, how is anyone supposed to learn when the restriction on stack exchange basically block anyone from actually asking wrong or mis-construed questions. That is the whole point of learning. I can't ask any more questions on stack-overflow so its like hitting a brick wall in my learning experience. \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:20
  • \$\begingroup\$ Oh, I see your point on line 18/19 yes, Thank you for pointing this out. Trying to understand you answer a bit better in the first block you have made an array called $stylesheets, but how does this link into the foreach statement as your not specifying $stylesheets anywhere & where is this $file pulling its value from? Not sure I fully grasp this answer yet, but I will continue to bash my head against it until i do... \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:35
  • \$\begingroup\$ Copied the code in your first block exactly as it is as a template to be edited & CPanel text editor is throwing an error: Syntax Error, unexpected T_DOUBLE_ARROW, expecting '']'............... ? is inside the php tags also? i removed the trailing , on each 'list' but this did not fix it. is on line 2? \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:46
  • \$\begingroup\$ I think i do understand the article you have included similar to how (Brackets) in maths means execute this part first. \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:54
  • 1
    \$\begingroup\$ On the first line, you have a syntax error. It has $stylesheets [ but should be $stylesheets = [. \$\endgroup\$ Commented Jun 1, 2019 at 17:20
5
\$\begingroup\$

Your current battery of if conditions needs a re-think. $_SERVER['PHP_SELF'] -- as long as it has a non-falsey value will evauate to true, satisfy the first expression, will never even reach $_SERVER['PHP_URL_PATH'] === "/mainHubV8.1.php", execute echo "Loading Styles for MainHubV8.1.php";, and nothing else will ever get a look.

It is unclear to me if you ever want to load multiple stylesheets. If so this would a second reason to opt for a switch block versus an if-elseif... block.

You probably intend to check if the string is found in $_SERVER['PHP_SELF'] or $_SERVER['PHP_URL_PATH']. Each variable must be separately checked (there are different techniques to perform that process).

I think you should choose one reliable source to make your comparison on.

To streamline your code without abandoning secure practices, I recommend a "whitelist" array of valid css filenames. If the incoming value exists in the whitelist, include the css file(s) by directly writing the $_SERVER value into the echo line(s).

If you cannot manage to get the 1-to-1 literal variable string to match your css file, then I recommend a lookup array instead of a switch block (because I hate how verbose all those break lines make the script).

\$\endgroup\$
3
  • \$\begingroup\$ When you say I recommend a "whitelist" array, would this be stored as php Variables inside the actual function or as a json list, if in php does it matter if these are public or private? Can you give any working examples of any such switch statements? With similar goals \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:18
  • \$\begingroup\$ I have seen this terminology a few times in different refernces to coding and never really understood it ""Truthy or Falsey" Surely if its true, then its true, false then false. evaluates to 1 || 0 there is no 0.75 in terms of truth? can you give an example of a falsey question &/or a truthy one? \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 16:38
  • 1
    \$\begingroup\$ Your whitelist array can be declared as a variable; or because you won't be making any changes to the data, you can declare it as a constant. A constant will be global (will be available everywhere -- no scope-related issues). I can't see any benefit to making the whitelist private. What does php consider to be loosely true or false: stackoverflow.com/a/80649/2943403 The execution of my advice is suitably presented at the end of YCS's answer; with exception that I would perform an isset() check when accessing the lookup array and issue a fallback action. \$\endgroup\$ Commented Jun 1, 2019 at 23:36
2
\$\begingroup\$

I wonder if you are asking the right question. I can't help but wonder where this code block could possibly run in order to make sense.

I will have to assume a lot, so here we go:

Why don't you create an associative array where the keys are the endpoint and the values are a string of your stylesheet.

This way you will be able to read that from a database one day.

Now take your endpoint (a note here: you want to look into REQUEST_URI and/or parse_url) and simply get your values out:

$styleSheets =['index.php'=>'style.css'];
$styleSheets[$currentRoute]

That said, feel free to share your code-base as I think you might want to get some feedback on your general structure.

\$\endgroup\$
1
  • \$\begingroup\$ The Code block I have provided, is currently set in the head section of a dedicated head file which will load on every page load for all pages, only the body, footer and css & or scripts will change with different URLs, i did look into parse_url but it confused me quite alot, still trying to learn php, step by step. \$\endgroup\$
    – Ryan Stone
    Commented Jun 1, 2019 at 3:47
1
\$\begingroup\$

a couple more helpful tips.

Depending on your conditions for each stylesheet, you may want to detect patterns in the URL to conditionally add stylesheets.

// This will target the index.php page or the '/'

  <?php if (basename($_SERVER['PHP_SELF']) == 'index.php') : ?>
        <link rel="stylesheet" href="items/home.css">    

// This will target anything with 'V8' in the URL

 <?php elseif (strpos($_SERVER['REQUEST_URI'], "V8") !== false) : ?>
        <link rel="stylesheet" href="items/all-V8.css">
    <?php endif; ?>

You could stick this directly in the HEAD or in an included file and will still work fine.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.