Jump to content

KevinM1

Moderators
  • Posts

    5,222
  • Joined

  • Last visited

  • Days Won

    26

Everything posted by KevinM1

  1. Thanks. Hmmm...now to figure out why my session variable isn't being set.
  2. Hey, I just wanted to say thanks for linking me to that flow diagram. It's nice seeing the main participants in action. I actually have CodeIgniter 1.6.1, as a sort of study aid, but I hate the way their documentation works. The big thing, now, is to try to copy/steal (mwahaha) their segmented URL scheme. I like that infinitely better than the standard get links.
  3. Can objects be passed around via sessions without any preprocessing, or do they require being url_encoded and/or serialized?
  4. You know what? That probably is the issue. On your first page load, nothing has been submitted. So, you can't get to the validator objects because they don't exist yet. Since you are using PHP5, I strongly suggest you use the __autoload() function to load your class files. It helps remove logical issues like this by being triggered whenever an unknown object is accessed. I can't imagine trying to do OOP without it.
  5. Oh, sure, I could go that way....
  6. Ah, nice. It's possible to either catch that notice in an Exception, or otherwise dispose of it, right?
  7. Sorry for the delay. I'm still not sure what's causing your error. I made a PHP4 test case, once again testing different output scenarios, and all variations I tried work. The class code below is slightly changed -- I made the regex a bit more manageable for a test -- but it is still largely (i.e. 95% or so) what I suggested earlier. <?php class Validator { var $errors = array(); function validate($validateThis) {} function setError($msg){ $this->errors[] = $msg; } function isValid(){ if ($this->errors) { return false; } else { return true; } } function fetch(){ if(!$this->errors){ return false; } else{ foreach($this->errors as $error){ return $error; } } } } class ValidateTelephone extends Validator { var $status = "Everything okay<br />\n"; function ValidateTelephone ($telephone){ $this->validate($telephone); $this->setStatus(); } function validate($telephone){ if(empty($telephone)) { $this->setError('Telephone field is empty'); } else { if(!preg_match("/^[0-9]*$/",$telephone)) { $this->setError('Telephone number in invalid format'); } } } function setStatus(){ if($this->fetch()){ $this->status = "Something wrong!<br />\n"; } } function getStatus(){ return $this->status; } } $validators = array(); $validators['goodNum'] = new ValidateTelephone('1234'); $validators['badNum'] = new ValidateTelephone('ABCD'); echo "Direct hash attempt:<br /><br />\n\n"; echo "Good number status: {$validators['goodNum']->getStatus()}"; echo "Bad number status: {$validators['badNum']->getStatus()}"; echo "<br />Foreach-loop test:<br /><br />\n\n"; foreach($validators as $key => $value){ echo "Key: $key -- Status: {$value->getStatus()}"; } echo "<br />Embedded into HTML test:<br /><br />\n\n"; ?> <div> Good number status: <?php echo $validators['goodNum']->getStatus(); ?> Bad number status: <?php echo $validators['badNum']->getStatus(); ?> </div> The output: I'm honestly baffled by your error. The only things I can think of is something not being set properly in the class code, or some syntax error neither of us are picking up on.
  8. Damn, that was a fast reply! Also, I'm bumping this just to ensure that either of you can see my last edited post.
  9. Ah, great, thanks guys! I thought I was more or less on the right track, but it's nice to get confirmation. Regarding question 3, specifically something done once vs. each time an instance is created/assigned -- does calling session_start() after a session is already in place destroy the current session? Or does it just not do anything?
  10. Hmm..I see what you're saying. It's just that my (albeit limited) *nix/C++ background has ingrained into my mind that lazy = good. Bare minimum to get the job done efficiently, and nothing else. To borrow a term from Zandstra, the extra layer of abstraction gives off a funny 'smell' to me. Just something I'll have to get used to.
  11. Hmm...nothing that would be causing the error is jumping out at me. I tried a quick test version that checks whether calling the function from the hash directly, as opposed to running it through a foreach-loop, was the culprit. Both tests worked fine: <?php abstract class Validator{ private $status = "Everything is good<br />\n"; private $error; function setError($message){ $this->error = $message; } function hasError(){ if($this->error){ return true; } else{ return false; } } function setStatus(){ if($this->hasError()){ $this->status = $this->error; } } function getStatus(){ return $this->status; } } class NameValidator extends Validator{ function __construct($name){ if(preg_match("/^[0-9]*$/", $name)){ $this->setError("Name's cannot have digits!<br />\n"); } $this->setStatus(); } } class TelephoneValidator extends Validator{ function __construct($phone){ if(preg_match("/^[a-zA-Z]*$/", $phone)){ $this->setError("In this test case, phone numbers cannot have letters!<br />\n"); } $this->setStatus(); } } $testCases = array(); $testCases['name'] = new NameValidator("1138"); $testCases['phone'] = new TelephoneValidator("THX"); echo "Foreach-loop test:<br /><br />\n\n"; foreach($testCases as $key => $value){ echo "Key: $key -- Status: {$value->getStatus()}"; } echo "\n<br />Direct hash calls:<br /><br />\n\n"; echo "Name status: {$testCases['name']->getStatus()}"; echo "Phone status: {$testCases['phone']->getStatus()}"; ?> Output: These tests were done in PHP5, but I wouldn't think that would make a difference. Have you coded up the set/getStatus functions yet? Dumb question, I know, but that's really the only thing I can think of at the moment.
  12. Odd...I would think that so long as you assigned a validator object to a specific hash element, it would work. Which object/line is it referring to?
  13. A few things: If possible, I suggest upgrading to PHP5. Its OOP capabilities are far better than PHP4's. In particular, I don't think PHP4 has __autoload(), which is a great built-in PHP function that will autoload the necessary class files automatically, without you needing to manually write all of the include/require statements. Here's a quick example: <?php function __autoload($className){ require_once("$className.php"); } It's as simple as that. Put the file with the __autoload function in your top-most page/script, and you should be golden. Along those lines, I tend to be a one class per file kind of guy. Since I'm using __autoload(), that kind of setup works great for me. However, for PHP4, I can understand trying to streamline class families into one file. Use whatever works best for you. In terms of instantiating objects, that's actually one of the more difficult things (at least, in my short experience) of OOP. Without completely dismantling your script, I suggest using a hash. So, something like: <?php $validators['firstName'] = new ValidateName($first_name, 'Forename'); . . . $validators['phone'] = new ValidateTelephone($telephone); . . . <p><label for="first_name">Forename:</label><label id="first_name_msg" class="valid">Required</label> <input type="text" <?php echo $validators['firstName']->getStatus(); ?> title="Please enter your first name" id="first_name" name="first_name" size="28" value="<?php echo $first_name; ?>" class="validate required first_name first_name_msg" /></p> . . . <p class="hint">Please enter a contact telephone number e.g. 01548 342645</p> <p><label for="telephone">Telephone:</label><label id="telephone_msg" class="valid">Required</label> <input type="text" <?php echo $validators['phone']->getStatus(); ?> title="Please enter your last name" id="telephone" name="telephone" size="28" value="<?php echo $telephone; ?>" class="validate required telephone telephone_msg" /></p> It's a bit sloppy, and not really OOP, but something along those lines should probably work.
  14. I don't think a Decorator is required here as validation typically has two functions: to (obviously) validate data, and to inform the user (among others) of incorrect data. Because of that, I don't think it necessary to remove the 'inform user' functionality from the base validator classes themselves. That said, why not just include two simple get/set functions that deal with the status of the validation? <?php class Validator { var $errors = array() function validate($validateThis) {} function setError($msg){ $this->errors[] = $msg; } function isValid(){ if (count($this->errors) > 0) { return false; } else { return true; } } function fetch(){ if(!$this->errors){ return false; } else{ foreach($this->errors as $error){ return $error; } } } } class ValidateTelephone extends Validator { var $status = "style=\"background-color:white\""; function ValidateTelephone ($telephone){ $this->validate($telephone); $this->setStatus(); } function validate($telephone){ if(empty($telephone)) { $this->setError('Telephone field is empty'); } else { if(!preg_match("/(^0[1-9]\d{1}\s\d{4}\s?\d{4}$)|(^0[1-9]\d{2}\s\d{3}\s?\d{4}$)|(^0[1-9]\d{2}\s\d{4}\s?\d{3}$)|(^0[1-9]\d{3}\s\d{3}\s?\d{2}$)|(^0[1-9]\d{3}\s\d{3}\s?\d{3}$)|(^0[1-9]\d{4}\s\d{3}\s?\d{2}$)|(^0[1-9]\d{4}\s\d{2}\s?\d{3}$)|(^0[1-9]\d{4}\s\d{2}\s?\d{2}$)/",$telephone)) { $this->setError('Telephone number in invalid format'); } } } function setStatus(){ if($this->fetch()){ $this->status = "style=\"background-color:#E7EFFB\""; } } function getStatus(){ return $this->status; } } ?> So, in your client code, assuming you've instantiated a ValidateTelephone object, all you'd need to do is something along the lines of: <input type="text" <?php echo $validateTelephoneObject->getStatus(); ?> title="Please enter a username" id="username" />
  15. I figured I'd ask this here, so as to not create more top-level threads. I got a very simple Front Controller to work by basically just copying Zandstra's code. One of the things that bugs me about his code (which is why I modified his Registry classes) is his habbit of creating redundant functions that don't actually do anything, at least, to my inexperienced eye. Case in point - his code (with the exception of the class name) for the abstract base Command class is: <?php abstract class MP_command_Command{ final function __construct(){} function execute(MP_controller_Request $request){ $this->doExecute($request); } abstract function doExecute(MP_controller_Request $request); } ?> I fail to see why there needs to be two execute functions, especially since they both have the same signature, and neither one is private, or access private attributes. Wouldn't it make more sense to simply: <?php abstract class MP_command_Command{ final function __construct(){} abstract function execute(MP_controller_Request $request); } ?> It just seems as though he's delegating for no real reason.
  16. I'm currently trying my hand at creating Registry classes that are very similar to those found in the Zandstra book. I thought it was a good idea to remove some of the initialization from the constructors and put them in their respective getInstance() methods. So, I have the following: Base Registry class: <?php abstract class MP_base_Registry{ private final function __construct(){} abstract protected function get($key); abstract protected function set($key, $value); } ?> RequestRegistry: <?php class MP_base_RequestRegistry extends MP_base_Registry{ private static $instance; private $requests = array(); static function getInstance(){ if(!self::$instance){ self::$instance = new self(); } return self::$instance; } protected function get($key){ return $this->requests[$key]; } protected function set($key, $value){ $this->requests[$key] = $value; } static function getRequest(){ return self::$instance->get('request'); } static function setRequest(MP_controller_Request $request){ self::$instance->set('request', $request); } } ?> SessionRegistry (unfinished as I have a question about it): <?php class MP_base_SessionRegistry extends MP_base_Registry{ private static $instance; static function getInstance(){ if(!self::$instance){ session_start(); self::$instance = new self(); } return self::$instance; } protected function get($key){ return $_SESSION[__CLASS__][$key]; } protected function set($key, $value){ $_SESSION[__CLASS__][$key] = $value; } /* inquire about the Complex $complex in Zandstra's book */ } ?> And, finally, ApplicationRegistry: <?php class MP_base_ApplicationRegistry extends MP_base_Registry{ private static $instance; private $values = array(); private $appFile = "data/applicationRegistry.txt"; private $isDirty = false; static function getInstance(){ if(!self::$instance){ self::$instance = new self(); $this->doReload(); } return self::$instance; } function __destruct(){ if($this->isDirty){ $this->save(); } } static function reload(){ self::instance->doReload(); } private function doReload(){ if(!file_exists($this->appFile)){ return false; } $serialized = file_get_contents($this->appFile, true); $fileContents = unserialize($serialized); if(is_array($fileContents)){ $fileContents = array_merge($fileContents, $this->values); $this->values = $fileContents; return true; } return false; } private function save(){ $saveData = serialize($this->values); file_put_contents($this->appFile, $saveData, FILE_USE_INCLUDE_PATH); $this->isDirty = false; } protected function get($key){ return $this->values[$key]; } protected function set($key, $value){ $this->values[$key] = $value; $this->isDirty = true; } static function isEmpty(){ return empty(self::$instance->values); } /*add static functions or use magic __get() and __set() to obtain/set specific data */ } ?> Okay, with that in place, here are my questions: 1. In SessionRegistry, Zandstra creates two publically available static methods that get and set session info. They look like this: <?php function getComplex(){ return self::$instance->get('complex'); } function setComplex(Complex $complex){ self::$instance->set('complex', $complex); } ?> I haven't read much further in the book, so I'm not sure if this is addressed later on, but is the Complex datatype there just as a hypothetical? Or is he suggesing that things saved in a session should all have the same base class (in this case, a class named Complex)? 2. In ApplicationRegistry, he (and thus, my code) seem to switch from using self::$instance and $this->something. This is a bit confusing. I realize that the former represents accessing something as part of a class, and the latter means actually accessing the object. That said, the object in question is actually referred to by itself via $instance. So, wouldn't accessing the private properties of the class have to be done like self::$instance->values, or something along those lines? 3. Are there any pitfalls you can see in me forcing the constructors to be empty? I figure that since it's basically a large singleton, the getInstance() method will always be called whenever one wants access to a Registry. Why not put the initialization processes in there when the first instance is created?
  17. I don't believe I've gotten to the point in the book where XML is used to control the ordering of command execution. The only XML I've seen so far is where he loads a config file into his ApplicationHelper object in order to obtain a hyptothetical dsn. It'll be interesting to see how his method differs from yours.
  18. You're right, I was confusing the two. That said, while FC uses Command objects, would it be necessary to use a CommandContext/RequestHelper object if your Controller is already employing an ApplicationHelper? I think that's where my initial gut feeling of redundancy stems from. Nevermind, I'm an idiot. The two (CommandContext and ApplicationHelper) aren't really similar. I don't know why I kept thinking otherwise.
  19. Thanks for the replies, both of you. I think the first step should be me trying my hand at some simple homegrown stuff. Trying to get a Registry to work, trying to get a Front Controller to work, that sort of thing. Then, off to a framework once I figure out how things should be put together.
  20. You're right, I was confusing the two. That said, while FC uses Command objects, would it be necessary to use a CommandContext/RequestHelper object if your Controller is already employing an ApplicationHelper? I think that's where my initial gut feeling of redundancy stems from.
  21. Nope, Front Controller vs. Command, as described in Zandstra's book (PHP Objects, Patterns, and Practice). The two seem pretty similar, and I believe Zandstra himself basically says that Front Controller itself is derived from Command (although, don't quote me on that as I don't have the book at hand at the moment). I should probably re-re-read those two sections of the book, but I'm still having problems seeing how the two would be used in concert. Command just seems redundant to me if there's a Front Controller in place.
  22. Because I don't know what Drupal is? In any event, I'm trying to roll my own, so to speak. Thanks for the link to the phpit article. There's one thing, though: like I asked in my first post, how would I handle the creation/editing of new pages? The rest all seems more or less what I expected, especially after doing a quick browse through the Code Igniter framework, but allowing a user to create new content still eludes me, especially when trying to figure out how to handle any images that may be added/removed (number of images allowed and their positioning) and trying to come up with a decent file naming scheme for these user-created pages.
  23. I decided to cross-post my original message from the design forum to here in the hopes of getting as much input as possible. I hope this is okay. Original message is below. ----------------------------------------------------------- This will be my first attempt at using OOP to make a fully functional, real project. The law firm at which my brother works wants their site redone, and he suggested me. Unfortunately, most of my PHP experience is in the form of writing code that modifies/improves existing systems. I've never created one from scratch before. The firm's site already has a simple CMS. One that allows one of the secretaries to add a new lawyer bio and/or text for other pages, but not the ability to add items to the navigation menu or change any of the existing main graphics. I believe, however, that they can add images to the pages (such as a new laywer's photo). There doesn't appear to be too much in the way of database info. Most of the pages on the current site appear to be static, from what I can see. With the exception of the admin area - which is where the secretary goes to add/modify pages on the site - there's no membership to speak of. I'm thinking, for the public side of the site, to use a Front Controller. Would I need anything else? In particular, are there any other patterns I should think of (Registry, Command, etc)? The admin backend seems a bit more tricky. Obviously, there needs to be a simple login system, but I'm having trouble trying to see how to handle both the creation of new pages, and the editing of existing pages. In particular, how would I handle the text input? Simple textarea field? Embedded TinyMCE editor? Something else? What about a file naming scheme? Should I just use a numeric id (probably the easiest in terms of mapping the files to the database)? Something more user friendly? This is the part that will trip me up the most, so any input here would be greatly appreciated.
  24. Yes, it (along with the sqlite driver) is a default extension in php5. The drivers however usually need to be installed seperately. Nice. Hopefully my hosting has them installed.
  25. Is it a standard component to PHP5?
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.