Jump to content

Help with namespace


NotionCommotion

Recommended Posts

I have a class which has two general types of methods.

  1. Those which are used by the core class, and shouldn't be overridden.
  2. Those which are "used" by the methods described above, and these can be overridden and new methods can be added.  They are all private or protected, and not public.

For those used by the core class, I use the "final" keyword to prevent.

 

I am not really versed in namespace, but this seems like where it might be used.

 

Could I get a couple of pointers where to start?

 

Thanks

 

 

 

 

 

 

 

Link to comment
Share on other sites

Namespaces? Something else entirely. Ever had a set of classes that are named similarly, like db_user/db_post or DatabaseUser/DatabasePost? You could use namespaces to help arrange the classes.

Before:

class db_user { }

class db_post { }

$user = new db_user();
$post = new db_post();
$user->post($post);
After:

namespace db {

	class user { }

	class post { }

}

namespace {

	use db\post; // so you can refer to it as "post" for short

	$user = new db\user();
	$post = new post();
	$user->post($post);

}

To your problem, final is exactly what you should be using.

Link to comment
Share on other sites

Maybe it has nothing to do with namespace.  Say I have the following script.  I have a bunch of tasks, and I want to be able to extend the class and modify or add new tasks.  It would be nice if I could add more tasks without having to worry about conflicting with one of the core methods.  How would this best be handled?  Thanks

class myGeneralClass
{
 //A core method which cannot be changed
 final public function doThis($method) {
   $this->$method();
 }

 protected function task1(){}
 protected function task2(){}
 protected function task3(){}
 protected function task4(){}
}

class mySpecificClass myGeneralClass
{
 protected function task1(){}    //Overide
 protected function task5(){}
 protected function task6(){}
 protected function task7(){}
 protected function doThis(){}    //Error!
}

$obj=new mySpecificClass();
$obj->doThis('task5');
Link to comment
Share on other sites

Keep in mind that the developer of the child class has to know about the parent class. You can simply push the "having to worry about conflicting" stuff onto the developer; as long as the parent class is locked down, make them figure out how their class should work.

 

This task thing... can you explain it more? I feel like there's a better strategy to deal with it than creating more and more methods in a child class. Personally I avoid any situation where a parent class needs to call a specific, unknown child method without the child class somehow describing itself to the parent (eg, reporting that it has additional tasks 5-7).

Link to comment
Share on other sites

This task thing... can you explain it more? I feel like there's a better strategy to deal with it than creating more and more methods in a child class. Personally I avoid any situation where a parent class needs to call a specific, unknown child method without the child class somehow describing itself to the parent (eg, reporting that it has additional tasks 5-7).

 

My validation class.  http://forums.phpfreaks.com/topic/291358-client-and-server-side-validation-passing-data-from-server-to-client/

 

I've created a method which does the same thing as every jQuery validation plugin method.  Those are the tasks.  Validate that a value is provided, validate that it is a valid phone number, etc.

 

The main classes are Load Configuration JSON, Validate, Sanitize, etc.

Link to comment
Share on other sites

Okay, but why are you using the subclasses to add methods? Overriding makes sense, sort of, with a validation class giving one implementation to a method and the sanitize class giving another, but they shouldn't be adding new methods into the mix.

 

Your strategy is to model jQuery so as long as you do that then there shouldn't be any problems: the parent class will use methods with the same name, and the extending classes can't be adding new methods with the same names because that then wouldn't match the jQuery interface anymore.

 

If you really do need to add methods, meaning that (for example) the base class can't validate phone numbers and you want to add that in with another class, then you have two options:

1. Add actual methods using traits. You'll define the functionality in one place, "add" it to the base class, and it will actually be executed as a real member of the base class. This is pretty much only about code reuse.

2. Make the code look like there are methods by using... I don't know the proper name but my boss calls it the "driver pattern". The base class transparently uses specific classes to provide the functionality that it seems to offer.

 

More on the latter because that's what I think you're trying to get:

 

Validation and sanitization (and whatever else you may want to do) is provided by one class per type. One class covers phone numbers, one class covers integers, etc. It then implements a "validator" interface which declares methods for validation and sanitization (and whatever).

interface IJqValidator {

	public function validate($value);

	public function sanitize($value);

}

class PhonenumberValidator implements IJqValidator { // lowercase 'n'

	public function validate($value) {
		// validate the phone number
	}

	public function sanitize($value) {
		// sanitize the phone number
	}	

}
Your base class then goes hunting for that class when needed.

class JqValidator {

	private static $validators = array();

	private static function getValidator($type) {
		if (!isset(self::$validators[$type])) {
			// $type="phonenumber", $class="PhonenumberValidator"
			$class = ucfirst(strtolower($type)) . "Validator";
			self::$validators[$type] = new $class();
		}
		return self::$validators[$type];
	}

	// the implementation here could go a few ways

	// 1. ->validate(type, value)

	public function validate($type, $value) {
		return self::getValidator($type)->validate($value);
	}

	// 2a. ->type->validate(value)

	public function __get($name) {
		return self::getValidator($name);
	}

	// 2b. ->type()->validate(value)

	public function __call($method, array $args) {
		return self::getValidator($method);
	}

	// 3. construct the class with a mode, validate/sanitize, and then use ->type(value)

	const MODE_SANITIZE = "MODE_SANITIZE";
	const MODE_VALIDATE = "MODE_VALIDATE";

	private $mode = "";

	public function __construct($mode) {
		$this->mode = $mode;
	}

