use same object for different files in php - php

I have two files say file1.php and file2.php. I have one php file named form in which class form has been defined.
I have created an object in file1.php as follow:
require_once('form.php');
$x=$_GET['field'];
$form = new Form("", "");
$personal = new Block("");
$address = new TextArea("address", $x, "", 3, 30);
$personal->add($address);
$form->add($personal);
echo $form;
now i want to use this object $form and $personal in another file file2.php which is as follow:
$personal = new Block("");
$name = new Text("name",$x);
$personal->add($name);
$form->add($personal);
echo $form;
how can i use these objects in php. please help.

If you include one PHP file into the other, there is no problem, as the code in both will get merged to the scope of the including code.
Otherwise, if you wish to us re-use the objects at different positions in your code, you can use a registry (see also: How is testing the registry pattern or singleton hard in PHP?) to store the instantiated object.
If you plan to re-use the same objects on the next page load you need to serialize them, store the serialized object in the session/cache (or elsewhere) and unserialize it after loading the next page. In that case you'll also need some mechanism to set up a database connection or perform other required tasks (see: __wakeup()).

Usually, you'll have to make a new instance of the object for each time a script is run.
If not, you could serialize the object, which puts it into a string format, then unserialize it when you need it, but you'll have to store the string somewhere. It's usually easier just to declare a new class.
In most cases like this, you'll use your object to modify values in a database. When the new instance is created (on page reload), it looks at the database to get the modified values. This way, the same instance doesn't have to persist across reloads.
Your class would use getters and setters ("accessors" and "modifiers") to work with the values you need - $address, for example.

first include file1.php
then just call the instances:
require_once('file1.php');
$name = new Text("name",$x);
$personal->add($name);
$form->add($personal);
echo $form;
keeping in mind that the instances of $form and $personal are already created in file1.php

Related

How to find out which objects on a page use a certain class

I have an old site to bring up to standard but I have to approach things in a certain way due to timing issues and certain restrictions preventing my urge to restructure the whole site properly from the bottom up.
Most of the work involves updating various include files.
So, these include files are called into a page which uses a class to generate an object, as usual,
The Problem:
There are lots of pages and they are not consistently coded (thanks to sub-standard previous developers on the site), so sometimes the class I want to use is in an object called $database, sometimes on other pages the object is called $dataBase, $connection, etc. etc.
There are several includes that I am working on and I feel that having to create a new object for each include on each page is extremely inefficient, hence this question:
Can I find out from PHP which, if any, object variables use a certain class?
An illustration:
Page index.php
require "class.sausages.inc.php";
$hotdog = new sausages();
$hotdog->somefunction();
//etc. etc.
include "some_file_i_need_to_work_on.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
Page index2.php
require "class.sausages.inc.php";
$hotdogs = new sausages();
$hotdogs->someOtherfunction();
//etc. etc.
include "some_file_I_need_to_work_on_3.php";
include "/folder/some_other_file_I_work_on.php";
//etc. etc.
So I need to work on the includes and so for each include file I do not know for sure the $name of the variable object created in the includes parent file. All I have is that it uses the class sausages.
Solution attempts
I read how to check if object of a class already exists in PHP? which has pretty much the same issue but the solution marked here is to generate a global, which I'm feeling is another layer and to be honest I'm not quite comfortable with it as an efficient solution.
What I am trying to avoid is a situation where each include on a particular page has to generate its own object, all from the same class (usually) established in the parent page.
As there's no guarentee in one include if another include is included, I don't think I can generate an object that the includes can all use collectively, or if I can, how can I do that?
What I would Like
I want to be able to find a way to establish in PHP:
has any object been generated using this class?
yes? Use that object in this include.
no? generate a new object from the class file.
Is this possible?
Notes:
There are about a dozen include files,
There are a lot of parent pages (50+). I think editing each one would be inefficient (but this will be done at a future point)
Some parent pages contain some include files, some contain others. There's no guarentee which includes are included in which files ( as far as I can tell so far).
Most but not all parent pages have already established a class object.
PHP 5.6.16
as per:
http://php.net/manual/en/internals2.opcodes.instanceof.php
You can check if certain variable is an instance of certain class:
if ($hotdog instanceof sausages){
// use $hotdog
}
else {
// create and use $hotdog
}
But it will not tell you anything about other variables.
You can also use this:
http://php.net/manual/en/function.get-defined-vars.php
to get a list of all defined vars into an array. You can then loop through the array to see if there are any instances of the class that you are interested in.
foreach (get_defined_vars() as $var)
{
if ( $var instanceof sausage) {
// use this var
}
}
This solution will do what you want, however you should note that it is probably safer to create a new object. When you use an already instantiated object inside an include, you have no idea what other operations have been performed with that object. THe sausage may have very well be fried by the time you start using it and it may not do exactly what you want.
You should also look into a singleton pattern .
Using this pattern you can always get an instance of the same class and be sure that there is only one instance created across the app.
To go back to your old app, say that you want to make sure there is only one instance of sausages class across the app.
define a singleton method inside the sausages class
search/replace all the occurances of new sausages with sausages::singleton()
inside the include, you can then safely use $hotdogs = sausages::singleton();
This will make much cleaner code than trying to detect wether there are any global instances of sausages.
For conclusion; I ended up taking Karolis' answer and generating a search system for the correct object variable, without needing to instigate a new one if one is already defined:
At the top of each of my includes:
foreach (get_defined_vars() as $varKey => $variable) {
if(is_object($variable) && $variable instanceof sausages) {
$$varKey = $variable;
}
}
//$$varKey = this is the instance object.
Obviously code for if no instanceof is set is not detailed here, but this code works for me so far.

