ok i had a thought and i know that i can do it with jquery but dont know if it could be done with php.

i would like to create a function where, if called it could see if the necessary files and code that it needs are in the head of the document and if not then append the code it needs just right before the /head tag.

or this could sound too good to be true to happen like that.

thanks in advance

Recommended Answers

All 3 Replies

Hey.

You want to scan the <link> and <script> tags in the HTML <head> tag to see if there are resources missing? - If so, the sure. That is most definitely possible with PHP.

We would need to know more about your code, though, to be able to give you any sort of advice on how to actually implement this. - I could give you a generic example... have to run right now though. I'll try to post something later if nobody else has.

yes i do want to scan the link script tags to, lets say, see if the jquery file is already called. or the css is already called. and if not then append it before the /head.

i dont have any code as of now. it was more of a though before i started. plus i wouldn't really know where to start on that.

Ok. So, assuming you have the HTML as a string inside PHP (like from a template, or something), and that you know which resources you need...

This function should check if there are tags missing from the header of the markup, and add them if they are. - I only tested it with <link> and <script> tags, but in theory this should work for any kind of element.

<?php
    /**
     * Makes sure the <head> section of the given HTML markup contains
     * the resources defined by the $resources parameter.
     * Each resource in the $resources array must contain a 'elem'
     * name and a 'match' array with a key -> value pair list of
     * attributes to match.
     * @param string $html The HTML markup to check.
     * @param array $resources An array of resources to check.
     */
    function validate_head($html, $resources)
    {
        // Verify the input parameters
        if(!$html || empty($html))
        {
            trigger_error("Input parameter '\$html' is invalid.", E_USER_WARNING);
            return false;
        }
        if(!$resources || empty($resources) || !is_array($resources))
        {
            trigger_error("Input parameter '\$resources' is invalid.", E_USER_WARNING);
            return false;
        }

        // Fetch the <head> of the markup. - I realize that regular 
        // expressions are not ideal for HTML, but the <head> section usually
        // remains predictible enough to be retrived like this.
        // (Granted that there is no inline JS/CSS)
        $regexp = '#(<head>.*?</head>)#is';
        $head = '';
        if(preg_match($regexp, $html, $matches))
        {
            $head = $matches[1];
            $html = preg_replace($regexp, '<head />', $html);
        }
        else
        {
            trigger_error('A <head> section was not found in the provided markup.', E_USER_WARNING);
            return false;
        }

        // Parse the <head> as XML
        $xml = new SimpleXMLElement($head);

        // Loop through the resources
        foreach($resources as $_index => $_resource)
        {
            // Make sure the resource is valid
            if(!isset($_resource['elem'], $_resource['match']) || count($_resource['match']) == 0)
            {
                trigger_error("Invalid resource at index #{$_index}. Skipping.", E_USER_WARNING);
                continue;
            }

            // Loop through each element in the header that matches 
            // the one the resource is looking for and see if it exist.
            $elementExists = false;
            foreach($xml->{$_resource['elem']} as $_elem)
            {
                // Loop through each attribute the resource needs to
                // match, reporting any attribute that doesn't match.
                $attributeExist = true;
                foreach($_resource['match'] as $_attr => $_value)
                {
                    // Check if the resource matches.
                    if($_elem[$_attr] != $_value)
                    {
                        $attributeExist = false;
                    }
                }

                // See if the loop reported any missing attributes.
                // If not, report that the element existed.
                if($attributeExist)
                {
                    $elementExists = true;

                    // Break out of the loop. No need to search futher.
                    break;
                }
            }

            // If the element wasn't reported found by the loop, add
            // it to the XML object.
            if(!$elementExists)
            {
                $newElem = $xml->addChild($_resource['elem']);
                foreach($_resource['match'] as $_attr => $_value)
                {
                    $newElem->addAttribute($_attr, $_value);
                }
            }
        }

        // Generate XML output based on the XML object.
        $newHead = $xml->asXML();
        $xml = null;

        // Remove the XML header from the XML output, leaving only
        // the HTML part.
        $newHead = preg_replace('#^<\?xml.*?\?>\s?#i', '', $newHead);

        // Fix the <script> tags. HTML requires them to be:
        //  <script *></script>, whereas XML returns them as:
        //  <script */>
        $newHead = preg_replace('#<script(.*?)/>#i', '<script$1></script>', $newHead);

        // Inject the new header back into the HTML
        $html = str_replace('<head />', $newHead, $html);

        return $html;
    }
?>

Which you can then use like so:

<?php
    header('content-type: text/html; charset=utf8');

    // An exmple HTML markup, just for testing.
	$html = <<<HTML
<!DOCTYPE html>
<html>
    <head>
        <title>Test stuff</title>
        <link rel="stylesheet" href="mycss.css" type="text/css" />
        <script type="text/javascript" src="myjs.js"></script>
    </head>
    <body>
        <p>Some stuff...</p>
    </body>
</html>
HTML;

    // A list of elements that should be in the header.
    // (Note that the 2nd and 4th elements don't exist in the above markup.)
    $required = array(
        array(
            'elem' => 'link',
            'match' => array(
                'type' => 'text/css',
                'href' => 'mycss.css',
                'rel' => 'stylesheet'
            )
        ),
        array(
            'elem' => 'script',
            'match' => array(
                'type' => 'text/javascript',
                'src' => 'imnumber2.js'
            )
        ),
        array(
            'elem' => 'script',
            'match' => array(
                'type' => 'text/javascript',
                'src' => 'myjs.js'
            )
        ),
        array(
            'elem' => 'link',
            'match' => array(
                'type' => 'text/css',
                'href' => 'imnotincluded.css',
                'rel' => 'stylesheet'
            )
        ),
    );

    // And here comes the magic!
    $newHTML = validate_head($html, $required);
    echo $newHTML;
?>

The above would output:

<!DOCTYPE html>
<html>
    <head>
        <title>Test stuff</title>
        <link rel="stylesheet" href="mycss.css" type="text/css"/>
        <script type="text/javascript" src="myjs.js"></script>
    <script type="text/javascript" src="imnumber2.js"></script><link type="text/css" href="imnotincluded.css" rel="stylesheet"/></head>
    <body>
        <p>Some stuff...</p>
    </body>
</html>

Hope this is what you are looking for.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.