Currently, I am reviewing websites written ten years ago. These websites uses the old MySQL API for PHP. PHP hasn't been upgraded since version 5.3, that's why I need to rewrite each database request from the old API to PDO.
The original coder has create for each table an object that wraps INSERT,SELECT and UPDATE requests.
On tables with a lot of rows, it is very painful to quote for each object each argument of each wrapped request, and there a dozen of sites that I must revise !
So, I think about a way to reduce the time spent on quoting each argument of the function by getting these in a loop and quote each of them in two lines of code in each function...
After viewing PHP manual, it seems that there is no way to get a reference of a function arguments. I can copy or count them, but can't get any reference.
Have you got any ideas or tips that will make this job sucks less ?
Here is an example of what I shouldn't do :
public function insert($titre, $tva, $intra, $remise = 0,
$tx_remise = 0, $frais = 0, $code = 0, $nom = '',
$design = '', $adr = '', $cp = '', $ville = '',
$tel = '', $fax = '', $rcs = '', $marq = '',
$marq_g = '')
{
$ville = htmlspecialchars($ville);
$design = htmlspecialchars($design);
$nom = htmlspecialchars($nom);
$adr = htmlspecialchars($adr);
$marq = htmlspecialchars($marq);
$marq_g = htmlspecialchars($marq_g);
$titre = $this->db->quote($titre);
$tva = $this->db->quote($tva);
$intra = $this->db->quote($intra);
$remise = $this->db->quote($remise);
$tx_remise = $this->db->quote($tx_remise);
$frais = $this->db->quote($frais);
$code = $this->db->quote($code);
$cp = $this->db->quote($cp);
$tel = $this->db->quote($tel);
$fax = $this->db->quote($fax);
$rcs = $this->db->quote($rcs);
And what I approximately want to do :
public function insert(...)
{
foreach($function->argumentsReference as $ref)
$ref = quote($ref)
Of course $function isn't a real object, it is just a way to explain my idea with code.
Thanks.
You can use get_defined_vars to retrieve an associative array of all variables in scope, so as long as you use this at the top of your function then you'll effectively have a named copy of all the function arguments. Note that this is different to using func_get_args, which won't contain any default arguments if not provided in the call.
You can apply some logic to all the arguments (quoting, etc) using something like:
<?php
function foo($a, $b, $c) {
foreach (get_defined_vars() as $key => $value) {
${$key} = $value * 2;
}
echo implode(', ', [$a, $b, $c]);
}
foo(1, 2, 3);
// 2, 4, 6
If you took PDO you need to use PDO::prepare and you get that rid of that problem.
What about this (PHP 5.6 or higher required):
function insert(...$data){
var_dump($data); // This returns an array of all passed arguments.
array_map($data, function($datum){
return htmlspecialchars($datum);
}
// Boom, now all entries in the $data array are "htmlspecialcharsified".
list($titre, $tva, $intra, $remise, $tx_remise, $frais, $code, $nom, $design, $adr, $cp, $ville, $tel, $fax, $rcs, $marq, $marq_g) = $data;
// As long as all parameters are passed in the correct order, you now have the desired variables available.
// Do your magic here
}
Related
I made a PHP script which is generating result "https://secure.nmi.com/api/v2/three-step/44505010"
44505010 is a number that changes every time. I need to create a $reference string which I can assign that dynamic number to $reference.
I tried this code but it doesn't seem to work. Can someone help me out?
$reference = getStr($page, 'https://secure.nmi.com/api/v2/three-step/','');
Thanks
Try this:
<?php
function getUrlPart($url = '') {
$urlarr = parse_url($url);
$split = explode('/', $urlarr['path']);
$c = 1;
while($split[count($split)-$c] == ''){
$c++;
}
return var_export($split[count($split)-$c], true);
}
$url = 'https://secure.nmi.com/api/v2/three-step/44505010//';
echo getUrlPart($url);
In this method you can get the route name at any depth, even with query parameters at the end.
$yourUrl = 'https://secure.nmi.com/api/v2/three-step/44505010';
$reference = (int) explode('/', $yourUrl)[6];
This assumes the general URL format does not change.
I use PHP (with KirbyCMS) and can create this code:
$results = $site->filterBy('a_key', 'a_value')->filterBy('a_key2', 'a_value2');
This is a chain with two filterBy. It works.
However I need to build a function call like this dynamically. Sometimes it can be two chained function calls, sometimes three or more.
How is that done?
Maybe you can play with this code?
chain is just a random number that can be used to create between 1-5 chains.
for( $i = 0; $i < 10; $i ++ ) {
$chains = rand(1, 5);
}
Examples of desired result
Example one, just one function call
$results = $site->filterBy('a_key', 'a_value');
Example two, many nested function calls
$results = $site->filterBy('a_key', 'a_value')->filterBy('a_key2', 'a_value2')->filterBy('a_key3', 'a_value3')->filterBy('a_key4', 'a_value4')->filterBy('a_key5', 'a_value5')->filterBy('a_key6', 'a_value6');
$chains = rand(1, 5)
$results = $site
$suffix = ''
for ( $i = 1; $i <= $chains; $i ++) {
if ($i != 1) {
$suffix = $i
}
$results = $results->filterBy('a_key' . $suffix, 'a_value' . $suffix)
}
If you are able to pass 'a_key1' and 'a_value1' to the first call to filterBy instead of 'a_key' and 'a_value', you could simplify the code by removing $suffix and the if block and just appending $i.
You don't need to generate the list of chained calls. You can put the arguments of each call in a list then write a new method of the class that gets them from the list and uses them to invoke filterBy() repeatedly.
I assume from your example code that function filterBy() returns $this or another object of the same class as site.
//
// The code that generates the filtering parameters:
// Store the arguments of the filtering here
$params = array();
// Put as many sets of arguments you need
// use whatever method suits you best to produce them
$params[] = array('key1', 'value1');
$params[] = array('key2', 'value2');
$params[] = array('key3', 'value3');
//
// Do the multiple filtering
$site = new Site();
$result = $site->filterByMultiple($params);
//
// The code that does the actual filtering
class Site {
public function filterByMultiple(array $params) {
$result = $this;
foreach ($params as list($key, $value)) {
$result = $result->filterBy($key, $value);
}
return $result;
}
}
If filterBy() returns $this then you don't need the working variable $result; call $this->filterBy() and return $this; and remove the other occurrences of $result.
I have a function that returns an array but for some things I only need one of the values from that array. Here is the function:
function url_vars() {
$bank = strtolower($_GET['bank']);
$bank = str_replace(',', '', $bank);
$bank = str_replace(' ', '_', $bank);
$type = $_GET['type'];
$term = $_GET['term'];
return array(
bank => $bank,
type => $type,
term => $term,
term_yrs => $term / 12
);
}
I tried to target one value from another function with $bank = url_vars()['bank']; but this seems to be incorrect as it is not working. How can I target a single value from this array? What is the correct way to do that?
In PHP 5.5 and higher, the url_vars()['bank'] syntax should work. However in lower version, you'll just have to assign the function return to a variable and then access the element from that.
$array = url_vars();
$bank = $array["bank"];
$vars = url_vars();
$bank = $vars['bank'];
I am creating a script that will locate a field in a text file and get the value that I need.
First used the file() function to load my txt into an array by line.
Then I use explode() to create an array for the strings on a selected line.
I assign labels to the array's to describe a $Key and a $Value.
$line = file($myFile);
$arg = 3
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
This works fine but that is a lot of code to have to do over and over again for everything I want to get out of the txt file. So I wanted to create a function that I could call with an argument that would return the value of $key and $val. And this is where I am failing:
<?php
/**
* #author Jason Moore
* #copyright 2014
*/
global $line;
$key = '';
$val = '';
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$arg = 3;
$Character_Name = 3
function get_plr_data2($arg){
global $key;
global $val;
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return;
}
get_plr_data2($Character_Name);
echo "This character's ",$key,' is ',$val;
?>
I thought that I covered the scope with setting the values in the main and then setting them a global within the function. I feel like I am close but I am just missing something.
I feel like there should be something like return $key,$val; but that doesn't work. I could return an Array but then I would end up typing just as much code to the the info out of the array.
I am missing something with the function and the function argument to. I would like to pass and argument example : get_plr_data2($Character_Name); the argument identifies the line that we are getting the data from.
Any help with this would be more than appreciated.
::Updated::
Thanks to the answers I got past passing the Array.
But my problem is depending on the arguments I put in get_plr_data2($arg) the number of values differ.
I figured that I could just set the Max of num values I could get but this doesn't work at all of course because I end up with undefined offsets instead.
$a = $cdata[0];$b = $cdata[1];$c = $cdata[2];
$d = $cdata[3];$e = $cdata[4];$f = $cdata[5];
$g = $cdata[6];$h = $cdata[7];$i = $cdata[8];
$j = $cdata[9];$k = $cdata[10];$l = $cdata[11];
return array($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l);
Now I am thinking that I can use the count function myCount = count($c); to either amend or add more values creating the offsets I need. Or a better option is if there was a way I could generate the return array(), so that it would could the number of values given for array and return all the values needed. I think that maybe I am just making this a whole lot more difficult than it is.
Thanks again for all the help and suggestions
function get_plr_data2($arg){
$myFile = "player.txt";
$line = file($myFile); //file in to an array
$c = explode(" ", $line[$arg]);
$key = strtolower($c[0]);
if (strpos($c[2], '~') !== false) {
$val = str_replace('~', '.', $c[2]);
}else{
$val = $c[2];
}
return array($key,$val);
}
Using:
list($key,$val) = get_plr_data2(SOME_ARG);
you can do this in 2 way
you can return both values in an array
function get_plr_data2($arg){
/* do what you have to do */
$output=array();
$output['key'] =$key;
$output['value']= $value;
return $output;
}
and use the array in your main function
you can use reference so that you can return multiple values
function get_plr_data2($arg,&$key,&$val){
/* do job */
}
//use the function as
$key='';
$val='';
get_plr_data2($arg,$key,$val);
what ever you do to $key in function it will affect the main functions $key
I was over thinking it. Thanks for all they help guys. this is what I finally came up with thanks to your guidance:
<?php
$ch_file = "Thor";
$ch_name = 3;
$ch_lvl = 4;
$ch_clss = 15;
list($a,$b)= get_char($ch_file,$ch_name);//
Echo $a,': ',$b; // Out Puts values from the $cdata array.
function get_char($file,$data){
$myFile = $file.".txt";
$line = file($myFile);
$cdata = preg_split('/\s+/', trim($line[$data]));
return $cdata;
}
Brand new to this community, thanks for all the patience.
I'd really appreciate anyone's help in this. Basically I want to make an array of lists made from other arrays in order to get round the limitations of wordpress' do_shortcode function. I'm doing this using a number of functions.
LONG VERSION OF THE PROBLEM:
The code currently looks like this:
/* These are the functions contained in a functions file */
function output_entry_data() {
$postdate = get_the_date('j/n/y');
$entrytitle = get_the_title();
return ('<li><p class="postmeta">'. $postdate. '</p><h3>'. $entrytitle. '</h3></li>');
}
function output_month_data($entrynomax = '', $month = '', $entrydata = '') {
$entryno = 1;
while($entryno <= $entrynomax) {
echo $entrydata[$entryno];
$entryno++;
}
}
function output_year_data($monthlynomax = '', $year = '', $monthlydata = '') {
$monthno = 1;
while($monthno <= $monthnomax) {
echo do_shortcode('<h4>[slider title="'. $month. '"]</h4><ul>'. $monthlydata[$monthno]. '</ul>[/slider]');
$monthno++;
}
}
/* This is from a loop that determines whether you have reached the end of a month or a year */
$entrydata[$entryno] = output_entry_data();
$entrynomax = $entryno;
$monthlydata = array($monthno => $monthno);
$monthlydata[$monthno] = return(output_month_data($entrynomax, $month, $entrydata));
$monthlynomax = $monthno;
$annualdata[$yearno] = array($yearno => $yearno);
$annualdata[$yearno] = return(output_year_data($monthlynomax, $year, $monthlydata));
$entryno = 1;
$monthno = 1;
$yearno++;
$yearo = get_the_date('Y');
/* The idea is that all the data gets outputted at the end of the loop like this: */
$yearnomax = $yearno;
echo ('<ul>');
$yearno = 1;
if($yearno <= $yearnomax) {
echo do_shortcode('<h3>[expand title ="'. $year. '"]</h3><ul>'. $annualdata[$yearno]. '</ul>[/expand]');
$yearno++;
}
echo('</ul>');
At the moment the code is successfully creating the $entrydata[$entryno] array because the function output_entry_data() simply returns a line of code each time.
However, when I try to create the array $monthlydata[$monthno] for each month, it simply runs the function output_month_data() and makes a big list of all the monthly entries, rather than passing the data to the array to be used by the other functions.
I can see that this is because I used 'return' in output_entry_data() and 'echo' in output_month_data()
SHORT VERSION OF THE PROBLEM
Each item in the array $entrydata[$entryno] is a string containing a list item tag, I want output_monthly_data() to return one big string of all the items in $entrydata[$entryno] to be used by other functions, rather than echo them as the code currently does. Can this be done when there's a while loop involved?
Many thanks, I'd appreciate any input here.
Yes, this is (easily) possible. There are at least two ways
Concatenate strings and return the resulting string:
function output_month_data($entrynomax = '', $month = '', $entrydata = '') {
$entryno = 1;
$return = '';
while($entryno <= $entrynomax) {
$return .= $entrydata[$entryno]; # concatenate strings
$entryno++;
}
return $return;
}
Store results in an array and use implode to return a string containing all items:
function output_month_data($entrynomax = '', $month = '', $entrydata = '') {
$entryno = 1;
$return = array();
while($entryno <= $entrynomax) {
$return[] = $entrydata[$entryno]; # append to array
$entryno++;
}
return implode('', $return); # change '' to any glue you want
}