public static function attr($string)
    {
        $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) {
            /**
             * This function is adapted from code coming from Zend Framework.
             *
             * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
             * @license   http://framework.zend.com/license/new-bsd New BSD License
             */
            /*
             * While HTML supports far more named entities, the lowest common denominator
             * has become HTML5's XML Serialisation which is restricted to the those named
             * entities that XML supports. Using HTML entities would result in this error:
             *     XML Parsing Error: undefined entity
             */
            static $entityMap = array(
                34 => 'quot', /* quotation mark */
                38 => 'amp',  /* ampersand */
                60 => 'lt',   /* less-than sign */
                62 => 'gt',   /* greater-than sign */
            );
            $chr = $matches[0];
            $ord = ord($chr);
            /*
             * The following replaces characters undefined in HTML with the
             * hex entity for the Unicode replacement character.
             */
            if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
                return '&#xFFFD;';
            }
            /*
             * Check if the current character to escape has a name entity we should
             * replace it with while grabbing the hex value of the character.
             */
            if (strlen($chr) == 1) {
                $hex = strtoupper(substr('00'.bin2hex($chr), -2));
            } else {
                $chr = iconv('UTF-8', 'UTF-16BE', $chr);
                $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
            }
            $int = hexdec($hex);
            if (array_key_exists($int, $entityMap)) {
                return sprintf('&%s;', $entityMap[$int]);
            }
            /*
             * Per OWASP recommendations, we'll use hex entities for any other
             * characters where a named entity does not exist.
             */
            return sprintf('&#x%s;', $hex);
        }, $string);

        return $string;
    }
public static function attr($string)
    {
        $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', function ($matches) {
            /**
             * This function is adapted from code coming from Zend Framework.
             *
             * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
             * @license   http://framework.zend.com/license/new-bsd New BSD License
             */
            /*
             * While HTML supports far more named entities, the lowest common denominator
             * has become HTML5's XML Serialisation which is restricted to the those named
             * entities that XML supports. Using HTML entities would result in this error:
             *     XML Parsing Error: undefined entity
             */
            static $entityMap = array(
                34 => 'quot', /* quotation mark */
                38 => 'amp',  /* ampersand */
                60 => 'lt',   /* less-than sign */
                62 => 'gt',   /* greater-than sign */
            );
            $chr = $matches[0];
            $ord = ord($chr);
            /*
             * The following replaces characters undefined in HTML with the
             * hex entity for the Unicode replacement character.
             */
            if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
                return '&#xFFFD;';
            }
            /*
             * Check if the current character to escape has a name entity we should
             * replace it with while grabbing the hex value of the character.
             */
            if (strlen($chr) == 1) {
                $hex = strtoupper(substr('00'.bin2hex($chr), -2));
            } else {
                $chr = iconv('UTF-8', 'UTF-16BE', $chr);
                $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
            }
            $int = hexdec($hex);
            if (array_key_exists($int, $entityMap)) {
                return sprintf('&%s;', $entityMap[$int]);
            }
            /*
             * Per OWASP recommendations, we'll use hex entities for any other
             * characters where a named entity does not exist.
             */
            return sprintf('&#x%s;', $hex);
        }, $string);

        return $string;
    }
public static function attr ( $ string ) { $ string = preg_replace_callback ( '#[^a-zA-Z0-9,\.\-_]#Su' , function ( $ matches ) { /**
             * This function is adapted from code coming from Zend Framework.
             *
             * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
             * @license   http://framework.zend.com/license/new-bsd New BSD License
             */ /*
             * While HTML supports far more named entities, the lowest common denominator
             * has become HTML5's XML Serialisation which is restricted to the those named
             * entities that XML supports. Using HTML entities would result in this error:
             *     XML Parsing Error: undefined entity
             */ static $ entityMap = array ( 34 => 'quot' , /* quotation mark */ 38 => 'amp' , /* ampersand */ 60 => 'lt' , /* less-than sign */ 62 => 'gt' , /* greater-than sign */ ) ; $ chr = $ matches [ 0 ] ; $ ord = ord ( $ chr ) ; /*
             * The following replaces characters undefined in HTML with the
             * hex entity for the Unicode replacement character.
             */ if ( ( $ ord <= 0x1f && $ chr != "\t" && $ chr != "\n" && $ chr != "\r" ) || ( $ ord >= 0x7f && $ ord <= 0x9f ) ) { return '&#xFFFD;' ; } /*
             * Check if the current character to escape has a name entity we should
             * replace it with while grabbing the hex value of the character.
             */ if ( strlen ( $ chr ) == 1 ) { $ hex = strtoupper ( substr ( '00' . bin2hex ( $ chr ) , - 2 ) ) ; } else { $ chr = iconv ( 'UTF-8' , 'UTF-16BE' , $ chr ) ; $ hex = strtoupper ( substr ( '0000' . bin2hex ( $ chr ) , - 4 ) ) ; } $ int = hexdec ( $ hex ) ; if ( array_key_exists ( $ int , $ entityMap ) ) { return sprintf ( '&%s;' , $ entityMap [ $ int ] ) ; } /*
             * Per OWASP recommendations, we'll use hex entities for any other
             * characters where a named entity does not exist.
             */ return sprintf ( '&#x%s;' , $ hex ) ; } , $ string ) ; return $ string ; }
Escapes untrusted data for inserting into safe HTML Attribute

<div attr='...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...'>content</div>   inside single quoted attribute
<div attr="...ESCAPE UNTRUSTED DATA BEFORE PUTTING HERE...">content</div>   inside double quoted attribute

Per QWASP:
Except for alphanumeric characters,
escape all characters with ASCII values less than 256 with the &#xHH; format (or a named entity if available)
to prevent switching out of the attribute. The reason this rule is so broad is that developers frequently
leave attributes unquoted. Properly quoted attributes can only be escaped with the corresponding quote.
Unquoted attributes can be broken out of with many characters, including [space] % * + , - / ; < = > ^ and |.

Warning: Only place untrusted data into a whitelist of safe attributes

Safe HTML Attributes include:
align, alink, alt, bgcolor, border, cellpadding, cellspacing, class, color, cols, colspan, coords, dir,
face, height, hspace, ismap, lang, marginheight, marginwidth, multiple, nohref, noresize, noshade, nowrap,
ref, rel, rev, rows, rowspan, scrolling, shape, span, summary, tabindex, title, usemap,
valign, value, vlink, vspace, width

FYI, example with unsafe attribute (vulnerable in Firefox v50.1, 2016-12-23):
$value = 'javascript:alert(1)';
<embed src="{{$value}}"></embed>             => <embed src="javascript:alert(1)"></embed>
<embed src="@escapeattr($value)"></embed>    => <embed src="javascript&#x3A;alert&#x28;1&#x29;"></embed>

@param string $string Untrusted data

@return string Escaped data for inserting into a safe HTML attribute
Escapes untrusted data for inserting into safe HTML Attribute