What is the best way to use many different instances of objects insider another PHP class?

I have a class called Page, which loads a PHP file for the current page, containing all the HTML (template file). In my template file, I want to use instances of other objects, that is initialized outside the Page class (ex. User, PDO or other classes). My problem is, how I do this the smartest way.
In my page class i have a method called get_page() which loads my template file (containing all the code for my GUI.
public function get_page() {
// Load theme template
...
$template_file = ABSPATH_THEME . 'tpl.' . $result['template_file'] . '.php';
if(file_exists($template_file)) {
$page = require_once($template_file);
return $page;
}
}
As you see the template file are loaded inside my Page class, and therefore will it not access instances of classes initialized outside my Page class.
I can come up with different solutions:
1) I pass all instances of the different classes to my class Page, when constructing my page. I think this is the right way, but can be very complex if I need 5, 10 or 20 different objects in my design.
2) Find a way to include the template file outside the Page class, but triggered from the get_page() function - have no clue how to do this, and if it is a good solution?
Can you please tell me what is best, and if there are some better ways to do it?
You can just include classes on the top of your php
eg. /CLASSPATH/ClassName.php
And then you can create an entity for that class once and use it everywhere
eg. $entity = new ClassName();
I think your best bet will be to pass them in as arguments, depending on what you need you may want to make them properties.
Edit: This is assuming that by "using instances of other objects" you mean that you need to use objects that have already been instantiated elsewhere.
If by "istances of other classes" you mean other generical objects (you mention PDO and user which are goos examples of this) I would store these in the $_SESSION array (or in $_GLOBAL array, $_SESSION being the best option in most cases).
Then you can access them just by using $_SESSION['PDO']->... and the like
One of the most popular method to handle php application rooting is to implement MVC design patern, or use an MVC Framework. Google 'MVC php' for details, good luck.
Take a look at the functions get_defined_vars and extract. Using these you can export variables from one scope to another.
A silly example could be: A function A transfer locally defined variable to a function B.
function A()
{
$var1 = "1";
$var2 = "2";
// etc
$data = get_defined_vars();
B($data);
}
function B($data)
{
extract($data);
// somescript.php can use $var1, $var2, etc if B is call from A.
require("somescript.php");
}
A();
The best practice is to use a ServiceLocator or an InversionOfControll-Container to retrieve class instances without violation of DI-Principle. For your template file you can create view helper objects to have direct access to other objects.

Php passing the same objects on another file

