Related
I am new to PHP and want to generate unique 10 digits number for my SKU Number. I tried using a date with IP address and got a unique value first time. But after a refresh or saving product data I still have that same SKU number. Any Help?? My code is:
<?php
if(!empty($_POST)) {
.....my code......
}
else{
$stamp = date("Ymdhis");
$ip = $_SERVER['REMOTE_ADDR'];
$sku = "$stamp-$ip";
$sku = str_replace(".", "", "$sku");
$sku = str_replace("-", "", "$sku");
$sku = str_replace(":", "", "$sku");
$sku = substr($sku, 0,10);
}
?>
Why not use the date to create a 10 digit unique number? year (4) + month with leading zero (2) + day with leading zero (2) + seconds with leading zero (2) = 10 digits
<?php
echo date("Ymds");
?>
Yall overcomplicating.
Use an existing library like random_compat (This library can generate strong random numbers and cryptographically secure random numbers.).
https://github.com/ircmaxell/random_compat/blob/master/lib/random.php
Example (your case):
$random = new \PHP\Random(true);
echo $random->token(10, '0123456789');
Here's a quick random-string-generator I wrote:
function generateRandomString($alpha = true, $nums = true, $usetime = false, $string = '', $length = 120) {
$alpha = ($alpha == true) ? 'abcdefghijklmnopqrstuvwxyz' : '';
$nums = ($nums == true) ? '1234567890' : '';
if ($alpha == true || $nums == true || !empty($string)) {
if ($alpha == true) {
$alpha = $alpha;
$alpha .= strtoupper($alpha);
}
}
$randomstring = '';
$totallength = $length;
for ($na = 0; $na < $totallength; $na++) {
$var = (bool)rand(0,1);
if ($var == 1 && $alpha == true) {
$randomstring .= $alpha[(rand() % mb_strlen($alpha))];
} else {
$randomstring .= $nums[(rand() % mb_strlen($nums))];
}
}
if ($usetime == true) {
$randomstring = $randomstring.time();
}
return($randomstring);
} // end generateRandomString
You can use it like this for what you need:
$SKU = generateRandomString(false, true, false, '', 10);
you could use this $sku = rand(1000000000,9999999999) this php function will generate a random no. every time
As designing a new platform we tried to integrate the IBAN numbers. We have to make sure that the IBAN is validated and the IBAN stored to the database is always correct. So what would be a proper way to validate the number?
As the logic was explained in my other question, I've created a function myself. Based on the logic explained in the Wikipedia article find a proper function below. Country specific validation.
Algorithm and character lengths per country at https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN.
function checkIBAN($iban)
{
if(strlen($iban) < 5) return false;
$iban = strtolower(str_replace(' ','',$iban));
$Countries = array('al'=>28,'ad'=>24,'at'=>20,'az'=>28,'bh'=>22,'be'=>16,'ba'=>20,'br'=>29,'bg'=>22,'cr'=>21,'hr'=>21,'cy'=>28,'cz'=>24,'dk'=>18,'do'=>28,'ee'=>20,'fo'=>18,'fi'=>18,'fr'=>27,'ge'=>22,'de'=>22,'gi'=>23,'gr'=>27,'gl'=>18,'gt'=>28,'hu'=>28,'is'=>26,'ie'=>22,'il'=>23,'it'=>27,'jo'=>30,'kz'=>20,'kw'=>30,'lv'=>21,'lb'=>28,'li'=>21,'lt'=>20,'lu'=>20,'mk'=>19,'mt'=>31,'mr'=>27,'mu'=>30,'mc'=>27,'md'=>24,'me'=>22,'nl'=>18,'no'=>15,'pk'=>24,'ps'=>29,'pl'=>28,'pt'=>25,'qa'=>29,'ro'=>24,'sm'=>27,'sa'=>24,'rs'=>22,'sk'=>24,'si'=>19,'es'=>24,'se'=>24,'ch'=>21,'tn'=>24,'tr'=>26,'ae'=>23,'gb'=>22,'vg'=>24);
$Chars = array('a'=>10,'b'=>11,'c'=>12,'d'=>13,'e'=>14,'f'=>15,'g'=>16,'h'=>17,'i'=>18,'j'=>19,'k'=>20,'l'=>21,'m'=>22,'n'=>23,'o'=>24,'p'=>25,'q'=>26,'r'=>27,'s'=>28,'t'=>29,'u'=>30,'v'=>31,'w'=>32,'x'=>33,'y'=>34,'z'=>35);
if(array_key_exists(substr($iban,0,2), $Countries) && strlen($iban) == $Countries[substr($iban,0,2)]){
$MovedChar = substr($iban, 4).substr($iban,0,4);
$MovedCharArray = str_split($MovedChar);
$NewString = "";
foreach($MovedCharArray AS $key => $value){
if(!is_numeric($MovedCharArray[$key])){
if(!isset($Chars[$MovedCharArray[$key]])) return false;
$MovedCharArray[$key] = $Chars[$MovedCharArray[$key]];
}
$NewString .= $MovedCharArray[$key];
}
if(bcmod($NewString, '97') == 1)
{
return true;
}
}
return false;
}
Slight modification of #PeterFox answer including support for bcmod() when bcmath is not available,
<?php
function isValidIBAN ($iban) {
$iban = strtolower($iban);
$Countries = array(
'al'=>28,'ad'=>24,'at'=>20,'az'=>28,'bh'=>22,'be'=>16,'ba'=>20,'br'=>29,'bg'=>22,'cr'=>21,'hr'=>21,'cy'=>28,'cz'=>24,
'dk'=>18,'do'=>28,'ee'=>20,'fo'=>18,'fi'=>18,'fr'=>27,'ge'=>22,'de'=>22,'gi'=>23,'gr'=>27,'gl'=>18,'gt'=>28,'hu'=>28,
'is'=>26,'ie'=>22,'il'=>23,'it'=>27,'jo'=>30,'kz'=>20,'kw'=>30,'lv'=>21,'lb'=>28,'li'=>21,'lt'=>20,'lu'=>20,'mk'=>19,
'mt'=>31,'mr'=>27,'mu'=>30,'mc'=>27,'md'=>24,'me'=>22,'nl'=>18,'no'=>15,'pk'=>24,'ps'=>29,'pl'=>28,'pt'=>25,'qa'=>29,
'ro'=>24,'sm'=>27,'sa'=>24,'rs'=>22,'sk'=>24,'si'=>19,'es'=>24,'se'=>24,'ch'=>21,'tn'=>24,'tr'=>26,'ae'=>23,'gb'=>22,'vg'=>24
);
$Chars = array(
'a'=>10,'b'=>11,'c'=>12,'d'=>13,'e'=>14,'f'=>15,'g'=>16,'h'=>17,'i'=>18,'j'=>19,'k'=>20,'l'=>21,'m'=>22,
'n'=>23,'o'=>24,'p'=>25,'q'=>26,'r'=>27,'s'=>28,'t'=>29,'u'=>30,'v'=>31,'w'=>32,'x'=>33,'y'=>34,'z'=>35
);
if (strlen($iban) != $Countries[ substr($iban,0,2) ]) { return false; }
$MovedChar = substr($iban, 4) . substr($iban,0,4);
$MovedCharArray = str_split($MovedChar);
$NewString = "";
foreach ($MovedCharArray as $k => $v) {
if ( !is_numeric($MovedCharArray[$k]) ) {
$MovedCharArray[$k] = $Chars[$MovedCharArray[$k]];
}
$NewString .= $MovedCharArray[$k];
}
if (function_exists("bcmod")) { return bcmod($NewString, '97') == 1; }
// http://au2.php.net/manual/en/function.bcmod.php#38474
$x = $NewString; $y = "97";
$take = 5; $mod = "";
do {
$a = (int)$mod . substr($x, 0, $take);
$x = substr($x, $take);
$mod = $a % $y;
}
while (strlen($x));
return (int)$mod == 1;
}
The accepted answer is not the preferred way of validation. The specification dictates the following:
Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid
Replace the two check digits by 00 (e.g. GB00 for the UK)
Move the four initial characters to the end of the string
Replace the letters in the string with digits, expanding the string as necessary, such that A or a = 10, B or b = 11, and Z or z = 35. Each alphabetic character is therefore replaced by 2 digits
Convert the string to an integer (i.e. ignore leading zeroes)
Calculate mod-97 of the new number, which results in the remainder
Subtract the remainder from 98, and use the result for the two check digits. If the result is a single digit number, pad it with a leading 0 to make a two-digit number
I've written a class that validates, formats and parses strings according to the spec. Hope this helps some save the time required to roll their own.
The code can be found on GitHub here.
top rated function does NOT work.
Just try a string with '%' in it...
I'm using this one :
function checkIBAN($iban) {
// Normalize input (remove spaces and make upcase)
$iban = strtoupper(str_replace(' ', '', $iban));
if (preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/', $iban)) {
$country = substr($iban, 0, 2);
$check = intval(substr($iban, 2, 2));
$account = substr($iban, 4);
// To numeric representation
$search = range('A','Z');
foreach (range(10,35) as $tmp)
$replace[]=strval($tmp);
$numstr=str_replace($search, $replace, $account.$country.'00');
// Calculate checksum
$checksum = intval(substr($numstr, 0, 1));
for ($pos = 1; $pos < strlen($numstr); $pos++) {
$checksum *= 10;
$checksum += intval(substr($numstr, $pos,1));
$checksum %= 97;
}
return ((98-$checksum) == $check);
} else
return false;
}
I found this solution in cakephp 3.7 validation class. Plain beautiful php realization.
/**
* Check that the input value has a valid International Bank Account Number IBAN syntax
* Requirements are uppercase, no whitespaces, max length 34, country code and checksum exist at right spots,
* body matches against checksum via Mod97-10 algorithm
*
* #param string $check The value to check
*
* #return bool Success
*/
public static function iban($check)
{
if (!preg_match('/^[A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}$/', $check)) {
return false;
}
$country = substr($check, 0, 2);
$checkInt = intval(substr($check, 2, 2));
$account = substr($check, 4);
$search = range('A', 'Z');
$replace = [];
foreach (range(10, 35) as $tmp) {
$replace[] = strval($tmp);
}
$numStr = str_replace($search, $replace, $account . $country . '00');
$checksum = intval(substr($numStr, 0, 1));
$numStrLength = strlen($numStr);
for ($pos = 1; $pos < $numStrLength; $pos++) {
$checksum *= 10;
$checksum += intval(substr($numStr, $pos, 1));
$checksum %= 97;
}
return ((98 - $checksum) === $checkInt);
}
This function check the IBAN and need GMP activate http://php.net/manual/en/book.gmp.php.
function checkIban($string){
$to_check = substr($string, 4).substr($string, 0,4);
$converted = '';
for ($i = 0; $i < strlen($to_check); $i++){
$char = strtoupper($to_check[$i]);
if(preg_match('/[0-9A-Z]/',$char)){
if(!preg_match('/\d/',$char)){
$char = ord($char)-55;
}
$converted .= $char;
}
}
// prevent: "gmp_mod() $num1 is not an integer string" error
$converted = ltrim($converted, '0');
return strlen($converted) && gmp_strval(gmp_mod($converted, '97')) == 1;
}
enjoy !
I am building a simple friend/buddy system, and when someone tries to search for new friends, I want to show partially hidden email addresses, so as to give an idea about who the user might be, without revealing the actual details.
So I want abcdlkjlkjk#hotmail.com to become abcdl******#hotmail.com.
As a test I wrote:
<?php
$email = "abcdlkjlkjk#hotmail.com";
$em = explode("#",$email);
$name = $em[0];
$len = strlen($name);
$showLen = floor($len/2);
$str_arr = str_split($name);
for($ii=$showLen;$ii<$len;$ii++){
$str_arr[$ii] = '*';
}
$em[0] = implode('',$str_arr);
$new_name = implode('#',$em);
echo $new_name;
This works, but I was wondering if there was any easier/shorter way of applying the same logic? Like a regex maybe?
here's something quick:
function obfuscate_email($email)
{
$em = explode("#",$email);
$name = implode('#', array_slice($em, 0, count($em)-1));
$len = floor(strlen($name)/2);
return substr($name,0, $len) . str_repeat('*', $len) . "#" . end($em);
}
// to see in action:
$emails = ['"Abc\#def"#iana.org', 'abcdlkjlkjk#hotmail.com'];
foreach ($emails as $email)
{
echo obfuscate_email($email) . "\n";
}
echoes:
"Abc\*****#iana.org
abcdl*****#hotmail.com
uses substr() and str_repeat()
Maybe this is not what you want, but I would go for this:
<?php
/*
Here's the logic:
We want to show X numbers.
If length of STR is less than X, hide all.
Else replace the rest with *.
*/
function mask($str, $first, $last) {
$len = strlen($str);
$toShow = $first + $last;
return substr($str, 0, $len <= $toShow ? 0 : $first).str_repeat("*", $len - ($len <= $toShow ? 0 : $toShow)).substr($str, $len - $last, $len <= $toShow ? 0 : $last);
}
function mask_email($email) {
$mail_parts = explode("#", $email);
$domain_parts = explode('.', $mail_parts[1]);
$mail_parts[0] = mask($mail_parts[0], 2, 1); // show first 2 letters and last 1 letter
$domain_parts[0] = mask($domain_parts[0], 2, 1); // same here
$mail_parts[1] = implode('.', $domain_parts);
return implode("#", $mail_parts);
}
$emails = array(
'a#a.com',
'ab#aa.com',
'abc#aaa.com',
'abcd#aaaa.com',
'abcde#aaaaa.com',
'abcdef#aaaaaa.com',
'abcdefg#aaaaaaa.com',
'abcdefgh#aaaaaaaa.com',
'abcdefghi#aaaaaaaaa.com'
);
foreach ($emails as $email){
echo '<b>'.$email.'</b><br>'.mask_email($email).'<br><hr>';
}
Result:
a#a.com
*#*.com
ab#aa.com
**#**.com
abc#aaa.com
***#***.com
abcd#aaaa.com
ab*d#aa*a.com
abcde#aaaaa.com
ab**e#aa**a.com
abcdef#aaaaaa.com
ab***f#aa***a.com
abcdefg#aaaaaaa.com
ab****g#aa****a.com
abcdefgh#aaaaaaaa.com
ab*****h#aa*****a.com
abcdefghi#aaaaaaaaa.com
ab******i#aa******a.com
Here's my alternate solution for this.
I wouldn't use the exact number of mask characters to match the original length of the email, but rather use a fixed length mask for privacy reasons. I would also set the maximum allowed characters to show as well as never show more than half of the email. I would also mask all emails less than a minimum length.
With those rules in mind, here's my function with optional parameters:
function maskEmail($email, $minLength = 3, $maxLength = 10, $mask = "***") {
$atPos = strrpos($email, "#");
$name = substr($email, 0, $atPos);
$len = strlen($name);
$domain = substr($email, $atPos);
if (($len / 2) < $maxLength) $maxLength = ($len / 2);
$shortenedEmail = (($len > $minLength) ? substr($name, 0, $maxLength) : "");
return "{$shortenedEmail}{$mask}{$domain}";
}
Tests:
$email = "";
$tests = [];
for ($i=0; $i < 22; $i++) {
$email .= chr(97 + $i);
$tests[] = $email . " -> " . maskEmail("{$email}#example.com");
}
print_r($tests);
Results:
Array
(
[0] => a -> ***#example.com
[1] => ab -> ***#example.com
[2] => abc -> ***#example.com
[3] => abcd -> ab***#example.com
[4] => abcde -> ab***#example.com
[5] => abcdef -> abc***#example.com
[6] => abcdefg -> abc***#example.com
[7] => abcdefgh -> abcd***#example.com
[8] => abcdefghi -> abcd***#example.com
[9] => abcdefghij -> abcde***#example.com
[10] => abcdefghijk -> abcde***#example.com
[11] => abcdefghijkl -> abcdef***#example.com
[12] => abcdefghijklm -> abcdef***#example.com
[13] => abcdefghijklmn -> abcdefg***#example.com
[14] => abcdefghijklmno -> abcdefg***#example.com
[15] => abcdefghijklmnop -> abcdefgh***#example.com
[16] => abcdefghijklmnopq -> abcdefgh***#example.com
[17] => abcdefghijklmnopqr -> abcdefghi***#example.com
[18] => abcdefghijklmnopqrs -> abcdefghi***#example.com
[19] => abcdefghijklmnopqrst -> abcdefghij***#example.com
[20] => abcdefghijklmnopqrstu -> abcdefghij***#example.com
[21] => abcdefghijklmnopqrstuv -> abcdefghij***#example.com
)
For instance :
substr($email, 0, 3).'****'.substr($email, strpos($email, "#"));
Which will give you something like:
abc****#hotmail.com
I'm using this:
function secret_mail($email)
{
$prop=2;
$domain = substr(strrchr($email, "#"), 1);
$mailname=str_replace($domain,'',$email);
$name_l=strlen($mailname);
$domain_l=strlen($domain);
for($i=0;$i<=$name_l/$prop-1;$i++)
{
$start.='x';
}
for($i=0;$i<=$domain_l/$prop-1;$i++)
{
$end.='x';
}
return substr_replace($mailname, $start, 2, $name_l/$prop).substr_replace($domain, $end, 2, $domain_l/$prop);
}
Will output something like:
cyxxxxxone#gmxxxxcom
I created a function can help someone
function hideEmail($email)
{
$mail_parts = explode("#", $email);
$length = strlen($mail_parts[0]);
$show = floor($length/2);
$hide = $length - $show;
$replace = str_repeat("*", $hide);
return substr_replace ( $mail_parts[0] , $replace , $show, $hide ) . "#" . substr_replace($mail_parts[1], "**", 0, 2);
}
hideEmail("name#example.com"); // output: na**#**ample.com
hideEmail("something#example.com"); // output: some*****#**ample.com
You can customize as you want .. something like this (if length is 4 or less display only the first)
function hideEmail($email) {
$mail_parts = explode("#", $email);
$length = strlen($mail_parts[0]);
if($length <= 4 & $length > 1)
{
$show = 1;
}else{
$show = floor($length/2);
}
$hide = $length - $show;
$replace = str_repeat("*", $hide);
return substr_replace ( $mail_parts[0] , $replace , $show, $hide ) . "#" . substr_replace($mail_parts[1], "**", 0, 2);
}
hideEmail("name#example.com"); // output: n***#**ample.com
hideEmail("something#example.com"); // output: some*****#**ample.com
Very simple RegExp way:
$email = preg_replace('/\B[^#.]/', '*', $email)
Results:
john#smith.com: j***#s*****.c**
abcdef#example.org: a*****#e******.o**
abcdef: a*****
Sometimes its good to show the last character too.
ABCDEFZ#gmail.com becomes
A*****Z#gmail.com
I will suggest you keep things simple.
Maybe something like this is simple enough
https://github.com/fedmich/PHP_Codes/blob/master/mask_email.php
Masks an email to show first 3 characters and then the last character before the # sign
function mask_email( $email ) {
/*
Author: Fed
Simple way of masking emails
*/
$char_shown = 3;
$mail_parts = explode("#", $email);
$username = $mail_parts[0];
$len = strlen( $username );
if( $len <= $char_shown ){
return implode("#", $mail_parts );
}
//Logic: show asterisk in middle, but also show the last character before #
$mail_parts[0] = substr( $username, 0 , $char_shown )
. str_repeat("*", $len - $char_shown - 1 )
. substr( $username, $len - $char_shown + 2 , 1 )
;
return implode("#", $mail_parts );
}
I m using femich answer above and tweak it a bit for my
function mask_email($email, $char_shown_front = 1, $char_shown_back = 1)
{
$mail_parts = explode('#', $email);
$username = $mail_parts[0];
$len = strlen($username);
if ($len < $char_shown_front or $len < $char_shown_back) {
return implode('#', $mail_parts);
}
//Logic: show asterisk in middle, but also show the last character before #
$mail_parts[0] = substr($username, 0, $char_shown_front)
. str_repeat('*', $len - $char_shown_front - $char_shown_back)
. substr($username, $len - $char_shown_back, $char_shown_back);
return implode('#', $mail_parts);
}
test123#gmail.com -> t*****3#gmail.com
you can pass in the number of character to show in the front and in the back
You can also try this....
<?php
$email = "abcdlkjlkjk#hotmail.com";
$resultmob = substr($email,0,5);
$resultmob .= "**********";
$resultmob .= substr($email,strpos($email, "#"));
echo $resultmob;
?>
Answer:-
abcdl******#hotmail.com
Another variant that was heavily influenced by the answers already shared.
This has two key extra benefits:
It keeps the first characters after a defined set of delimiters, making it more readable while still preserving privacy.
It works with longer domain endings such as .org.uk and .com.au
Example: firstname.lastname#example.co.uk becomes f********.l*******#e*****.c*.u*
function mask_email( $email ) {
$masked = '';
$show_next = true;
foreach ( str_split( $email ) as $chr ) {
if ( $show_next ) {
$masked .= $chr;
$show_next = false;
}
else if ( in_array( $chr, array('.', '#', '+') ) ) {
$masked .= $chr;
$show_next = true;
}
else {
$masked .= '*';
$show_next = false;
}
}
return $masked;
}
Try this function. This will work with valid emails, such as "Abc\#def"#iana.org.
function hideEmail($email){
$prefix = substr($email, 0, strrpos($email, '#'));
$suffix = substr($email, strripos($email, '#'));
$len = floor(strlen($prefix)/2);
return substr($prefix, 0, $len) . str_repeat('*', $len) . $suffix;
}
echo hideEmail('abcdljtrsjtrsjlkjk#hotmail.com');
echo hideEmail('"abc\#def"#iana.org');
Returns
abcdljtrs*********#hotmail.com
"abc\*****#iana.org
I have a function
function hide_email($email){
$final_str = '';
$string = explode('#', $email);
$leftlength = strlen($string[0]);
$string2 = explode('.', $string[1]);
$string2len = strlen($string2[0]);
$leftlength_new = $leftlength-1;
$first_letter = substr($string[0], 0,1);
$stars = '';
$stars2 = '';
for ($i=0; $i < $leftlength_new; $i++) {
$stars .= '*';
}
for ($i=0; $i < $string2len; $i++) {
$stars2 .= '*';
}
$stars;
return $final_str .= $first_letter.$stars.'#'.$stars2.'.'.$string2[1];
}
echo hide_email('Hello#PHP.com');
There was an issue in case if there would be 1 character before #. I have fixed in below function.
function obfuscate_email($email)
{
$em = explode("#",$email);
if(strlen($em[0])==1){
return '*'.'#'.$em[1];
}
$name = implode(array_slice($em, 0, count($em)-1), '#');
$len = floor(strlen($name)/2);
return substr($name,0, $len) . str_repeat('*', $len) . "#" . end($em);
}
Here is version with only 2 lines (if you remove function stuff).
<?php
function censor_email($str,$amount=2, $char='*') {
list($local, $domain)=explode("#",$str);
return substr($local,0,$amount).str_repeat($char,strlen($local)-$amount)."#".$domain;
}
?>
function maskEmail($email) {
preg_match('/^.?(.*)?.#.+$/', $email, $matches);
return str_replace($matches[1], str_repeat('*', strlen($matches[1])), $email);
}
echo maskEmail('abcdefgh#example.com')
echo maskEmail('abh#example.com')
echo maskEmail('ah#example.com')
echo maskEmail('a#example.com')
returns
a******h#example.com
a*h#example.com
ah#example.com
a#example.com
This is what I did, as I required exact number of string count same as plain email.
This function only shows first & last two characters before "#"
function mask_email($email)
{
$em = explode("#",$email);
$len = strlen($em[0]);
$substr_count = 1;
if($len > 6)
$substr_count = 2;
$first = substr($em[0], 0,$substr_count);
$last = substr($em[0], -$substr_count);
$no_of_star = $len - ($substr_count * 2);
return $first.str_repeat('*', $no_of_star).$last."#".end($em);
}
Though this is an old thread & has many answers already. I want to share my own snippet too.
Which checks if it's a valid email or not.
How much characters to censor & to show.
What character should be used to censor.
function get_censored_email($email, $show_chars = 3, $censor_char = '*'){
if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
$char_length = strlen($email);
$censor_count = $char_length - $show_chars;
$return_email = substr($email, 0, $show_chars);
$return_email .= str_repeat("*", $censor_count);
return $return_email;
}
}
$email = 'noman.ibrahim115#gmail.com';
echo get_censored_email($email, 3, '*'); // returns nom***********************
Method 1:
<?php
function hideEmailAddress($email) {
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
list($first, $last) = explode('#', $email);
$first = str_replace(substr($first, '3'), str_repeat('*', strlen($first)-3), $first);
$last = explode('.', $last);
$last_domain = str_replace(substr($last['0'], '1'), str_repeat('*', strlen($last['0'])-1), $last['0']);
$hideEmailAddress = $first.'#'.$last_domain.'.'.$last['1'];
return $hideEmailAddress;
}
}
$email = "test#example.com";
echo hideEmailAddress($email);
?>
Method 2:
<?php
function hideEmailAddress($email) {
$em = explode("#",$email);
$name = implode(array_slice($em, 0, count($em)-1), '#');
$len = floor(strlen($name)/2);
return substr($name,0, $len) . str_repeat('*', $len) . "#" . end($em);
}
$email = 'test#example.com';
echo hideEmailAddress($email);
?>
This string has 78 characters with HTML and 39 characters without HTML:
<p>I really like the Google search engine.</p>
I want to truncate this string based on the non-HTML character count, so for example if I wanted to truncate the above string to 24 characters, the output would be:
I really like the Google
The truncation did not take into account the html when determining the number of characters to cut off, it only considered the stripped count. However, it didn't leave open HTML tags.
Alright so this is what I put together and it seems to be working:
function truncate_html($string, $length, $postfix = '…', $isHtml = true) {
$string = trim($string);
$postfix = (strlen(strip_tags($string)) > $length) ? $postfix : '';
$i = 0;
$tags = []; // change to array() if php version < 5.4
if($isHtml) {
preg_match_all('/<[^>]+>([^<]*)/', $string, $tagMatches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
foreach($tagMatches as $tagMatch) {
if ($tagMatch[0][1] - $i >= $length) {
break;
}
$tag = substr(strtok($tagMatch[0][0], " \t\n\r\0\x0B>"), 1);
if ($tag[0] != '/') {
$tags[] = $tag;
}
elseif (end($tags) == substr($tag, 1)) {
array_pop($tags);
}
$i += $tagMatch[1][1] - $tagMatch[0][1];
}
}
return substr($string, 0, $length = min(strlen($string), $length + $i)) . (count($tags = array_reverse($tags)) ? '</' . implode('></', $tags) . '>' : '') . $postfix;
}
Usage:
truncate_html('<p>I really like the Google search engine.</p>', 24);
The function was grabbed from (made a small modification):
http://www.dzone.com/snippets/truncate-text-preserving-html
I am using base36 to shorten URLs. I have an id of a blog entry and convert that id to base36 to make it smaller. Base36 only includes lowercase letters. How can I include uppercase letters? If I use base64_encode it actually makes the string longer.
you can find examples of source-code to create short-urls containing letters (both lower and upper case) and number on those two articles, for instance :
Create short IDs with PHP - Like Youtube or TinyURL
Building a URL Shortener
Here is the portion of code used in that second article (quoting) :
$codeset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($codeset);
$n = 300;
$converted = "";
while ($n > 0) {
$converted = substr($codeset, ($n % $base), 1) . $converted;
$n = floor($n/$base);
}
echo $converted; // 4Q
And you can pretty easily encapsulate this in a function -- only thing to consider is that $n is to be received as a parameter :
function shorten($n) {
$codeset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($codeset);
$converted = "";
while ($n > 0) {
$converted = substr($codeset, ($n % $base), 1) . $converted;
$n = floor($n/$base);
}
return $converted;
}
And calling it this way :
$id = 123456;
$url = shorten($id);
var_dump($url);
You get :
string 'w7e' (length=3)
(You can also add some other characters, if needed -- depending on what you want to get in your URLs)
Edit after the comment :
Reading through the second article (from which I got the shortening code), you'll find the code that does the un-shortening.
Encapsulating that code in a function shouldn't be that hard, and might get you something like this :
function unshorten($converted) {
$codeset = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($codeset);
$c = 0;
for ($i = strlen($converted); $i; $i--) {
$c += strpos($codeset, substr($converted, (-1 * ( $i - strlen($converted) )),1))
* pow($base,$i-1);
}
return $c;
}
And calling it with a shortened-url :
$back_to_id = unshorten('w7e');
var_dump($back_to_id);
Will get you :
int 123456
function dec2any( $num, $base=62, $index=false ) {
// Parameters:
// $num - your decimal integer
// $base - base to which you wish to convert $num (leave it 0 if you are providing $index or omit if you're using default (62))
// $index - if you wish to use the default list of digits (0-1a-zA-Z), omit this option, otherwise provide a string (ex.: "zyxwvu")
if (! $base ) {
$base = strlen( $index );
} else if (! $index ) {
$index = substr( "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ,0 ,$base );
}
$out = "";
for ( $t = floor( log10( $num ) / log10( $base ) ); $t >= 0; $t-- ) {
$a = floor( $num / pow( $base, $t ) );
$out = $out . substr( $index, $a, 1 );
$num = $num - ( $a * pow( $base, $t ) );
}
return $out;
}
Shamelessly borrowed from a commenter on PHP's base_convert() page (base_convert() only works up to base 32).