I'm wondering; lets say you start an object in a new class; at the beginning of your app.
If you later pass that object into another class; as a variable and add/modfiy something on it. Will it be updated in the original object and its home class?
Or does it become a 'new' object, a different object in a new class? And will it continue to be the same throughout their uses. In either part of the app?
This is for my own clarification, as opposed to a specific coding question.
objects are passed by reference in php5, so the object is "updated", unless you clone it.
An object doesn't start, it is instantiated, it becomes an instance of a class.
You can't pass an object to a class. You can pass it to a function or a method, with no difference in these 2.
In every language with proper OOP, objects are passed as reference, so any updates anywhere on that object is reflected everywhere. It's an object, you pass it, modify it, and it remains modified.
You should reread what classes are. Obligatory car example ahead:
Imagine a class Car. Now you create a new instance of that abstract concept:
$myCar = new Car();
$myCar->color = "blue";
$yourCar = new Car();
$yourCar->color = "red";
Every object has its own properties. The class may set default values in its constructor functions, but changing one car's color to orange doesn't impact any other car.
In php5 (php4 oo is weird, I wouldn't suggest it to a beginner), every time you assign from a variable that contains an object, the object reference is copied. Therefore, after executing
$ourCar = $yourCar;
$ourCar->color = "yellow";
, $yourCar->color is "yellow".
Related
I'm having the same poblem about making a copy of an object without reference in PHP but that soluction is not working.
I want to take all elements of a collection, change one property (add months) and push that new element into a new collection.
So I've used clone in order to get a totally new instance of an Invoice wich should be affected just that instance, but is not.
With this code:
while($thisInvoiceYear <= CURRENT_YEAR) {
$clonedInvoice = clone($thisInvoice);
$this->extendedInvoices->push($clonedInvoice);
$toSaveInvoice = $this->extendedInvoices->last();
$thisInvoiceYear = $this->getCurrentYear($toSaveInvoice);
$toSaveInvoice->Schedule->StartDate = Carbon::parse($toSaveInvoice->Schedule->StartDate)->addMonths($period);
unset($clonedInvoice);
}
Where $thisInvoice is an object of the Invoice collection, $this->extendedInvoices is a method of the class Invoice.
The problem is that every change done in $toSaveInvoice also affects to the original collection element. After 3 iterations, date is the same for all elements of extendedInvoices and should not be:
I am using Laravel 5.2, but I think there aren't helpers to clone an element of a collection.
Do you know why clone() is not working? Thanks a lot for your help.
A good idea is to read the manual first and ask a question on SO later.
From PHP manual:
Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.
An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.
$copy_of_object = clone $object;
When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables will remain references.
Even though the manual describes PHP 5 behavior, I can assure you, from my own experience, that PHP 7 behaves the same way.
If you need to clone with something else inside, implement the __clone method and define what exactly and how the object has to be cloned.
So lets say I have a class that is composed of other classes.
class HttpRequest
{
public $session = new Session();
// .. the rest of the HttpRequest code
}
Now, I want to have access to Session class through HttpRequest class so Im using composition.
But does this breaks laws of OOP Encapsulation or Data hidding that states that all properties should be protected, and accessed through setter and getter methods?
Is this wrong:
$request = new HttpRequest();
$request->session->set('id', 5);
or should I use this:
$request = new HttpRequest();
$session = $request->getSession();
$session->set('id', 5);
Encapsulation states that properties shoud be protected.
How to provide access to inner classes then? Is the first example wrong as far as proper OOP goes?
There are valid reasons to not allow direct access to the object:
Allows for manipulation of the object outside of the object itself. If you make the property public, any part of your code could overwrite $session on the HttpRequest class, and you'd have a tough time tracking it down. Encapsulation from a data protection standpoint is there to ensure that only the object's methods can directly alter the object.
Allows you to gracefully handle the case in which that variable is not set. If, for some reason, $session does not get set on your class - you'll immediately have a fatal when you try to call a method on it. If you wrap it in a getter, you could check for that condition and create a new instance of the class on the fly.
Follows true "OO" paradigms
However, in some cases I would say it is okay to do this. Particularly if you know that the property will always be set (and the only way in which it would not be set is not a supported way to use the object).
It also makes sense depending on how the property is going to be accessed. Symfony2 uses this in their Request classes. It feels natural in that case, as the "query" "post" and "request" vars are all "ParameterBag"s (glorified arrays). However, they do expose a getter for the Session object - likely because of it's use case.
In short: it really depends on how you'll be using the variable. In this particular case, I'd say it doesn't much matter.
I like your first option, (It's the one using composition), and look that has encapsulation (I don't know what makes the function set), but I suppose that it's modifying some attribute through the function of the "component" object "session", that pattern is also known as "delegation".
On the other hand if you use encapsulation you cannot user "public", that is allowing to be modified for everybody. It's because of this that you user setters or getter, or in your code "set"
I know this is old, but I would use neither of these. Does your HttpRequest object really need to hold onto the Session object or can a Session object be passed into some functions of the HttpRequest object that need it? Is there a strong case for having HttpRequest store this object?
I'm pretty proficient with PHP, outside of OOP - which I am just now starting to jump in to.
I've been watching videos and reading tutorials, but they are all still pretty confusing...
If I have
FILE 1 (class.time.php)
class Time {
function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
and then in a nother php page I've got
FILE 2 (page.php)
I can do
include('class.time.php');
and then anywhere in this page I can then do
$time = new Time; //Calling the class and setting the class to a variable
$time->GetTime(); //This is BASICALLY saying (run the 'GetTime' function in the 'Time Class'
My main question is, is the comment above (This is BASICALLY saying.....) correct? or is there a better way to think of it?
regarding method calls
I would make one correction to your statement, hinting a little more accurately at what Object Orientation is all about. Your comment reads:
run the 'GetTime' function in the 'Time Class'
Which is only kinda accurate, and expounding on it may clarify OOP for you. For the purposes of this post, I might rephrase it this way:
run the 'GetTime' method (which is defined in the Time class) bound to the object stored in $time
See the difference? You aren't just calling a function from a class, you are saying "get the processing instructions from the class, but bind those instructions to this specific object and then execute.
It may sound like mincing words, but it's critical to understanding encapsulation. Objects of a class share their method definitions, but they do not share data.
You can think of an object as essentially a set of two things:
A block of memory holding it's own, personal data
A pointer to a set of methods with special access to that data
(the "special" nature of the methods' relationship to the data is either implicit or explicit, it's up to you)
The distinction is readily evident when you start using "member variables" (sometimes called "object properties", "instance variables (aka ivars)", or similar names). Consider this sample code:
class Person {
public $name;
public printName() {
echo $this->name;
}
}
$me = new Person();
$you = new Person();
$me->name = "Chris";
$you->name = "Alex";
$me->printName(); // "Chris"
$you->printName(); // "Alex"
This highlights the fact that each object has it's own memory for instance variables. They share the definition of those variables, as well as the blocks of code written to process those variables.
The special variable $this is of particular interest to my overall intention with this answer: the same variable in the same method definition actually points to a different object depending on which object you call the method on.
regarding new
Now to the previous line, where your comment reads (in regard to $time = new Time):
Calling the class and setting the class to a variable
The way I would phrase it is:
Make an instance of this class, and allow me to access the instance through $time
That word, instance will be a big concept to get solid before moving on. You don't call a class, you call a method, and you don't (in PHP at least) set the value of variables to be a class, you set them to point to instances of the class. Sometimes people use the words instance and object interchangeably, which is fine. But you should not use them interchangeably with the word class.
Let's get technical:
When you use the new operator, technically you are telling PHP to do two things:
grab some fresh memory, exactly enough to store all the member variables defined in the class
call a special method on that new object to allow me to initialize my object
So if you call new twice, you grab enough memory for 2 objects, and so on. PHP uses your class definition to figure out how much memory to allocate for you, and find the special method to call.
That special method is called __construct, and is guaranteed to be called when your objects are created, with that special $this variable pointing to your shiny new memory. Here's a sample of how you might use it:
class Foo {
private $createdTime;
public function __construct() {
$this->createdTime = time();
}
}
$myFoo = new Foo;
Even though you don't see it, __construct() was called and the value of $createdTime was initialized.
Yes, basically your assumption is correct (apart from syntax errors).
However thats not a very good OO design.
Have a look at this, it give some good examples of OO design: http://www.math-cs.gordon.edu/courses/cs211/ATMExample/
That is correct, but the syntax should be:
$time = new Time();
$time->GetTime();
(don't forget the parentheses, otherwise you are referring to class properties)
Also, it is a good idea to declare your methods as public, protected, or private. If you are going to call the GetTime method from outside the class, it would need to be public.
Since in this case "get time" will never change and accepts no parameters, you would do best to put this into a static method, since it's a waste to instantiate a class in this situation
eg:
class Time {
static public function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
Time::GetTime(); // gets the time, no need to do $time = new Time();
In my opinion you are doing it correct, but for using a simple built-in date function, using it via class would probably just over complicate it.
Following is an excellent article for learning OOP in PHP
PHP OOP for beginners
So I have an object that could hold a string which contains some data, I have to validate the object or string but I cannot think why I would pass it into the method rather than the constructor, is there certain cases when I should pass it through the constructor rather than the method or through the method rather than the constructor ?
This is PHP code.
Constructor is also method differences is just in its usage. There are some things that we need to do at creation of an object of some class so for those things we pass object/setting arguments to constructor and when we need to process some data in context of that class we use method.
I think this was what u wanted to ask "difference b/w usage of method and constructor". If you got some coding issue tell me the scenario.
Pass an object into a constructor if you need it to be saved in the object for later use by one or more methods. Then, if you assign it, or a copy of it, to a member variable, it becomes part of the object's "state".
If the object to be passed is transient, and you only need it for the lifetime of the method, then you can pass it as an argument to the method.
Passing an arg through an object constructor has only one nominal benefit, and that is you are removing the extra step of calling setter(s) directly.
$foo = new Foo($dbo);
// Same thing as
$foo = new Foo();
$foo->setDbo($dbo);
Personally, I prefer to call setters explicitly rather than pass them through to the constructor because I don't want to end up with 15 signature arguments, and I can see how the calling code is using the object.
From time to time, I do use constructors for preparing related objects, but never for passing arguments.
I am using 'this' keyword for a long time. But when someone asks me to explain it, I am confused that how to explain it. I know that I can use this in a method of class to access any variable and method of the same class.
class MyClass{
function MyMethod1(){
echo "Hello World";
}
function MyMethod2(){
$this->MyMethod1();
}
}
Is it a object of a class that we don't need to initialise and can be used only within the class or anything else. How to explain?
Thanks
A class is a mold for an object: it specifies how the object looks like (variables) and what it can do (functions).
If you instanciate a class: you create an object. If you create the class, you can use "this" to refer to the object itsself. This is why you can't set the "this", because it's related to the object. It's a special, read-only variable.
this references the current object instance of a class.
this is an implicitly parameter passed to the methods of a class: it is scoped to a method and allows access to all of the object's members.
Like their name suggests, instance methods operate on instances of a class. How do they know which one to operate on? That's what the this parameter is for.
When you invoke an instance method, you're really invisibly passing in an extra parameter: the object to invoke it on. For example, when you have this:
class Basket {
public function a() {
$this-> ...;
// ...
}
// ...
}
and you call $some_basket->a(), behind the scenes you're actually calling something like Basket::a($some_basket). Now a() knows which Basket you want to work with. That special parameter is what this refers to: the current object you're dealing with.
short:
$this gives you access to the object variables (and methods) Edit: within the class :) Edit 2: (but not in static methods of the class) :D
Several people have explained it in similar terms, but thought I'd add that when speaking to people unfamiliar with object oriented programming, I explain that the class definition is the blueprint, as for a house, and "this" is the actual house you're working with at that moment. There might be other houses that look exactly the same, but this is the specific object (house).
A class is a template or a 'die' for an object.
Lets use the classic 'bicycle' example. There are many huffy bikes out there. However, we have created one bike, and we can use the 'this' keyword to refer to 'this' bike.
In more a more technical sense, a class is a template for an object that will be instantiated. At run time, after an object has been instantiated, or had an instance of itself created, we can then use the keyword 'this' internally to refer to the instance that runs that method.