I've recently switched from PHP 5.6 to PHP7. A previous PHP script which worked fine in PHP 5.6 is now duplicating columns data in PHP 7. I'm not seeing why. The code:
function cleanData(&$str)
{
$str = preg_replace("/\t/", "\t", $str);
$str = preg_replace("/\r?\n/", "\n", $str);
if(strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
// force certain number/date formats to be imported as strings
if(preg_match("/^0/", $str) || preg_match("/^+?\d{8,}$/", $str) || preg_match("/^\d{4}.\d{1,2}.\d{1,2}/", $str))
{
$str = "'$str";
}
}
$day_num = date(d);
$month_num = date(n);
$year_num = date(Y);
// file name for download
$filename = "Subscriber_list_" . $month_num . "-" . $day_num . "-" . $year_num . ".xls";
header("Content-Type: application/vnd.ms-excel");
header("Content-Disposition: attachment;
filename=\"$filename\"");
header('Cache-Control: max-age=0');
echo "ID \t Title \t First Name \t Last Name \t E-Mail \n";
$news_query = mysqli_query("SELECT DISTINCT id, title,firstname, lastname, email FROM users WHERE newsletter = 1 ");
while($row =mysqli_fetch_array($news_query, MYSQL_ASSOC)) {
array_walk($row, 'cleanData');
echo implode("\t", array_values($row)) . "\n";
}
exit;
The DB is fairly standard. Thanks in advance.
I think this is because you're using the MYSQL_ASSOC constant instead of MYSQLI_ASSOC when you fetch rows from the query.
That typo happened to work when you were on PHP 5, because those two constants have the same value. But the MYSQL_ASSOC constant is undefined in PHP 7 since the MYSQL extension has been removed, so mysqli_fetch_array goes with the default behavior of fetching both numeric and associative keys, hence the duplicated columns.
This is solved, Thanks.
I re-wrote the script using:
<pre>
function fetch_assoc($result) {
return mysqli_fetch_assoc($result);
}
</pre>
Related
I am checking ( or want to check ) if the counter gets to 5 I want to reset the counter back to one and start again until all the records have been read,I have the following code on a test page:
<?php do {
if ($count == 5) { $count = 1;}
echo $count;
echo "<div id=\"col$count\"><div id=\"col$count-content\"><img class=\"resetImg\" name=\"colpic$count\" src=\"assets/images/student_artwork/thumb_" . $row_rsILU['ilu_artwork'] . "\" alt=\"\" style=\"background-color: #999966\"><br><br><span class=\"artistName\">" . $row_rsILU['ilu_fname'] . " " . $row_rsILU['ilu_lname'] . "</span> <br><hr>
Concept Artist<br>
email#artistdomain.ca<br>
416-833-1111<br>
www.portfolio.ca<br>
</div></div>";
$count++;
} while ($row_rsILU = mysql_fetch_assoc($rsILU)); ?>
The record set has three records in it but the count always seems to stop at two and only shows the two images. I am checking the count and if it gets to 5, I want to reset it to 1 and start over again until the total records in the record set have been read. Maybe I am just getting tired but I cannot get this. Would appreciate anyones help on this.
Cheers,
Dave
According to your code, you are trying to echo the row before actually fetching it (I mean the first iteration). Why not just use while loop instead?
<?php
while ($row_rsILU = mysql_fetch_assoc($rsILU)) {
if ($count == 5) { $count = 1;}
echo $count;
echo "<div id=\"col$count\"><div id=\"col$count-content\"><img class=\"resetImg\" name=\"colpic$count\" src=\"assets/images/student_artwork/thumb_" . $row_rsILU['ilu_artwork'] . "\" alt=\"\" style=\"background-color: #999966\"><br><br><span class=\"artistName\">" . $row_rsILU['ilu_fname'] . " " . $row_rsILU['ilu_lname'] . "</span> <br><hr>
Concept Artist<br>
email#artistdomain.ca<br>
416-833-1111<br>
www.portfolio.ca<br>
</div></div>";
$count++;
}
?>
Please let me know if that solves your problem.
Humm ... well now, this is embarrassing! Turns out there was a second, older SELECT statement in the code that I missed and so it was not returning one of the three records because it was not looking for it, based on the older SELECT statement. Sorry about that but thanks for your help.
I'm trying to get perltidy to format an if statement like this:
if ($self->image eq $_->[1]
and $self->extension eq $_->[2]
and $self->location eq $_->[3]
and $self->modified eq $_->[4]
and $self->accessed eq $_->[5]) {
but no matter what I try, it insists on formatting it like this:
if ( $self->image eq $_->[1]
and $self->extension eq $_->[2]
and $self->location eq $_->[3]
and $self->modified eq $_->[4]
and $self->accessed eq $_->[5]) {
Also, is there any way to get the last line of this block:
$dbh->do("INSERT INTO image VALUES(NULL, "
. $dbh->quote($self->image) . ", "
. $dbh->quote($self->extension) . ", "
. $dbh->quote($self->location) . ","
. $dbh->quote($self->modified) . ","
. $dbh->quote($self->accessed)
. ")");
to jump up to the previous line like the other lines:
$dbh->do("INSERT INTO image VALUES(NULL, "
. $dbh->quote($self->image) . ", "
. $dbh->quote($self->extension) . ", "
. $dbh->quote($self->location) . ","
. $dbh->quote($self->modified) . ","
. $dbh->quote($self->accessed) . ")");
Here is what I'm currently doing:
perltidy -ce -et=4 -l=100 -pt=2 -msc=1 -bar -ci=0 reporter.pm
Thanks.
I don't have much to offer on the 1st question, but with the 2nd, have you considered refactoring it to use placeholders? It would probably format up better, automaticaly do the quoting for you and give you (and the users of your module) a healthy barrier against SQL injection problems.
my $sth = $dbh->prepare('INSERT INTO image VALUES(NULL, ?, ?, ?, ?, ?)');
$sth->execute(
$self->image, $self->extension, $self->location,
$self->modified, $self->accessed
);
I've also found format skipping: -fs to protect a specific segment of code from perltidy. I'd put an example here but the Site seems to do a hatchet job on it...
I'm rather new to the concept of Regex. I understand basic regex I use in bash script. The following snippet of code is from a program I'm writing to automatically update Wordpress plugins on the server.
Anyway the concept is that this piece of code is part of a subroutine which recurses through .php files in a directory, and tries to pattern match files starting with "Version:", "version:", "*Version:" etc from the file, and if pattern is matched, another sub then tries to extract the value following the character ":" to get the correct version number.
$searchpath=$path."/".$plugins[$i];
#files = <$searchpath/*.php>;
print "Search path is ".$searchpath."\n";
OUT: foreach $file (#files)
{
print "Checking alternate php file: ".$file."\n";
open(txt, $file);
while($line = <txt>)
{
for ($line)
{
s/^\s+//;
s/\s+$//;
}
if ( $line =~ /^Version:|^version:|^\* Version:|\sVersion:/ )
{
print "Version found in file ".$file."\n";
$varfound=1;
close(txt);
$ver=&read_extract($file);
print $ver."\n";
$pluginversion[$i]=$ver;
print "Array Num ".$i." Stored plugin name:".$plugins[$i]." Version found ".$ver." Version stored ".$pluginversion[$i]."\n";
last OUT;
}
}
}
The issue is that I seem to be having an error in logic, and the file actually matches " . phpversion() . "\n"; Version stored " . phpversion() . "\n" for the search query. With my limited knowledge I find it difficult to understand what's wrong, and would be eager for some advice.
The other subs referred to are included below:
sub read_extract
{
my $pl_version="";
open(txt, my $file=$_[0]);
while($line = <txt>)
{
for ($line)
{
s/^\s+//;
s/\s+$//;
}
if ( $line =~ /^Version:|^version:|^\* Version:|\sVersion:/ )
{
$pl_version=&extract_version($line);
}
}
close(txt);
$pl_version;
}
sub extract_version
{
my $line=$_[0];
$string=substr($line,rindex($line, ":")+1);
for ($string)
{
s/^\s+//;
s/\s+$//;
}
$string;
}
If my subroutine is required in full, I can include it. However my debug lines show this:
Processing xcloner-backup-and-restore...Search path is /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/admin.cloner.html.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/admin.cloner.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/admin.xcloner-backupandrestore.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/admin.xcloner.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/cloner.config.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/cloner.cron.php
Checking alternate php file: /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/cloner.functions.php
Version found in file /var/www/virtual/joel.co.in/vettathu.com/htdocs/wp-content/plugins/xcloner-backup-and-restore/cloner.functions.php
" . phpversion() . "\n";
Array Num 26 Stored plugin name:xcloner-backup-and-restore Version found " . phpversion() . "\n"; Version stored " . phpversion() . "\n";
which seems to be where the error is.
Well, that's a lot of redundant code there. If you have the line already, why do you need to close the file and find the line again? All you need to do is capture the string when you find the line:
if ( $line =~ /^\*?\s?Version:(.*)/i ) {
my $version = $1;
So, by using the /i modifier, your match is case insensitive. By placing ? after \* and \s they can match 0 or 1 time. By using (.*) the rest of the line is captured to $1.
Your regex was lacking a ^ beginning of line anchor in the last match, which I assumed was a typo. If not, you can simply change the regex to /\bVersion:(.*)/i. And the \b is only useful for avoiding partial matches, such as subversion: foo.
I tried so many codes that I found on internet but none of them would work.
I have a HTML code something like this.
<div class="usernameHolder">Username: user123</div>
what I want is get the text user123 from this line of code, of course this code is with the rest of the HTML content (an HTML page) Can anyone point me to the right direction?
$text = #source=~ /Username:\s+(.*)\s+</;
print $text;
but it won't return anything.
If the HTML is in a string:
$source = '<div class="usernameHolder">Username: user123</div>';
# Allow optional whitespace before or after the username value.
$text = $source=~ /Username:\s*(.*?)\s*</;
print $1 . "\n"; # user123
If the HTML is in an array:
#source = (
'<p>Some text</p>',
'<div class="usernameHolder">Username: user123</div>',
'<p>More text</p>'
);
# Combine the matching array elements into a string.
$matching_lines = join "",grep(/Username:\s*(.*?)\s*</, #source);
# Extract the username value.
$text = $matching_lines =~ /Username:\s*(.*?)\s*</;
print $1 . "\n"; # user123
A more-compact version using an array:
#source = (
'<p>Some text</p>',
'<div class="usernameHolder">Username: user123</div>',
'<p>More text</p>'
);
# Combine the matching array elements in a string, and extract the username value.
$text = (join "",grep(/Username:\s*(.*?)\s*</, #source)) =~ /Username:\s*(.*?)\s*</;
print $1 . "\n"; # user123
Your second \s+ doesn't match anything, since there is no space between user123 and the following tag.
How about this?
/Username:\s*(.*?)\s*</
Here, \s* is discarding spaces if there are any, and .*? is there so that you don't grab most of the document in the process. (See greedy vs. non-greedy)
My Perl is fairly rusty so please forgive. Trying to write a query using a variable. Have tried reformatting, just can't seem to get it correctly. Here is my code, not sure what I'm doing wrong.
my $d_var = "$3\n";
my $query="SELECT id FROM `accounts` WHERE (`accounts`.`named` = ?) LIMIT 1";
my $st_h = $db_h->prepare($query);
$st_h->bind_param(1, '$d_var');
$st_h->execute;
my $row = $st_h->fetchrow_array();
Please double check:
$3 contains something reasonable
concatenating $3's value and "\n" (by interpolation) is correct ("\n" in field?)
as ' doesn't interpolate => my $st_ht->bind_param(1, $d_var);
(I don't understand the DBI Docs as Chris Ledet does.)
On 2nd thought:
This code snippet:
my $v = "nix nix 1001";
print "$v\n";
print '$v\n', "\n";
if ($v =~ m/(nix) (nix) (\d+)/) {
print 'found: ', $3, "\n";
$sth = $dbh->prepare('SELECT * FROM sample01.csv WHERE GRUPPE=?');
$sth->bind_param(1, $3);
$sth->execute;
while(my #row = $sth->fetchrow_array()) {
print '|', join( '|', #row ), "|\n";
}
} else {
print "no match\n";
}
and the output:
DBI: 1.616 DBD::CSV: 0.33
|00000089-6d83-486d-9ddf-30bbbf722583|2011-09-17 16:25:09|1001|
|000004c9-92c6-4764-b320-b1403276321e|2011-11-09 13:52:30|2000|
nix nix 1001
$v\n
found: 1001
|00000089-6d83-486d-9ddf-30bbbf722583|2011-09-17 16:25:09|1001|
should illustrate:
' does not interpolate, your '$d_var' will pass this variable name literally to DBI
a valid match needs no "\n" to 'work'
the param sequence for bind_param is number, value
Not sure why you're even using bind_param. In my opinion, it's far simpler to just pass extra values into execute.
my $d_var = "$3\n";
my $query = 'SELECT id FROM accounts` WHERE (`accounts`.`named` = ?) LIMIT 1';
my $st_h = $db_h->prepare($query);
$st_h->execute($d_var);
my $row = $st_h->fetchrow_array();
Have you considered switching to DBIx::Class?
What does this mean?
my $st_ht->bind_param(1, '$d_var');
There is no variable being introduced, so why the my?
I have $3 printing out prior to execution and there is data contained within the string.
I have d_var="$3\n" as the variable $3 is being generated by a Regex string and doesn't seem to work without \n.
Tried what Chris suggested above, however did not work.
Aside from what Dan said (removing the single quote), you binded your param to a possibly none Statement handle object $st_ht->bind_param(...) it should be $st_h->bind_param(...).