is it possible to only instantiate my class once and have the data that has been passed into my class available globally?
In my case I have a class called Mail and I'm instantiating it once on my main page. How can I get the information gathered by the methods available to other parts of my site without having to make a new Mail object?
On some of my files, i need to re include the Mail.class.php because they are outside the scope of the main include php page. But vital information has already been gathered into the already created object Mail. I need to access that information, and I don't want to dump the information into sessions either.
Consider using a Dependency Injection container. The basic principle is what you are describing: define an instance of a class as a service in your container, and allow it to be used from anywhere in your code that has access to the container.
The Symfony framework's DI component is available as a separate component, or you can check out Pimple as a lightweight example. These are two that I use; I'm sure there are many others.
Two options I can think of...
1) Use globals, do NOT do this.
2) Make your mail class a singleton, so whenever you instantiate it, you have the data you set.
is it possible to only instantiate my class once and have the data that has been passed into my class available globally?
Yes, that's possible. Once you instantiated your class, it's an object assigned to a variable. You can pass that variable along in your program and then you have access to the object.
In my case I have a class called Mail and I'm instantiating it once on my main page. How can I get the information gathered by the methods available to other parts of my site without having to make a new Mail object?
This is called dependency injection, other parts of your site have a dependency on objects of even other parts of your site. So you need to inject that dependency, e.g. as a function parameter for a simple example:
Main page:
$mail = new Mail;
other_part($mail);
Other part:
function other_part(Mail $mail)
{
$mail; # there you have it
}
you can post the object in json format to other pages or you could make a temporary file/dbtable to hold the info. or sessions but that was not an option ;-). don't think its possible to do it in an other way. but hey, I'm not an expert.
Related
I have searched and searched and found tons of examples but it seems that everyone has a different opinion about how and when to use session, some use it some say it is evil...
Here is my use case.
I have a Class that has several variables that will need to be used on every page in my application. These variables values are set by making a SOAP call to an API that I am working with. The SOAP call is relatively quick but I am trying to understand how to avoid making a call to the API on every page. I would much prefer to make the call once and then "store" the values somewhere.
I would think that I would just create an Instance of my class on some say Init.php page, make the SOAP calls and then store the whole class in session. Then on all of my pages include the Init.php page. In that page I would do a check to see if the Class existed in the session and if so then pull it form the session.
I know I have to serialize\deserialize the class to do this but I am looking for some feedback here on weather this is the right way to satisfy this use case or if there is a better option?
I am kinda new to PHP, mostly a .NET guys and in .NET the session is generally the best way forward.
All input is appreciated.
thanks
I assume when you stay "serialize\deserialize the class," you really mean you want to serialize/deserialize a class instance (an object) in the session, not the actual class definition. Be careful when using the terms class, instance, and object, since they are not interchangeable and can lead to confusion.
An object can be easily stored in a PHP session. PHP automatically serializes the object at the end of the request and deserializes it when the session data is read on the next request.
session_start();
if (!isset($_SESSION['soap'])) {
$_SESSION['soap'] = doSoapRequest(); // Returns an instance of your class.
}
When an object is serialized, only the variables defined in the class are saved along with the name of the class. When it is unserialized, the class definition must be available (that is, either autoloader or explicitly included into the script). Unserializing will create a class instance with the same data as the object that was previously serialized.
I'm relatively new to PHP, and I'm looking for a way to define certain objects as globally accessible from throughout the project, from multiple PHP scripts.
In Java, if I've to access some objects globally, I define some public class named Globals , and define the objects that I need to access as static in the Globals class. I then access those objects wherever I need with: Globals.variable_name .
So basically, I need to initialize these global objects only once and then use them whenever I need them..
One use case:
I've a class named Logger that has methods to log certain events in a log file. I need to have 1 Logger instance/object that can be used by all the PHP scripts in the project, whenever they've to log something. I'd rather not have each PHP script using it's own instance of Logger.
The naive Java-like approach I tried, that did not work:
I created a public class named Globals in a separate PHP file (named Globals.php) with one static object of type Logger, named $logHandle. I included this PHP file in all other PHP files where I need this Logger object. I then tried to access this object , using Globals->logHandle from one of the other PHP scripts. This attempt failed miserably.
Is there some similar approach?
Thanks.
PHP is not Java.
In web applications, the PHP environment is initialized for each request - and each request is handled in a different process with it's own memory space. It is possible to share access to data (including serialized objects, but not resources such as database connections and file handles) across different instances. You probably know this already but have not yet realised how it influences the way you write code.
I'd rather not have each PHP script using it's own instance of Logger
Why not?
One very good reason is that allowing multiple processes to write to the same open file handle requires locking to prevent the file getting all mesed up. BUT THIS IS PHP - STOP REINVENTING THINGS FROM SCRATCH. Writing to stderr will append the details to the webserver error log or use the OS syslog facilities - that's what they are there for.
It is impossible to have the same object available to all instances of PHP - you can unserialize an object in all instances - but then it's not the same object. You can run a daemon with a single object which might be accessible to all other PHP instances via a socket connection - but it's not running in the same address space.
If you validly have a class that you want to be universally available via an object with a fixed name, then simply create an instance of the object in each script or via an include file. The approach you tried is the way to go about this (but don't name your objects with reserved words). We don't know why it failed because you didn't provide any error messages or code.
I assume you're asking about common case (now only web-oriented application). And for that - no, you can not define some thing like you've described, in native way. This is the thing that is called superglobals in PHP.
But on the other hand - you need to do that for some reason, not "just because you want it". And, if so - then use configuration file. Create some application configuration file, read it once at start of application (bootstrap) and you'll get all needed values. I'm not saying anything about file structure - it can be xml/ini/yaml/whatever/you/like. But the idea is - to split this logic from application structure itself and use separate file for storing desired values.
Another option is to use some separate PHP file(s) and include it at bootstrap. Define all needed variables/constants in that file(s) and you'll get similar behavior. Note, that in terms of namespaces it's less "global" and you'll need to resolve all that cases manually.
For web-applications, however, one of possible solutions may be using sessions. $_SESSION is a superglobal array and it will behave like you want (i.e. will be accessible from everywhere). But that is not applicable always - and not always you'll want to deal with sessions to store session-independent data.
you can do like this
you said that you have included in all other classes change methods in your global class to static
<?php
class Logger {
public static function log($msg) {
// ...
}
}
you can use it like
Logger::log($msg);
http://www.php.net/manual/en/reserved.variables.globals.php
i think that is what you're after.
To access a static attribute in PHP you need to call it with the Class::$attribute notation, and the static methods need to be called with the Class::method() notation.
The -> notation is used when calling attributes of a class instance.
Without using CodeIgniter I would normally just do;
require_once("object");
test = new object();
How would I go about doing this in CodeIgniter?
Edit: for example this class could be a video game object. It might be holding a number of variables, for example title, age,description etc. There would also be variable get/set methods for the above variables.
For example, I might use this class to help contain the information created by a database search.
Codeigniter uses the Singleton design pattern and most of your classes are loaded using the loader class (as needed, in a constructor, or in the autoload config file) and are then available via the Codeigniter Super Object $this->my_model. As Kai Qing noted, using a Model would typically entail:
// In the constructor, controller method, or autoload
$this->load->model('my_model');
// Then to use a method simply
$this->my_model->my_method();
In Codeigniter classes are more like utility classes to group like functionality. However, you can always use native PHP in Codeigniter to require a class and then instantiate your own objects.
I'm writing my first basic bare bones MVC patterns setup in PHP. I know global variables are bad, and I aslo know I don't want all of my classes to have access to all of my config vars.
I have a settings.php file that I would like to define a bunch of constants in, like my db connection info, directory structure info, email addresses and so on. It will be one centralized location that holds all of my important information.
What's the best way to implement a config class so that each of my base classes for my controller and model only have access to the config vars they need? For example, my model base class should have access to by db connection info.
Basically I am just asking how anybody whole rolls their own MVC setup handles config information without declaring global variables, like we used to back in the procedural days.
Thanks.
You're going to get a bunch of answers on this as it basically boils down to preference.
Personally, ive used a config array. example:
$conf['db']['username'] = "username";
$conf['db']['password'] = "password";
Then just pass byref the pieces you need into where they need to go.
I rolled my own MVC setup. (Still going strong. Might open source it). The way I do it is to have an init script that passes all those constants to a controlling class.
The controlling class is a Singleton. So anytime another class needs access to it, it just gets the existing instance of the controlling class and all the variables are available from it.
I know that Singleton pattern is bad because it uses global state. But in most applications, you need to have a single instance of a class, like a database connection.
So I designed my Database object without using the singleton pattern but I instanciate it only once.
My question is, how can I access my object in the low level classes (deep in the object graph) without passing it all over the place?
Let's say I have an application controller which instanciates (ask a factory to instanciate it actually) a page controller which instaciates a User model which requires the database object.
Neither my app controller nor my page controller need to know about the database object but the User class does. How am I suppose to pass the object to it?
Thanks for your time!
Consider using a global container:
You register the objects that are indeed relevant to the several subsystems of the application.
You then request that container those objects.
This approach is very popular in dependency injection frameworks (see Symfony DI, Yadif).
Singleton is bad, no doubt about it.
In the case you describe, the database object is an implementation detail of the User object. The layers above need only know about the User, not the database object.
This becomes much more apparent if you hide the user object behind an interface and only consume that interface from the layers above.
So the page controller should deal only with the interface, not the concrete class that depends on the database object, but how does in create new instances? It uses an injected Abstract Factory to create instances of the interface. It can deal with any implementation of that interface, not only the one that relies on a database object.
Once more, you hide the page controller behind an interface. This means that the concrete implementation's reliance on the Abstract Factory becomes another implementation detail. The Application Controller only consumes the page controller interface.
You can keep wrapping objects like that like without ever needing to pass around instances. Only in the Composition Root do you need to wire all dependencies together.
See here for a related answer with examples in C#: Is it better to create a singleton to access unity container or pass it through the application?
The way I've always accomplished this is to implement a static getInstance function that will return a reference to the single instance of that class. As long as you make sure that the only way you access the object is through that method, you can still ensure that you only have one instance of the singleton. For example:
class deeply_nested_class {
public function some_function() {
$singleton = Singleton::getInstance();
}
}
There are two main objects involved in loading/saving a user using the database: the user and the repository.
You seem to have implemented the functionality on the User, but I think it belongs on the Repository. You should pass the user to the Repository to save it.
But, how do you get hold of the Repository? This is created once at the top level and passed into services that need it.
The construction dependency graph and the call dependency graph are not the same thing.
Given the example you outlined, you are almost there. You are already using a factory to instantiate your page controller, but your page controller is instantiating the users directly and as your User needs to know the database.
What you want to do is use a factory to instantiate your User objects. That way the factory can know about the database and can create User instances which know about it too. You will probably be better off making interfaces for all the dependencies, which will help with testing and will mean your code is nicely decoupled.
Create an IUserFactory which creates IUser implementations and pass this into your PageControllerFactory, then your ApplicationController only needs to know about the PageControllerFactory, it doesn't need to know anything about the IUserFactory or the database.
Then in your application start up you can create all of your dependencies and inject them in to each other through the constructors.