1) Suppose I have 2 php files: fileA.php, and fileB.php
And I have 1 class file: myClassFile.php
in fileA.php, I need to instantiate a MyClass class in myClassFile.php:
...
myObject = new MyClass();
...
in fileB.php, I need to use the myObject object created in fileA.php.
How would I do that? Is using sessions the way to go?
$_SESSION["my_object"] = myObject;
or are there better ways? Specifically, how will it be implemented?
2) Suppose I don't use solutions similar to the above.. Will myObject in fileA.php be lost (destroyed, or freed) when the user proceeds to fileB.php? That is, will there be no more reference to myObject in fileB.php?
It sounds like you're doing something unnecessary complicated.
The information you passed and treated in MyClass has to be available somehow in the object.
Create a method to extract all these information to an array and save this array in a session. When reaching the next page, create an instance of MyClass again and feed the object in another method for this purpose with the information array from your session.
I am not an expert but if your object is like a configuration object which you need to access from many places then consider using Singleton pattern

move object from 1 page to another?

Hay guys. I'm kinda new to OOP in PHP. I've learnt how to write and create objects. Is there a way to take an object and pass it to another script? either using GET or POST or SESSION or whatever. If there isn't how would i assign an object some variables on one page, then assign the same object more variables on another page?
Thanks
You can store objects in the session but you need to include the file which contains the class definition before calling session_start() (or use class autoloading and set this up before you start the session). For example:
On every page:
//include class definition
require('class.php');
//start session
session_start();
1st page:
$object = new class();
$object->someProperty = 'hello';
//store in session
$_SESSION['object'] = $object;
Subsequent pages:
$object = $_SESSION['object'];
//add something else, which will be stored in the session
$object->anotherPropery = 'Something';
Here is an example with autoloading in respect to the answer by Tom Haigh:
Before you start the session:
function __autoload($className) {
$file = PATH_TO_FOLDER_WITH_ALL_CLASS_FILES."/".$className.'.php';
if(file_exists($file)) {
require_once $file;
}
}
session_start();
Page passing the object:
$object = new class();
$object->someProperty = 'hello';
//store in session
$_SESSION['object'] = $object;
Page receiving the object:
$object = $_SESSION['object'];
//add something else, which will be stored in the session
$object->anotherPropery = 'Something';
The autoload method will automatically load the objects while you retrieve data from session.
You could store the object in a SESSION.
You can serialize the object and pass through GET or POST.
If you want the object to persist across the site, then SESSION is probably your best bet.
You can use the $_SESSION. but it will only be for that session.
Using an object on multiple 'scripts':
First, you have to decide what kind of structure your OOP application has.
If you use something like MVC pattern, you do not have to this by using SESSION or REQUEST, because you can 'plug' the objects you want to use into 'one'.
What does this mean?
A quick example:
User A enters your site index.php
Now you can load the content from a static index.html,
but if you want to check whether the user is authenticated to see specific contents e.g. the 'Admin Login', you can use include_once('Authentication.php') and initiate a class from this file, e.g. <?php $Auth = new Auth_Handler; ?>
This will make the Auth class also available in the index.php or any other file you want to include this class.
If you want to pass the authentication class' return value to another file e.g. 'register.php' you can use the SESSION or any other Cache.
Passing whole objects is not recommend due to their size.
Including and initiating the wanted classes at the beginning of files is much better.
And passing the returns by SESSION uses less space.
It really depends one which framework or API you want to use, or what project you want to create.

PHP __PHP_Incomplete_Class Object with my $_SESSION data

