Unsetting attributes of dynamic PHP objects - php

I have a dynamic class referenced by $row->attributes(), that has some overloaded (dynamic) properties, e.g. $row->attributes()->property1.
I want to unset property1. I've tried $row->attributes()->__unset("property1") and unset($row->attributes()->property1). No joy.
Anyone know how to do this?

It's unclear from the question whether you have used this approach, if you have, I'll remove this answer.
Take a look at __unset, simple example is:
class Foo
{
public function __unset($property)
{
unset($this->__my_property_holder[$property]);
}
}
You simply need to do unset($row->attributes()->property1), and it will actually invoke Foo->__unset('property1').

Related

How to pass a variable into multiple functions

In my screenshot below you can see I have a list of functions that run a routine, fairly in-depth routine.
Previously, I have ben repeating this routine in multiple classes, but now I would like to consolidate those multiple classes into one class and execute only one function, by passing a variable into that function to determine the output to return.
I know how to pass the variable into "one" function, but how can I pass the variable ($this_id) into my multiple functions below? Basically, whatever $this_id is from get_output($this_id); I want that same variable value to be carried over into the other $this_id functions. See screenshot...
I searched online and all answers I've seen show how to do this in a non static way, but I'm only familiar with calling things statically, really. I tried the obj way, but couldn't get it to work.
Example, execution...
$header = 'CustomTheme_output';
$header::get_output('header');
(please disregard any lose code, the code is what I have so far from trying multiple ways. private $id and __construct are from the online solutions I have been trying)
Could you please clue me in on how I can correctly achieve this? I would be sooo happy to get rid of all the repetitive code, folders and files I have! - Thanks!
Either you pass it directly into each method call:
public function foo($this_id) {
$this->bar($this_id);
}
Or you make it a class attribute, and simply ACCESS it from the various methods:
public function foo($this_id) {
$this->id = $this_id;
$this->bar();
}
public function bar() {
do_something($this->id);
}

How to create an object using Factory method, instead of supplying alternative object constructor

I am having some trouble applying Factory Pattern.
I have a class that I usually call as Product($modelNumber, $wheelCount). But in a part of legacy code that I am refactoring, I do not have $modelNumber, and only have $productID, where the link between {$modelNumber, $productID} is in the database (or in my case I can hardcode it, as I only have a select few products at the moment).
I need to be able to create my class using $productId, but how?
Using Procedural ways I would have a function that does the lookup, and I would put that function in a file, and include that file anywhere where I need to do the lookup. Thus do this:
$modelNumber = modelLookup($productId)
Product($modelNumber, $wheelCount);
But how do I do it using Object Oriented way?
Note: I have posted a more detailed situation here: https://softwareengineering.stackexchange.com/q/233518/119333 and this is where Factory pattern (and other patterns, like interfaces and function pointer passing) were suggested conceptually, but I hit a wall when trying to implement them in PHP. It kind of seems like a simple question, but I think there are several ways to do it and I am a bit lost as to how. And so I need some help.
I provided a conceptual answer to your SRP problem on Programmers Exchange but I think I can demonstrate it here.
What you basically want is some other object that will do the work to get you the model number of given product ID.
class ProductModelNumberProvider {
public function findByProductId($productId) {
// The lookup logic...
}
}
Your factory should provide a setter constructor so it can make use of this object internally to lookup the model number if needed. So basically you will end up with a ProductFactory similar to this.
class ProductFactory {
private $productModelNumberProvider;
public function __construct(ProductModelNumberProvider $productModelNumberProvider) {
$this->productModelNumberProvider = $productModelNumberProvider;
}
public function getProductByIdAndWheels($productId, $wheels) {
$modelNumber = $this->productModelNumberProvider($productId);
return $this->getProductByModelNumberAndWheels($modelNumber, $wheels);
}
public function getProductByModelNumberAndWheels($modelNumber, $wheels) {
// Do your magic here...
return $product;
}
}
EDIT
On second thought the setter is not the best approach since having a ProductModelNumberProvider instance is mandatory. That is why I moved it to have it injected through the constructor instead.
I can think of something like this:
$factory = new ProductBuilder();
$factory->buildFromProductId($productId, $wheelCount); //uses modelLookup() internally
$factory->buildFromModelNumber($modelNumber, $wheelCount); //just returns Product()
It is basically creating a class on top of the procedural function, but it does separate the logic of creating the class separately from looking up the mapping.

