...

View Full Version : Function to automate variables from db



PaulC2K
08-20-2012, 07:08 PM
Im trying to get my head around how i would write a function to pull a load of configuration values from a database, and build variables from it too.



id config_id name var value
1 1 Foo foo foo
2 1 Bar bar bar


What i'd like to do is create a function that looked for config_id = '1', then created an array for each entry with the designated variable name, its 'label' and the value for it.
I then need to return the values, and be able to unpack it.

Is this remotely possible, or am i better off just banging my head against the wall for 30min now and save myself doing that over a few days. :D
Has anyone got any suggestions? how i'd go about doing that, if theres anything which would be helpful to look up which would help me with this? my coding knowledge is quite basic, i usually get by with persistence (think along the lines of monkeys & typewriters and your on the right lines :D) so any pointers in the right direction for a command that might help would be a big help, as i doubt anyone will want to write something out, but pointers would be great, as would be an idea as to whether it'd be too complicated.

Thx :thumbsup:

==============================
Update: Post #7
AFAIK its all working fine, although if anyone can have a nosy for potential weaknesses it'd be handy.
My level of coding is poor, so i suspect theres poor coding practice in there, but i think it should work fine.

Fou-Lu
08-20-2012, 07:56 PM
Are you meaning so you end up with the $var = $value? I don't recommend that you do this if you can avoid it since it requires you to extract an unknown set of variables into scope. If you really need to do this, you can look at using extract(), but make sure you know what variables you are dealing with and what to do on a conflict of a variable that already exists. Its really only useful within a loop though, unless you construct an array that names the key=>value association between the var and value in the table above.

Keeping it as an array would be no problem. Pulling that out of the SQL is trivial and as an associative would give you name, var, and value in the set of each record pulled.

PaulC2K
08-20-2012, 08:23 PM
yeah, i'd basically be creating a function which pulled an undetermined number of variables out from thin air almost. with the name of the variable, its value, and a label all stored in the database and this function would pull them all.
There wouldnt be an issue of duplication, each 'config' would use the same type of info, they'd just have their own values. for example, if it was for a site theme, you'd have entries for text style, colour, size, background colour, stuff like that. and there'd be 10 different variations (themes), but if i added a border colour then i wouldnt need to write it into the function, it'd adapt and generate $border_colour = '#123456'.


Writing the initial loop aspect, i can get my head around that in time, and a dozen trial & error runs at it i suspect. Writing the return is going to be the complicated part i'd guess.

return array ([insert an indeterminate number of variables, of indeterminate name]);
then ive got to know the contents within the returned array, in order to 'unpack' it.

One solution i think might work, is to take 2 runs at it. firstly to do a scan of the database, get the values of all potential variables and put that into an array of a fixed name, that can then be returned, and used to know what the 2nd attempt will be compiling, and that way i know what to unpack.

I dunno, maybe im creating too much work for myself, i just hate the idea of deciding to implement a new element to the 'config' and then have to write that into the function, then add it to the edit page and update db code etc.
If i could just write a script that fetched all the variables, displayed them all inside a form, and then submitted everything into the database, it'd be much easier to work with.
I suspect the time i'd spend implementing this would be about as long as doing it the simple way and all the time spend modifying it manually, its a pain eitherway :D

PaulC2K
08-20-2012, 08:57 PM
Apologies in advance for any coding practices used which are ancient :D

I've bypassed the function, im just trying to pull the data and display it, and heres what i have:


$variables = array();
$sql9="SELECT * FROM `event_config` WHERE `season_id` LIKE '$season_id'";
$result9 = mysql_query($sql9,$db);
while ($myrow9 = mysql_fetch_array($result9))
{
${$myrow9['config_var']}['label'] = $myrow9['config_name'];
${$myrow9['config_var']}['value'] = $myrow9['config_value'];
array_push($variables, $myrow9['config_var']);
}

foreach ($variables as $var)
{
echo " Label = ".$var['label']." | Value = ".$var['value']."<br>";
}

echo "<br><br> Label = ".$webname['label']." | Value = ".$webname['value']."<br>";


Im getting:

Label = w | Value = w
Label = s | Value = s
Label = p | Value = p
Label = f | Value = f
Label = s | Value = s
Label = d | Value = d
Label = l | Value = l
Label = s | Value = s

