Sorry if the title is not enough clear, I didn't know how to write it better.
The situation is that I a have a cron job that sends mails to users. I have language files, and depending in the configuration of the user I want to send the mail in his language.
But I don't know how to do this.
Each language file have constants definitions like:
en.php define('DATE','Date'); define('TIME','Time');
es.php define('DATE','Fecha'); define('TIME','Hora');
And I need to display the correct labels depending the user language, but I'm in a while loop:
while ($row = mysql_fetch_array($res)) {
if ($row['lang'] == en) //load the english labels
}
So I think I can't use something like "include_once" in each iteration.
The problem is that you use PHP Constants for it so once they are set, you can't really change them within the script. Try to rewrite your constants and all references of them into variables.
Let's say that your language files are named like this lang.code.php and the script that will send the email is in sendemail.php. You can do something like this:
In lang.en.php
<?php
$terms['date'] = 'Date';
In lang.es.php
<?php
$terms['date'] = 'Fecha';
In sendemail.php:
<?php
function sendEmail($language = 'en')
{
include "lang.$language.php";
extract($terms);
$to = 'foo#bar.com';
$subject = 'Test';
$body = "The $date today is: " . date('r');
mail(...);
}
foreach($users as $user)
sendEmail($user->preferredLanguage);
You can then reference terms in your language files using their keys in the $terms array. Of course you'd have to create validation checks for the language files, directory traversals, etc. But that's one way to implement it.
If you can't rewrite your code then I suggest putting all of the email contents in one file and use file_get_contents() to fetch the email content via HTTP. Inside that file, you'd have a conditional which loads the language file you need.
Let's say that the file that will generate the email contents is called emailcontent.php, you can do something like this:
In lang.en.php
<?php
define('DATE', 'Date');
In lang.es.php
<?php
define('DATE, 'Fecha');
In emailcontent.php
<?php
require "lang.{$_GET['lang']}.php";
echo 'The ' . DATE . ' today is: ' . date('r');
In sendemail.php
<?php
$to = 'foo#bar.com';
$subject = 'Test';
foreach($users as $user)
{
$contents = file_get_contents('http://yourhost.com/emailcontent.php?lang=en');
mail(...);
}
Of course you need to add some security checks to prevent local file inclusion, access to emailcontent.php, etc. But this is the gist of it. However this has a big overhead in terms of latency and repeated compilation of your PHP code. If there was any other way to clear the global score for each email, then that is the better way to go. But this is the only way I can think of if you can't rewrite your code.
In this can I thing you should store the template to datebase its self, based on language you can fetch from DB
Or
Another way you have to get every variable conditional like
en.php define('DATE_EN','Date'); define('TIME','Time');
es.php define('DATE_FR','Fecha'); define('TIME','Hora');
if ($row['lang'] == en)
DATE_EN
else
DATE_FR
In your case constants will not work, since they cannot be changed during the execution.
Instead, I would recommend including all language information in one file, these can be constants each containing a different array:
langs.php
define('EN', array(
'DATE' => 'Date',
'TIME' => 'Time',
));
define('ES', array(
'DATE' => 'Fecha',
'TIME' => 'Hora',
));
Next, you can add a value to the array $row for each user, or you can use a variable like $lang which will be overwritten every while loop.
require_once 'langs.php' //or include_once
while ($row = mysql_fetch_array($res)) {
if ($row['lang'] == en) { //load the english labels
$lang = EN;
} elseif ($row['lang'] == es {
$lang = ES;
}
echo "Welcome {$row['name']}, today it's {$lang['DATE']}" //will display the corresponding $lang value
}
Related
I am trying to loop through all the php files listed in an array called $articleContents and extract the variables $articleTitle and $heroImage from each.
So far I have the following code:
$articleContents = array("article1.php", "article2.php"); // array of all file names
$articleInfo = [];
$size = count($articleContents);
for ($x = 0; $x <= $size; $x++) {
ob_start();
if (require_once('../articles/'.$articleContents[$x])) {
ob_end_clean();
$entry = array($articleContents[$x],$articleTitle,$heroImage);
array_push($articlesInfo, $entry);
}
The problem is, the php files visited in the loop have html, and I can't keep it from executing. I would like to get variables from each of these files without executing the html inside each one.
Also, the variables $articleTitle and $heroImage also exist at the top of the php file I'm working in, so I need to make sure the script knows I'm calling the variables in the external file and not the current one.
If this is not possible, can you please recommend an alternative method?
Thanks!
Don't do this.
Your PHP scripts should be for your application, not for your data. For your data, if you want to keep it file-based, use a separate file.
There are plenty of formats to choose from. JSON is quite popular. You can use PHP's built-in serialization as well, which has support for more PHP-native types but is not as portable to other frameworks.
A little hacky but seems to works:
$result = eval(
'return (function() {?>' .
file_get_contents('your_article.php') .
'return [\'articleTitle\' => $articleTitle, \'heroImage\' => $heroImage];})();'
);
Where your_article.php is something like:
<?php
$articleTitle = 'hola';
$heroImage = 'como te va';
The values are returned in the $result array.
Explanation:
Build a string of php code where the code in your article scripts are wrapped inside a function that returns an array with the values you want.
function() {
//code of your article.php
return ['articleTitle' => $articleTitle, 'heroImage' => $heroImage];
}
Maybe you must do some adaptations to the strings due <?php ?> tags placements.
Anyway, this stuff is ugly. I'm very sure that it can be refactored in some way.
Your problem (probably) comes down to using parentheses with require. See the example and note here.
Instead, format your code like this
$articlesInfo = []; // watch your spelling here
foreach ($articleContents as $file) {
ob_start();
if (require '../articles/' . $file) { // note, no parentheses around the path
$articlesInfo[] = [
$file,
$articleTitle,
$heroImage
];
}
ob_end_clean();
}
Update: I've tested this and it works just fine.
So i have this code, $value2 is an array of values that I edit.
I have .txt document for each of the variable in the array.. for exemple
sometext_AA.txt
sometext_BB.txt
I currently have over 50 text files, and it make a BIG BIG BIG php files because i have the following code made for each of the files for exemple sometext_AA.txt...
I would like to make one script(the following) so that one script will work for all of my $value2(I do not delete the old texts files when the value are changed so i am unable to just make script to read all different text file, it has to be done that it read the active $value2 and process them...
I am not even sure if I am on the good way but i really hope someone can help me out.
Thank you!
$value2 = array("AA","BB","CC");
foreach($value2 as $value3) {
foreach($random1_' .$value3' as $random2_' .$value3') {
$random3_' .$value3' = 'sometext_.$value3'.txt;
$random4_' .$value3' = json_encode(file_get_contents($random3_' .$value3'));
echo $random4_' .$value3';
}
}
This is a exemple of current text i have in my file, I have a very big php file, and, id like a code to make it simple
foreach($random1_AA as $random2_AA) {
$random3_AA = 'sometext_AA.txt;
$random4_AA = json_encode(file_get_contents($random3_AA));
echo $random4_AA;
}
foreach($random1_BB as $random2_BB) {
$random3_BB = 'sometext_BB.txt;
$random4_BB = json_encode(file_get_contents($random3_BB));
echo $random4_BB;
}
foreach($random1_CC as $random2_CC) {
$random3_CC = 'sometext_CC.txt;
$random4_CC = json_encode(file_get_contents($random3_CC));
echo $random4_CC;
}
foreach($random1_DD as $random2_DD) {
$random3_DD = 'sometext_DD.txt;
$random4_DD = json_encode(file_get_contents($random3_DD));
echo $random4_DD;
}
I think that this is what you are looking for, using the $var_{$var_in_var} syntax that PHP allows (so you can include a variable in a variable name).
$value2 = array("AA","BB","CC");
foreach($value2 as $value3) {
foreach($random1_{$value3} as $random2_{$value3}) {
$random3_{$value3} = 'sometext_'.$value3.'.txt';
$random4_{$value3} = json_encode(file_get_contents($random3_{$value3}));
echo $random4_{$value3};
}
}
However, I stongly advise you to consider the following points in order to make your code maintainable:
Use appropriate variable names representing the real content of each variable (you shoud never use "value1", "value2", etc. as the name tells nothing about the variable content).
Don't use variables in variable names unless absolutely necessary, which is not your case. You can use arrays, which are better suited for doing that.
In fact, I don't even know what $random1_XX and $random2_XX are supposed to be. I don't see you defining them in the code sample you posted.
Here is an example of how clear and concise you code may be if you use my advice and if all you need to read all the files and print them in JSON format (which is the only thing the program sample you posted would be doing after corrections).
$file_codes = array('AA', 'BB', 'CC');
foreach($file_codes as $file_code) {
echo json_encode(file_get_contents('sometext_'.$file_code.'.txt'));
}
Of course, if you have anything else in your program (maybe some code using the variables $random3_XX and $random4_XX?), I cannot guess what it is so I can't really offer you help to optimize this code.
I am writing some code to create fields automatically, which will save me a load of time. I have got most of my code working, but I have came across one error with the code, which is preventing me from achieving my final goal.
The code is as follows:
while ($i <= $numFields) {
$type = "\$field{$i}_Data['type']";
$name = "\$field{$i}_Data['name']";
$placeholder = "\$field{$i}_Data['placeholder']";
$value = "\$field{$i}_Data['value']";
echo '<input type="'.$type.'" name="'.$name.'" placeholder="'.$placeholder.'" value="'.$value.'">';
$i++;
}
The $numFields variable is defined at the top of my script, and I have worked out that it is something to do with how I am setting the variables $type, $name etc.
The end result is to create inputs depending on properties set in variables at the top of the script, The only issue I am having is with the settings of the variables, as said above.
If any extra code/information is needed, feel free to ask.
Thank you.
NOTE - There is no physical PHP error, it's purely an error with this:
"\$field{$i}_Data['value']";
There are a few ways we could write this one out, but they are all extensions of variable expansion and/or variable-variables.
Basically, we just need to put the variable name in a string and then use that string as the variable (much like you're currently doing with $i inside the string):
$type = ${"field{$i}_Data"}['type'];
$name = ${"field{$i}_Data"}['name'];
// ...
However, if you don't mind an extra variable, this can be written more cleanly by saving it like so:
$data = ${"field{$i}_Data"};
$type = $data['type'];
$name = $data['name'];
// ...
I want to use the array function of PHP to translate a website. I have created PHP files with arrays in them for all the text to be translated.
<?php
//ESPANOL
$lang = array(
'work' => 'Trabajo'
'packaging' => 'Empaque'
);
And then I am calling them inside my nav.php file, and will in the content section too.
<?php include('includes/languages/es.php'); ?>
<?php echo $lang['work']; ?>
All pretty straight forward.
What I want to know is how to switch between these array files without editing the HTML, so that I don't have to link to another 'index_es.php' etc. I understand that the link would be something like this, but I don't know how this is going to work.
English
I'm guessing I need to include another file that includes the language files and then the link can choose from them but I don't know what the code would be for this.
Would it involve including a 'lang_directory' above the link and then somehow including from there??
**Also I would like to avoid using Zend/Gettext translation becuase I want to learn this inside out.
You can make another dimension containing the target language. Then pass a GET parameter to select that language. If the language isn't recognized you can fallback to English. Here's a sample.
$languages = array(
'en' => array(
'work' => 'work',
'packaging' => 'packaging'
),
'es' => array(
'work' => 'Trabajo',
'packaging' => 'Empaque'
),
);
// default language to use when the requested isn't found
$defaultLanguage = 'en';
// language requested via GET
$requested = $_GET['locale'];
// use the requested language if it exists, otherwise the default language
$language = isset($languages[$requested]) ? $requested : $defaultLanguage;
// our translations
$translation = $languages[$language];
// "work" translated based on the language
echo $translation['work'];
And the link for Español would look like this.
index.php?locale=es
I'd keep your array system, correct the links into something like index.php?lang=en and then include your file depending on the lang parameter:
if ( isset($_GET['lang']) && file_exists('includes/languages/'.$_GET['lang'].'.php') ){
include_once('includes/languages/'.$_GET['lang'].'.php');
}
And if you want to keep the language parameter in your session, do something like this:
if ( isset($_GET['lang']) && file_exists('includes/languages/'.$_GET['lang'].'.php') ){
$_SESSION['lang'] = $_GET['lang'];
}
if ( !isset($_SESSION['lang']) ){
// Default language
$_SESSION['lang'] = 'en';
}
include_once('includes/languages/'.$_SESSION['lang'].'.php');
One way to do this is by using sessions.
Make a lang.php file that will be used to change between languages.
<?php
//Start session
session_start();
//Do we get a lang variable
if (isset($_GET['lang'])) {
//Make sure we only get the lang filename
$lang = basename($_GET['lang']);
//If the file exists, then save it to session
if (file_exists('includes/languages/' . $lang . '.php'))
$_SESSION['lang'] = $lang;
}
//If the client were refered here (via hyperlink) send them back
if (isset($_SERVER['HTTP_REFERER']))
header('location: ' + $_SERVER['HTTP_REFERER']);
?>
In the header of the files you want multiple languages, insert.
<?php
//Start session
session_start();
//Default language
$lang = 'english';
//If the client have set a language, use that instead
if (isset($_SESSION['lang']))
$lang = $_SESSION['lang'];
//Load language file
include('includes/languages/' . $lang . '.php');
?>
The links to change language will then be like this:
Español|English
Out can also take the code from the lang.php file and put in a included file that will be loaded before the inclusion of language file and remove the HTTP_REFERER redirection.
The links to change language will then be like this:
Español|English
this is my front controller
$pages = array("matches", "boards", "search", "articles", "interviews", "userlist", "teams", "servers", "awards", "gallery", "qids");
if (!$_SERVER['QUERY_STRING']) include('home_en.php');
elseif (isset($_GET['matchid'])) include('matchid.php');
elseif (isset($_GET['boardid'])) include('boardid.php');
elseif (isset($_GET['articleid'])) include('articleid.php');
elseif (isset($_GET['interviewid'])) include('interviewid.php');
elseif (isset($_GET['userid'])) include('profi.php');
elseif (isset($_GET['teamid'])) include('teamid.php');
elseif (isset($_GET['serverid'])) include('serverid.php');
elseif (isset($_GET['awardid'])) include('awardid.php');
elseif (isset($_GET['galleryid'])) include('galleryid.php');
elseif (isset($_GET['threadid'])) include('threadid.php');
elseif (isset($_GET['blogid'])) include('blogid.php');
..
elseif (in_array($_GET['content'], $pages)) include($_GET['content']);
else echo "File not found =(";
could i somehow add the identifiers to the array too? but i want the pages as index.php?matchid=9438 and for regular pages: index.php?content=matches
would really aprricate some ideas
thanks!
My Suggestion, From My Comment is this:
In order to check what type of id it is, you should use two $_GET parameters. One is the type (match, award, server, etc), one is the ID. That way you don't have to check for 500 different $_GET parameters, just the value of 2. Much more standardized.
Second, you want to make all of it under 1 file for the ID showing.
In the spirit of writing less code, not more, it would be relatively easy to change the SQL statement to grab the record based on if $_GET['type'] was match, award, team, etc. This is of course given that they will probably look the same. If they don't, instead of writing new code to grab each type, instead write code to display it differently
All Variables in this code much be validated/sanatized beforehand.
// First Get the Type
$type = $_GET['type'];
// Then the ID
$id = $_GET['id'];
// SANITIZE YOUR DATA. Replace this with your sanitization.
die("SANITIZE YOUR DATA HERE");
// Get Data Here
$sql = "SELECT * FROM table WHERE type=".$type." AND id=".$id;
$data = mysql_query($sql);
// Next, Include a template based on the data.
// Global the variable so it can be used in the file
Global $data;
include($type."-template.php");
I agree with Tom -- you should look into using a framework such as Zend, Cake, Symfony, Kohana, CodeIgniter, ez-Components, or Seagull. The advantage of using a framework is that they have already solved a lot of issues for you, including:
1) How to structure your code
2) How to interpret pretty urls (i.e. /x/1/y/2 instead of ?x=1&y=2)
3) Where to put certain types of code (html, php, configs, etc)
4) How to fix something you can't figure out (because these frameworks have communities)
and much much more...
That being said, maybe you don't want all the overhead of using a framework (it does require you to learn a lot). In that case, I recommend Rasmus Lerdorf's "No Framework PHP Framework". Rasmus is the creator of PHP, so you know he knows his stuff.
Lastly, to answer your actual question, here's how I would do it:
could i somehow add the identifiers to the array too?
i want the pages as index.php?matchid=9438
and for regular pages: index.php?content=matches
Sure, but yes, as Chacha102 said, you will need 2 parameters: $area (page) and $id.
Example: index.php?area=articles&id=2345
Then you can re-organize & simplify your 'front controller' this way:
/index.php
/areas/articles.php
/areas/boards.php
etc.
Instead of naming the templates articleid.php, just call it articles.php -- this way your area name also tells you which template to use.
$valid_areas = array("matches", "boards", "search", "articles",
"interviews", "userlist", "teams", "servers",
"awards", "gallery", "qids");
$area = strtolower(trim($_REQUEST['area'])); //if you are not posting any forms, use $_GET instead
$id = (int)$_REQUEST['id']; //if you are not posting any forms, use $_GET instead
if(!$id)
{
include('home_en.php');
}
if(!in_array($area), $valid_areas))
{
echo 'Sorry, the area you have requested does not exist: '.$area;
exit();
}
else
{
$template = '/templates/'.$area.'.php';
if(!file_exists($template))
{
echo 'Sorry, the file you have requested does not exist: '.$area.' '.$id);
}
else
{
include($template);
}
}
It might help to go ahead and use a framework such as Zend:
http://framework.zend.com/
You could do this:
<?php
$controllerDefault = 'home';
function sanitize($str)
{
return str_replace(array('.', '/', '\\'), '', $str);
}
//Prevent of Remote File Inclusion
$controller = sanitize($_GET['controller']);
$id = intval($_GET['id']);
if (empty($controller))
{
$controller = $controllerDefault;
}
if (!empty($id))
{
$controller .= 'id';
}
$controllerFile = $controller . '.php';
if (!file_exists($controllerFile)
|| $controller == 'index') //for not recursive index.php include :)
{
exit('Controller "'.$controllerFile.'" not exists');
}
include($controllerFile);
?>
Using this code you can use your application like:
http://yoursite.com/index.php //include('home.php')
http://yoursite.com/index.php?id=285230 //include('homeid.php')
http://yoursite.com/index.php?controller=matches //include('matches.php')
http://yoursite.com/index.php?controller=matches&id=28410 //include('matchesid.php')
http://yoursite.com/index.php?controller=notexists //ERROR! Controller "notexists" not exists
http://yoursite.com/index.php?controller=../../etc/passwd //ERROR! Controller "etcpasswd" not exists
I hope you like it
PD: the code is not tested, but I hope you catch my idea