How to define constant in class constructor?

Can I define a class constant inside the class constructor function ?
(based on certain conditions)
That goes against the idea of class constants - they should not be dependent on a specific instance. You should use a variable instead.
However, if you insist on doing this, are very adventurous and can install PHP extensions, you can have a look at the runkit extension that allows to modify classes and their constants at runtime. See this doc: http://www.php.net/manual/en/function.runkit-constant-add.php
I don't think you can.
It wouldn't make sense, either - a class constant can be used in a static context, where there is no constructor in the first place.
You'll have to use a variable instead - that's what they're there for.
Try look here:
http://php.net/manual/en/language.oop5.constants.php
http://php.net/manual/en/language.oop5.static.php
Hope this helps.
As far as standard instance constructors go, there is no way to do this, and as others have pointed out, it wouldn't make sense. These constructors are called per created object instance, at the point they are created. There is no guarantee this constructor would get called before some code tried to access the constant. It also doesn't make sense in that the code would get called over and over again each time a new instance was constructed, whereas a const should only get set once.
It would be nice if PHP either offered some kind of static constructor that let you set the value one time for uninitialized constants, or allowed more types of expressions when defining constants. But these are not currently features of PHP. In 2015 an RFC was made that proposed adding static class constructors, but it is, at the time of me writing this answer, still in the draft status, and has not been modified since 2017.
I think the best alternative for now is to not use constants in this kind of scenario, and instead use static methods that return the value you want. This is very simple in that it only uses the PHP language features as is (not requiring any special extensions), these static methods can be called in the standard way, and you don't need to hack the autoloading process to call some kind of initializer function that sets static variables. The method might need to rely on private static variables in order to make sure the same instance is returned every time, if an object instance is being returned. You would need to write the implementation of this method to be constant like in the sense that it will always return the same thing, but takes advantage of being able to do things you can't do with a constant, like return on object instance or rely on complex expressions or function calls. Here is an example:
final class User
{
/** #var DefinitelyPositiveInt|null */ private static $usernameMaxLength;
public static function getUsernameMaxLengthConst(): DefinitelyPositiveInt
{
if ($usernameMaxLength === null) {
$usernameMaxLength = new DefinitelyPositiveInt(40);
}
return $usernameMaxLength;
}
}
$usernameInput.maxLength = User::getUsernameMaxLengthConst();
This is still not a perfect solution because it relies on the programmer to write these in a constant like way when that is desired (always returning the same value). Also, I don't like that the best place to document the fact that it is a const is in the method name, thus making it even longer to call. I also don't like that you now have to call it as a method instead of just accessing a property, which would be syntactically nicer.
This example is essentially an implementation of a singleton, but sometimes the purpose of a singleton is to be a constant rather than just a singleton. What I mean is, you might want the instance to always exist, and it might be an immutable type (none of the properties are public or mutable, only having methods that return new objects/values).
I am sorry to break it to you but it is not possible in vanilla PHP.
I am not very sure about frameworks or extensions but I am sure that it is not possible in vanilla PHP.
I recommend you to use variables instead.
You still can't, but maybe some of these (progressively weirder) ideas (just ideas, not true solutions) will work for you:
(1) You could use a private property, with a public getter method. The property cannot be modified outside the class, such as constants, but unfortunately it is accessed as a method, not as a constant, so the syntax is not the same.
class aClass{
private $const;
function __construct($const){
$this->const=$const;
}
function const(){
return $this->const;
}
}
$var1=new aClass(1);
echo $var1->const(); //Prints 1
(2) If you really want this value to be accessed as constant from outside, you can use define () inside the constructor. Unfortunately it doesn't get tied to the class or object name (as it do when you use const, using for example myClass::myConst). Furthermore, it only works if you create a single instance of the class. The second object you create is going to throw an error for redefining the constant, because is untied.
class otherClass{
function __construct($const){
define('_CONST',$const);
}
function const(){
return _CONST;
}
}
$var2=new otherClass('2');
echo $var2->const(); //Prints 2
echo _CONST; //Prints 2
#$var3=new aClass('3'); //Notice: Constant _CONST already defined
echo _CONST; //Still prints 2!
(3) Perhaps that last problem can be solved by giving variable names to the constants, related to the object to which they belong. This may be a bit weird... but maybe it works for someone.
class onemoreClass{
private $name;
function __construct($const,$name){
$this->name=$name;
$constname=$this->name."_CONST";
define($constname,$const);
}
function const(){
return constant($this->name.'_CONST');
}
}
$name='var4';
$$name=new onemoreClass(4,$name);
echo $var4->const(); //Prints 4
echo var4_CONST; //Prints 4
$name='var5';
$$name=new onemoreClass(5,$name);
echo $var5->const(); //Prints 5
echo var5_CONST; //Prints 5