The label is the first letter only, and the value seems to be a repeat of the label, it doesnt match the answer.

for the last line of the script, giving it a asking for a variable i know it should create, i get the results i expect to get. What am i missing in the foreach?

PaulC2K
08-20-2012, 11:40 PM
Got there eventually with the single letters, i was using $var['label'] instead of ${$var}['label'].

I expected that to take me a fair number of hours, rather than about 1hr. Now it just needs to be put into a function, thats the bit i expect to struggle with though.
I'll take a look at that tomorrow though, at least i know i can compile the data and extract it however i need, i just need to package it up into a function now. :thumbsup:

PaulC2K
08-21-2012, 01:14 AM
Had a quick mess, with some dummy info, and i can figure out how to write 99% of the function, and how to turn the output into what i want, however ive no idea how to write the bit passing the info through.

ie
return array($var1, $var2, $var3);
& list ($var1, $var2, $var3) = function();

Those work if i know for certain the name of the variable, and how many there are, and hard code it for them. I need something thats flexible.

I need something that takes my list of variables its just generated, and enters all of them into the 'return' part so it turns
return array($all_my_variables);
into return array($var1, $var2, $var3);
or return array($var1, $var2, $foo, $bar); etc.

likewise i need the same for list ($all_my_variables) = function();


I already have an array with say:
Array ( [0] => numberOne [1] => numberTwo [2] => numberThree [3] )
which lists all the variables it needs to pass through. I also have it as a text, ie '$numberOne, $numberTwo, $numberThree' incase i can 'paste' it into something and let it read the names of the variables from that.
If either of those would be useful, i dont know how to use them.

So i need to know how to write the exit for a function with an unknown number of variables, of unknown names. I suspect doing the reverse will be a similar process?
Anyone any idea how i can do that??

Otherwise, i think everything is done, i just dont know how the final piece of the jigsaw needs to be wrote :o

PaulC2K
08-21-2012, 11:49 AM
ok, think i figured it out by putting the automated arrays into a single array of a given name, that way i can pass that through.

Its not pretty by all means, but it works :D


function partThree($season_id)
{
require ($_SERVER["DOCUMENT_ROOT"]."/public/mysql_eventsdb.php");
$var_master = array();

$sql9="SELECT * FROM `event_config` WHERE `season_id` LIKE '$season_id'";
$result9 = mysql_query($sql9,$db);
while ($myrow9 = mysql_fetch_array($result9))
{
${$myrow9['config_var']}['variable'] = $myrow9['config_var'];
${$myrow9['config_var']}['label'] = $myrow9['config_name'];
${$myrow9['config_var']}['value'] = $myrow9['config_value'];

array_push($var_master, ${$myrow9['config_var']} );
}

return $var_master;
}





$var_master = partThree($season_id);

foreach ($var_master as $var)
{
$var_name = $var['variable'];

${$var_name}['variable'] = $var['variable'];
${$var_name}['label'] = $var['label'];
${$var_name}['value'] = $var['value'];

echo ${$var_name}['variable']." | ".${$var_name}['label']." | ".${$var_name}['value'] ."</br>";
}



Managed to re-write it and cut a chunk out just while writing this post :D

So that creates an array, with a name defined within the database, and gives it a 'label' and a value. It adds the array to a master array, which the function returns to the user.
From there, its just breaking it down, recreating the individual variables/arrays, and echoing them to check they're correct.

I have to admit, i expected it to take me a hell of a lot longer to wrap my head around it, and im surprised ive been able to create the function, and output the data in just 20 lines of code, i expected hundreds :thumbsup:


Anyone able to suggest any improvements, or highlight any problems?

Lamped
08-21-2012, 12:59 PM
Well, I've seen this thread twice just deleting spam, so out of decency I'll reply too ;)

Firstly, never, ever, ever determine variable names from a database or user input. Ever. You're going to have a problem, the worst of which will be someone hacking the script. Put it into an associative array instead: $data[$var_name]['label'] = $var['label']; Every time you do what you did up there, God kills a kitten. You now have a whole litter on your conscience.

