I'm merging two different versions of a translations array. The more recent version has a lot of changes, over several thousand lines of code.
To do this, I loaded and evaluated the new file (which uses the same structure and key names), then loaded and evaluated the older version, overwriting the new untranslated values in the array with the values we already have translated.
So far so good!
However, I want to be able to echo out the constructor for this new merged array so I can cut and paste it into the new translation file, and have job done (apart from completing the rest of the translations..).
The code looks like this (lots of different keys, not just index):
$lang["index"]["chart1_label1"] = "Subscribed";
$lang["index"]["chart1_label2"] = "Unsubscribed";
And the old..
$lang["index"]["chart1_label1"] = "Subscrito";
$lang["index"]["chart1_label2"] = "Não subscrito";
After loading the two files, I end up with a merged $lang array, which I then want to echo out in the same form, so it can be used by the project.
However, when I do something like this..
foreach ($lang as $key => $value) {
if (is_array($value)) {
foreach ($value as $key2 => $value2) {
echo "$lang['".$key."']"; // ... etc etc
}
}
}
..obviously I get "ArrayIndex" etc etc instead of "$lang". How to echo out $lang without it being evaluated..? Once this is working, can add in the rest of the brackets etc (I realise they are missing), but just want to make this part work first.
If there's a better way to do this, all ears too!
Thanks.
edit:
What I was really looking for was this:
"Note: Unlike the three other syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings."
So no need even to escape. May come in handy one day for someone... about merging the arrays, there's a great recursive array merging function on the PHP manual page for array_merge(), which also came in handy.
Thanks to whoever downvoted! Love you too.
Either escape the $: "\$lang" or use single quotes: '$lang'
Note that you really don't need to post a whole page of backstory, if your entire question just boils down to "how do I output a dollar sign in PHP"
there is var_export() function, but I do not understand the purpose of this terrible mess.
It's all too... manual
why not to use a gettext - an industry standard for multi-language site?
or at least some other format, more reliable than plain PHP one?
Programming code is not intended to be written automatically.
Related
What is the best way to debug an array so that you can see what values are being stored and in what keys in the array they are being stored at? Also how do you make it so that it's easier to look at visually so that you don't have to keep looking through the array for the key and it's value in the one line print_r() function?
EDIT:
I now realize that print_r() is not the only solution to debugging arrays. So if you have alternate solutions that would be lovely as well to learn more about debugging.
EDIT2:
Ayesh K, ITroubs and Robert Rozas have mentioned both Krumo and Kint this far, if you have others feel free to post them. Also thanks to Raveren for writing Kint!
Every PHP developer should have a function for this. My function is below:
function r($var){
echo '<pre>';
print_r($var);
echo '</pre>';
}
To nicely print data, just call r($data);. If you want more detail, you could use this function:
function d($var){
echo '<pre>';
var_dump($var);
echo '</pre>';
}
here's mine...
demo: http://o-0.me/dump_r/
repo: https://github.com/leeoniya/dump_r.php
composer: https://packagist.org/packages/leeoniya/dump-r
you can restyle it via css if needed.
Everyone suggests print_r which is in core and works really well.
But when it comes to view a large array, print_r() drives me nuts narrowing down the output.
Give a try to krumo.
It nicely prints the array with visual formatting, click-expand and it also gives you the exact array key call that you can simply copy and paste.
<?php
krumo($my_array);
?>
Itroubs mentioned Kint as a better alternative to Krumo. (Thanks ITroubs!)
I use var_dump....now if you want some more, check out this site:
http://raveren.github.io/kint/
and
http://krumo.sourceforge.net/
The best practice to visually see the values/keys in an array is the following:
echo "<pre>".print_r($array,TRUE)."</pre>";
The true is required as it changes it into a string, the output will be:
array(
key1 => value,
key2 => value,
...
)
Quick solution: Open the source code of the page, and you'll see print_r's output in several lines and perfectly indented.
print_r is not one lined (it uses \n as new line, not <br>). Add a <pre>...</pre> around it to show the multiple lines.
print_r() uses \n as its line delimiter. Use <pre> tags or view the page's source code to make it look right. (on Windows, Linux works with \n)
You can either look source code or use var_dump() or print_r() with <pre>...</pre>
I personally, never liked all this fancy stuff, i use print_r() because it's not overwhelming and it gives enough information.
Here is mine:
if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Debug')
{
echo '<strong><i>FILE : </i></strong>'.__FILE__.'<strong> <i>LINE : </i></strong>'.__LINE__.'<pre>';
print_r($var);
echo '</pre>';
die;
}
This if statement is to ensure that other people don't see what you've printed.
There is a good add-on for Mozila-Firefox and Google Chrome called "user agent switcher", where you can create your custom user agents. So I create a user agent called "Debug", and when I'm working, I change the user agent.
If I use default user agent nothing will happen and the page wont die;, only you and people who also change the user agent to "Debug" will see the printed variable. This is helpful if you want to debug a problem in a production environment, and you don't want the page to die; and it is also good if other people are also working on the project and you don't want to interrupt them by killing the page.
Then I echo out the current File and Line, this is helpful when you work in a framework or CMS or any other big project with thousands of files and folders, and while debugging, if you might forget where you've typed die; or exit; and you need to remember where you've been and which variables you have printed.
I use the NetBeans IDE for PHP development, I have a macro set up so when you select a variable and use it, it will paste this debugging tool to the text editor and put the selection inside a print_r(); function. If you also use NetBeans, you can use this macro:
cut-to-clipboard
"if(isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'Debug')"
insert-break
"{"
insert-break
"echo '<strong><i>FILE : </i></strong>'.__FILE__.'<strong> <i>LINE :</i></strong>'.__LINE__.'<pre>';"
insert-break
"print_r("
paste-from-clipboard
remove-line-begin
");"
insert-break
"echo '</pre>';"
insert-break
"die;"
You just need to select the $variable and use the macro.
To be honest, I'm surprised that print_r() (print human-readable). There are three native functions which each have their advantages and disadvantages in printing data to a document. As mentioned elsewhere on the page, wrapping your output in <pre> ... </pre> tags will be very beneficial in respecting newlines and tabbing when printing to an html document.
The truth is that ALL php developers, from newbie to hobbyist to professional to grand wizard level 999, need to have the following techniques in their toolbox.
Here is a non-exhaustive demo which exposes some of the differences.
var_export() is the format that I use most often. This function wraps strings in single quotes. This is important in identifying trailing whitespace characters and differentiating numeric types versus string types. To maintain the integrity of the output data and permit instant portability of the data into a runnable context, single quotes and backslashes are escaped -- don't let this trip you up.
print_r() is probably my least-used and the least-informative function when data needs to be inspect. It does not wrap strings in any kind of delimiting character so you will not be able to eyeball invisible characters. It will not escape backslashes, single quotes, or double quotes. It wraps keys in square braces which may cause confusion if your keys contain square braces originally.
var_dump() is uniquely powerful in that it expresses data types AND the byte count for strings. This is hands-down the best tool when there is a risk that you might have unexpected multibyte characters interfering with the success/stability of your script.
Depending on your php version and which function you use, you may see differing values with same input data. Pay careful attention to float values.
debug_zval_dump() very much resembles the output of var_dump(), but also includes a refcount. This native function is not likely to provide any additional benefit relating to "debugging an array".
There are also non-native tools which may be of interest (most of which I've never bothered to use). If you are using a framework, Laravel for instance, offers dd() (dump and die) as a diagnostic helper method. Some devs love the collapsed/expandable styling of this tool, but other devs loudly voice their annoyance at the tedious clicking that is necessary to expose nested levels of data.
As a sideways approach to printing iterable data, you could entertain the idea of echoing a json-encoded string with the JSON_PRETTY_PRINT. This may reveal some things that could cause trouble like multibyte and whitespace characters, but don't forget that this is literally "encoding" the data. In other words, it is converting data from one form to another and it will mutate certain occurrences in the process. Like var_export(), a json encoded string is an excellent form to maintain data integrity when it needs to be tranferred from one place to another (like from your project to your Stack Overflow question!).
2 short questions based on trying to make my code more efficient (I think my ultimate quest is to make my entire (fairly complex) website based on some sort of MVC framework, but not being a professional programmer, I think that's going to be a long and steep learning curve..)
In this code, is there a way to merge the if statement and for loop, to avoid the nesting:
if($fileatt['name']!=null)
{
$attachedFiles = "You uploaded the following file(s)\n";
for($i=0;$i<count($docNames);$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}
}
At the moment, I do the fairly standard thing of splitting my $_POST array from a form submission, 'clean' the contents and store the elements in individual variables:
$name = cleanInput($_POST['name']);
$phone = cleanInput($_POST['phone']);
$message = cleanInput($_POST['message']);
...
(where cleanInput() contains striptags() and mysql_real_escape_string())
I had thought that keeping all the information in an array might my code more efficient, but is there a way to apply a function to all (or selected) elements of an array? For example, in R, this is what the apply() function does.
Alternatively, given that all my variables have the same name as in the $_POST array, is there a way to generate all the variables dynamically in a foreach loop? (I know the standard answer when people ask if they can dynamically generate variables is to use a hashmap or similar, but I was interested to see if there's a technique I've missed)
You can use extract and combine it with array_map
extract(array_map('cleanInput', $_POST), EXTR_SKIP);
echo $name; // outputs name
Be warned that $_POST could be anything and user can then submit anything to your server and it becomes a variable in your code, thus if you have things like
if(empty($varName)) { } // assumes $varName is empty initially
Could easily bypassed by user submitting $_POST['varName'] = 1
To avoid mishaps like this, you can have a whitelist of array and filter out only those you need:
$whitelist = array('name', 'phone', 'message');
$fields = array();
foreach($_POST as $k => $v) {
if(in_array($k, $whitelist)) $fields[$k] = $v;
}
extract(array_map('cleanInput', $fields));
1) To the first question, how to merge the if and the for loop:
Why would you want to merge this, it will only make the code more difficult to read. If your code requires an if and afterwards a for loop, then show this fact, there is nothing bad with that. If you want to make the code more readable, then you can write a function, with a fitting name, e.g. listAttachedFiles().
2) To the question about cleaning the user input:
There is a difference between input validation and escaping. It's a good thing to validate the input, e.g. if you expect a number, then only accept numbers as input. But escaping should not be done until you know the target system. So leave the input as it is and before writing to the db use the mysql_real_escape_string() function, before writing to an HTML page use the function htmlspecialchars().
Combining escape functions before needed, can lead to invalid data. It can become impossible to give it out correctly, on a certain target system.
Personally I think that the performance cost of using an "If" statement is worth the benefit of having easily readable code. Also you have to be sure that you actually use fewer cycles by combining, if there is such a way.
I'm not sure I follow your second question, but have you looked at extract() and array_walk() yet?
Point 1 is premature optimization. And you want get any better performance / readability by doing so. (similar for using arrays for everything).
Point 2 - AaaarrgghhH! You should only change the representation of data at the point where it leaves PHP, using a method approporiate to the destination - not where it arrives in PHP.
To make your for loop more efficient don't use Count() within the condition of your loops.
It's the first thing they teach in school. As the For loops are reevaluating the conditions at each iterations.
$nbOfDocs = count($docNames); //will be much faster
for($i=0;$i<$nbOfDocs;$i++)
{
$attachedFiles = $attachedFiles. " - " . $docNames[$i] . "\n";
}
How do Perl hashes work?
Are they like arrays in PHP or some completely different beast?
From what I understand all it is is an associative array right? This is what I thought until I began
to talk to a Perl programmer who told me I was completely wrong, but couldn't explain it in a way
that didn't make my eyes cross.
Anyway, the way that I thought it worked was like this
PHP's:
$argv['dog_name'] = 'missy';
$argv[0] = 'tree';
same as Perl's:
my %argv{'dog_name'} = 'missy';
my $argv[0] = 'tree';
Right? But you cannot print(%argv{'dog_name'}), you have to (revert?) to print($argv{'dog_name'}) which is confusing?
Is it trying to print as a variable now, like you would in PHP, echo $argv['dog_name']; ? Does this mean (again) that a hash is
just a PHP associative array with a % to declare but a $ to access?
I don't know, I'm hoping some PHP/Perl Guru can explain how hashes work, and how similar they are
to PHP's arrays.
To write
$argv['dog_name'] = 'missy';
$argv[0] = 'tree';
in Perl, you would write it as follows:
$argv{dog_name} = 'missy';
$argv{0} = 'tree';
if you had strict on, which you should, then you will need to predeclare the variable:
my %argv;
$argv{dog_name} = 'missy';
$argv{0} = 'tree';
If the above is a bit repetitive for you, you could write it:
my %argv = (
dog_name => 'missy',
0 => 'tree',
);
You can find more detail on the perldata manpage.
In short, the reasons why the sigils change from % to $ is that %hash refers to a plural hash (a list of key value pairs), and $hash{foo} refers to a single element of a hash. This is the same with arrays, where # refers to the full array, and $ refers to a single element. (for both arrays and hashes a leading # sigil with a subscript means a slice of the data, where multiple keys are passed and a list of values are returned)
To elaborate slightly on Ambrose's answer, the reason for your confusion is the difference between the philosophy of using sigils in Perl and PHP.
In PHP, the sigil is attached to the identifyer. E.g. a hash identifyer will ALWAYS have a hash sigil around it.
In Perl, a sigil is attached to the way you are accessing the data structure (are you accessing 1 value, a list of values, or a whole hash of values) - for details see other excellent answers such as Eric's.
%argv{'dog_name'} is a syntax error. You need $argv{'dog_name'} instead.
But you are correct that a perl hash is just an associative array (why perl chose to use a different terminology, I don't know).
For a complete understanding of hashes, I recommend reading any of the vast number of perl tutorials or books that cover the topic. Programming Perl is an excellent choice, or here's a random online tutorial I found as well.
I would, as Flimzy, also recommend Programming Perl. As a recent PHP to Perl convert myself, it has taught me a great deal about the language.
The % symbol is used to create a full 'associative array', as we would think of it. For example, I could create an associative array by doing the following:
%hash = ('key1' => 'value1', 'key2' => 'value2');
I could then print it out like so:
print %hash;
The output would be something like:
'key2value2key1value1'
This is, I believe, known as 'list context', since the % indicates that we are talking about a range of values.
On the other hand, if I wanted to access a single value, we would have to use the $ sigil. This, as 'Programming Perl' tells us, can be thought of as an 'S' for 'Scalar'. We have to use the $ sign whenever we are talking about a singular value.
So, to access an individual item in the array, I would have to use the following syntax:
print $hash{'key1'};
The same is true of arrays. A full array can be created like so:
#array = ('abc', '123');
and then printed like so:
print #array;
But, to access a single element of the array I would type instead:
print $array[0];
There are lots of basic principles here. You should read about 'list context' and 'scalar context' in some detail. Before long you will also want to look at references, which are the things you use to create multimensional structures in Perl. I really would recommend 'Programming Perl'! It was a difficult read in chapters, but it certainly does cover everything you need to know (and more).
The sigil changing really isn't as complicated as you make it sound. You already do this in English without thinking about it.
If you have a set of cars, then you would talk about "these cars" (or "those cars"). That's like an array.
my #cars = ('Vauxhall', 'Ford', 'Rolls Royce');
If you're talking about just one car from that set, you switch to using "this car". That's like a single element from an array.
say $car[1]; # prints 'Ford';
Similar rules also apply to hashes.
I would say your confusion is partly caused by one simple fact. Perl has different sigils for different things. PHP has one sigil for everything.
So whether you're putting something into an array/hash, or getting something out, or declaring a simple scalar variable, in PHP you always use the dollar sign.
With perl you need to be more specific, that's all.
The "sigil", i.e. the character before the variable name, denotes the amount of data being accessed, as follows:
If you say $hash{key}, you are using scalar context, i.e. one value.
For plural or list context, the sigil changes to #, therefore #hash{('key1', 'key2')} returns a list of two values associated with the two keys respectivelly (might be written as #hash{qw(key1 key2)}, too).
%hash is used to acces the hash as a whole.
The same applies to arrays: $arr[0] = 1, but #arr[1 .. 10] = (10) x 10.
I hope that you are not expecting to get a full tutorial regarding perl hashes here. You don't need a Perl guru to explain you hashes, just a simple google search.
http://www.perl.com/pub/2006/11/02/all-about-hashes.html
PS: please increase your accept ratio - 62% is pretty low
Solution?
Apparently there isn't a faster way, I'm okay with that.
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
I am passing in values into a php script. I am using $_GET so the URL looks like this:
/poll_results.php?Sports=tennis&cat=Sports&question=Pick+your+favorite+sports
Now I know how to accept those values and place them into variables like so:
$sports = $_GET['Sports'];
$cat = $_GET['cat'];
$question = $_GET['question'];
Super simple yet if I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason. I know there is a better way of doing this. I have tried list($var, $var, $var) = $_GET but that doesn't work with an associative array just indexed ones (i think).
I also tried variable variables like so:
foreach($_GET as $value) {
$$values = $value;
echo $$values;
}
But that gave me a Notice: Undefined variable: values in poll_results.php on line 14. Line 14 is the $$values = $value. I don't know if that's a big deal or not... but I'm not turning off error reporting as I am still in the process of building the script. It does do what I want it to do though...
Any answers will be copied and pasted into my question so the next person knows :D
Thanks guys!
Your second bit of code is wrong. It ought to be like
foreach ($_GET as $key => $value) {
$$key = $value;
}
if i understand your intent. However, you're basically reinventing register_globals, which....eh. That'll get ya hacked.
If you have certain variables you want to get, you could do like
foreach (array('Sports', 'cat', 'question') as $key)
{
$$key = $_GET[$key];
}
which is less likely to overwrite some important variable (whether by accident or because someone was messing around with URLs).
Use parse_url() to extract the query string from a URL you've got in a string, then parse_str() to extract the individual arguments of the query string.
If you want to pollute your script with the contents of the superglobals, then you can use extract(). however, be aware that this is basically replicating the hideous monstrosity known as "register_globals", and opens all kinds of security vulnerabilities.
For instant, what if one of the original query arguments was _GET=haha. You've now trashed the $_GET superglobal by overwriting it via extract().
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
If I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason.
What you are trying to do will, unless curbed, become a bad habit and even before then is a waste of time.
Type out the variables: your digits like exercise and your brain can take it easy when it doesn't have to figure out which variables are available (or not, or maybe; which would be the case when you use variable variables).
You can use
foreach($_GET as $key => $value)
To preserve the key and value associativity.
Variable variables (the $$value) are a bad idea. With your loop above say you had a variable named $password that is already defined from some other source. Now I can send $_GET['password'] and overwrite your variable! All sorts of nastiness can result from this. It's the same reason why PHP abandoned register_globals which essentially does the same thing.
My advice: use $_POST when possible. It keeps your URLs much cleaner for one thing. Secondly there's no real reason to assign the array to variables anyway, just use them where you need them in the program.
One good reason for this, especially in a large program, is that you'll instantly know where they came from, and that their data should not be trusted.
I just started using php arrays (and php in general)
I have a code like the following:
languages.php:
<?php
$lang = array(
"tagline" => "I build websites...",
"get-in-touch" => "Get in Touch!",
"about-h2" => "About me"
"about-hp" => "Hi! My name is..."
);
?>
index.php:
<div id="about">
<h2><?php echo $lang['about-h2']; ?></h2>
<p><?php echo $lang['about-p']; ?></p>
</div>
I'm using hypens (about-h2) but I'm not sure if this will cause me problems in the future. Any suggestions?
Between camel case and underscores it's personal taste. I'd recommend using whatever convention you use for regular variable names, so you're not left thinking "was this one underscores or camel case...?" and your successor isn't left thinking about all the ways they could torture you for mixing styles. Choose one and stick to it across the board.
That's why hyphens is a very bad idea - also, rarely, you'll want to use something like extract which takes an array and converts its members into regular variables:
$array = array("hello" => "hi", "what-up" => "yup");
extract($array);
echo $hello; // hi
echo $what-up; // FAIL
Personally, I prefer camel case, because it's fewer characters.
I'm actually surprised no one said this yet. I find it actually pretty bad that everyone brings up variable naming standards when we are talking about array keys, not variables.
Functionally wise, you will not have any problems using hyphens, underscores, camelCase in your array keys. You can even use spaces, new lines or null bytes if you want! It will not impact your code's functionality^.
Array keys are either int or string. When you use a string as a key, it is treated as any other string in your code.
That being said, if you are building a standardized data structure, you are better off using the same standard you are using for your variables names.
^ Unless you are planning to typecast to a (stdClass) or use extract(), in which case you should use keys which convert to valid variable names in order to avoid using ->{"My Key Is"} instead of ->myKeyIs. In which case, make sure your keys conform to [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.
You can use what ever feels most compfortable, however, I would not recommend using hypehens.
The common approach is to use camelCase and that is what a lot of standards in frameworks ask for.
I recommend using this.
$thisIsMyVariable
$this-is-not-how-i-would-do-it
Also, you can find that using hyphens could make your variables appear like subtracting. So you have to then use
$object->{”Property-Here”}
Its just not nice. :(
Edit, sorry I just saw that you asked about the question in Array, not variables. Either way, my answer still applies.
I would append all into one word. If not appending it all together, I would either shorten it or use _.
In the long run, whatever you decide to choose just be consistent.
Many folks, including Zend, tell programmers to use camel case, but personally I used underscores as word separators for variable names, array keys, class names and function names. Also, all lowercase, except for class names, where I will use capitals.
For example:
class News
{
private $title;
private $summary;
private $content;
function get_title()
{
return $this->title;
}
}
$news = new News;
The first result in Google for "php code standards" says:
use '_' as the word separator.
don't use '-' as the word separator
But, you can pretty much do whatever you want if you don't already have standards to follow. Just be consistent in what you do.
When looking at your code: Maybe you can even avoid some work with arrays and keys if you use something like gettext http://de2.php.net/manual/en/intro.gettext.php for your internationalization efforts from the very beginning.
This will finally result in
<h2><?php _("About me..."); ?></h2>
or
<?php
$foo = _("About me...");
...
?>
I strongly recommend using underscore to separate words in a variable especially where the language is case sensitive.
For non case sensitive languages like vb, camelCase or CamelCase is best.