eldan88 Posted May 25, 2013 Share Posted May 25, 2013 Hey, I am trying to creating a database object that does all my database findings, and use it as a sub class for all my other classes that will be needing to use it. I have created a sub_class called database_object.php which will be my parent class. I am trying to create a method in the database_object.php that can see if the property exists in any master class that I attach it to., I am having trouble finding a way to do that. I have a way to do this if the method was inside the the master class , but not when I am extending the master class with my sub_class. This is how I currently have it with the method inside the master class. Any suggestion on how to use the property_exists from the parent class? protected function attributes() { $attributes = array(); foreach(static::$db_fields as $field) { if(property_exists($this, $field)) { $attributes[$field] = $this->$field; } } return $attributes; } Quote Link to comment Share on other sites More sharing options...
KevinM1 Posted May 25, 2013 Share Posted May 25, 2013 This sounds really convoluted, and not at all like good OO design. Quote Link to comment Share on other sites More sharing options...
requinix Posted May 25, 2013 Share Posted May 25, 2013 (edited) Use __get, __set, (__isset and __unset too) and store the data in an array in the parent class. Magic methods Edited May 25, 2013 by requinix Quote Link to comment Share on other sites More sharing options...
448191 Posted May 25, 2013 Share Posted May 25, 2013 Magic: bad. Proper (SOLID+): good. And yes, that's simplified to a nauseating level. As a sidenote, method names should be commands. Possibly you learned JavaScript first, JS frameworks have a nasty habit of sacrificing semantics in favor of a few key presses. With the exception of more elaborate frameworks such as ExtJS. Quote Link to comment Share on other sites More sharing options...
448191 Posted May 25, 2013 Share Posted May 25, 2013 Maybe you could share all classes involved in your architecture. Conceptually there's no such thing as a "master class". Quote Link to comment Share on other sites More sharing options...
requinix Posted May 25, 2013 Share Posted May 25, 2013 Magic methods are that bad? What's wrong with an implementation like /** * @property-read int $id * @property string $name * @property int $size */ class Photograph extends DatabaseObject { // ... } abstract class DatabaseObject { private $data = array(); public function __get($name) { if (isset($this->data[$name])) { return $this->data[$name]; } else { // error } } public function __set($name, $value) { if (isset($this->data[$name])) { // check accessibility/validation/etc and set } else { // error } } } Quote Link to comment Share on other sites More sharing options...
ignace Posted May 25, 2013 Share Posted May 25, 2013 (edited) Any kind of magic in your app is bad, I think everyone agrees on that and when you can avoid it, you should. Like overloading operators in C++ and Ruby. At some point it bites you. And when you really need to, you should properly document it (@property, @method). To use your example, in this particular case (which is a pretty bad use of __set and __get yet ever so popular) you would end up with a lot of code for each supported property inside __set and __get (possibly making each method extend beyond what you can fit on your screen, which should be a clear indication something is wrong) and each time your class would need more properties you would have to dig into that already messy code and extend it and hope you don't break anything in the process. Basically you end up emulating what OO provides out of the box. Also __set and __get are PHP4 artifacts which are since PHP5 replaced by proper interfaces ArrayAccess and Serialize for __sleep and __wakeup. Edited May 25, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
ignace Posted May 25, 2013 Share Posted May 25, 2013 (edited) Besides there is no magic necessary: class Photograph extends SplFileInfo implements ImageInterface { private $width; private $height; private $mimeType; public function __construct($filename) { list($this->width, $this->height) = $image = getimagesize($filename); $this->mimeType = $image['mime']; parent::__construct($filename); } public function getWidth() {} public function getHeight() {} public function getMimeType() {} } interface ImageResizeStrategy { public function resize(ImageInterface $image); } class FixedResize implements ImageResizeStrategy { .. public function resize(ImageInterface $image) { .. } } class ProportionalResize implements ImageResizeStrategy { .. public function resize(ImageInterface $image) { .. } } Edited May 25, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
requinix Posted May 25, 2013 Share Posted May 25, 2013 Not to push the issue too far off topic but Besides there is no magic necessary:By using getters and setters, that's true. But I absolutely hate having them if only for the sake of having them - whether it's a property or a method, it's just syntax. (As I've heard it, the concept of getters and setters originated with code generation tools and I hate those too.) Meanwhile if their implementations are beyond simply getting and setting (ie, requires some amount of special logic) then that means there's underlying issues with how the data can or should be used and they require more complicated functionality beyond "change $X to Y". Take width, height, and MIME type. As far as I'm concerned outside code should be able to read those three without having to jump through hoops. It's not sensitive data. But setting any of them by themselves should not be possible because (eg) a] the image is immutable, or b] doing so is not merely a matter of setting a new value since it involves resizing (width/height) or converting the image (MIME type). And both of those are actions performed on the entity as a whole, not quick changes to some attributes. On the other hand an image caption may be arbitrary so simply getting and setting should suffice. I'm also implying, or trying to imply, that this all requires an intelligent setup (that, honestly, I'm very used to using) with concerns about visibility, immutability, validity, and issues like that. If you can't have that then you're precluding this whole idea. Quote Link to comment Share on other sites More sharing options...
ignace Posted May 25, 2013 Share Posted May 25, 2013 (edited) I agree entirely with what you said, and it's also what I meant in my previous post that an "intelligent setup", as you put it, is the goal. But you answered your own question then, unless I missed your argument for __set/__get in your previous post? Edited May 25, 2013 by ignace Quote Link to comment Share on other sites More sharing options...
448191 Posted May 25, 2013 Share Posted May 25, 2013 (As I've heard it, the concept of getters and setters originated with code generation tools and I hate those too.) Any form of boilerplate is a PITA. But without a defined interface you can forget about polymorphism. Your client code becomes coupled to some unknown runtime factor. Concretely, how does hour client code know wheter or not it can invoke DataBaseObject::getFoo()? Granted, you could employ a variant of duck-typing by enclosing calls in a try/catch block catching a BadMethodCallException, or add method to DataBaseObject that allows clients to check the existence of a piece of data before it calls a getter, but then you are moving your boilerplate from the class to its clients, doesn't solve anything and the boilerplate in the class actually provides better encapsulation than scattering your application with unneeded error handling or state assertions. Hope that makes sense. Quote Link to comment Share on other sites More sharing options...
eldan88 Posted May 25, 2013 Author Share Posted May 25, 2013 Thanks for all your help guys. This is all new to me so I need def read through and do some research on the comments you guys have posted. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.