Secondly I'm going to explain why you got the first letter only: Strings can be accessed like an array too, a zero indexed array, $str[0] is the first character. If you access a string with $str['notanumber'], PHP thinks it's being smart and converts 'notanumber' to an int. The int value of notanumber is 0: the first character. This can also lead to seemingly weird results if your string happens to begin with a number...

PaulC2K
08-21-2012, 04:41 PM
Oh im sure I have millions of litters on my conscience :D If i was a builder, i'd be using superglue and selotape ;)

Im not sure i follow the difference though to be honest, thats assuming i can understand what an associative array is first :o (googling it doesnt make it instantly clearer how it'd help).

The database would hopefully hold hundreds of configuration settings, which influence how a small, but important aspect of the site, would act.
I guess I could create a text file like an ini file, get the config from that. I could also manually update every required page to add any new options within a config that i'd add, its time consuming but not the end of the world.

But i dont get what that advice offers tbh, its not that i disgree with it, i dont understand it.
Currently my config data is stored in a database, and i manually request every piece of info before making use of it. I need to add a way to update all the values associated with that config, and give groups of people access to edit their groups config settings.
Just a simple form, updating the data back to the db.

Because i cant predict how i'll expand it, i thought it made sense to write a function to fetch all the config settings and put them in an array. That way i can pull specific values from it, and i can write a form that allows me to edit every value within that config, whether theres 2 settings or 20, I wouldnt need to lift a finger.

I get that you say its a vulnerable method, but not what the suggestion means. Are you saying the previously posted array is vulnerable, or taking it from the database?

In terms of the sort of content within these, they're not like php configuration or major site settings, they're visual styles, dates in which areas should be accessible, labels for the areas, they're settings which change the way that group interacts with the user, what it should display etc.

I dont quite 'get' the advice, so thats a bit more info if that sheds light on what im doing, what should i be looking to modify, where am i vulnerable??

Thanks for doing the thread tidy-up too, damn spambots :mad: theres been 3 in total this morning.

Fou-Lu
08-21-2012, 06:06 PM
lol
Whether you use a file or a database is really quite irrelevant. The biggest problem is I don't see how you are actually using this.
Fetching database or file information and promoting to variables I don't like. I am happy with the use of hardcoded variables and ini generated variables (to an extent). The problem without the hardcode or ini approach is you simply cannot detect and know what the variables are within the script before runtime, and this I don't like. An array is a better solution to this, but I don't know what level of reliance you currently have.

If you are in a spot where you have already specified hardcoded variables, then you really have no alternative but to extract to a variable. This is actually a lot easier to do than what you have here, but you cannot make use of more than one key => value combo at a time, so you have an extra field you want. It looks to me that you need the var, value and label, but I don't know what all three of these represent. Another part of the problem is simply the scope.

Since you do have the three, a better option is to look into an OO solution for this. Objects are passed by object reference in PHP5, so you can retrieve original object pointers created within functions, so you can get around a scope issue by either passing or returning. So for this, I'd write two classes, one variable and one variables to do all the work for me:


class Variable
{
private $lable;
private $varname;
private $value;

public function __construct($label, $varname, $value)
{
$this->label = $label;
$this->varname = $varname;
$this->value = $value;
}

public function getLabel()
{
return $this->label;
}

public function getVarname()
{
return $this->varname;
}

public function getValue()
{
return $this->value;
}
}

class Variables implements IteratorAggregate
{
private $ao;

public function __construct()
{
$this->ao = new ArrayObject();
}

public function addVariable(Variable $v)
{
if (isset($this->ao[$v->getVarname()]))
{
throw new RuntimeException("Variable is already in list");
}
$this->ao[$v->getVarname()] = $v;
}

public function getIterator()
{
return $this->ao->getIterator();
}

public function getVariableByName($sVar)
{
return isset($this->ao[$sVar]) ? $this->ao[$sVar] : null;
}

public function getVariableValueByName($sVar)
{
return isset($this->ao[$sVar]) ? $this->ao[$sVar]->getValue() : null;
}
}

Just something simple; the variables class in particular would really need a rewrite, and observers should be used in case the Variable class is given the ability to change the varname so it can trigger an update to the list and toss if it's given a duplicate.
The nice part is the usage:


function getSomeData()
{
$variables = new Variables();
$sQry = 'SELECT label, varname, value FROM databasetable WHERE condition';
if ($qry = mysql_query($sQry))
{
while ($row = mysql_fetch_assoc($qry))
{
$variables->addVariable(new Variable($row['label'], $row['varname'], $row['value']));
}
}
return $variables;
}

$variables = getSomeData();

printf("Variable value for 'bar' is %s" . PHP_EOL, $variables->getVariableValueByName("bar"));


A procedural approach to the above is to simply make use of a static array, and handle it preferably by returned reference and several functions to deal with it. It effectively ends up about the same but is called differently.


function &populateData()
{
static $a;
if (empty($a))
{
// you query here. I'll just write it hardcoded for this example.
// the query will need to create the offsets as appopriately
$a = array();
$_tmpArray = array(
array('Fou', 'fou', 'fou'), // just a bit of humor :)
array('Bar', 'bar', 'bar')
);
foreach ($_tmpArray AS $row) // This is the simulated query
{
list($label, $varname, $value) = $row;
$a[$varname] = array('label' => $label, 'value' => $value);
}
}

return $a;
}

function getVariableByName($varname)
{
$a = populateData();
return $a[$varname];
}

function getVariableValueByName($varname)
{
$a = populateData();
return isset($a[$varname]['value']) ? $a[$varname]['value'] : null;
}

printf("Variable 'fou': %s" . PHP_EOL, print_r(getVariableByName("fou"), true));
printf("Variable value for 'bar': %s" . PHP_EOL, getVariableValueByName("bar"));

// And the purpose of the by ref
$a = &populateData();
$a['anewvar'] = array('label' => 'A New Var', 'value' => 'anewvar');

foreach ($a AS $var => $info)
{
printf("Variable %s is given info of %s" . PHP_EOL, $var, print_r($info, true));
}

printf("Variable 'anewvar' value: %s" . PHP_EOL, getVariableValueByName("anewvar"));


For an example.

And finally, if you really must have a variable itself given the value of the varname from the database, simply inject it into the $GLOBALS. I don't recommend this since it is tougher to track:


function getSomeData()
{
// your query here
while ($row = mysql_fetch_assoc($qry))
{
if (!isset($GLOBALS[$row['varname']])
{
$GLOBALS[$row['varname']] = array('label' => $row['label'], 'value' => $row['value']);
}
}
}

And then after the call, a global will exist with the name given by $row['varname']. I had to make it an array still since I haven't a clue the relationship between varname, label and value.

Hope that helps.

PaulC2K
08-21-2012, 06:07 PM
i've no idea what im doing, but maybe im on the right lines :D:D

The mass slaughtering of innocent kittens is due to my method of introducing the values into the code, by using $var_name['label'] rather than anything to do with pulling from databases or the actual practice of generating these variables, its the naming??

I dont think the function would be a problem, but then WTF do i know, so i updated that too (i suspect i dont need to, seeing as they're never really 'live' within the site?) and i've also copied the 'associative array' example.
Am i remotely close, or miles off as usual?? :D


function partFive($season_id)
{
require ($_SERVER["DOCUMENT_ROOT"]."/public/mysql_eventsdb.php");
$var_master = array();

$sql9="SELECT * FROM `event_config` WHERE `season_id` LIKE '$season_id'";
$result9 = mysql_query($sql9,$db);
while ($myrow9 = mysql_fetch_array($result9))
{
echo "** ".$myrow9['config_var']." ** <br>";
$data[$myrow9['config_var']]['variable'] = $myrow9['config_var'];
$data[$myrow9['config_var']]['label'] = $myrow9['config_name'];
$data[$myrow9['config_var']]['value'] = $myrow9['config_value'];

array_push($var_master, $data[$myrow9['config_var']] );
}

return $var_master;
}



foreach ($var_master as $var)
{
$var_name = $var['variable'];
$data[$var_name]['variable'] = $var['variable'];
$data[$var_name]['label'] = $var['label'];
$data[$var_name]['value'] = $var['value'];

echo $data[$var_name]['variable'] ." | ". $data[$var_name]['label'] ." | ". $data[$var_name]['value'] ."</br>"; }

Any better?

PaulC2K
08-21-2012, 07:08 PM
Fou-Lu - :eek:
I think my poor brain melted before i even got to the first example :(

They're just various pieces of information which influence whats displayed in a specific area of the site.
The table consists of:
id, config_id, variable name, label for it, the value.



id c_id var label value
1 1 name Event Name CodingForums Event
2 1 signup Signup Type public
3 1 open Open Date 2012/01/01
4 1 close Close Date 2013/01/01

5 2 name Event Name Another Event
6 2 signup Signup Type invitation
7 2 open Open Date 2012/09/01
8 2 close Close Date 2012/10/01

At the moment in my database, every 'config' has 7 pieces of info, compared to the 4 above, every config should consist of the same 7 pieces (or however many i implement), same [var] & [label] but with their own [value]. If the site gets finished, there would be hundreds of configurations.


With the script, i want to be able to fetch all the configuration settings for a particular event (config_id) within an array.

My coding ability is limited at best, i absorb next to nothing i learn as im coding (goes for a lot of things unfortunately) and the terminology goes whoosh over my head a lot of the time so its a pain trying to explain what i want, cos i dont know the correct way to explain it, and often what i need to do. correct coding practice goes out the window typically, not cos i dont care, but cos i wouldnt know where to begin and most of my coding is spelt out in the simplest of terms (so i can understand it, and cos i dont know the efficient or best methods).

What i wanted to do was create a private page, a form with the config settings for that 'event'. name, signup, open & close. I could write the page, put 4 text boxes, the submit to db code etc, thats fine. But if i add a new entry to that config, say background_colour, 9 1 colour Background Colour #ff0000 i'd have to modify the form.

With this method, i dont.
I'd have an array with every associated value for that config -> name, signup, open, close & colour.
I can create a loop which displays a textbox for every setting, then submit each value into the database when prompted.
i'd just request $data[colour]['value'] and get my answer.


It just creates a dynamic form for me, there may be far better ways of doing it, but im a n00b, i've been coding in my spare time for around 10 years and this is pretty much my level. I wont create anything special, and it'll be anything but efficient, i just hope to implement the functionality i want to give the sites.
The project im working on at the moment is way over my head, and ive already put around 1500hrs into it over a number of years, and about 5 people have seen it (its not live, thankfully :D). I get by with determination, passion, google, an absolute ton of trial & error, and as a last resort i'll post on here for assistance (cos i'd rather find the answer myself).

Maybe the application is pointless, i dunno, i just thought it'd save me time if the form was self-generating, and i could leave it alone while still adding other settings to it and it adapting.
The childish manner in which its wrote, thats just where im at, i dont know any better, and attempts to try and learn from reading almost nothing is absorbed, and learning from doing isnt all that much more successful. :( Its pretty much what i have to do to make it work, its that or nothing really.

Fou-Lu
08-21-2012, 07:23 PM
Can you have multiple c_id available at the same time? If not, any of the examples I have would work fine (the first one though the oop Variable class has the wrong property, it should be private $label not private $lable).
Since I made variables iterable, then it can be fetched in a foreach:


foreach ($variables AS $variable)
{
printf('<label for="%s">%s</label><input type="text" name="%s" id="%s" value="%s" />' . PHP_EOL, 'id_' . $variable->getVarname(), $variable->getLabel(), $variable->getVarname(), 'id_' . $variable->getVarname(), $variable->getValue());
}

PaulC2K
08-21-2012, 07:58 PM
No, only 1 c_id is active.

In the code ive posted, ive got the table 'event_config' and im using '$season_id' (same as 'c_id' in example) to pull all the settings relating to that season event.

There would be hundreds of events run over time, and the config table would hold a load of individual settings relevant to how it operates.
The structure of the events are held elsewhere, but the basic settings would be held here. Every event would have the same pieces of information it'd need, but they'd have their own values - each one needs a start date, but they'd have the same variable name and the label is just for explaining what its for really.

tbh, as much as i appreciate the code you've gone to the trouble of providing for me, i cant even read it to understand what its doing. its way beyond my understanding. I cant rely upon something that makes no sense to me if you know what i mean :o sorry

Is what ive wrote earlier still bad practice? it seems to be doing the job i need from it, but if its still got a significant vulnerability to it then i'll either fix it (if i can) or give up and go back to hard coded pages & updating it as and when needed.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum