updating php variables stored in file - php

I want to start using configuration.php file, like joomla or wp is using too to store some almost static variables like db logins, theme id or selected language. Problem is, that I dont know how to handle with updating this values. Is there possibility how to edit this variables separately, or I have to always replace whole content of the file? Lets say, that I have config.php file with content like:
class DB {
public $theme = 1;
public $db_host = 'abc';
public $db_user = 'adsabc';
public $db_pwd = 'dsads';
public $db_charset = 'utf8';
public $lang = 'gb';
public $debug= 0;
public $gzip = 0;
}
And I want to change variable $lang = 'gb'; to $lang = 'de'; What is most effective way to do this with php?

You can write a PHP script that will look for and replace those values, but parsing code with regex or similar would be a bad idea.
Instead, you'd be better to implement a JSON file or something similar which you could store your values in, e.g:
{
"lang": "gb",
// everything else
}
Then modify your configuration file to parse that file into variables:
private function parseConfig()
{
$json = json_decode(file_get_contents('yourconfig.json'));
$this->lang = $json->lang;
$this->anotherVar = $json->anotherVar;
}
This way, reading and writing variable data to a contained file is much more manageable than modifying a PHP file (introducing tenfold ways you can break your configuration file, which is the backbone of your site!).

You may have some success with var_export(). You'll probably need to eval() it to read it (make sure you do this inside of a function scope), then file_put_contents() the output of var_export. Then it will be editable by hand. It may or may not look exactly as you want it to, though.

Related

Injecting PHP Variables into HTML Code

This has probably been asked before, but I couldn't find the answer to my question with some preliminary searches, so here it is:
A very simple example of my current method of injecting PHP variables into HTML is as follows:
HTML (file.php):
<tag><?php echo $variable; ?></tag>
PHP:
$variable = "value";
ob_start();
include "file.php";
$results = ob_get_clean();
This achieves the correct result just fine, but it annoys me every time that I have to copy and paste those three lines to get variables injected into my HTML files. There's a chance I might want to change the details of this injection functionality at a later date, and it's currently scattered in a couple hundred locations throughout my code.
In a perfect world, I would move those three lines to a separate function that takes the file path as an input, and returns the "compiled" result. However, the function would then no longer have access to the calling scope, and I would have to pass the variables in as another input. The only thing I'm able to think of for doing that is:
function injectVariables($filePath, array $variables)
{
//Built-in PHP function, extracts array key => value pairs into variable $key = value pairs in the current scope
extract($variables);
ob_start();
include $filePath;
return ob_get_clean();
}
That certainly gets the job done, and it will be what I implement if there aren't any better solutions, but it seems less than ideal to me. It involves creating an array every time this runs, just to loop through it and extract all the variables, which just feels a bit wrong to me.
Does anyone know of any other methods that might work?
Not really sure what you are asking, but here is my answer
I don't know the structure of your code, but I hope you are using a MVC approach (or at least something which deals with classes) so that you can do the following:
In your main controller, you create a class variable like viewData which will be an array. And you put in it everything you want
$this->viewData['username'] = $username;
$this->viewData['myArray'] = array('foo' => 'bar');
$this->viewData['menuSubview'] = 'path_to_menu_subview.php';
Then, you create a render function.
public function render()
{
extract($this->viewData);
ob_start();
include("myfile.php");
return ob_get_clean();
}
And in myfile.php (with the HTML) you can simply do what you used so far
<div id="menu"><?php include($menuSubview);?></div>
<p><?=$username;?></p>
<p><?=$myArray['foo'];?></p>
The whole code can be something like this.
class Something {
protected $viewData;
protected $viewFile;
public function logic()
{
$this->userProfile();
echo $this->render();
}
public function userProfile()
{
$this->viewData['username'] = 'John The Ripper';
$this->viewFile = 'myFile.php';
}
public function render()
{
extract($this->viewData);
ob_start();
include($this->viewFile);
return ob_get_clean();
}
}
Here's a simplified class that stores data and allows for recursive rendering of files that all have access to the save data form the initial instance.
class View {
// view data
protected $_data = [];
/**
* Set view data
*/
public function __set( $key, $value )
{
$this->_data[ $key ] = $value;
}
/**
* Get view data
*/
public function __get( $key )
{
if( array_key_exists( $key, $this->_data ) )
{
return $this->_data[ $key ];
}
return null;
}
/**
* Render view file
*/
public function render( $file )
{
if( is_file( $file ) )
{
$view = $this;
ob_start();
include( $file );
return ob_get_clean();
}
return 'File not found: '.$file;
}
}
Just use the variable $view inside your included files to access the data in the class, or render() another partial file that can do the same thing, and so on.
// Bootstrap a View instance and add some data
$view = new View;
$view->dataOne = 'valueOne';
$view->dataTwo = 'valueTwo';
// Render main template
echo $view->render( 'template.php' );
Inside template.php
<header>
<?= $view->render( 'header.php' ) ?>
</header>
<h1><?= $view->dataOne ?></h1>
<p><?= $view->dataTwo ?></p>
Nothing is wrong with your injectVariables() function, it is in fact a good idea.
You shouldn't have performance impact anyway (If this is your main concern your are doing premature optimization !)
Your view (HTML) shouldn't know about the internal of your application. (You split responsability - this is a huge subject that I won't talk deep)
You know if something end-up into $variables it has been build/formatted or is revelent to be display for $filePath.
In complex system you may end up with a variable with a pdf generator, why would the HTML want that? The only purpose of the HTML is to DISPLAY HTML data.
Some variables from your logic will end-up in $variables almost every time such as session informations (Who is currently logged), for your case this is normal.
In the perfect world if you put a class into $variables it should be designed only for purpose of your HTML even if it is almost the same object as your logic.
As an exemple I designed a Session class in my logic. It does have method such as Logout() and EnsureIsAlive() as well as field such as FullName. FullName is going to be use by my HTML because I want to display it in the header of my page.
I should have a Session class for the HTML that only contains a FullName field because the HTML has only one job and is it to display data. Login() and EnsureIsAlive() are specific for the logic and aren't related at all with displaying data.
In reallity time is always a constraint and because you are writing all by yurself from scratch you may end-up just sending the logic Session class into $variables.
Design note : I'm a C# programmer and we always use class over array to pass parameters as a good pratice and it does affect the exemple about how to pass FullName to your HTML. In your case, instead of creating a class dedicated for the HTML you could also create a simple array :
$variables['Session'] = array('FullName' => $mySession->fullName).
That way you still avoid your HTML to have access to the unrelated method specific for your logic. I'm not sure if it is a good pratice in php...
Keep context variables clean
If you do call injectVariables() more than once (for different $PathFile) you may not want the same variables.
One injectionVariables() could be for a widget, another for a complete complete page.
Why would a TimeWidget need your totalInvoice variable?
You also have the ability to prepare multiples $variables at the same time because each injectVariables() will have his own parameters.
I'm not up-to-date but I know phpBB template system use (back near 2000) the exact same pattern as your injectVariables()).
You wrote that each of your page do call injectVariables(), you could also (but it may be complex) do it only in one file - like php frameworks.
Framework handle HTTP requests into one specific file
(eg. http://yoursite.com/hello/world or http://yoursite.com/login would call (internaly) http://yoursite.com/index.php?page=hello&subpage=world and http://yoursite.com?page=login).
Then this page (index.php in my exemple) would include a specific file (controller) according with his GET parameters ($_GET['page'] and $_GET['subpage']).
The controller job would be to fetch data, apply logic then fill $variables.
Then index.php will call injectVariables() with the releated HTML.

PHP find half-unknown string in file

I am writing some code, but I got stuck at the point where I wanted to implement a language system apart from the database (maybe integrating it later).
At the moment I have these lines of code in my language class:
final public function findTexts()
{
global $engine;
$file = file_get_contents('./styles/'.$engine->getStyle().''.$engine->getPage());
if(strpos($file, '%%'))
{
echo "String found";
}
}
Let me show you my other function:
final public function getText($text)
{
global $engine, $LANG;
$text = str_ireplace($text, $LANG[substr($text, 2, -2)], $text);
echo $text;
}
What I wanted to do, is check a file (which is inside a styles folder) for a string (for example %%Hi%%). Inside my language file I says Hi == Hello, so when I do the getText function it will say 'Hello'. But, I want to make it simple so you only have to type %%Hi%% inside your file, and the language class will automatically check all strings containing %% at the beginning, and %% at the end, and will replace the string inside the %% and %% with the given string inside the language file.
Hope that is enough info...
Many thanks!
You can accomplish this by using regular expressions and preg_replace_callback. See my example below:
<?php
final public function findTexts()
{
global $engine;
$file = file_get_contents('./styles/'.$engine->getStyle().''.$engine->getPage());
$language = $this;
$file = preg_replace_callback('/(%%([^%]+)%%)/',function($matches) use ($language){
$word = $matches[2];
return $language->getText($word);
},$file);
}
This method can become very slow if you have a lot of files or a lot of replacements. It's great if you are doing a very small personal website. If you're doing something a bit bigger, I highly recommend caching the result so you don't have to recompute it for every request and file.

how to modify php config class file like in joomla?

for example, i have "config.php":
<?php
class Config {
public $var1 = 'ex1';
public $var2 = 'ex2';
}
?>
and i have "index.php"
<?php
include ('config.php');
$a = new Config();
$a->var1='changed_ex1';
$a->var2='changed_ex2';
UPDATE($a,'config.php');
?>
so here is the question - what shoud be in UPDATE function to write changes into config.php?=)
I highly do not recommend writing files to store configuration. I'd rather store config in the database if I need to change the settings during runtime.
But if you insist on your chosen path, your UPDATE function will need to read the entire file and either regex-replace the necessary keys, or simply re-render the entire thing based on stored data and the data you need to change.