Call parent constructor before child constructor in PHP

I was wondering if its possible to call the parents __construct(), before the child's __construct() with inheritance in PHP.
Example:
class Tag {
__construct() {
// Called first.
}
}
class Form extends Tag {
__construct() {
// Called second.
}
}
new Form();
Ideally, I would be able to do something in between them. If this is not possible, is there an alternative, which would allow me to do this?
The reason I want to do this is to be able to load a bunch of default settings specific to the Tag that Form can use when __construct() is called.
EDIT: Sorry forgot to add this.. I'd rather not call the parent class from the child class. It's simply because it exposes some private data (for the parent) to the child, when you pass it as an argument
This is what I want to do:
$tag = new Tag($privateInfo, $publicInfo);
$tag->extend(new Form()); // Ideal function, prob doesn't work with inheritance.
Tag.php
class Tag {
private $privateInfo;
public $publicInfo;
__construct($private, $public) {
$this->privateInfo = $private;
$this->publicInfo = $public;
}
}
Form.php
class Form extends Tag {
__construct() {
echo $this->publicInfo;
}
}
Make sense?
Thanks!
Matt Mueller
Just call parent::__construct in the child.
class Form extends Tag
{
function __construct()
{
parent::__construct();
// Called second.
}
}
yeah just call parent::__construct() in your construct
Yes, but only internally (i.e., by writing a PHP extension), so if I were you I'd settle with calling parent::__construct(). See this section on the PHP wiki.
Sorry, PHP is not Java. I think not requiring (implicitly or explictly) the super constructor to be called was a very poor design decision.
From the sounds of it you may want to rethink your design so that you don't need to pass the parameters in the constructor. If you don't think it can be done, ask it as a question, you might be surprised by some of the suggestions.
The child class has the ability to override the parent constructor without calling it at all. I would recommend having a final method in the parent class. That way everyone knows you don't want this being overriden, and any inherited class (rightly) has access to do whatever it wants in the constructor.
class Father {
private $_privateData;
final function setPrivateData($privateData) {
$this->_privateData = $privateData;
}
}
Another, not recommended, more "reinventing the wheel", solution would be to define a function in the parent class, say _construct(), that's called in its own construct. Its not really clear, doesn't use language features/constructs, and is very specific to a single application.
One last thing to keep in mind: you can't really hide information from the child class. With Reflection, serialize, var_dump, var_export and all these other convenient APIs in the php language, if there is code that shouldn't do anything with the data, then there's not really much you can do asides from not store it. There are libraries and such that help create sandboxes, but its hard to sandbox an object from itself.
Edit: Somehow I missed Artefacto's answer, and I suppose he is right (I've never tried writing an extension to do that). Still, implementing it breaks developer expectations while making it harder to actually see code to explain what's going in.

Better to use an Object or a Static Function in PHP?

I am trying to learn OO and classes and all that good stuff in PHP, I am finally learning the sytax good enough to use it some and I am curious if there is any benefit of starting a new object instead of just using static methods...let me show some code for what I mean...
<?PHP
test class
{
public function cool()
{
retunr true;
}
}
//Then calling it like this
$test = new test();
$test->cool();
?>
OR
<?PHP
test class
{
public static function cool()
{
retunr true;
}
}
//Then calling it like this
test::cool();
?>
I realize this is the most basic example imaginable and the answer probably depends on the situation but maybe you can help me understand a little better
For your example, it is better to use a static function, but most situations will not be so simple. A good rule of thumb to start with is that if a method doesn't use the $this variable, then it should be made static.
Think of classes like 'blueprints' to an object. you want to use the static method when it is a general function that could apply to anywhere, and use methods when you want to reference that specific object.
Here is an article that discusses differences in performance between these concepts:
http://www.webhostingtalk.com/showthread.php?t=538076.
Basically there isn't any major difference in performance, so then the choice is made based on your design.
If you are going to create an object several times, then obviously a class makes sense.
If you are creating a utility function that isn't tied to a particular object, then create a static function.

Categories