Question
I have a fairly static website with just a few basic PHP usage. Now the customer would like to have this website translated. I do have a solution, but it's cumbersome and I was wondering how others are doing it and what is the standard (in frameworks, etc.).
My Way
My way (I have simplified it a bit for the sake of easier understanding): I generate a PHP array for each language from the database and store this array in a language file, like es.php for Spanish.
I then translate a string in HTML using a tr function like this:
Before:<h1>Hello World</h1>
After: <h1><?php echo tr('Hello World'); ?></h1> which gives <h1>Hola Mundo</h1> for Spanish.
The Problem
This is cumbersome and error prone. I have to go through each .php file and replace all the hardcoded strings with this PHP tag with echo.
Is there a better way? How are others doing it? If needed, I can elaborate on my implementation.
You should look into the PHP GETTEXT extension, it is very fast and will scan your PHP files for strings to translate with .MO and .PO files
You then can simply do something like __('Hello World'); or if you already have all the strings with tr('Hello World'); then you could just modify the tr function to pass it through __(string) or gettext(string) like..
function tr($string){
__($string)
}
A little late for you, I suppose but in case someone like me stumbles across this thread... Because I currently have the same problem you do.
Unfortunately, there doesn't appear to be a "non-cumbersome way" to do this with PHP. Everything seems to involve lots of function-calls (if you have a lot of text).
Well... there is ONE convenient way. Not exactly safe though. Manipulating the output buffer before it's sent to the user:
=> http://dev-tips.com/featured/output-buffering-for-web-developers-a-beginners-guide
So you could depending on the language chosen just define an array filled with "from->to"-data and replace all the readable text in your buffer by looping through that.
But of course... if you e.g. replace "send" (English) with "senden" (German) and you link to a "send.html", it would break that link.
So if one has to translate not only long, definitely unique strings but also shorter ones, one would have to manipulate only the text that is readable to the user. There is a solution for that too - however, that is JavaScript based:
=> http://www.isogenicengine.com/documentation/jquery-multi-language-site-plugin/
You could always punt and translate your site using Google's Tools and Resources.
Generally, I consider a multilingual site no longer to be "static". I use Drupal to implement sites. It has some excellent internationalization options.
Try this solution. It works for me. It has french and english translation.
Index.php
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>How to Translate your Site in Runtime using Jquery - demo</title>
<link rel="stylesheet" href="css/main.css" type="text/css" />
<script src="js/jquery.min.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<div class="example">
<h3>How to Translate your Site in Runtime using Jquery - demo</h3>
<div id="content">
<div class="lang_switcher">
<button id="en" class="lang">EN</button>
<button id="fr" class="lang">FR</button>
</div>
<div style="clear:both;"></div>
<!-- nav menu start -->
<ul id="nav">
<li>Home</li>
<li>Peoples >>
<ul>
<li>All list</li>
<li>Online</li>
</ul>
</li>
<li>Articles >>
<ul>
<li>JavaScript</li>
<li>PHP</li>
<li>HTML</li>
<li>CSS</li>
</ul>
</li>
<li>Contact us</li>
</ul>
<!-- nav menu end -->
<div style="clear:both;"></div>
<h2 key="welcome" class="tr">Welcome guests</h2>
<hr />
<div key="a_man" class="tr">A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.</div>
</div>
</div>
</body>
</html>
main.js
// preparing language file
var aLangKeys=new Array();
aLangKeys['en']=new Array();
aLangKeys['fr']=new Array();
aLangKeys['en']['home']='Home';
aLangKeys['en']['peoples']='Peoples >>';
aLangKeys['en']['all_list']='All list';
aLangKeys['en']['online']='Online';
aLangKeys['en']['articles']='Articles >>';
aLangKeys['en']['js']='JavaScript';
aLangKeys['en']['php']='PHP';
aLangKeys['en']['html']='HTML';
aLangKeys['en']['css']='CSS';
aLangKeys['en']['contact_us']='Contact us';
aLangKeys['en']['welcome']='Welcome guests';
aLangKeys['en']['a_man']='A man bribes a rabbit with wicked dentures to run away with him in a sailboat via an ambulance. Bribing Koalas to remain illegally in one place. Trees anchor me in place. / Your mom drives the ambulance, but the city is farther than it appears.';
aLangKeys['fr']['home']='Accueil';
aLangKeys['fr']['peoples']='Peuples >>';
aLangKeys['fr']['all_list']='Toutes les listes';
aLangKeys['fr']['online']='En ligne';
aLangKeys['fr']['articles']='Articles >>';
aLangKeys['fr']['js']='JavaScript';
aLangKeys['fr']['php']='Php';
aLangKeys['fr']['html']='Html';
aLangKeys['fr']['css']='Css';
aLangKeys['fr']['contact_us']='Contactez nous';
aLangKeys['fr']['welcome']='Bienvenue aux invites';
aLangKeys['fr']['a_man']="Un homme soudoie un lapin avec des prothèses méchantes pour s'enfuir avec lui dans un voilier via une ambulance. Corruption des Koalas pour qu'ils restent illégalement à un endroit. Les arbres m'ancrent en place. / Votre mère conduit l'ambulance, mais la ville est plus loin qu'il n'y paraît.";
$(document).ready(function() {
// onclick behavior
$('.lang').click( function() {
var lang = $(this).attr('id'); // obtain language id
// translate all translatable elements
$('.tr').each(function(i){
$(this).text(aLangKeys[lang][ $(this).attr('key') ]);
});
} );
});
And some css- main.css
body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0}
.example{background:#FFF;width:500px;height:500px;font-size:80%;border:1px #000 solid;margin:0.5em 10% 0.5em;padding:1em 2em 2em;-moz-border-radius:3px;-webkit-border-radius:3px}
.lang_switcher{float:right;overflow:hidden;}
/* nav menu styles */
#nav,#nav ul{list-style:none;font:10px verdana, sans-serif;border:1px solid #000;background:#fff;position:relative;z-index:200;border-color:#eca #b97 #a86 #edb;border-width:1px 2px 2px 1px;margin:0;padding:0 0 5px}
#nav{height:25px;padding:0}
#nav table{border-collapse:collapse}
#nav li{float:left;padding:0 20px 0 10px}
#nav li li{float:none}
#nav li a li{float:left}
#nav li a{display:block;float:left;color:#888;height:25px;padding-right:5px;line-height:25px;text-decoration:none;white-space:nowrap}
#nav li li a{height:20px;line-height:20px;float:none}
#nav li:hover{position:relative;z-index:300;background:#fff}
#nav a:hover{position:relative;z-index:300;text-decoration:underline;color:#b75}
#nav :hover ul{left:0;top:22px}
#nav a:hover ul{left:-10px}
#nav li:hover li:hover > ul{left:-15px;margin-left:100%;top:-1px}
#nav li:hover > ul ul{position:absolute;left:-9999px;top:-9999px;width:auto}
#nav li:hover > a{text-decoration:underline;color:#b75}
#nav a:hover a:hover ul,#nav a:hover a:hover a:hover ul,#nav a:hover a:hover a:hover a:hover ul,#nav a:hover a:hover a:hover a:hover a:hover ul{left:100%;top:-1px}
#nav ul,#nav a:hover ul ul,#nav a:hover a:hover ul ul,#nav a:hover a:hover a:hover ul ul,#nav a:hover a:hover a:hover a:hover ul ul{position:absolute;left:-9999px;top:-9999px}
Do way i translate my website is
Under doctype have lang then your selected lang, eg below,
Then create a php function to get this by $_POST['get'],
and have have that function load up the selected language file/db etc,
I made a class to do mine
class WILang
{
function __construct()
{
$this->WIdb = WIdb::getInstance();
}
public static function all($jsonEncode = true) {
// determine lanuage
$language = self::getLanguage();
//echo $language;
$WIdb = WIdb::getInstance();
//$file = WILang::getFile($language);
//echo $file;
//echo $language;
if ( ! self::isValidLanguage($language) )
die('Language file doesn\'t exist!');
else {
$sql = "SELECT * FROM `wi_trans` WHERE `lang` = :file";
$query = $WIdb->prepare($sql);
$query->bindParam(':file', $language, PDO::PARAM_STR);
$query->execute();
//$result = array();
while ($result = $query->fetchAll(PDO::FETCH_ASSOC)) {
echo "{";
foreach ($result as $res) {
echo '"' .$res['keyword'] .'":"' . $res['translation'] . '",';
//return array($res['keyword'] => $res['translation'] ,);
}
echo "}";
}
}
}
public static function get($key ) //, $bindings = array()
{
// determine language
$language = self::getLanguage();
$WIdb = WIdb::getInstance();
$sql = "SELECT * FROM `wi_trans` WHERE `keyword`=:key AND lang=:lang";
$query = $WIdb->prepare($sql);
$query->bindParam(':key', $key, PDO::PARAM_STR);
$query->bindParam(':lang', $language, PDO::PARAM_STR);
$query->execute();
$res = $query->fetch(PDO::FETCH_ASSOC);
if($res > 0)
return $res['translation'];
else
return '';
}
public static function setLanguage($language)
{
// check if language is valid
if ( self::isValidLanguage($language) ) {
//set language cookie to 1 year
setcookie('wi_lang', $language, time() + 60 * 60 * 24 * 365, '/');
// update session
WISession::set('wi_lang', $language);
//refresh the page
header('Location: ' . $_SERVER['PHP_SELF']);
}
}
public static function getLanguage()
{
// check if cookie exist and language value in cookie is valid
if ( isset ( $_COOKIE['wi_lang'] ) && self::isValidLanguage ( $_COOKIE['wi_lang'] ) )
return $_COOKIE['wi_lang']; // return lang from cookie
else
return WISession::get('wi_lang', DEFAULT_LANGUAGE);
}
private static function getTrans($language)
{
$WIdb = WIdb::getInstance();
//$file = WILang::getFile($language);
//echo $file;
//echo $language;
if ( ! self::isValidLanguage($language) )
die('Language file doesn\'t exist!');
else {
//$language = include $file;
//return $language;
$sql = "SELECT * FROM `wi_trans` WHERE `lang` = :file";
$query = $WIdb->prepare($sql);
$query->bindParam(':file', $language, PDO::PARAM_STR);
$query->execute();
//$result = array();
while ($result = $query->fetchAll(PDO::FETCH_ASSOC)) {
echo "{";
foreach ($result as $res) {
echo '"' .$res['keyword'] .'":"' . $res['translation'] . '",';
//return array($res['keyword'] => $res['translation'] ,);
}
echo "}";
}
}
}
private static function getFile($language)
{
$WIdb = WIdb::getInstance();
$sql = "SELECT * FROM `wi_lang` WHERE `lang` = :file";
$query = $WIdb->prepare($sql);
$query->bindParam(':file', $language, PDO::PARAM_STR);
$query->execute();
$res = $query->fetch(PDO::FETCH_ASSOC);
//echo $res['lang'];
if ($res > 0)
return $res['lang'];
else
return '';
}
private static function isValidLanguage($lang)
{
$file = self::getFile($lang);
//echo $file;
if($file == "")
//if ( ! file_exists( $file ) )
return false;
else
return true;
}
}
Related
How can I create a dynamic menu created in a database?
A sample of the menu table :
ID NAME URL IDPARENT
----------------------------------
1 Accueil #Accueil 0
2 Parcs #Parcs 0
3 Allemagne #Allemagne 2
4 Berlin #Berlin 3
5 France #France 2
6 Contact #Contact 0
The result should be :
<ul>
<li>Accueil</li>
<li>Parcs</li>
<ul>
<li>Allemagne</li>
<ul>
<li>Berlin</li>
</ul>
<li>France</li>
</ul>
<li>Contact</li>
</ul>
SOLVED : My code :
<?php
//connection to the database
$dbhandle = mssql_connect('*****', '*****', '*****')
or die("Couldn't connect to Server");
//select a database to work with
$selected = mssql_select_db("*****", $dbhandle)
or die("Couldn't open database");
//declare the SQL statement that will query the database
$query = "SELECT * FROM CATEGORIES ";
//execute the SQL query and return records
$result = mssql_query($query);
//display the results
while($row = mssql_fetch_array($result))
{
// Assign by reference
$thisref = &$refs[ $row['ID'] ];
// add the the menu parent
$thisref['IDCategoriePere'] = $row['IDCategoriePere'];
$thisref['NOM'] = $row['NOM'];
$thisref['URL'] = $row['URL'];
// if there is no parent id
if ($row['IDCategoriePere'] == 0)
{
$list[ $row['ID'] ] = &$thisref;
}
else
{
$refs[ $row['IDCategoriePere'] ]['children'][ $row['ID'] ] = &$thisref;
}
}
function create_menu( $arr )
{
$html = "\n<ul>\n";
foreach ($arr as $key=>$val)
{
$html .= '<li>'.$val['NOM']."</li>\n";
if (array_key_exists('children', $val))
{
$html .= create_menu($val['children']);
}
}
$html .= "</ul>\n";
return $html;
}
echo create_menu( $list );
//close the connection
mssql_close($dbhandle);
?>
It works fine ! but when i tried to put css (http://cssmenumaker.com/menu/flat-jquery-responsive-menu), the dropdown doesn't show :(
Result with and witout css :
<style>
/* CSS Document */
#import url(http://fonts.googleapis.com/css?family=Open+Sans);
#import url(http://fonts.googleapis.com/css?family=Bree+Serif);
#container {
margin: 0 auto;
}
nav {
margin: 50px 0;
background-color: #E64A19;
}
nav ul {
padding: 0;
margin: 0;
list-style: none;
position: relative;
}
nav ul li {
display:inline-block;
background-color: #E64A19;
}
nav a {
display:block;
padding:0 10px;
color:#FFF;
font-size:20px;
line-height: 60px;
text-decoration:none;
}
nav a:hover {
background-color: #000000;
}
/* Hide Dropdowns by Default */
nav ul ul {
display: none;
position: absolute;
top: 60px; /* the height of the main nav */
}
/* Display Dropdowns on Hover */
nav ul li:hover > ul {
display:inherit;
}
/* Fisrt Tier Dropdown */
nav ul ul li {
width:170px;
float:none;
display:list-item;
position: relative;
}
/* Second, Third and more Tiers */
nav ul ul ul li {
position: relative;
top:-60px;
left:170px;
}
/* Change this in order to change the Dropdown symbol */
li > a:after { content: ' +'; }
li > a:only-child:after { content: ''; }
</style>
<!-- WITH PHP -->
<div id="container">
<nav>
<?php
//connection to the database
$dbhandle = mssql_connect('*****', '*****', '*****')
or die("Couldn't connect to Server");
//select a database to work with
$selected = mssql_select_db("*****", $dbhandle)
or die("Couldn't open database");
//declare the SQL statement that will query the database
$query = "SELECT * FROM CATEGORIES ";
//execute the SQL query and return records
$result = mssql_query($query);
//display the results
while($row = mssql_fetch_array($result))
{
// Assign by reference
$thisref = &$refs[ $row['ID'] ];
// add the the menu parent
$thisref['IDCategoriePere'] = $row['IDCategoriePere'];
$thisref['NOM'] = $row['NOM'];
$thisref['URL'] = $row['URL'];
// if there is no parent id
if ($row['IDCategoriePere'] == 0)
{
$list[ $row['ID'] ] = &$thisref;
}
else
{
$refs[ $row['IDCategoriePere'] ]['children'][ $row['ID'] ] = &$thisref;
}
}
function create_menu( $arr )
{
$html = "\n<ul>\n";
foreach ($arr as $key=>$val)
{
$html .= '<li>'.$val['NOM']."</li>\n";
if (array_key_exists('children', $val))
{
$html .= create_menu($val['children']);
}
}
$html .= "</ul>\n";
return $html;
}
echo create_menu( $list );
//close the connection
mssql_close($dbhandle);
?>
</nav>
</div>
<!-- WITHOUT PHP -->
<div id="container">
<nav>
<ul>
<li>ACCUEIL</li>
<li>PARCS
<!-- First Tier Drop Down -->
<ul>
<li>ALLEMAGNE
<!-- Second Tier Drop Down -->
<ul>
<li>BERLIN</li>
</ul>
</li>
<li>FRANCE
</li>
</ul>
</li>
<li>CONTACT</li>
</ul>
</nav>
</div>
Please give for a detailed answer all informations like your database type and also the query or all of your code. Also the column name NAME is a reserved SQL Keyword, so normally it is not a good idea but mssql is mostly not ANSI, so it is maybe not interesting :)
If you want a multidimensional menu, then you cannot only print out the table. You have first to order the data (pass all childs to parent) and then you can create your menu. For that you are using normally with recursive functions or methods like here the create_menu function.
<?php
$serverName = "serverName\instanceName";
$connectionInfo = array( "Database"=>"dbName", "UID"=>"username", "PWD"=>"password");
// connect to sql server
$conn = sqlsrv_connect( $serverName, $connectionInfo );
if( $conn === false ) {
die( print_r( sqlsrv_errors(), true));
}
// create an array to hold the references
$refs = array();
// create and array to hold the list
$list = array();
$tsql = "SELECT ID, IDPARENT, NAME, URL FROM menu_items ORDER BY NAME;"
$stmt = sqlsrv_query( $conn, $tsql);
if( $stmt === false) {
die( print_r( sqlsrv_errors(), true) );
}
while($row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC))
{
// Assign by reference
$thisref = &$refs[ $row['ID'] ];
// add the the menu parent
$thisref['IDPARENT'] = $row['IDPARENT'];
$thisref['NAME'] = $row['NAME'];
$thisref['URL'] = $row['URL'];
// if there is no parent id
if ($row['IDPARENT'] == 0)
{
$list[ $row['ID'] ] = &$thisref;
}
else
{
$refs[ $row['IDPARENT'] ]['children'][ $row['ID'] ] = &$thisref;
}
}
mssql_close($conn);
/**
*
* Create a HTML menu from an array
*
* #param array $arr
* #param string $list_type
* #return string
*
*/
function create_menu( $arr )
{
$html = "\n<ul>\n";
foreach ($arr as $key=>$val)
{
$html .= '<li>'.$val['NAME']."";
if (array_key_exists('children', $val))
{
$html .= create_menu($val['children']);
}
$html .= "</li>\n";
}
$html .= "</ul>\n";
return $html;
}
echo create_menu( $list );
?>
This question already has answers here:
Is there a pretty print for PHP?
(31 answers)
Closed 7 months ago.
I have a simple $_GET[] query var set for showing testing data when pulling down queries from the DB.
<?php if($_GET['test']): ?>
<div id="test" style="padding: 24px; background: #fff; text-align: center;">
<table>
<tr style="font-weight: bold;"><td>MLS</td></tr>
<tr><td><?php echo KEY; ?></td></tr>
<tr style="font-weight: bold;"><td>QUERY</td></tr>
<tr><td><?php echo $data_q; ?></td></tr>
<tr style="font-weight: bold;"><td>DATA</td></tr>
<tr><td><?php var_dump($data); ?></td></tr>
</table>
</div>
<?php endif; ?>
When I do var_dump, as expected it's this big array string that is all smushed together. Is there a way to add in line breaks at least for this or display the var_dump in a way that's more readable? I'm open to jQuery suggestions on manipulating the string after it's posted.
I really love var_export(). If you like copy/paste-able code, try:
echo '<pre>' . var_export($data, true) . '</pre>';
Or even something like this for color syntax highlighting:
highlight_string("<?php\n\$data =\n" . var_export($data, true) . ";\n?>");
Reusable function:
function highlight_array($array, $name = 'var') {
highlight_string("<?php\n\$$name =\n" . var_export($array, true) . ";\n?>");
}
You can do the same with print_r(). For var_dump() you would just need to add the <pre> tags:
echo '<pre>';
var_dump($data);
echo '</pre>';
Try xdebug extension for php.
Example:
<?php var_dump($_SERVER); ?>
Outputs:
Use preformatted HTML element
echo '<pre>';
var_dump($data);
echo '</pre>';
I have make an addition to #AbraCadaver answers.
I have included a javascript script which will delete php starting and closing tag.
We will have clean more pretty dump.
May be somebody like this too.
function dd($data){
highlight_string("<?php\n " . var_export($data, true) . "?>");
echo '<script>document.getElementsByTagName("code")[0].getElementsByTagName("span")[1].remove() ;document.getElementsByTagName("code")[0].getElementsByTagName("span")[document.getElementsByTagName("code")[0].getElementsByTagName("span").length - 1].remove() ; </script>';
die();
}
Result before:
Result After:
Now we don't have php starting and closing tag
I don't seem to have enough rep to close this as a duplicate, but it is one if someone else can do that. I posted the same thing over at A more pretty/informative Var_dump alternative in PHP? but for the sake of saving time, I'll copy/paste it here too:
I had to add another answer here because I didn't really want to go through the steps in the other solutions. It is extremely simple and requires no extensions, includes etc and is what I prefer. It's very easy and very fast.
First just json_encode the variable in question:
echo json_encode($theResult);
Copy the result you get into the JSON Editor at http://jsoneditoronline.org/ just copy it into the left side pane, click Copy > and it pretty prints the JSON in a really nice tree format.
To each their own, but hopefully this helps some others have one more nice option! :)
Here's an alternative, actively maintained open source var_dump on steroids:
https://github.com/php-sage/sage
It works with zero set up and is more useable than Xdebug's var_dump and symfony/var-dumper.
Example which bypasses the dumped object size limit on the fly with Kint:
require 'sage.phar';
+d( $variable ); // append `+` to the dump call
Here's a screenshot:
If it's "all smushed together" you can often give the ol' "view source code" a try. Sometimes the dumps, messages and exceptions seem like they're just one long string when it turns out that the line breaks simply don't show. Especially XML trees.
Alternatively, I've once created a small little tool called InteractiveVarDump for this very purpose. It certainly has its limits but it can also be very convenient sometimes. Even though it was designed with PHP 5 in mind.
The best what and easiest way to get nice var_dump is use xDebug (must have for any php dev)
Debian way install
In console: apt-get install php-xdebug
after that you should open php.ini (depends on which stack you use) for it's /etc/php/7.0/fpm/php.ini
Search for display_errors
set same -> display_errors = On
Check html_errors in same file a little bit below, it's also must be On
Save and exit
After open /etc/php/7.0/fpm/conf.d/20-xdebug.ini
And add to the end:
```
xdebug.cli_color=1
```
Save and exit.
A lot other available option and documentation for xdebug can be founded here.
https://xdebug.org/docs/
Good luck and Have Fun !!!
Result
You could use this one debugVar() instead of var_dump()
Check out: https://github.com/E1NSER/php-debug-function
Here is my function to have a pretty var_dump. Combined with Xdebug, it helps a lot to have a better view of what we are dumping.
I improved a bit the display of Xdebug (give some space around, separator between values, wrap long variables, etc).
When you call the function, you can set a title, a background, a text color to distinguish all your var_dump in a page.
Or not ;)
/**
* Pretty var_dump
* Possibility to set a title, a background-color and a text color
*/
function dump($data, $title="", $background="#EEEEEE", $color="#000000"){
//=== Style
echo "
<style>
/* Styling pre tag */
pre {
padding:10px 20px;
white-space: pre-wrap;
white-space: -moz-pre-wrap;
white-space: -pre-wrap;
white-space: -o-pre-wrap;
word-wrap: break-word;
}
/* ===========================
== To use with XDEBUG
=========================== */
/* Source file */
pre small:nth-child(1) {
font-weight: bold;
font-size: 14px;
color: #CC0000;
}
pre small:nth-child(1)::after {
content: '';
position: relative;
width: 100%;
height: 20px;
left: 0;
display: block;
clear: both;
}
/* Separator */
pre i::after{
content: '';
position: relative;
width: 100%;
height: 15px;
left: 0;
display: block;
clear: both;
border-bottom: 1px solid grey;
}
</style>
";
//=== Content
echo "<pre style='background:$background; color:$color; padding:10px 20px; border:2px inset $color'>";
echo "<h2>$title</h2>";
var_dump($data);
echo "</pre>";
}
function var_view($var)
{
ini_set("highlight.keyword", "#a50000; font-weight: bolder");
ini_set("highlight.string", "#5825b6; font-weight: lighter; ");
ob_start();
highlight_string("<?php\n" . var_export($var, true) . "?>");
$highlighted_output = ob_get_clean();
$highlighted_output = str_replace( ["<?php","?>"] , '', $highlighted_output );
echo $highlighted_output;
die();
}
There is a Symfony package for this: https://symfony.com/doc/current/components/var_dumper.html.
Here is a function I made for showing arrays in a nice way:
function nicevar($var,$title=''){
if(is_array($var)){
$table = '<table>';
if($title){
$table .= '<tr><th colspan="20">'.$title.'</th></tr>';
}
foreach($var as $k => $v){
$table .= '<tr>';
$table .= '<td><b>'.$k.'</b></td>';
$table .= '<td>';
if(is_array($v)){
$table .= nicevar($v);
}else{
$table .= $v;
}
$table .= '</td>';
$table .= '</tr>';
}
$table .= '</table>';
}else{
$table = $var;
}
return $table;
}
usage:
echo nicevar($_SESSION['debug'],'Structure of debug');
use this styling to make it nice:
<style>
body {
padding: 30px;
}
table {
margin: 5px;
}
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
th {
background-color: #9fff96;
}
th, td {
padding: 2px;
border-spacing: 2px;
}
</style>
in CI4, it's simpler to make the output prettier:
dd($this->request);
here is the result
I wrote a function (debug_display) which can print, arrays, objects, and file info in pretty way.
<?php
function debug_display($var,$show = false) {
if($show) { $dis = 'block'; }else { $dis = 'none'; }
ob_start();
echo '<div style="display:'.$dis.';text-align:left; direction:ltr;"><b>Idea Debug Method : </b>
<pre>';
if(is_bool($var)) {
echo $var === TRUE ? 'Boolean(TRUE)' : 'Boolean(FALSE)';
}else {
if(FALSE == empty($var) && $var !== NULL && $var != '0') {
if(is_array($var)) {
echo "Number of Indexes: " . count($var) . "\n";
print_r($var);
} elseif(is_object($var)) {
print_r($var);
} elseif(#is_file($var)){
$stat = stat($var);
$perm = substr(sprintf('%o',$stat['mode']), -4);
$accesstime = gmdate('Y/m/d H:i:s', $stat['atime']);
$modification = gmdate('Y/m/d H:i:s', $stat['mtime']);
$change = gmdate('Y/m/d H:i:s', $stat['ctime']);
echo "
file path : $var
file size : {$stat['size']} Byte
device number : {$stat['dev']}
permission : {$perm}
last access time was : {$accesstime}
last modified time was : {$modification}
last change time was : {$change}
";
}elseif(is_string($var)) {
print_r(htmlentities(str_replace("\t", ' ', $var)));
} else {
print_r($var);
}
}else {
echo 'Undefined';
}
}
echo '</pre>
</div>';
$output = ob_get_contents();
ob_end_clean();
echo $output;
unset($output);
}
Use
echo nl2br(var_dump());
This should work ^^
Is there any already done php class that could parse a link like Facebook, Google+ or Digg does? To get the title, some text and images from the page? :)
Thanks
Here is some code I pinched from sitepoint.com. I have used it a few times and it seems to work nicely...
<?php
define( 'LINK_LIMIT', 30 );
define( 'LINK_FORMAT', '%s' );
function parse_links ( $m ){
$href = $name = html_entity_decode($m[0]);
if ( strpos( $href, '://' ) === false ) {
$href = 'http://' . $href;
}
if( strlen($name) > LINK_LIMIT ) {
$k = ( LINK_LIMIT - 3 ) >> 1;
$name = substr( $name, 0, $k ) . '...' . substr( $name, -$k );
}
return sprintf( LINK_FORMAT, htmlentities($href), htmlentities($name) );
}
$s = 'Here is a text - www.ellehauge.net - it has some links with e.g. comma, www.one.com,in it. Some links look like this: http://mail.google.com - mostly they end with aspace or carriage return www.unis.no<br /> - but they may also end with a period: http://ellehauge.net. You may even putthe links in brackets (www.skred-svalbard.no) (http://one.com).From time to time, links use a secure protocol like https://gmail.com |This.one.is.a.trick. Sub-domaines: http://test.ellehauge.net |www.test.ellehauge.net | Files: www.unis.no/photo.jpg |Vars: www.unis.no?one=1&~two=2 | No.: www.unis2_check.no/doc_under_score.php |www3.one.com | another tricky one:http://ellehauge.net/cv_by_id.php?id%5B%5D=105&id%5B%5D=6&id%5B%5D=100';
$reg = '~((?:https?://|www\d*\.)\S+[-\w+&##/%=\~|])~';
print preg_replace_callback( $reg, 'parse_links', $s );
?>
This looks like something you could use:
http://www.redsunsoft.com/2011/01/parse-link-like-facebook-with-jquery-and-php/
index.php
<script type="text/javascript" src="http://ajax.googleapis.com/
ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<style>body
{
font-family:Arial, Helvetica, sans-serif;
font-size:12px;
}
#contentbox
{
width:458px; height:50px;
border:solid 2px #dedede;
font-family:Arial, Helvetica, sans-serif;
font-size:14px;
margin-bottom:6px;
}
.img
{
float:left; width:150px; margin-right:10px;
text-align:center;
}
#linkbox
{
border:solid 2px #dedede; min-height:50px; padding:15px;
display:none;
}</style>
<script type="text/javascript">
$(document).ready(function()
{
$("#contentbox").keyup(function()
{
var content=$(this).val();
var urlRegex = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&##\/%?=~_|!:,.;]*[-A-Z0-9+&##\/%=~_|])/ig;
// Filtering URL from the content using regular expressions
var url= content.match(urlRegex);
if(url.length>0)
{
$("#linkbox").slideDown('show');
$("#linkbox").html("<img src='link_loader.gif'>");
// Getting cross domain data
$.get("urlget.php?url="+url,function(response)
{
// Loading <title></title>data
var title=(/<title>(.*?)<\/title>/m).exec(response)[1];
// Loading first .png image src='' data
var logo=(/src='(.*?).png'/m).exec(response)[1];
$("#linkbox").html("<img src='"+logo+".png' class='img'/><div><b>"+title+"</b><br/>"+url)
});
}
return false;
});
});
//HTML Code
<textarea id="contentbox"></textarea>
<div id="linkbox"></div>
</script>
urlget.php
<?php
if($_GET['url'])
{
$url=$_GET['url'];
echo file_get_contents($url);
}
?>
source
I am working on some PHP classes that can do some basic profiling, debugging, and error handling. Yes I know about XDebug and it's great, but I would like to have some classes as well for my library to do some of this type of stuff.
Below is a class I am working on that will show an error message when one occurs and will show me the line number it happened on as well as the source code for that line and the X amount of lines below and above the error line. Similar to in this image below... (may have to view image in new window/tab to see larger version)
Here is my class code I have as of right now for this...
<?php
class Debugger
{
public static function debug_source($file, $line_number, $padding = 5)
{
if (!$file or !is_readable($file)) {
return false;
}
// Open the file and set the line position
$file = fopen($file, 'r');
$line = 0;
// Set the reading range
$range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
// Set the zero-padding amount for line numbers
$format = '% ' . strlen($range['end']) . 'd';
$source = '';
while (($row = fgets($file)) !== false)
{
// Increment the line number
if (++$line > $range['end'])
break;
if ($line >= $range['start']){
// Make the row safe for output
$row = htmlspecialchars($row, ENT_NOQUOTES);
// Trim whitespace and sanitize the row
$row = '<span class="number">' . sprintf($format, $line) . '</span> ' . $row;
if ($line === $line_number){
// Apply highlighting to this row
$row = '<span class="line highlight">' . $row . '</span>';
} else{
$row = '<span class="line">' . $row . '</span>';
}
// Add to the captured source
$source .= $row;
}
}
// Close the file
fclose($file);
echo '<div id="exception_error">';
echo ' <h1><span class="type"> Error [ 345 ]</span></h1>';
echo ' <div class="content">';
echo ' <p>Test error message on line number ' . $line_number. '</p>';
echo ' <p><pre class="source"><code>' . $source . '</code></pre></p>';
echo ' </div>';
echo '</div>';
}
}
// Testing the class above.
$file = 'bitmask/bitmasktest.php';
$line_number = 82;
$line_number_padding = 5;
$debugger = new Debugger();
$debugger->debug_source($file, $line_number, $line_number_padding);
?>
So I am looking for ways to improve and add on to this. It is not complete yet, this is just a start.
A couple of basic questions.
1) Should I declare all variables in a class like this at the top? For example in this class I access the properties like this $file, $line_number, $padding. Should I declare them at the top (all properties) like...
<?php
//public/private/protected
public $this->file;
private $this->$line_number;
private $this->padding;
// etc, etc, for every single property used in a class method
// or should I access them how I currently do in
// this class like $file, $line_number, etcc????
?>
?>
2) To make the output look correct from my method above, it needs this CSS data below in the page, I know I should probably include a CSS file for it or add it to my other css files, but my goal is to have this class be self contained, so the class can be ran anywhere and have the correct output. Should I somehow have a method that outputs the CSS needed for this class or what are some good ideas to keep it self contained and still look the way I want it (like in the image)?
<style type="text/css">
#exception_error {
background: #ddd;
font-size: 1em;
font-family:sans-serif;
text-align: left;
color: #333333;
}
#exception_error h1,
#exception_error h2 {
margin: 0;
padding: 1em;
font-size: 1em;
font-weight: normal;
background: #911911;
color: #FFFFFF;
}
#exception_error h1 a,
#exception_error h2 a {
color: #FFFFFF;
}
#exception_error h2 {
background: #666666;
}
#exception_error h3 {
margin: 0;
padding: 0.4em 0 0;
font-size: 1em;
font-weight: normal;
}
#exception_error p {
margin: 0;
padding: .4em;
}
#exception_error a {
color: #1b323b;
}
#exception_error p {
margin: 0;
padding: 0.1em 0;
}
#exception_error pre.source {
margin: 0 0 1em;
padding: 0.4em;
background: #fff;
border: dotted 1px #b7c680;
line-height: 1.2em;
}
#exception_error pre.source span.line {
display: block;
}
#exception_error pre.source span.highlight {
background: #f0eb96;
}
#exception_error pre.source span.line span.number {
color: #666;
}
</style>
<style type="text/css">
.linenum{
text-align:right;
background:#FDECE1;
border:1px solid #cc6666;
padding:0px 1px 0px 1px;
font-family:Courier New, Courier;
float:left;
width:17px;
margin:3px 0px 30px 0px;
}
code {/* safari/konq hack */
font-family:Courier New, Courier;
}
.linetext{
width:700px;
text-align:left;
background:white;
border:1px solid #cc6666;
border-left:0px;
padding:0px 1px 0px 8px;
font-family:Courier New, Courier;
float:left;
margin:3px 0px 30px 0px;
}
br.clear {
clear:both;
}
</style>
Thank you for any help, I realize these are some really newby like questions but I do need some help, I don't want to pick up any bad habits.
First: the way to declare class properties is like this:
class Debugger {
public $file;
private $line_number;
private $padding;
}
Now, class properties only make sense if they remain constant between operations (function calls) performed on the same object -- in other words, if their values can be "reused" between calls. In your case, the only one of these which it makes sense to reuse is $padding (set it once and then call debug_source multiple times with the same padding). The other two should remain function parameters.
Second:
There is absolutely no way you can make Debugger be self-container and have it produce valid HTML in the context of your page at the same time, unless you make all those styles inline. Of course this solution is far from optimal, but it's the only one that you can use in this case.
1) No. Property declaration does not include the $this keyword. You only use that when accessing the properties, eg
class Foo
{
private $foo;
private $bar;
public function __construct($foo, $bar)
{
$this->foo = $foo;
$this->bar = $bar;
}
}
2) In this case, I'd be more inclined to include all the relevant style attributes in your generated markup. Then it will be truly stand-alone and is how XDebug formats its debug messages.
I'm trying to create a variable background, where the image changes based on the time of day. This code I have USED to work, but I did something somewhere along the line and didn't notice that the functionality had broken. Can someone explain to me why this doesn't work?
<html>
<?php
function day()
{
if ( $hour >= 6 && $hour <= 18 )
{
return 1;
} else { return 0; }
}
?>
<style type="text/css">
body
{
background-image: url('<?php echo (day() ? 'images/day_sheep.jpg'
: 'images/night_sheep.jpg'); ?>');
background-position: 50% 50%;
background-repeat: no-repeat;
background-color: silver
}
a {text-decoration:none;}
a:link {color:#ff0000;}
a:visited {color:#0000FF;}
a:hover {text-decoration:underline;}
</style>
</html>
Inside your function day(), $hour is unset. It will be treated as 0 in a numerical context, and if you enable reporting of notices, you will see notices warning you of an unset variable. Did it used to be a global variable? Did you remove code that set its value or declared it as global?
Edit: Also, on a point of style, I feel it would look neater to have an external CSS file like this:
body {
background-position: 50% 50%;
background-repeat: no-repeat;
background-color: silver
}
body.day {
background-image: url('images/day_sheep.jpg');
}
body.night {
background-image: url('images/night_sheep.jpg');
}
and then you can get rid of the CSS section of your php script, but include the above CSS file, and you need only have the following:
<body class="<?php echo day() ? 'day' : 'night'; ?>">
You never declare what $hour is.
<html>
<?php
function day()
{
$hour = date('G');
if ( $hour >= 6 && $hour <= 18 )
{
return 1;
} else { return 0; }
}
?>
... snip ...