php function for language translation

For multi-language usage of CMS, they translate terms by a function similar to
function __($word) {
include 'fr.php';
if(!empty($lang[$word])) {$translated=$lang[$word];
} else {
$translated = $word;
}
return $translated;
}
Since we need to use this function several times in a php page, as all words and phrases will be echoed by __(' '); does the function need to include the language time every time, or it will be cached for the function after first load?
Since the language file contains a complete list of words and phrased used throughout the website (thousands of key/value), pho needs to load this long array into memory every time a page is visited. Is it really the best approach to add multi-language feature to a CMS?
If you can't use gettext() for some reason, you'd be better off, with something like this, to put it into an object with the included language strings as a static array, something like:
class Message {
private static $_messages = array();
public static function setMessageLibrary($sMessageLibrary) {
require_once $sMessageLibrary;
self::$_messages = $aMsgs;
}
public static function getMessage($sMessageId) {
return isset(self::$_messages[$sMessageId]) ? self::$_messages[$sMessageId] : "";
}
}
Your message library file (included with the setMessageLibrary() static function), of which you'll have one per language, will need a variable in it called $aMsgs which might look something like:
// Messages for fr-FR
$aMsgs = array(
'hello_everybody' => "Bonjour tout le monde"
...
and so on
);
Since it's all static but within the object you can effectively cache that included language file by setting it at the start of your script.
<?php
Message::setMessageLibrary('/lang/fr-FR/messages.inc.php');
echo Message::getMessage('hello_world');
echo Message::getMessage('another_message');
echo Message::getMessage('yet_another_message');
?>
All three messages will then reference the single language array stored in Message::$_messages
There's no sanitisation, nor sanity checks in there, but that's the basic principle anyway ... if you can't use gettext() ;)
1) it won't be cached, use include_once instead
2) no, i think gettext is doing it another/better way
IIRC, it will do some caching.
No, it's not. Check out gettext.

Parse PHP Session in Javascript

