$start = true;
$new = "";
foreach($array as $val)
{
if($start = true && $val != " ")
{
$start = false;
$new .= strtoupper($val);
}
elseif($val == " ")
{
$new .= " ";
$start = true;
}
else
{
$new .= strtolower($val);
}
$start = false;
}
Basically what happens is $start NEVER becomes false AND everything becomes capitalized. So it looks like the first if IS running, but for some reason NEVER SETS $start to false.
I cannot stress it enough: use the yoda condition
if(true == $var)
or generally:
if(CONSTANT == $VARIABLE)
and not
if($VARIABLE == CONSTANT) //which you'd wrongly type as "="
PHP would have told you what went wrong in that case - no matter how tired you are.
Looking for this bug (it happens to the best of the best too) is frustrating.
Let the tool (PHP) be supportive to you, don't make it work against you.
That was on a more general note. As for your problem, it's doable with a one-liner:
<?php
$array = "hEllo woRlD";
var_dump(ucwords(strtolower($array)));
$start = true is an assignment, not a comparison. Use ==.
You're using a single equals in your test, which means "assignment". You probably meant == (equality), but in this case, with booleans, you don't need to compare at all:
$start = true;
$new = "";
foreach($array as $val)
{
if($start && $val != " ") // <-- remove the = true here
{
$start = false;
$new .= strtoupper($val);
}
elseif($val == " ")
{
$new .= " ";
$start = true;
}
else
{
$new .= strtolower($val);
}
$start = false;
}
Right now, it's getting interpreted as "Set $start to true && $val != " "" - definitely not what you intended.
$start = true && $val != " " means:
$start = (true && $val != " ")
$start = ($val != " ")
$start = !($val == " ") // $start is true except when $val is a single space.
I believe you meant $start == true.
Are you just trying to upper case the first character of every word? If so, look into ucwords.
Related
I am upgrading a codebase that makes use of pass by reference
Main function
function splitSqlFile(&$ret, $sql)
{
$sql = trim($sql);
$sql_len = strlen($sql);
$char = '';
$string_start = '';
$in_string = false;
for ($i = 0; $i < $sql_len; ++$i) {
$char = $sql[$i];
if ($in_string) {
for (;;) {
$i = strpos($sql, $string_start, $i);
if (!$i) {
$ret[] = $sql;
return true;
}else if ($string_start == '`' || $sql[$i-1] != '\\'){
......
}else {
......
} // end if...elseif...else
} // end for
}
else if ($char == ';') {
$ret[] = substr($sql, 0, $i);
$sql = ltrim(substr($sql, min($i + 1, $sql_len)));
$sql_len = strlen($sql);
if ($sql_len) {
$i = -1;
} else {
// The submited statement(s) end(s) here
return true;
}
}else if (($char == '"') || ($char == '\'') || ($char == '`')) {
$in_string = true;
$string_start = $char;
} // end else if (is start of string)
// for start of a comment (and remove this comment if found)...
else if ($char == '#' || ($char == ' ' && $i > 1 && $sql[$i-2] . $sql[$i-1] == '--')) {
......
if (!$end_of_comment) {
// no eol found after '#', add the parsed part to the returned
// array and exit
$ret[] = trim(substr($sql, 0, $i-1));
return true;
} else {
.....
} // end if...else
} // end else if (is comment)
} // end for
// add any rest to the returned array
if (!empty($sql) && trim($sql) != '') {
$ret[] = $sql;
}
return true;
}
Calling the function
$sqlUtility->splitSqlFile($pieces, $sql_query);
foreach ($pieces as $piece)
{
.......
}
If the above variable splitSqlFile(&$ret, $sql) have the "&" before it, the program does run successfully, but if it is removed, now splitSqlFile($ret, $sql), It will start returning the 'invalid argument supplied for foreach' error.and when I try using the "is_array" function to check if it is an array, the result is always "NULL".
Why you get the error:
By removing the & from $ret, you are no longer referencing the variable in the function call. In this case, $pieces. So when you do a foreach on $pieces after calling the function, it will error because $pieces is basically a null variable at that point.
function splitSqlFile(&$ret,$sql) {
$ret[] = 'stuff';
}
splitSqlFile($pieces,$sql);
// $pieces will be an array as 0 => 'stuff'
foreach ($pieces as $piece) { } // will not error
vs:
function splitSqlFile($ret,$sql) {
$ret[] = 'stuff';
}
splitSqlFile($pieces,$sql);
// $pieces will be a null variable, since it was never assigned anything
foreach ($pieces as $piece) { } // will error
Alternative to no reference:
So if you want to remove the & and no longer pass by reference, you have to do other changes to the function to get that value back out. And depending on the codebase, this could mean a whole lot of work everywhere that function is used!
Example:
function splitSqlFile($sql) {
$ret = [];
$ret[] = 'stuff';
return array('result'=>true,'ret'=>$ret);
}
// $result will contain multiple things to utilize
// if you will only need that variable once (does not accumulate)
$result = splitSqlFile($sql);
foreach ($result['pieces'] as $piece) { }
// if that variable is added by multiple calls, and displayed later... merge
$pieces = [];
$result = splitSqlFile($sql_1);
$pieces = array_merge($pieces,$result['pieces']);
$result = splitSqlFile($sql_2);
$pieces = array_merge($pieces,$result['pieces']);
foreach ($pieces as $piece) { }
A second example (passing in the array as you go... gets confusing):
function splitSqlFile($pieces_in,$sql) {
$pieces_in[] = 'stuff';
return array('result'=>true,'pieces_out'=>$pieces_in);
}
$pieces = [];
$result = splitSqlFile($pieces,$sql_1);
$pieces = $result['pieces_out'];
$result = splitSqlFile($pieces,$sql_2);
$pieces = $result['pieces_out'];
foreach ($pieces as $piece) { }
As you can see, not only does it change the return values that has to be dealt with, but it also changes how it is called. Again, if this function is used in a thousand places in the code... serious headaches!
Conclusion:
I would honestly keep the reference as it is. It was done that way to make accumulating debug data easier, and direct. Otherwise you have a lot of code changes to do toget rid of the reference.
However that can simply be my opinion on the matter.
I am working on a php site that needs to search a set of files with any combination of search fields.
The possible search fields are
id, year, building, lastname, firstname, birthdate
The folder structure and file names are as such
/year/building/file.pdf
The filenames contain the data to search
id_lastname_firstname_MM_dd_yy.pdf
I have everything working on the site except this part. Originally I only had ID, year, and building and I was able to do if's to check for every possibility of combinations. Now there is way more combinations so it much more complex.
I was thinking nested if and in_array or such, but there has to be a better way. I just learning my way around php.
I would like to be able to search with any combination of fields. I can change the filenames if it helps.
I started with something like this
function search($transcripts, $studentid=null, $year=null, $building=null, $last=null, $first=null, $birthdate=null){
$ext = '.pdf';
date_default_timezone_set('America/Los_Angeles');
$dir_iterator = new RecursiveDirectoryIterator("../transcripts");
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
if ($file->isFile()){
$path = explode('\\',$file->getPath());
$fname = explode('_', $file->getBasename($ext));
if($path[1] == $year){
if($path[2] == $building){
if(in_array($last, $fname, true)){
if((in_array($first, $fname, true)){
if((in_array($birthdate
Originally I had seperate functions depending on which fields where filed in.
function bldStuSearch($building, $studentid, $transcripts){
$ext = '.pdf';
date_default_timezone_set('America/Los_Angeles');
$dir_iterator = new RecursiveDirectoryIterator("../transcripts");
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file) {
$results = explode('\\',$file->getPath());
//var_dump($results);
if (($file->isFile()) && ($file->getBasename($ext)==$studentid) && ($results[2] == $building)){
//echo substr($file->getPathname(), 27) . ": " . $file->getSize() . " B; modified " . date("Y-m-d", $file->getMTime()) . "\n";
$results = explode('\\',$file->getPath());
//var_dump($results);
//$building = $results[2];
$year = $results[1];
//$studentid = $file->getBasename($ext);
array_push($transcripts, array($year, $building, $studentid));
//var_dump($transcripts);
//$size += $file->getSize();
//echo '<br>';
}
}
//echo "\nTotal file size: ", $size, " bytes\n";
if (empty($transcripts))
{
header('Location: index.php?error=2'); exit();
}
return $transcripts;
}
Now I am trying to have one search function to check for any combination? Any idea that would at least put in the right direction?
Thanks.
So I had an idea about doing a scoring system but then dismissed it. I came back to it and found a way to make it work using a weighted scoring system.
This allows the search to be super flexible and maintain being portable, not requiring a database for the metadata and using the filename as the search data without having to search each PDF. I am using A-Pdf splitter to split the PDF into separate files and add the metadata to the filename.
I hope someone some day finds this useful for other searches. I am really happy the way this turned out.
I will post the entire code when I am done on http://github.com/friedcircuits
One thing I should change is to use named keys for the arrays.
Here is the resulting code. Right now the birthdate has to be entered as m-d-yyyy to match.
function search($transcripts, $studentid=null, $year=null, $building=null, $last=null, $first=null, $birthdate=null){
$ext = '.pdf';
$bldSearch = false;
date_default_timezone_set('America/Los_Angeles');
if (($building == null) AND ($year == null)){ $searchLocation = "../transcripts";}
elseif (($year != null) AND ($building != null)){$searchLocation = "../transcripts/".$year."/".$building;}
elseif ($year != null) {$searchLocation = "../transcripts/".$year;}
elseif ($building != null) {
$searchLocation = "../transcripts/";
$bldSearch = true;
}
else{$searchLocation = "../transcripts";}
$dir_iterator = new RecursiveDirectoryIterator($searchLocation);
$iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
$score = 0;
foreach ($iterator as $file) {
if ($file->isFile()){
//Fix for slashes changing direction depending on search path
$path = str_replace('/','\\', $file->getPath());
$path = explode('\\',$path);
$fname = explode('_', $file->getBasename($ext));
//var_dump($path);
//echo "<br>";
//var_dump($fname);
//echo "<br>";
//fix for different search paths
if($path[1] == "transcripts"){
$pYear = $path[2];
$pbuilding = $path[3];
}
else{
$pYear = $path[1];
$pbuilding = $path[2];
}
if ($bldSearch == true){
if ($building != $pbuilding) {continue;}
}
//$fname[1] = #strtolower($fname[1]);
//$fname[2] = #strtolower($fname[2]);
if($fname[0] == $studentid){
$yearS = $pYear;
$buildingS = $pbuilding;
$studentidS = $fname[0];
$lastS = $fname[1];
$firstS = $fname[2];
$birthdateS = $fname[3];
array_push($transcripts, array($yearS, $buildingS, $studentidS, $lastS, $firstS, $birthdateS));
continue;
}
if($pYear == $year){
$score += 1;
}
if($path[2] == $building){
$score += 1;
}
if(#strpos(#strtolower($fname[1]),$last) !== false){
$score += 3;
}
if(#strpos(strtolower($fname[2]), $first) !== false){
$score += 3;
}
if($fname[3] == $birthdate){
$score += 3;
}
//echo $score." ";
if ($score > 2) {
$yearS = $pYear;
$buildingS = $pbuilding;
$studentidS = $fname[0];
$lastS = $fname[1];
$firstS = $fname[2];
$birthdateS = $fname[3];
array_push($transcripts, array($yearS, $buildingS, $studentidS, $lastS, $firstS, $birthdateS));
//var_dump($transcripts);
}
}
$score = 0;
}
if (empty($transcripts))
{
header('Location: index.php?error=2'); exit();
}
return $transcripts;}
Is there any way to make this code shorter ?
If ($Item_1 != "_") { $items1 = explode("_", $Item_1); } Else {}
If ($Item_2 != "_") { $items2 = explode("_", $Item_2); } Else {}
If ($Item_3 != "_") { $items3 = explode("_", $Item_3); } Else {}
If ($Item_4 != "_") { $items4 = explode("_", $Item_4); } Else {}
If ($Item_5 != "_") { $items5 = explode("_", $Item_5); } Else {}
If ($Item_6 != "_") { $items6 = explode("_", $Item_6); } Else {}
If ($Item_7 != "_") { $items7 = explode("_", $Item_7); } Else {}
If ($Item_8 != "_") { $items8 = explode("_", $Item_8); } Else {}
If ($Item_9 != "_") { $items9 = explode("_", $Item_9); } Else {}
If ($Item_10 != "_") { $items10 = explode("_", $Item_10); } Else {}
If ($Item_11 != "_") { $items11 = explode("_", $Item_11); } Else {}
If ($Item_12 != "_") { $items12 = explode("_", $Item_12); } Else {}
I try it make shorter with For but it doesnt work example:
For ($i = 1; $i <= 12; $i++) {
If (${$Item_ . $i} != "_") .... dont work for me :/
}
Any ideas?
The idea is good. You just had a little error while building the variable name. Use the following code:
for ($i = 1; $i <= 12; $i++) {
if (${"Item_$i"} != "_") .... should work
}
What you are doing is called variable variables in php. Check the manual about that for further info and examples.
Another idea: Why not using an array? this should suite better here:
$item = array (
'foo', 'bar', 'test', 'xyz', ...
);
for ($i = 1; $i <= count($item); $i++) {
if ($item[$i] != "_")
}
Further note, that you can use the ternary operator to shorten the if statement. (note that I wouldn't do that in this situation because it is less readable, but I'll at least mention it for completeness):
$item[$i] != "_" ? $other[$i] = 'something' : 1; // no else block, just a `NOP 1`;
For clarity try this:
$item_var = "Item_".$i;
If ($$item_var != "_"){}
You should probably be using arrays instead if var1, var2, etc. You could easily use a loop too.
I have the following code, I seem to be having problems with booleans in php, when ever i dump out the value of bCreatedEvent it is just empty, what am i doing wrong and I'm using booleans wrong? It also fails my logic check so i can redirect at the bottom. I'm fairly new to php, but thought most of this should work similar to c/c++.
$dbTheatreCMS = new TheatreCMSDB();
$iEventID = $dbTheatreCMS->InsertNewEvent($sTitle, $sCompany, $iCreateID, $sNotes, $sPrePrice, $sRegPrice);
$bEventCreated = False;
echo "bEventCreated1 = " . $bEventCreated . "<br/>";
$bEventInfoInserted = True;
$bEventRolesInserted = True;
if ($iEventID > 0)
{
$bEventCreated = true;
if (isset($_POST["Venues"], $_POST["EventDates"]))
{
$aiVenueIDs = $_POST["Venues"];
$adtEvents = $_POST["EventDates"];
if (count($adtEvents) == count($aiVenueIDs)) // These should be the same length
{
for ($i = 0; $i < count($adtEvents); $i++)
{
$bEventInfoInserted &= ($dbTheatreCMS->InsertNewEventInfo($iEventID, $aiVenueIDs[$i],$adtEvents[$i]) > 0) ? true :false;
}
}
}
if (isset($_POST["Troupers"], $_POST["Roles"]))
{
$trouperIDs = $_POST["Troupers"];
$roles = $_POST["Roles"];
if (count($trouperIDs) == count($roles))
{
for ($i = 0; $i < count($trouperIDs); $i++)
{
$bEventInfoInserted &= ($dbTheatreCMS->InsertNewTroupeInfo($iEventID, $trouperIDs[$i],$roles[$i]) > 0)? true:false;
}
}
}
}
echo "bEventCreated = " . $bEventCreated . "<br/>";
echo "bEventInfoInserted = " . $bEventInfoInserted . "<br/>";
echo "bEventRolesInserted = " . $bEventRolesInserted . "<br/>";
$bEventCreated = $bEventCreated & $bEventInfoInserted & $bEventRolesInserted;
echo "$bEventCreated = " . $bEventCreated . "<br/>";
if($bEventCreated == True)
{
echo "<script type='text/javascript'>window.localStorage.href = 'some page.php';</script>";
}
output
bEventCreated1 =
bEventCreated =
bEventInfoInserted = 1
bEventRolesInserted = 1
0 = 0
echo false will look empty use var_dump($bEventCreated)
Also & is a bitwise operator I think you mean &&
$bEventCreated = $bEventCreated & $bEventInfoInserted & $bEventRolesInserted;
Make sure you always use identical or not identical comparison operators when doing a boolean condition:
if($bEventCreated === TRUE)
If a value is false, it will not echo or print a value. See for example:
<?php
$true = true;
$false = false;
echo $true."\n";
echo $false."\n";
var_dump($true)."\n";
var_dump($false);
?>
http://codepad.org/98bR4bfn
There are some quirks with booleans in PHP. This two links may help:
http://pl.php.net/manual/en/language.types.boolean.php
http://pl.php.net/manual/en/language.types.string.php#language.types.string.casting
When you echo a variable it is first converted to a string.
When FALSE or NULL is converted to a string they are converted to an empty string, "". TRUE is converted to "1". Arrays are converted to "Array". Resources are undefined although they are currently converted like "Resource #N". Objects will throw an error if they don't implement __toString().
I'm participating in one of the Code Golf competitions where the smaller your file size is, the better.
Rather than manually removing all whitespace, etc., I'm looking for a program or website which will take a file, remove all whitespace (including new lines) and return a compact version of the file. Any ideas?
You could use:
sed 's/\s\s+/ /g' youfile > yourpackedfile`
There is also this online tool.
You can even do it in PHP (how marvelous is life):
$data = file_get_contents('foobar.php');
$data = preg_replace('/\s\s+/', ' ', $data);
file_put_contents('foobar2.php', $data);
You have to note this won't take care of a string variable like $bar = ' asd aa a'; it might be a problem depending on what you are doing. The online tool seems to handle this properly.
$ tr -d ' \n' <oldfile >newfile
In PowerShell (v2) this can be done with the following little snippet:
(-join(gc my_file))-replace"\s"
or longer:
(-join (Get-Content my_file)) -replace "\s"
It will join all lines together and remove all spaces and tabs.
However, for some languages you probably don't want to do that. In PowerShell for example you don't need semicolons unless you put multiple statements on a single line so code like
while (1) {
"Hello World"
$x++
}
would become
while(1){"HelloWorld"$x++}
when applying aforementioned statements naïvely. It both changed the meaning and the syntactical correctness of the program. Probably not too much to look out for in numerical golfed solutions but the issue with lines joined together still remains, sadly. Just putting a semicolon between each line doesn't actually help either.
This is a PHP function that will do the work for you:
function compress_php_src($src) {
// Whitespaces left and right from this signs can be ignored
static $IW = array(
T_CONCAT_EQUAL, // .=
T_DOUBLE_ARROW, // =>
T_BOOLEAN_AND, // &&
T_BOOLEAN_OR, // ||
T_IS_EQUAL, // ==
T_IS_NOT_EQUAL, // != or <>
T_IS_SMALLER_OR_EQUAL, // <=
T_IS_GREATER_OR_EQUAL, // >=
T_INC, // ++
T_DEC, // --
T_PLUS_EQUAL, // +=
T_MINUS_EQUAL, // -=
T_MUL_EQUAL, // *=
T_DIV_EQUAL, // /=
T_IS_IDENTICAL, // ===
T_IS_NOT_IDENTICAL, // !==
T_DOUBLE_COLON, // ::
T_PAAMAYIM_NEKUDOTAYIM, // ::
T_OBJECT_OPERATOR, // ->
T_DOLLAR_OPEN_CURLY_BRACES, // ${
T_AND_EQUAL, // &=
T_MOD_EQUAL, // %=
T_XOR_EQUAL, // ^=
T_OR_EQUAL, // |=
T_SL, // <<
T_SR, // >>
T_SL_EQUAL, // <<=
T_SR_EQUAL, // >>=
);
if(is_file($src)) {
if(!$src = file_get_contents($src)) {
return false;
}
}
$tokens = token_get_all($src);
$new = "";
$c = sizeof($tokens);
$iw = false; // Ignore whitespace
$ih = false; // In HEREDOC
$ls = ""; // Last sign
$ot = null; // Open tag
for($i = 0; $i < $c; $i++) {
$token = $tokens[$i];
if(is_array($token)) {
list($tn, $ts) = $token; // tokens: number, string, line
$tname = token_name($tn);
if($tn == T_INLINE_HTML) {
$new .= $ts;
$iw = false;
}
else {
if($tn == T_OPEN_TAG) {
if(strpos($ts, " ") || strpos($ts, "\n") || strpos($ts, "\t") || strpos($ts, "\r")) {
$ts = rtrim($ts);
}
$ts .= " ";
$new .= $ts;
$ot = T_OPEN_TAG;
$iw = true;
} elseif($tn == T_OPEN_TAG_WITH_ECHO) {
$new .= $ts;
$ot = T_OPEN_TAG_WITH_ECHO;
$iw = true;
} elseif($tn == T_CLOSE_TAG) {
if($ot == T_OPEN_TAG_WITH_ECHO) {
$new = rtrim($new, "; ");
} else {
$ts = " ".$ts;
}
$new .= $ts;
$ot = null;
$iw = false;
} elseif(in_array($tn, $IW)) {
$new .= $ts;
$iw = true;
} elseif($tn == T_CONSTANT_ENCAPSED_STRING
|| $tn == T_ENCAPSED_AND_WHITESPACE)
{
if($ts[0] == '"') {
$ts = addcslashes($ts, "\n\t\r");
}
$new .= $ts;
$iw = true;
} elseif($tn == T_WHITESPACE) {
$nt = #$tokens[$i+1];
if(!$iw && (!is_string($nt) || $nt == '$') && !in_array($nt[0], $IW)) {
$new .= " ";
}
$iw = false;
} elseif($tn == T_START_HEREDOC) {
$new .= "<<<S\n";
$iw = false;
$ih = true; // in HEREDOC
} elseif($tn == T_END_HEREDOC) {
$new .= "S;";
$iw = true;
$ih = false; // in HEREDOC
for($j = $i+1; $j < $c; $j++) {
if(is_string($tokens[$j]) && $tokens[$j] == ";") {
$i = $j;
break;
} else if($tokens[$j][0] == T_CLOSE_TAG) {
break;
}
}
} elseif($tn == T_COMMENT || $tn == T_DOC_COMMENT) {
$iw = true;
} else {
if(!$ih) {
$ts = strtolower($ts);
}
$new .= $ts;
$iw = false;
}
}
$ls = "";
}
else {
if(($token != ";" && $token != ":") || $ls != $token) {
$new .= $token;
$ls = $token;
}
$iw = true;
}
}
return $new;
}
// This is an example
$src = file_get_contents('foobar.php');
file_put_contents('foobar3.php',compress_php_src($src));
If your code editor programs supports regular expressions, you can try this:
Find this: [\r\n]{2,}
Replace with this: \n
Then Replace All
Notepad++ is quite a nice editor if you are on Windows, and it has a lot of predefined macros, trimming down code and removing whitespace among them.
It can do regular expressions and has a plethora of features to help the code hacker or script kiddie.
Notepad++ website
Run php -w on it!
php -w myfile.php
Unlike a regular expression, this is smart enough to leave strings alone, and it removes comments too.