	public function __call($method, array $args) {
		switch ($this->mode) {
			case self::MODE_SANITIZE:
				return self::getValidator($method)->sanitize($args[0]);
			case self::MODE_VALIDATE:
				return self::getValidator($method)->validate($args[0]);
		}
	}

}
I personally don't like #2 or #3 because there's no autocomplete support and I have a philosophy that if I can't get IDE support for something then it is probably a bad idea and needs to be done differently. Fortunately, I'm guessing that #1 wouldn't be a problem based on how I think you're using the rest of the code.
Link to comment
Share on other sites

Thank you Requinix,

 

 

Okay, but why are you using the subclasses to add methods?

I didn't think I was.  Please let me know why you feel so.
 

Overriding makes sense, sort of, with a validation class giving one implementation to a method and the sanitize class giving another, but they shouldn't be adding new methods into the mix.

I decide to add a new method to the jQuery validition plugin which validates that the input is a given Yiddish word.  Unfortunately, my PHP class doesn't have this validation function, so I will need to add it to it as well.
 

Your strategy is to model jQuery so as long as you do that then there shouldn't be any problems: the parent class will use methods with the same name, and the extending classes can't be adding new methods with the same names because that then wouldn't match the jQuery interface anymore.

Again, no Yiddish.
 

...then you have two options:

Haven't dived into it yet, but I expect I don't I like Option #3, and dislike option #2 even more.  Please let me give this more thought.

 

Validation and sanitization (and whatever else you may want to do

Oh yea, I forgot.  A big one is create the JavaScript object which is used by the jQuery validation plugin, but I think/hope I have that one covered.
 

... is provided by one class per type. One class covers phone numbers, one class covers integers, etc. It then implements a "validator" interface which declares methods for validation and sanitization (and whatever).

I am lost.  Probably me, but please elaborate

Link to comment
Share on other sites

I didn't think I was.  Please let me know why you feel so.

Then I misunderstood. Nevermind.

 

I decide to add a new method to the jQuery validition plugin which validates that the input is a given Yiddish word.  Unfortunately, my PHP class doesn't have this validation function, so I will need to add it to it as well.

Yeah, that's what I'm getting at: having to add a new method every time suggests using a different coding strategy.

 

Again, no Yiddish.

Then vice versa: the parent can't possibly have a "yiddish" method because jQuery doesn't, but a subclass could. Either the parent will have the method and the children shouldn't, or a child will and the parent shouldn't, but both won't have it.

 

Oh yea, I forgot.  A big one is create the JavaScript object which is used by the jQuery validation plugin, but I think/hope I have that one covered.

That would be a third method to add to the interface: a way of serializing the requirements or behavior or whatever. Preferably you'd stuff some information into an object and then code can serialize (via the JsonSerializable interface and json_encode(), for instance) the class's data into the Javascript.

 

I am lost.  Probably me, but please elaborate

It's describing what I did in the first bit of code: one class (PhonenumberValidator) per type (a phone number) that implements an interface (IJqValidator). You could have another class (EmailValidator) per type (an email address) that implements the same interface.

class PhonenumberValidator implements IJqValidator { // lowercase 'n'

	public function validate($value) {
		// US number: 3+3+4 = 10 digits

		// as a courtesy, strip common separators transparently. sanitize() will remove them again later
		$value = preg_replace('/[-(). ]/', '', $value);

		return ctype_digit($value) && strlen($value) == 10;
	}

	public function sanitize($value) {
		// strip everything but numbers
		return preg_replace('/\D/', '', $value);
	}	

}

class EmailValidator implements IJqValidator {

	public function validate($value) {
		return $this->sanitize($value) === $value;
	}

	public function sanitize($value) {
		return filter_var($value, FILTER_VALIDATE_EMAIL);
	}

}
Link to comment
Share on other sites

Ah, I now see you you are creating a file with a separate class to validate and sanitize each given thing. If one wanted to add a new method, they would add a new file with a new class for the given thing, right?

 

I was planning on creating a single class which includes core methods as well as all validation methods and sanitation methods.  If one wanted to add a new method, they would just extend that class and add the method.

 

I probably see the advantage of your approach, but please confirm you feel it is the right way to go.

 

Below is my total implementation.  The validation class is attached (tried to add to this post, but must have been too long and didn't format correctly).  I realize it is a bunch of script and don't expect you to go through it all, but would appreciate any comments.

 

Thanks

 

Main page

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="jquery.js" /></script>
    <script type="text/javascript" src="getValidationObj.php" /></script>
    <script type="text/javascript">
        (function() {
            $("#myForm").validate(validation_JSON);
        });
    </script>
</head>
<body>
    <form id="myForm">
        <input name="name" type="text" />
        <input name="email" type="text" />
    </form>
</body>
<html>

getValidationObj.php
    Note that I know Jacques1 said not to use PHP to generate JS, however, I don't know a workaround.
    Yes, I could create JSON instead, however, the client would on same cases need to use eval() which is also not ideal
 

<?php
header('Content-Type: application/javascript');
$config_file='/path/to/aGivenPagesValidationFile.json';
$modify_file=array('isNameRequired'=>true);
$validate=new validate($config_file,$modify_file);
exit("var validation_JSON ={$validate->getJSON()};");
?>

aGivenPagesValidationFile.json

{
    "rules": {
        "name": "{isNameRequired}",
        "email": {
            "required": true,
            "email": true
        }
    },
    "messages": {
        "name": "Please specify your name",
        "email": {
            "required": "We need your email address to contact you",
            "email": "Your email address must be in the format of name@domain.com"
        }
    }
    "sanitizers": {}
}

Script to save data

<?php
$config_file='/path/to/aGivenPagesValidationFile.json';
$modify_file=array('isNameRequired'=>true);
$validate=new validate($config_file,$modify_file);
$data=$validate->sanitize($_POST);
$errors=$validate->validate($data);
if(empty($errors))
{
    //Save the data
}
?>

validate.php

Edited by NotionCommotion
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.