I have recently gone into extending my site using node.js and have come to realisation I need a session handler for my PHP sessions. Now everything was cool and dandy and node.js reads the php sessions and can propogate it's own session with the php ones. I am using database sessions so the session data gets saved into a field in the database.
I have however found a slight problem. I am attempting to read the session data into node.js and it's really quite a strange string. I have been able to get the strucutre of each session variable down to:
'field_name'|'type':'length':'value';
Now on certain strings the value field can be missing on other strings the length can be missing (when a variable is Null). The type can also be more than b, s, i; it can also be N (NULL).
I had originally thought up of a huge translator for JS but this just somehow seems a very wrong way to do it.
Has anyone here tried to extract php session variables in JS before and is there any kind of script that could help? Maybe there is a formatting thing I can use on PHP side to make my life a lot easier in node.js?
Edit: the Schema looks like:
{ _id: { id: 'L:\u00c1\u009d\u008e\u00ad\u000e}<\u0002\u0000\u0000' }
, session_id: 'a2clfnjhopv1srs5k5elgbfjv5'
, user_id: 0
, session_data: 'logged|b:0;uid|i:0;server_key|N;AUTH_TIER2|b:0;email|s:0:"";cheese|s:6:"cheese";'
, active: 1
, expires: 1278920567
}
This is the mongo db record for a user session. The field needing to be translated is session_data. There is some kind of formatting error when pasting it in since stackoverflow wont format that as code when I try and make it for some reason.
I tried to JSONfy the field before but it lost it's types and didn't read Null entries etc so I stopped that
Thanks,
I'm relatively sure PHP uses the serialize and unserialize functions to handle session data.
There is a JavaScript implementation of unserialize in PHP.JS, you can find it here: http://phpjs.org/functions/unserialize
Here is a session_decode function based on the unserialize function of phpjs:
https://github.com/vianneyb/phpjs/blob/master/functions/var/session_decode.js
works for me!
Just to reply with the way I've found: force PHP to use JSON instead :
Use the class below, with session_set_save_handler to store data as JSON and let PHP still using his own system.
Link this class using this function at the beginning of each script you use session :
http://php.net/manual/ru/function.session-set-save-handler.php
PS : here the class use memcache to store JSON resulting object, on Node.JS, use a memcache object, and retrieve like this :
get the PHPSESSID from cookies
use that characters string to bring a key from memcached with "sessions/id" where id is the key and session just the string (see class below).
Now you should have only JSON in memcache, so it's becoming a simple game with Node.JS to work with.
PS : of course you can work with/improve this, you can also use this not only with memcache (a db for example)
<?php
/**
* This class is used to store session data with memcache, it store in json the session to be used more easily in Node.JS
*/
class memcacheSessionHandler{
private static $lifetime = 0;
private static $memcache = null;
public function __construct(){
self::$memcache = new Memcache();
self::$memcache->addServer('localhost', 11211);
}
public function __destruct(){
session_write_close();
self::$memcache->close();
self::$memcache = null;
}
public static function open(){
self::$lifetime = ini_get('session.gc_maxlifetime');
return true;
}
public static function read($id){
$tmp = $_SESSION;
$_SESSION = json_decode(self::$memcache->get("sessions/{$id}"), true);
$new_data = session_encode();
$_SESSION = $tmp;
return $new_data;
}
public static function write($id, $data){
$tmp = $_SESSION;
session_decode($data);
$new_data = $_SESSION;
$_SESSION = $tmp;
return self::$memcache->set("sessions/{$id}", json_encode($new_data), 0, self::$lifetime);
}
public static function destroy($id){
return self::$memcache->delete("sessions/{$id}");
}
public static function gc(){
return true;
}
public static function close(){
return true;
}
}
?>
I had the same problem. I needed to integrate php with node.js. I used js-php-unserialize to do this. The use is pretty straightforward.
var PHPUnserialize = require('php-unserialize');
console.log(PHPUnserialize.unserializeSession(yourData));
For example if you
var yourData = 'A|s:1:"B";userID|s:24:"53d620475e746b37648b4567";';
you will get this result:
{
A: 'B',
userID: '53d620475e746b37648b4567'
}

Categories