|
Jeremy Falcon wrote: Unix/Linux says piss off n00b unless you pound your brains into a bloody pulp R(ing)TFM, and don't catch the endless exceptions to the rules, because we never F'ing documented them for you! And if we did, we put them in some obscure location that is only findable after your exposed brain stem smashes through the screen, triggering an epileptic-like seizure that miraculously moves your fingers into an archaic 'man' command line sequence that infinite monkeys could never reproduce.
FTFY
|
|
|
|
|
Touché.
Seriously though, the docs are out there, they just tend to be more decentralized than say MSDN. I found it's the same thing with learning wxWidgets too, part of the pain was just finding good documentation online. Open source drawback I suppose, everyone wants to code, nobody wants to write docs.
If I were just starting out with PHP and *nix these days, I'd totally be pouring myself into books at the very least to help the learning curve.
Jeremy Falcon
|
|
|
|
|
My frustration with their mentality is that the barrier to entry is too high, like you pointed out. I once had to change a password for a MySQL database, so I followed the instructions here[^]. Note the "'" (single quote) surrounding the password. Since I was doing it from a Windows command prompt there was a whole other level nobody mentioned. Doing it that way actually entered " ' "s in the password! And logging in became impossible. So changing the password was the only option, once I figured out what the issue was (at least fifteen minutes of "OH SH*T, WHAT DID I DO???")
Then there were four more hours ahead of me, because of a single friggin space! None of the examples online showed that the correct command is "mysqladmin -u root -p'xyz123' password newPassword". Note the lack of space between the "p" and the " ' ". I wanted to kill... And that wasn't my first exposure to their stuff.
I'm not afraid of command prompts, having once helped administer a Windows/Solaris hybrid network, but issues like the previous are far too abundant in that world. I want to actually get something done on my computer, not dig through documentation all day.
|
|
|
|
|
David O'Neil wrote: Then there were four more hours ahead of me, because of a single friggin space! None of the examples online showed that the correct command is "mysqladmin -u root -p'xyz123' password newPassword". Note the lack of space between the "p" and the " ' ". I wanted to kill... And that wasn't my first exposure to their stuff.
Oh yeah, that totally annoyed me too. At one point I read there was some technical reason for it, but at the end of the day I suspect that's a load of BS.
David O'Neil wrote: I'm not afraid of command prompts, having once helped administer a Windows/Solaris hybrid network, but issues like the previous are far too abundant in that world. I want to actually get something done on my computer, not dig through documentation all day.
Fair enough, but just about any environment has its quirks. Although I don't have many examples I can think of off the top of my head (old age tends to do that), it still 'tis be true.
Jeremy Falcon
|
|
|
|
|
Jeremy Falcon wrote: (old age tends to do that)
I wasn't going to say that the network involved Windows for Workgroups.... , so I know the aging feeling.
PS - If you ever have a moment, and care to give some feedback on PHP code, how could this program[^] be improved? That was a self-teaching marathon, having never really touched PHP before, and I'm certain there are probably many tricks I missed, and language issues that could be improved, but the end product seems to work. Thanks. (If not, no problem.)
|
|
|
|
|
It looks pretty solid. I do have a few nit-picky things, just to help tighten it up. Not required, but will help it run a bit smoother...
Article Code: require_once("phpPayPalIpnClass.php"); Relative paths are a no-go if you ever want to run this code on the command line instead of the web. That's because your current directory will be the directory you are in when calling the script and not the one the script is actually in. The web server dances around that. What I do is something like this in the main PHP file to the app to handle both web and command line invocations.
define('BASE_PATH', realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR);
require_once BASE_PATH . 'my/relative/path.php';
Article Code: $this->logger->log("Processing a payment.\r\n"); Instead of explicit line breaks like that, it's better to use the constant PHP_EOL, so platform translation happens automatically.
$this->logger->log("Processing a payment." . PHP_EOL);
Article Code: $_POST['txn_id'] A hacker can easily mess with GET or POST data. And, if you try to access a variable that way without checking for its existence first the script can crash and burn. So I always validate / sanitize my input and perform checks before using them. Something like this at the very least...
if(isset($_POST['txn_id']))
Article Code: $this->logger->log("\r\nSENT:\r\n" . $header . $response . "\r\n\r\n"); If you're using double quotes for a string literal you don't have concatenate strings to include variables. You can just type them as part of the string and PHP will translate it automatically.
$nl = PHP_EOL;
$this->logger->log("$nlSENT:$nl$header$response$nl$nl");
Anyway, that's at first glance. Should make it a bit more cool looking if nothing else.
Jeremy Falcon
|
|
|
|
|
Thanks! I'll change it up, and update the article in the next week or so with the improvements, with more thanks at that time!
|
|
|
|
|
Oh, one more (quick?) question, if I may. So this:
Quote: require_once BASE_PATH . 'my/relative/path.php';
would become something like this:
Quote: require_once BASE_PATH . '/home/user/phpPayPalController.php'
and exposing it that way (because anyone can look at the html for the landing page, which has to have that on it) doesn't make it easier to hack the db password and setup files that are at that protected subdirectory location?
Thanks!
|
|
|
|
|
Let's assume you have a PHP file in /home/myapp/myfile.php . Then BASE_PATH would end up being /home/myapp/ at this point. So you'd want to do do something like require_once BASE_PATH . 'myfile.php'; . Whereas before it was just require_once 'myfile.php'; . However, this way the file will be included regardless of how the script is executed.
Jeremy Falcon
|
|
|
|
|
Oh. OK. That means since the main entry file is an html page, visible onsite, the base path would be it, and the require_once would be something like require_once BASE_PATH . '../../../myFile.php'; , depending upon how many subdirectories it was above the directory. Thanks.
|
|
|
|
|
Keep in mind the path would no longer be relative to the actual file doing the including, but to the BASE_PATH constant. So if you had something like /home/myapp/mymodule/myotherfile.php that included some files in say /home/myapp/newdir/awesome.php , you'd want to do something like this require_once BASE_PATH . 'newdir/awesome.php'; .
Keep in mind, BASE_PATH is only set once, in the main file that's first run. It's then in the global scope as other files are included. So all other files just reference it.
Jeremy Falcon
|
|
|
|
|
So in my case, the top-level, visible file would have:
require_once BASE_PATH . '../../../phpPayPalController.php';
or however many levels were required, and all of the hidden files, below public, would also have the same thing, but the file names would be changed, i.e.,
require_once BASE_PATH . '../../../phpMyMailClass.php'; , even though they are all at the same location. That makes sense now.
Thanks! And Thanks for the time!
|
|
|
|
|
You wouldn't need to use .. in the path anymore. Think of BASE_PATH as pointing to the root of the application and all other files stem from that, not the actual file doing the including.
Jeremy Falcon
|
|
|
|
|
Responded via email, because it isn't really appropriate for the lounge (and hasn't been for a couple posts). Thanks!
|
|
|
|
|
I accidentally deleted it. I usually do that with CP notifications and just go to the site to read them. So... mind sending it again?
Jeremy Falcon
|
|
|
|
|
I will post it here, then.
What you said has left me in a state of confusion. To simplify my case, say the landing page is at www.randommonkeyworks.com/landing.php, which is at [serverSpecificStuff]/home/user/public_html. This is what BASE_PATH will become because of the PHP declaration.
The main file included by that landing page is one subdirectory up, at [serverSpecificStuff]/home/user/, so it is hidden from the outside world, non-public. You've indicated I don't need to use the .. relative path inclusion technique like BASE_PATH . "..\hidden1.php" to get to it, but I can't see how that is possible because BASE_PATH points to the user subdirectory, not the home subdirectory.
Additionally, the hidden1.php includes 4 more files, say they are numbered 2 through 5. They are also at the home subdirectory, non-public. Therefore, unless PHP and the server are smart enough to expand the environment (or whatever magic is being done) to include the home subdirectory because it had to look for hidden1.php there, doesn't the hidden1.php file also need to include 2 - 5 as relative to the BASE_PATH , i.e., require_once (BASE_PATH . "..\hidden2.php"); , and the same for the other three files?
Unless, maybe I added another line to the PHP:
define('HIDDEN_PATH', realpath(dirname(__FILE__)) . DIRECTORY_SEPARATOR . "..\");
(if that is the way to do it in PHP, which it probably isn't with my luck) in the landing.php file, and used that path for all includes everywhere. Perhaps that is what you were getting at, but just overlooked the fact that all the included files were not in BASE_PATH.
Many thanks for the time and trouble!
David O'Neil
|
|
|
|
|
I get what you're saying now. Then all that's needed to make the base directory one level higher. You can do that by calling dirname twice from landing.php like so:
define('BASE_PATH', realpath(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR);
And then you could build on top of that to have a public path as well.
define('BASE_PATH', realpath(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR);
define('PUB_PATH', BASE_PATH . 'public_html' . DIRECTORY_SEPARATOR);
So now BASE_PATH points to [serverSpecificStuff]/home/user/ and PUB_PATH points to [serverSpecificStuff]/home/user/public_html/ and you can use them as needed when including files.
There is one tiny caveat to this however, if the files are located just one level up from / then you'll end up with something like //, which isn't a valid directory. So as long as your files aren't directly in /home then you're good to go no matter where you put the files on the system and no matter how they are invoked.
Jeremy Falcon
|
|
|
|
|
In the interest of rock-solid code. This would be the most fault-tolerant way:
$base = realpath(dirname(dirname(__FILE__)));
define('BASE_PATH', $base == DIRECTORY_SEPARATOR ? $base : $base . DIRECTORY_SEPARATOR);
define('PUB_PATH', BASE_PATH . 'public_html' . DIRECTORY_SEPARATOR);
require_once BASE_PATH . 'some/hidden/file.php';
require_once PUB_PATH . 'some/public/file.php';
Jeremy Falcon
|
|
|
|
|
Thanks! Have a bunch of 5s!
|
|
|
|
|
Anyway, to address some points...
Marc Clifton wrote: I despise silent exits, not even a little whimper of "$foobar" not defined.
Completely configurable. Use the debug version of php.ini that ships with your distribution while doing development. Error messages like this are turned off by default for production and for a good reason, you're supposed to have proper error handling.
Marc Clifton wrote: I detest prefixing variables with "$", it harks back to the days of BASIC ass$="you are".
That has to do with its Unix roots man. If you're done a lot of Perl and shell scripting, you'd be very familiar with the good ol' $ .
Marc Clifton wrote: I piss on your brace style if ( condition ) {
Come on Marc, really?
Marc Clifton wrote: Which of course promotes non-OOD spaghetti code practices, which is what I'm fixing right now. It's a amazing to me how people can f**** up less than 500 lines of code into an untestable morass of garbage.
True, PHP allows for OO and procedural code. And that allows for crap code by some dev. But C++ also allows you to shoot yourself in the foot and we don't blame the language.
Jeremy Falcon
|
|
|
|
|
Wow. Thanks for the feedback. I will fuss with the ini file, that'll be really helpful as, without intellisense, I make a lot of stupid mistakes.
Speaking of which, I'm using this nifty plug-in (it's something like $75) for Visual Studio that does a lot of the syntax highlighting and intellisense stuff, and most awesome of all, I can debug PHP code right in the IDE!
Jeremy Falcon wrote: Come on Marc, really?
I know, that was low. I really don't like that style of bracing though, I find it harder to visually distinguish code outside the if block with code on the inside.
Again, thanks for the great feedback!
Marc
|
|
|
|
|
Marc Clifton wrote: Speaking of which, I'm using this nifty plug-in (it's something like $75) for Visual Studio that does a lot of the syntax highlighting and intellisense stuff, and most awesome of all, I can debug PHP code right in the IDE!
You and me too man and I use PHP daily. And yet, at the age of 35 me and intellisense are best buds Also, I've seen that plug-in, if I wasn't using PhpEd like crack-cocaine I'd give it a whirl.
Marc Clifton wrote: I know, that was low. I really don't like that style of bracing though, I find it harder to visually distinguish code outside the if block with code on the inside.
Not sure I follow. It's no different than the C-family where white space is not important. This is perfectly valid PHP code:
<?php
namespace Application;
class MyClass extends BaseClass
{
public function MyFunction()
{
if(blah)
{
}
}
}
?>
Marc Clifton wrote: Again, thanks for the great feedback!
Any time man, you know I got your back. Ask away any question you have.
Jeremy Falcon
|
|
|
|
|
Jeremy Falcon wrote: Any time man, you know I got your back. Ask away any question you have.
I just had fun with this little piece of code:
array_walk_recursive($xmlResponse, array ($xml, 'addChild'));
Turns out array_walk_recursive passes the K=>V as $value, $key, and the XmlSimpleElement of course wants $element, $value.
Now, I did not write that code, I'm just fixing what someone else wrote. Sure was funny though when (after considerable massaging) I ran my unit test and the element/values were backwards! It is odd though that array_walk_recursive doesn't provide the params as $key, $value, but it's actually much more annoying that the programmer who used that function used it incorrectly for the task at hand.
Marc
|
|
|
|
|
Oh you're gonna find some "oddities" in there like that. I totally agree it would make more sense to order it key then value, like when doing a foreach loop.
That being said, there are better ways to traverse an XmlSimpleElement object. Unless it's been properly converted, treating it as a straight array will run into issues, and you'll loose XML metadata attributes, etc.
At the very least, if you're using PHP 5.5, you could do something like this with an anonymous function to at least make it a ton more readable...
array_walk_recursive($xmlResponse, function($item, $key)
{
});
Jeremy Falcon
|
|
|
|
|
Jeremy Falcon wrote: That being said, there are better ways to traverse an XmlSimpleElement object.
In this case, "xmlResponse" is an array to generate the XML response. As it is, I simply coded it like this:
function XmlAsString($array)
{
$xml = new SimpleXMLElement('<response/>');
foreach($array as $key => $value)
{
$xml->addChild($key, $value);
}
return $xml->asXML();
}
which does correctly what was originally intended.
I'm having to use PHP 5.4, but I like your anonymous function example, very cool. I think that actually works in 5.4 as well, but not sure.
Marc
|
|
|
|
|