I receive from my MySQL database a multidimensional array
Array
(
[0] => Array
(
[page] => categorypropose
[value] => baby-sitters
[id] => 357960
)
[1] => Array
(
[page] => categorysearch
[value] => adéquate pour garder
[id] => 357961
)
...
)
In this array, I have some ISO-8859-1 to UTF8 conversion to do via a 'homemade' function "loadtext".
But when I do this :
$array = $query->result_array();
foreach($array as &$k)
{
foreach ($k as &$value)
{
//Works
$value = $this->loadtext($value, 'ISO-8859-1');
}
}
//Back to normal as $this->loadtext never existed
print_r($array);
It doesn't conserve the changes (When I echo $value, it works, but the modification is not kept at the end ...)
EDIT : This is the function loadtext that I am oblige to use (actually, I didn't make it but I have to use it ...)
function loadtext($text,$charset){
$text = stripslashes($text);
if($charset!="UTF-8")
$text = iconv("UTF-8",$charset,$text);
$text = str_replace(" :"," :",$text);
$text = str_replace(" ;"," ;",$text);
$text = str_replace(" !"," !",$text);
$text = str_replace(" ?"," ?",$text);
$text = str_replace(" ."," .",$text);
$text = str_replace(" …"," …",$text);
return $text;
}
You could try it like this:
$array = $query->result_array();
foreach($array as &$k)
{
foreach ($k as $i => &$value)
{
//Works
$k[$i] = $this->loadtext($value, 'ISO-8859-1');
}
}
//Back to normal as $this->loadtext never existed
print_r($array);
But better yet, you could try using the MySQL function CONVERT() in your query so that the strings you get back are already in UTF8 format.
http://dev.mysql.com/doc/refman/5.0/en/charset-convert.html
At the very least, use PHP's mb_convert_encoding() instead of your homemade function. There's no reason to reinvent the wheel.
http://jp2.php.net/manual/en/function.mb-convert-encoding.php
I found a simple answer myself which works very wellfor me bur using another method in php to change the value i get from mysql result
// ur array from mysql
$array = $query->result_array();
//try it works 100 % for me just one line of code to modify
$result= iconv('UTF-8', 'ASCII//TRANSLIT',$array);
source : php.net
// or if doesnt work then u can try like this to modify u can put it inside a foreach loop where you are loopin values
$page = array['page']; // to acces that element in the array where to modify
$result= iconv('UTF-8', 'ASCII//TRANSLIT',$page);
It occurred to me that there's another solution to this particular problem that avoids the issue of modifying an array by reference altogether.
$array = array_map(function ($row) {
return array_map(function ($col) { return mb_convert_encoding($col, 'ISO-8859-1'); }, $row);
}, $query->result_array());
This uses anonymous functions which are only available since PHP 5.3 so, if you have something older, you'll have to implement it differently and it might not be worth the trouble but I think it's a pretty good way to go.
Also, it may be more efficient/look cleaner to do it like this:
$colFn = function ($col) { return mb_convert_encoding($col, 'ISO-8859-1'); };
$rowFn = function ($row) use ($colFn) { return array_map($colFn, $row); };
$array = array_map($rowFn, $query->result_array());
Related
I have string like this
$string = 'title,id,user(name,email)';
and I want result to be like this
Array
(
[0] => title
[1] => id
[user] => Array
(
[0] => name
[1] => email
)
)
so far I tried with explode function and multiple for loop the code getting ugly and i think there must be better solution by using regular expression like preg_split.
Replace the comma with ### of nested dataset then explode by a comma. Then make an iteration on the array to split nested dataset to an array. Example:
$string = 'user(name,email),office(title),title,id';
$string = preg_replace_callback("|\(([a-z,]+)\)|i", function($s) {
return str_replace(",", "###", $s[0]);
}, $string);
$data = explode(',', $string);
$data = array_reduce($data, function($old, $new) {
preg_match('/(.+)\((.+)\)/', $new, $m);
if(isset($m[1], $m[2]))
{
return $old + [$m[1] => explode('###', $m[2])];
}
return array_merge($old , [$new]);
}, []);
print '<pre>';
print_r($data);
First thanks #janie for enlighten me, I've busied for while and since yesterday I've learnt a bit regular expression and try to modify #janie answer to suite with my need, here are my code.
$string = 'user(name,email),title,id,office(title),user(name,email),title';
$commaBetweenParentheses = "|,(?=[^\(]*\))|";
$string = preg_replace($commaBetweenParentheses, '###', $string);
$array = explode(',', $string);
$stringFollowedByParentheses = '|(.+)\((.+)\)|';
$final = array();
foreach ($array as $value) {
preg_match($stringFollowedByParentheses, $value, $result);
if(!empty($result))
{
$final[$result[1]] = explode('###', $result[2]);
}
if(empty($result) && !in_array($value, $final)){
$final[] = $value;
}
}
echo "<pre>";
print_r($final);
After migrating some content from WordPress to Drupal, I've got som shortcodes that I need to convert:
String content:
Irrelevant tekst...
[sublimevideo class="sublime"
poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png"
src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v"
src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v"
width="560" height="315"]
..more irrelevant text.
I need to find all variables within the shortcode [sublimevideo ...] and turn it into an array:
Array (
class => "sublime"
poster => "http://video.host.com/_previews/600x450/sbx-60025-00-da-FMT.png"
src1 => "http://video.host.com/_video/H.264/LO/sbx-60025-00-da-FMT.m4v"
src2 => "(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-FMT.m4v"
width => "560"
height => "315"
)
And preferably handle multiple instances of the shortcode.
I guess it can be done with preg_match_all() but I've had no luck.
This will give you what you want.
$data = 'Irrelevant tekst... [sublimevideo class="sublime" poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png" src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v" src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v" width="560" height="315"] ..more irrelevant text.';
$dat = array();
preg_match("/\[sublimevideo (.+?)\]/", $data, $dat);
$dat = array_pop($dat);
$dat= explode(" ", $dat);
$params = array();
foreach ($dat as $d){
list($opt, $val) = explode("=", $d);
$params[$opt] = trim($val, '"');
}
print_r($params);
In anticipation of the next challenge you will face with processing short codes you can use preg_replace_callback to replace the short tag data with it's resultant markup.
$data = 'Irrelevant tekst... [sublimevideo class="sublime" poster="http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png" src1="http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v" src2="(hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v" width="560" height="315"] ..more irrelevant text.';
function processShortCode($matches){
// parse out the arguments
$dat= explode(" ", $matches[2]);
$params = array();
foreach ($dat as $d){
list($opt, $val) = explode("=", $d);
$params[$opt] = trim($val, '"');
}
switch($matches[1]){
case "sublimevideo":
// here is where you would want to return the resultant markup from the shorttag call.
return print_r($params, true);
}
}
$data = preg_replace_callback("/\[(\w+) (.+?)]/", "processShortCode", $data);
echo $data;
You could use the following RegEx to match the variables:
$regex = '/(\w+)\s*=\s*"(.*?)"/';
I would suggest to first match the sublimevideo shortcode and get that into a string with the following RegEx:
$pattern = '/\[sublimevideo(.*?)\]/';
To get the correct array keys I used this code:
// $string is string content you specified
preg_match_all($regex, $string, $matches);
$sublimevideo = array();
for ($i = 0; $i < count($matches[1]); $i++)
$sublimevideo[$matches[1][$i]] = $matches[2][$i];
This returns the following array: (the one that you've requested)
Array
(
[class] => sublime
[poster] => http://video.host.com/_previews/600x450/sbx-60025-00-da-ANA.png
[src1] => http://video.host.com/_video/H.264/LO/sbx-60025-00-da-ANA.m4v
[src2] => (hd)http://video.host.com/_video/H.264/HI/sbx-60025-00-da-ANA.m4v
[width] => 560
[height] => 315
)
This is my interpretation, I come from a WordPress background and tried to recreate the setup for a custom php project.
It'll handle things like [PHONE] [PHONE abc="123"] etc
The only thing it falls flat on is the WordPress style [HERE] to [HERE]
Function to build a list of available shortcodes
// Setup the default global variable
function create_shortcode($tag, $function)
{
global $shortcodes;
$shortcodes[$tag] = $function;
}
define shortcodes individually, e.g. [IFRAME url="https://www.bbc.co.uk"]:
/**
* iframe, allows the user to add an iframe to a page with responsive div wrapper
*/
create_shortcode('IFRAME', function($atts) {
// ... some validation goes here
// The parameters that can be set in the shortcode
if (empty($atts['url'])) {
return false;
}
return '
<div class="embed-responsive embed-responsive-4by3">
<iframe class="embed-responsive-item" src="' . $atts['url'] . '">
</iframe>
</div>';
});
Then when you want to pass a block of html via the shortcode handling do... handle_shortcodes($some_html_with_shortcodes);
function handle_shortcodes($content)
{
global $shortcodes;
// Loop through all shortcodes
foreach($shortcodes as $key => $function){
$matches = [];
// Look for shortcodes, returns an array of ALL matches
preg_match_all("/\[$key([^_^\]].+?)?\]/", $content, $matches, PREG_UNMATCHED_AS_NULL);
if (!empty($matches))
{
$i = 0;
$full_shortcode = $matches[0];
$attributes = $matches[1];
if (!empty($attributes))
{
foreach($attributes as $attribute_string) {
// Decode the values (e.g. " to ")
$attribute_string = htmlspecialchars_decode($attribute_string);
// Find all the query args, looking for `arg="anything"`
preg_match_all('/\w+\=\"(.[^"]+)\"/', $attribute_string, $query_args);
$params = [];
foreach ($query_args[0] as $d) {
// Split the
list($att, $val) = explode('=', $d, 2);
$params[$att] = trim($val, '"');
}
$content = str_replace($full_shortcode[$i], $function($params), $content);
$i++;
}
}
}
}
return $content;
}
I've plucked these examples from working code so hopefully it's readable and doesn't have any extra functions exclusive to our setup.
As described in this answer, I'd suggest letting WordPress do the work for you using the get_shortcode_regex() function.
$pattern = get_shortcode_regex();
preg_match_all("/$pattern/",$wp_content,$matches);
This will give you an array that is easy to work with and shows the various shortcodes and affiliated attributes in your content. It isn't the most obvious array format, so print it and take a look so you know how to manipulate the data you need.
From what I understand youtube.com uses three types of urls for their video links.
http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related
http://www.youtube.com/watch?v=8uLPtmCroQ8
http://youtu.be/8uLPtmCroQ8
I get this url submitted to my site in any one of these different ways and I store the url into a custom field called $video_code. I need to strip it of any parameters that come after the id of the video so if a user submit the first url above, &feature=related gets stripped. I'm using php.
If I understand your problem correctly, You could use something like this to store the video id in the databse and then construct the url as you like.
function getVideoId($url)
{
$parsedUrl = parse_url($url);
if ($parsedUrl === false)
return false;
if (!empty($parsedUrl['query']))
{
$query = array();
parse_str($parsedUrl['query'], $query);
if (!empty($query['v']))
return $query['v'];
}
if (in_array(strtolower($parsedUrl['host']), array('youtu.be', 'www.youtu.be')))
return trim($parsedUrl['path'], '/');
return false;
}
$input = array('http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related', 'http://www.youtube.com/watch?v=8uLPtmCroQ8', 'http://youtu.be/8uLPtmCroQ8');
foreach ($input as $url)
{
echo getVideoId($url) . PHP_EOL;
}
In which language did you want to this? If it is in PHP you should look at this.
You could also do a regular expressions to split the string. Take a look here: http://www.php.net/manual/en/function.preg-split.php
Use this code:
$arr=array(
'http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related',
'http://www.youtube.com/watch?v=8uLPtmCroQ8',
'http://youtu.be/8uLPtmCroQ8',
);
for($i=0; $i<count($arr); $i++){
$urlarr = parse_url($arr[$i]);
if (!empty($urlarr['query'])) {
parse_str($urlarr['query']);
$qarr = array();
if (!empty($v))
$qarr['v'] = $v;
$urlarr['query'] = http_build_query($qarr);
$arr[$i] = http_build_url('', $urlarr);
}
}
print_r($arr);
OUTPUT:
Array
(
[0] => http://www.youtube.com/watch?v=8uLPtmCroQ8
[1] => http://www.youtube.com/watch?v=8uLPtmCroQ8
[2] => http://youtu.be/8uLPtmCroQ8
)
function getVideoCode($url){
$videoCode;
$code_parse = parse_url($url);
if(empty($code_parse["query"])){
$videoCode = str_replace("/"," ",$code_parse["path"]);
}else{
$videoCode = clearQuery($code_parse["query"]);
}
echo $videoCode;
}
function clearQuery($query){
$redundant = array("v", "&", "feature","=","related");
return str_replace($redundant," ",$query);
}
It is not a professional code but It's easy to understand.When I call like this:
getVideoCode("http://youtu.be/8uLPtmCroQ8");
getVideoCode("http://www.youtube.com/watch?v=8uLPtmCroQ8");
getVideoCode("http://www.youtube.com/watch?v=8uLPtmCroQ8&feature=related");
The Output is
8uLPtmCroQ8
8uLPtmCroQ8
8uLPtmCroQ8
I am using this function to translate stuff:
function t($string)
{
global $_ACTIVE_LANGUAGE;
if(is_array($_ACTIVE_LANGUAGE) && array_key_exists($string,$_ACTIVE_LANGUAGE) )
{
return (!empty($_ACTIVE_LANGUAGE[$string])) ? $_ACTIVE_LANGUAGE[$string] : $string;
} else {
return $string;
}
}
It works well, I put t('hola') and if there's the english file with the array 'hola' => 'hello' it translates it.
However, now I want to be able to translate strings which can contain more text than just the string, like this example:
$string1 = 'download-file-justin-bieber-awesome-voice.html';
$string2 = 'view-file-rihanna-very-sexy.html';
$string3 = 'mostseen12345.html';
$string4 = 'incredible:stuff-and:real-things.html';
$array = array
(
'download-file' => 'descargar-archivo',
'view-file' => 'ver-archivo',
'mostseen' => 'masvistos',
'incredible:stuff' = 'cosas:increibles'
}
I want the script to be able to translate the parts in the keys of the array in the given strings. Is this possible at all?
You could check out str_replace() at the php-manual.
$from = array('download-file','view-file','mostseen','incredible:stuff');
$to = array('descargar-archivo','ver-archivo','masvistos','cosas:increibles');
$translated_string = str_replace($from,$to,$original_string);
I have some php files that includes some language constants
define("_SEARCH","Search");
define("_LOGIN","Login");
define("_WRITES","writes");
define("_POSTEDON","Posted on");
define("_NICKNAME","Nickname");
now I need to read each file and list all constants and their values
and to return an output like this :
constant name :
value is :
so I think there should be function to list all defined constants of a given php file.
I'm aware of functions like token_get_all or get_defined_constants but i wasn't able to do it.
If the files do contain nothing but define statements, you can use get_defined_constants:
function getUserDefinedConstants() {
$constants = get_defined_constants(true);
return (isset($constants['user']) ? $constants['user'] : array());
}
$constantsBeforeInclude = getUserDefinedConstants();
include('file.php');
$constantsAfterInclude = getUserDefinedConstants();
$newConstants = array_diff_assoc($constantsAfterInclude, $constantsBeforeInclude);
What it does is basically: get_defined_constants(true) gives us an array of arrays with all available constants, sorted by sections (core, user, ..) - the array under the key 'user' gives us all user-defined constants that we defined in our php code using define, up to that point. array_diff_assoc gives us the difference between this array before and after the file got included.. and that is exactly a list of all constants that got defined in that specific file (as long as there is none of the declarations a duplicate, meaning a constant with that exact name has been defined before - but this would cause an error anyway).
this is the php script you need:
<?php
//remove comments
$Text = php_strip_whitespace("your_constants_file.php");
$Text = str_replace("<?php","",$Text);
$Text = str_replace("<?","",$Text);
$Text = str_replace("?>","",$Text);
$Lines = explode(";",$Text);
$Constants = array();
//extract constants from php code
foreach ($Lines as $Line) {
//skip blank lines
if (strlen(trim($Line))==0) continue;
$Line = trim($Line);
//skip non-definition lines
if (strpos($Line,"define(")!==0) continue;
$Line = str_replace("define(\"","",$Line);
//get definition name & value
$Pos = strpos($Line,"\",\"");
$Left = substr($Line,0,$Pos);
$Right = substr($Line,$Pos+3);
$Right = str_replace("\")","",$Right);
$Constants[$Left] = $Right;
}
echo "<pre>";
var_dump($Constants);
echo "</pre>";
?>
The result will be something similar to this:
array(5) {
["_SEARCH"]=>
string(6) "Search"
["_LOGIN"]=>
string(5) "Login"
["_WRITES"]=>
string(6) "writes"
["_POSTEDON"]=>
string(9) "Posted on"
["_NICKNAME"]=>
string(8) "Nickname"
}
Late to the game here but I had a similar issue. You could use an include() substitute/wrapper function that logs constants in an accessible global array.
<?php
function include_build_page_constants($file) {
global $page_constants ;
$before = get_defined_constants(true);
include_once($file);
$after = get_defined_constants(true);
if ( isset($after['user']) ) {
if ( isset($before['user']) ) {
$current = array_diff_assoc($after['user'],$before['user']);
}else{
$current = $after['user'];
}
$page_constants[basename($file)]=$current;
}
}
include_and_build_page_constants('page1.php');
include_and_build_page_constants('page2.php');
// test the array
echo '<pre>'.print_r($page_constants,true).'</pre>';
?>
This will result in something like:
Array
(
[page1.php] => Array
(
[_SEARCH] => Search
[_LOGIN] => Login
[_WRITES] => writes
[_POSTEDON] => Posted on
[_NICKNAME] => Nickname
)
[page2.php] => Array
(
[_THIS] => Foo
[_THAT] => Bar
)
)
Assuming that you want to do this on runtime, you should take a look at PHP Reflection, specifically at the ReflectionClass::getConstants() which lets you do exactly what you seem to want.
I too had the same problem. I went from jondinham's suggestion, but I prefer to use regex, as it is a bit easier to control and flexible. Here's my version of the solution:
$text = php_strip_whitespace($fileWithConstants);
$text = str_replace(array('<?php', '<?', '?>'), '', $text);
$lines = explode(";", $text);
$constants = array();
//extract constants from php code
foreach ($lines as $line) {
//skip blank lines
if (strlen(trim($line)) == 0)
continue;
preg_match('/^define\((\'.*\'|".*"),( )?(.*)\)$/', trim($line), $matches, PREG_OFFSET_CAPTURE);
if ($matches) {
$constantName = substr($matches[1][0], 1, strlen($matches[1][0]) - 2);
$constantValue = $matches[3][0];
$constants[$constantName] = $constantValue;
}
}
print_r($constants);