I've got a site setup that, on page load, turns all user submitted strings into SafeString objects. For those unfamiliar with SafeString, it basically forces the user to echo out sanitized data preventing XSS and whatnot..
Anyways, there's a problem. My $_SESSION array is being filled with __PHP_Incomplete_Class Object. From what I've read, this is due to not initializing the class before the session and then storing class objects in the session.
Here's my code:
require_once __WEBROOT__ . '/includes/safestring.class.php';
$temp = array
(
&$_SERVER, &$_GET, &$_POST, &$_COOKIE,
&$_SESSION, &$_ENV, &$_REQUEST, &$_FILES,
&$HTTP_SERVER_VARS, &$HTTP_GET_VARS,
&$HTTP_POST_VARS, &$HTTP_COOKIE_VARS,
&$HTTP_POST_FILES, &$HTTP_ENV_VARS
);
function StringsToSafeString(&$array)
{
foreach ($array as $key => $value)
{
if (is_string($array[$key]))
{
$array[$key] = new SafeString($value);
}
if (is_array($array[$key]))
{
StringsToSafeString($array[$key]);
}
}
}
StringsToSafeString($temp);
unset($temp);
I can't think of a way to rewrite this which would solve the problem :/
Any ideas?
When you're accessing $_SESSION, you're not just changing the current script's copy of the data read from the session, you're writing SafeString objects back into the active session.
But putting custom objects in the session is dodgy and something I would generally try to avoid. To be able to do it you have to have defined the class in question before calling session_start; if you don't, PHP's session handler won't know how to deserialise the instances of that class, and you'll end up with the __PHP_Incomplete_Class Object.
So avoid frobbing the session. If you must take this approach, make a copy of the data from $_SESSION into a local $mysession array. However, I have to say I think the whole idea of a SafeString is dangerous and unworkable; I don't think this approach is ever going to be watertight. Whether a string of raw text is ‘safe’ is nothing to do with where it came from, it is a property of how you encode it for the target context.
If you get another text string from a different source such as the database, or a file, or calculated within the script itself, it needs exactly the same handling as a string that came from the user: it needs to be htmlspecialchars​ed. You're going to have to write that escape anyway; the safestring gains you nothing. If you need to send the string to a different destination format, you would need a different escape.
You cannot encapsulate all string processing problems into one handy box and never think about them again; that's just not how strings work.
I know it's been years since this was asked, but I'm posting my answer because none of the answers above actually explain to the OP what is actually wrong.
PHP serializes its sessions using the built-in serialize and unserialize methods. serialize of PHP has the ability to serialize PHP objects (aka class instances) and convert them to string. When you unserialize those strings, It converts them back those same classes with those values. Classes who have some private properties and want to encode/decode that or do something complex in their serialization/deserialization implement the Serializable class and add serialize and unserialize methods to the class.
When PHP's unserialize tries to unserialize a class object, but the class name isn't declared/required, instead of giving a warning or throwing an Exception, it converts it to an object of __PHP_Incomplete_Class.
If you don't want your session objects to convert to __PHP_Incomplete_Class, You can do it by either requiring the class files before you invoke session_start, or by registering an autoload function.
You just have to include the safestring.class.php before you call session_start() when you want to read the SafeString objects from $_SESSION variable:
<?php
require_once __WEBROOT__ . '/includes/safestring.class.php';
session_start();
print_r($_SESSION);
and yeah, if you are using PHP framework that (most probably) calls session_start() internally, make sure you require_once the class file beforehand (use hooks or whatever mechanisms that the framework provides).
I solved the problem using json_encode and json_decode function.
This is where I wanted to assign the value to session.
$user_json = json_encode($user);
$_SESSION['user'] = $user_json;
This is where I show the user after decoding the json
session_start();
$user_json= $_SESSION['user'];
$user = json_decode($user_json);
This solves my problem but I am not sure about performance or security. I haven't checked them.
Lukman's answer is correct. But you already mention that in your question, so apparently you can't instantiate the class before the session starts, for some reason.
You may want to check if sessions start automatically in the php config:
http://www.php.net/manual/en/session.configuration.php#ini.session.auto-start
If they are and yu cant help that, you may want to check if you can have your classes autoloaded prior to that:
http://php.net/manual/en/language.oop5.autoload.php
If all else fails, you can still serialize the objects before you store them in a session, and unserialize them each them you retrieve them:
http://php.net/manual/en/function.serialize.php
I dont see in your code where you store your variables, but it would be something like
$mystuff = unserialize($_SESSION["mystuff"]);
$mystuff->dostuff();
$_SESSION["mystuff"] = serialize($mystuff);
Be sure to load the class definition before you unserialize your variables
$2c,
*-pike
I just dealt with something like this. Took me hours to finally find how my order was screwed.
I had a file being called asynchronously.
myFile.php
that file contained the following..
$result = include ("myOtherFile.php");
return $result;
Myotherfile.php has something like this
require_once "lib/myClassLibs.php";
require_once "webconfig.php";
the webconfig.php had the session_start() call in it.
The lib/myClassLibs has all the class info init. If you check before the webconfig call, you can see that the class is available.
If you check before the webconfig call, you will also see that the session has started already. If you check before the lib/myClassLibs.php, you will see the session is already started.
Checking in myFile.php before you include MyOtherFile.php, you find the session has not started.
This represented legacy code that has worked for the last 8 years without me fiddling with it. I pulled the includes out of the "MyOtherFile.php". Now my sessions are synching properly.
I solved this problem by including the __autoload function at the top of my php file. So it looks like this:
<?php
require_once("path/to/include.inc");
//Needed for serialization/deserialization
function __autoload($class_name) {
include "path/to/". $class_name . '.php';
}
In PHP 5, this function isn't be needed but I was stuck until I used this function. Hope this helps someone else!
I know this is a really old question but I ran into this problem. After more research and experimenting I came up with a what I think is an acceptable alternative to storing classes in the session. It might be a bit hackish, but works for my current project.
NOTE: this work-around works for me because I start a session when a user logs in and don't want to include every possible class the user might, or might not encounter during the session. Including all the classes doesn't seem practical or efficient (but maybe this isn't any better ???).
First, my base class contains the following code that populates the object attributes from a given array, automatically.
class BaseClass {
public function __construct($properties=[]){
if (!empty($properties)) {
array_walk($properties, function ($val, $key) {
$this->fromArray($key, $val);
});
}
}
public function fromArray($property, $value){
return (property_exists($this, $property)) ? $this->$property = $value : null;
}
public function toArray(){
return get_object_vars($this);
}
}
The Work-Around:
I use the toArray() method to convert a class instance to an array before it goes into the session, then create a new instance of the class when fetching it from the session.
$_SESSION['user'] = $userInstance->toArray();
// ... do stuff ...
$userInstance = new User($_SESSION['user']);
This is also really handy for writing classes to a database and converting to JSON. Both of which are made easier when working with a PHP array.
Like I said above, this may or may not be the most efficient way to handle this problem. It also raises the question, "should I be using PHP classes if I'm just going to convert to arrays?"
I run into the same problem and the solution was inspired by #bobince answer
To be able to do it you have to have defined the class in question before calling
session_start
First, my session was set like this:
$_SESSION["customer"] = $customerObj;
Then before calling the session_start(), I have to load or defined the class first by importing it and then call session_start() right after
require 'entity/Customer.php';
ob_start();
session_start();
$customer = new Customer();
if (isset($_SESSION["customer"]))
{
$customer = $_SESSION["customer"];
echo $customer->getCustomerName();
}
My mistake was sending the user to a PHP page without including the class in that page, only in the original page.
Looked something like this:
index.php
include __DIR__.'AirInfo.php';
session_start();
$plan = new Plan();
header('Location: session.php');
session.php
// Should have put include __DIR__.'AirInfo.php' here
session_start();
My mistake here was that I had set the session.auto_start setting to on. The session would then be initialized before any line of code (including the autoloader) will be called.
I have the same problem with Google Photo API When Try to Authenticate my app and Access Photo API.
Solve it by just use session_start() after include and all use statements.
Here my complete code:
include "./vendor/autoload.php";
use Google\Auth\Credentials\UserRefreshCredentials;
use Google\Photos\Library\V1\PhotosLibraryClient;
use Google\Photos\Library\V1\PhotosLibraryResourceFactory;
use Google\Auth\OAuth2;
session_start();
//rest of code comes here
Short version of #bobince's excellent answer, if you're using an MVC framework and a classmap or psr-4 autoloading etc...
[front controller]
//Do this before session start because session has an object that will not work
// if the class has not been loaded already
require_once('vendor/autoload.php');
//Start a session after your autoload
session_start();
You might just be calling,
session_start();
session_start();
twice in your code. Call it once. Check required php classes for repeats. This was the fix for me.

Categories