tags:

views:

44

answers:

4

I am using PHP's magic __set and __get methods to access a private array in a class. Use of the class can include "setting" new properties as well as using existing ones. I want to make sure the property names created or requested (i.e. $myObj->FakeProperty) are valid according to the following rules:

  1. Property names must begin with either a letter or underscore [A-z_]
  2. If it begins with an underscore, it must be followed by a letter
  3. So long as the first two rules are met, the name may contain any of [A-z0-9_]

My current RegEx isn't doing the trick; with my test values, _12 always falls through the cracks.

Test Fields:

albert12
12Albert
_12
_Albert12
_12Albert
_____a_1

RegEx:

^(?=_*[A-z]+)[A-z0-9_]+$
+2  A: 

/^[a-z_][a-z0-9_]+$/i

Coronatus
That works, and its basically just what I'll be using. You and stereofrog effectively provided the same answer, but I gave it to sf for providing the link to the official docs. Thanks!
Brian Lacy
+4  A: 

according to docs, the following would match any valid php identifier

/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/
stereofrog
Assuming this is going to be used with preg_match, don't forget the `D` modifier.
salathe
Thanks for the reference, it was helpful.. I had forgotten about that page in the docs. I'm toning it down a bit, but this is the solution I'll be using. Thanks stereofrog.
Brian Lacy
+2  A: 
too much php
nice one ------
Gordon
I'm doing this primarily to allow convenient access to simple database fields names. I don't care about (and frankly would prefer to avoid) really complex identifiers, just simple ones like `$myObj->simpleVar`.
Brian Lacy
+1  A: 

Maybe I am missing something, but __get and __set are only triggered when you already tried to access a syntactically valid propertyname that is unavailable via the object's public API. If you want to make sure the element you are trying to access exists in the private array, use array_key_exists:

class Foo {
    protected $data = array(
    'bar' => 'baz'
    );
    public function __get($name)
    {
        if(array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        throw new BadMethodCallException('Invalid property');
    }
}

$obj = new Foo;
$obj->123; // Syntax Error => __get won't be called
$obj->foo; // valid syntax, but not in array => BadMethodCall Exception
$obj->bar; // returns baz
Gordon
I also allow "new" properties to be set this way, so I'm trying to catch valid identifiers in the "__set" rather than the "__get".
Brian Lacy
Oh, and I'm sure you're right that get and set wouldn't let you create an invalid variable anyway, so I could just leave it alone in my case. But the scenario pointed out by <i>too much php</i> is also a concern; I'd rather block crazy property names, which the regex will also assist with. Thanks for your help.
Brian Lacy