inner "nested" classes?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Average_Joe

    inner "nested" classes?

    Hello PHP people,

    Was wondering if PHP5 had some sort of "nested class" functionality.

    I'm trying to figure out how to return an object (with a private
    constructor) that has access to variables in another class.

    Something like:

    $obj = $factory->getObject("123 4");

    Where getObject() is the ONLY way to get an instance of $obj.

    $obj has access to private data from the $factory object.

    Kind of like inner and anonymous classes in java I guess.

    Any approach to doing this in PHP5?

    Jamie
    --
    http://www.geniegate.com Custom web programming
    User Management Solutions Perl / PHP / Java / UNIX

  • Chung Leong

    #2
    Re: inner "nested&qu ot; classes?


    "Average_Jo e" <joe@geniegate. com> wrote in message
    news:slrnch2u58 .bqc.joe@pong.t unestar.net...[color=blue]
    > Hello PHP people,
    >
    > Was wondering if PHP5 had some sort of "nested class" functionality.
    >
    > I'm trying to figure out how to return an object (with a private
    > constructor) that has access to variables in another class.
    >
    > Something like:
    >
    > $obj = $factory->getObject("123 4");
    >
    > Where getObject() is the ONLY way to get an instance of $obj.
    >
    > $obj has access to private data from the $factory object.
    >
    > Kind of like inner and anonymous classes in java I guess.
    >
    > Any approach to doing this in PHP5?
    >
    > Jamie
    > --
    > http://www.geniegate.com Custom web programming
    > User Management Solutions Perl / PHP / Java / UNIX
    >[/color]

    Don't know if such mechanism thing exists in PHP5. You can always use uniqid
    to generate a unique class name, then define the class with eval. If the
    name is kept private, then the class is private.

    $class = uniqid("Inner") ;
    eval(<<<CLASS

    class $class {
    }

    CLASS
    );


    Comment

    • Pieter Nobels

      #3
      Re: inner &quot;nested&qu ot; classes?

      Chung Leong wrote:[color=blue]
      > Don't know if such mechanism thing exists in PHP5. You can always use uniqid
      > to generate a unique class name, then define the class with eval. If the
      > name is kept private, then the class is private.
      >
      > $class = uniqid("Inner") ;
      > eval(<<<CLASS
      >
      > class $class {
      > }
      >
      > CLASS
      > );
      >
      >[/color]

      That would be not only one of the ugliest hacks I've ever seen, it also
      wouldn't be very effective. You can get all declared classes via
      http://php.net/get_declared_classes. Security by obscurity by itself
      isn't a good idea IMHO.

      I've been thinking about this problem a while ago and came to the
      conclusion it wasn't possible.

      --
      Pieter Nobels

      Comment

      • Zurab Davitiani

        #4
        Re: inner &quot;nested&qu ot; classes?

        Average_Joe wrote:
        [color=blue]
        > Something like:
        >
        > $obj = $factory->getObject("123 4");
        >
        > Where getObject() is the ONLY way to get an instance of $obj.[/color]

        OK, let's see - I don't have PHP5 handy to test it right now, but try
        something like this:

        class factory {

        function __construct() {
        $tr = debug_backtrace ();
        if($tr[1]['class'] != 'A' || $tr[1]['function'] != 'getObject')
        throw new Exception;
        }

        function getObject() {
        self::$instance = new factory;
        return(clone(se lf::$instance)) ;
        }
        }

        $obj = factory::getObj ect();

        Again, this is untested - so I don't know if it will work but may be worth
        trying. Since I don't know what the purpose of this is, I can't provide any
        more feedback to suggest other methods of accomplishing it.

        Comment

        • Zurab Davitiani

          #5
          Re: inner &quot;nested&qu ot; classes?

          Zurab Davitiani wrote:
          [color=blue]
          > if($tr[1]['class'] != 'A' || $tr[1]['function'] !=[/color]
          'getObject'

          This should read
          if($tr[1]['class'] != 'factory' || $tr[1]['function'] != 'getObject'

          Comment

          • Chung Leong

            #6
            Re: inner &quot;nested&qu ot; classes?

            "Pieter Nobels" <pieterRE@MOVEp cmania.be> wrote in message
            news:_prQc.2044 60$AB4.10434601 @phobos.telenet-ops.be...[color=blue]
            > Chung Leong wrote:[color=green]
            > > Don't know if such mechanism thing exists in PHP5. You can always use[/color][/color]
            uniqid[color=blue][color=green]
            > > to generate a unique class name, then define the class with eval. If the
            > > name is kept private, then the class is private.
            > >
            > > $class = uniqid("Inner") ;
            > > eval(<<<CLASS
            > >
            > > class $class {
            > > }
            > >
            > > CLASS
            > > );
            > >
            > >[/color]
            >
            > That would be not only one of the ugliest hacks I've ever seen, it also
            > wouldn't be very effective. You can get all declared classes via
            > http://php.net/get_declared_classes. Security by obscurity by itself
            > isn't a good idea IMHO.
            >
            > I've been thinking about this problem a while ago and came to the
            > conclusion it wasn't possible.[/color]

            This is PHP after all. The source code to the class would be available so
            it'd be just as easy to remove the "private" keyword in order to access the
            private variable. The use of private method/classes has nothing to do with
            security so I don't know what you're driving at.


            Comment

            • Chung Leong

              #7
              Re: inner &quot;nested&qu ot; classes?

              "Zurab Davitiani" <agt@mindless.c om> wrote in message
              news:6AEQc.298$ QJ3.14@newssvr2 1.news.prodigy. com...[color=blue]
              > Zurab Davitiani wrote:
              >[color=green]
              > > if($tr[1]['class'] != 'A' || $tr[1]['function'] !=[/color]
              > 'getObject'
              >
              > This should read
              > if($tr[1]['class'] != 'factory' || $tr[1]['function'] != 'getObject'[/color]

              Very clever solution. One tiny problem: PHP collapses function names to
              lower case, so the comparison should be to 'getobject'.


              Comment

              • Zurab Davitiani

                #8
                Re: inner &quot;nested&qu ot; classes?

                Chung Leong wrote:
                [color=blue]
                > "Zurab Davitiani" <agt@mindless.c om> wrote in message
                > news:6AEQc.298$ QJ3.14@newssvr2 1.news.prodigy. com...[color=green]
                >> Zurab Davitiani wrote:
                >>[color=darkred]
                >> > if($tr[1]['class'] != 'A' || $tr[1]['function'] !=[/color]
                >> 'getObject'
                >>
                >> This should read
                >> if($tr[1]['class'] != 'factory' || $tr[1]['function'] != 'getObject'[/color]
                >
                > Very clever solution. One tiny problem: PHP collapses function names to
                > lower case, so the comparison should be to 'getobject'.[/color]

                That's no longer true for PHP5, unless it's some part of optional PHP4
                compatibility mode. PHP5 class and function/method names are in their
                proper case.

                I finally got around to trying this solution in PHP5, and it worked OK - one
                thing missing is a static $instance property definition inside the class. I
                still don't get what is the point of this though - maybe developers who
                don't read docs - enforce factory class programatically ?

                Comment

                • Average_Joe

                  #9
                  Re: inner &quot;nested&qu ot; classes?

                  In article <rKmdndf2wZqF1o ncRVn-rg@comcast.com> , Chung Leong wrote:[color=blue]
                  > "Pieter Nobels" <pieterRE@MOVEp cmania.be> wrote in message
                  > news:_prQc.2044 60$AB4.10434601 @phobos.telenet-ops.be...[color=green]
                  >> Chung Leong wrote:[color=darkred]
                  >> > Don't know if such mechanism thing exists in PHP5. You can always use[/color][/color]
                  > uniqid[color=green][color=darkred]
                  >> > to generate a unique class name, then define the class with eval. If the
                  >> > name is kept private, then the class is private.
                  >> >
                  >> > $class = uniqid("Inner") ;
                  >> > eval(<<<CLASS
                  >> >
                  >> > class $class {
                  >> > }
                  >> >
                  >> > CLASS
                  >> > );
                  >> >
                  >> >[/color]
                  >>
                  >> That would be not only one of the ugliest hacks I've ever seen, it also
                  >> wouldn't be very effective. You can get all declared classes via
                  >> http://php.net/get_declared_classes. Security by obscurity by itself
                  >> isn't a good idea IMHO.
                  >>
                  >> I've been thinking about this problem a while ago and came to the
                  >> conclusion it wasn't possible.[/color]
                  >
                  > This is PHP after all. The source code to the class would be available so
                  > it'd be just as easy to remove the "private" keyword in order to access the
                  > private variable. The use of private method/classes has nothing to do with
                  > security so I don't know what you're driving at.[/color]

                  Seems like no matter how hard we try to squelch the right brain in
                  programming.. a persons artistic side has to come out. :-)

                  The idea of random generated class names is artistic to some, but ugly
                  to others. Thats my theory anyhow. :-)

                  In *my* case, it wouldn't work, since I need the inner class to have
                  access to private variables and methods in it's envelope class.

                  Jamie
                  --
                  http://www.geniegate.com Custom web programming
                  User Management Solutions Perl / PHP / Java / UNIX

                  Comment

                  • Average_Joe

                    #10
                    Re: inner &quot;nested&qu ot; classes?

                    In article <fntRc.2418$Gy. 1304@newssvr27. news.prodigy.co m>, Zurab Davitiani wrote:[color=blue]
                    > I finally got around to trying this solution in PHP5, and it worked OK - one
                    > thing missing is a static $instance property definition inside the class. I
                    > still don't get what is the point of this though - maybe developers who
                    > don't read docs - enforce factory class programatically ?[/color]

                    Simple example:

                    Say you've got:

                    <?php
                    class Invoice() { .. }

                    class Item() { ... }

                    // You want to do:

                    $item = $invoice->getItem("P100" );

                    echo $item->title();

                    echo $item->getInvoice()->title(); // get the invoice title.

                    ?>

                    The idea here is that at no point can anything except Invoice() generate
                    an instance of Item. (Item has a private constructor)

                    Furthermore. Say Item is an interface or abstract class, the actual items
                    are different, but all of them implement an "Item" interface. This way,
                    you could have a Clothing Item, Electronics Item, etc.. each with
                    methods specific to the item type. You also can be reasonably assured
                    that all Item()'s haven't been constructed outside an Invoice().

                    You know when working with the code that each Item must have a parent
                    Invoice instance, down the road, if an Item required access to stuff in
                    the Invoice class (such as a is_sales_tax() method ?) You would be able
                    to access it, w/out giving access to other areas of the application. (So
                    that if is_sales_tax() were to change, (lets say sales tax became
                    dependant on country or something) you would know it was accessed ONLY
                    in Invoice() and any Item's it generated, making changes easier)

                    Aside from this, PHP5 is looking really _really_ good. :-)

                    Jamie
                    --
                    http://www.geniegate.com Custom web programming
                    User Management Solutions Perl / PHP / Java / UNIX

                    Comment

                    • Zurab Davitiani

                      #11
                      Re: inner &quot;nested&qu ot; classes?

                      Average_Joe wrote:
                      [color=blue]
                      > Simple example:
                      >
                      > Say you've got:
                      >
                      > <?php
                      > class Invoice() { .. }
                      >
                      > class Item() { ... }
                      >
                      > // You want to do:
                      >
                      > $item = $invoice->getItem("P100" );
                      >
                      > echo $item->title();
                      >
                      > echo $item->getInvoice()->title(); // get the invoice title.
                      >
                      > ?>
                      >
                      > The idea here is that at no point can anything except Invoice() generate
                      > an instance of Item. (Item has a private constructor)[/color]

                      OK, that's close to how I imagined it as well. In this case, you would make
                      sure that Item constructor was only called from Invoice class, or throw an
                      exception. I cannot think of another way to do this other than with
                      debug_backtrace which is really a workaround (or a hack) for this, not a
                      language feature.

                      Since the check would be already done, the Item constructor need not be
                      private in this case. Indeed if it was, Invoice wouldn't be able to
                      construct it since the call would come from global namespace.
                      [color=blue]
                      > Furthermore. Say Item is an interface or abstract class, the actual items
                      > are different, but all of them implement an "Item" interface. This way,
                      > you could have a Clothing Item, Electronics Item, etc.. each with
                      > methods specific to the item type. You also can be reasonably assured
                      > that all Item()'s haven't been constructed outside an Invoice().[/color]

                      In order to make sure this works with abstract classes, you would have to
                      call the parent constructor explicitly. Also, you would have to allow the
                      parent constructor to complete instantiation - i.e. not throw an exception
                      - when it's called from a __construct function of a class whose parent
                      class is "Item". You can use get_parent_clas s for that.

                      Also, it's not pretty but every derived class would have to have a similar
                      check in its constructor. You may create a common method for this in parent
                      that's inherited by derived classes, but backtrace values would have to
                      come from constructor function and passed to that method.
                      [color=blue]
                      > You know when working with the code that each Item must have a parent
                      > Invoice instance, down the road, if an Item required access to stuff in
                      > the Invoice class (such as a is_sales_tax() method ?) You would be able
                      > to access it, w/out giving access to other areas of the application. (So
                      > that if is_sales_tax() were to change, (lets say sales tax became
                      > dependant on country or something) you would know it was accessed ONLY
                      > in Invoice() and any Item's it generated, making changes easier)[/color]

                      This is more or less easier to implement. When calling the Item constructor
                      from Invoice (or through a separate method), pass $this and set it as
                      Item's parent property; then refer back to it from the Item class by
                      calling $this->getParent() or $this->parent.
                      [color=blue]
                      > Aside from this, PHP5 is looking really _really_ good. :-)[/color]

                      I would have preferred multiple inheritance to interfaces.

                      Comment

                      Working...