Where are the instantiated objects stored in zend framework? - php

I'm a beginner in Zend Framework and I find it hard to understand their documentation.
The only PHP Framework I have used was CodeIgniter.
I am used to this method in utilizing libraries:
//load the My_Library class and assign the object to $this->myLibrary property
$this->load->library('my_Library'); //CodeIgniter way
public function index()
{
$this->my_Library->method(); //make use of the methods in the loaded library
}
So far I'm figuring out how this code works in zend, say in the bootstrap class:
protected function _initSetDoctype()
{
$doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_STRICT');
}
And in the layout.phtml file we can put:
<?php echo $this->doctype() ?>
My question is: Since I have instantiated a new Zend_View_Helper_Doctype();
How did ZF assign $this->doctype and made this available in view?
Is there some kind of storage where these values update the view object?
I'm trying to find out how the flow works in zend so I could have a better understanding on how to make use of its resources. Sorry for my English if it's hard to understand #_#
Thank you very much!

Usually ZF uses Zend_Registry to store instances of objects that it creates. The specific example that you provided (i.e. _initSetDoctype) works, because constructor of Zend_View_Helper_Doctype will check if it is already stored in Zend_Registry or not. So, in your bootstrap, new Zend_View_Helper_Doctype() will store doctype info in a registry (because it is created for the first time), and than in the layout.phtml, the stored value in the registry will be retrieved.
Other ZF resources (or objects) such as Zend_View, Zend_Layout, are also stored and access through registry.
Off course, you can also store your own objects (or whatever) in a registry. This way, you will be able to access them in every place of you ZF app.

Related

Autoload a simple DAO in Symfony2+Propel

I've been working on a project and I decided it'd be a good idea to have some sort of, like, DAO, but simplified.
Basically, the only thing I want from it (right now, at least) is to fetch me objects by model name and id. I wrote this very simple piece of code:
class DAO {
public static function get($className,$id) {
$queryName = $className."Query";
if (!class_exists($className) || !class_exists($queryName)) {
return false;
}
$q = $queryName::create()->filterByID($id)->find();
return $q;
}
}
However, I found myself stuck with the implementation. I guess I need to somehow autoload it so that it'll be able to check for the existence of the classes and so that I could use it anywhere inside my app, but I don't know how. Can anyone help me out? Or if there's a better way to do that, I'll appreciate any input.
What you're looking for is a Service.
Definition from the documentation:
Put simply, a Service is any PHP object that performs some sort of
"global" task. It's a purposefully-generic name used in computer
science to describe an object that's created for a specific purpose
(e.g. delivering emails). Each service is used throughout your
application whenever you need the specific functionality it provides.
Defining your class as a service is as simple as this:
app/config/config.yml
...
services:
my_dao:
class: Your\Bundle\DAO
...
Now you can access DAO in your controllers doing something like this:
$dao = $this->get('my_dao');
When you make this call, the Service Container will create an instance of your class and return it. There will always be at most one instance (singleton) and if it's never called, it won't even be instantiated.
I recommend reading the documentation.
Opinion
It seems like you're having trouble adapting to the Symfony way.
If you take a look at The Book you'll see that the Entity Manager in conjunction with your entity's Repository handle most of what DAO's traditionally did. In other words, there's really no need for your DAO class.
For example, fetching any object by id is as easy as:
$om->getRepository('YourBundle:YourModel')->find($id);
Anyway, if you're particularly fond of that approach, you may want to try this project.

Persistent objects in CodeIgniter

I have an php object which I want to be accessible whenever I want. I want to create this object once and keep it persistent so that I don't have to reload it again. Also I would like this object to be accessible in my controllers/models etc.
Can this be achieved in CodeIgniter/PHP without using session?
Or maybe using session, but will I be able to access its methods?
This object is created using PHP COM library from my dll file
Here is sample of my object:
$myDllObject = new COM("MyDLL.MyCLass");
PHP has an execution model where each web request from the host environment generates a new, fresh PHP environment which is destroyed when the request is completed.
So the simple answer is no, you cannot create an object and persist it between requests. You must "persist" the object in some other way:
Through serialization/deserialization, using sessions, a database, a key-value store like APC, a file on the file system, or some other method.
By having a separate long-running process hold the object, and having PHP objects communicate with it via some IPC method, such as shared memory, pipes, sockets, etc.
I don't know much about COM, but since COM objects can be created outside the running process I suspect that there is probably some (not-PHP specific) method of connecting to an existing one rather than creating a new one. (This is essentially option 2 above, using the COM services as the IPC.)
A little digging through the PHP COM library docs reveals the com_get_active_object() function, which may bring you to a working solution. However, you will probably need to learn more about COM from non-PHP sources. Also, read the big fat warning about using a single COM object concurrently:
Using com_get_active_object() in a web server context is not always a smart idea. Most COM/OLE applications are not designed to handle more than one client concurrently, even (or especially!) Microsoft Office. You should read ยป Considerations for Server-Side Automation of Office for more information on the general issues involved.
This suggests to me that creating a singleton COM object shared among all requests is actually what you don't want to do!
If that doesn't work, PHP has an object serialization method that allows you to serialize the running state of an object to a string and deserialize it back again to the same state. You can customize this by adding the __sleep() and __wakeup() methods to your class. This mechanism has it's share of quirks and I don't know how well the PHP COM library proxy objects would support it.
I'm not very familiar with the PHP COM library but if it's a object couldn't you maintain it's state by creating a object in your base controller and creating it there. Then just extend your other classes from your Base class.
class Base_Controller extends CI_Controller
{
public $myDllObject;
public function __construct()
{
$this->myDllObject = new COM("MyDLL.MyCLass");
}
}
/* End of file MY_Controller.php /
/ Location: ./application/core/MY_Controller.php */
Example Controller
// ------------------------------------------------------------------------
class YourController extends Base_Controller
{
public function __construct()
{
if (is_object($this->myDllObject))
{
echo 'Yep';
}
else
{
echo 'Nope';
}
}
}
See the CodeIgniter documentation on Creating Libraries.
Once your library is created you can choose to have it autoloaded in config/autoload.php, or, you may load the library using $this->load->library('yourlib');
If you need to create a new instance of this class on every page request, consider putting the instantiation in the constructor of your controller. Or, create a base controller class and put it in that constructor.

accessing the getOptions() of Zend_Application_Bootstrap_Bootstrap

I'm using the default Zend_Application design pattern which loads a zend config ini file automatically in the application bootstrap and I need to ini file's variables across many models and controllers.
Right now, I'm solving it by settings the config object as a key into Zend_Registry:
protected function _initConfig()
{
$config = new Zend_Config($this->getOptions());
Zend_Registry::set('config', $config);
}
Generally, I don't like using Zend_Registry, as it doesn't offer code auto complete in my IDE, and it's hard to keep track on what I have in the registry namespace.
Is there another way to access the Zend_Application's config ini?
In a controller you should be able to do:
$this->getInvokeArg('bootstrap')->getOptions();
to access the config. For models you really should be passing in the options you need. Otherwise your only choice is really the registry.
You could always initialise it as needed yourself with
$options = new Zend_Config_Ini('/path/to/config.ini',
'config');
Wich is pretty much what the bootstrap does for you. Then you would have autocomplete on $options. But you would have to initialise it everytime you need it.
I think modifying your code to suit autocomplete is not the greatest idea ever. But this is personnal.
If I am not mistaken with Zend Studio 8/9 (maybe 7) you DO have autocomplete even for objects returned by Zend_Registry::get().

How to access libraries inside a controller?

I'm building a small framework that I can use for repeated mundane stuff on future small projects.
I'm stuck on the best way to access libraries from inside a controller. I originally implemented a system similar to CodeIgniter's whereby my main controller class is basically a super object and loads all the classes into class variables which are then accessed by extending the controller and doing like $this->class->method()
I find that a little ugly, though. So I thought of just loading each class individually on a per-use basis in each controller method.
What's the best (cleanest) way of doing this?
To only ever have one instance of each class, you could create a simple service container.
class ServiceContainer
{
protected $services;
public function get($className)
{
if (!array_key_exists($className, $this->services)) {
$this->services[$className] = new $className;
}
return $this->services[$className]
}
}
Then create one ServiceContainer instance per application. Inject the container into all of your controllers and use
public function someAction()
{
$this->container->get('Mailer')->send($email_data);
}
Simple example, and obviously needs a lot of work to make useable (for instance autoloading needed and handling of file paths for ease of use, or easier way to add services without getting them, etc).
I dont like the way CodeIgniter does it. Its never seemed right to me. I favor an auto loading class pushed onto the spl_autoload stack. And then just calling the class as normal like:
$class = new SomeClass();
PHP provides autoload functionality with SPL and spl_autoload (and related functions). You can register a custom autoloader for your library code.
For the shared functionality handled by your application, have you considered the Front Controller design pattern?

codeigniter - best practice library with many classes

I'm building a library for our CodeIgniter app, but it requires many classes (currently I'm at 12).
Is there a best practice for packaging these many clients into one library. So I can just make one call to load it. i.e:
$this->load->library('soaplibrary');
Thanks!
As Summer points out, they have handled this situation somewhat elegantly in CI 2.0 with the concept of Drivers.
With a Driver, you actually create a subdirectory within your 'libraries' directory that contains your 'super' class, and another directory for 'child' classes. Better visual representation of the structure...
This was taken from Here.
and once you have constructed your library, here is the documentation on how to use it.
In CI 2.0, there are drivers to handle this situation. Good luck!
In CodeIgniter 3.1.9 when you load a library file, all classes in this file are included into code.
Let's say in soaplibrary.php you have
class SoapLibrary {
public function someMethod(...
class Test {
public function anotherMethod(...
In your controller you can do:
$this->load->library('soaplibrary');
//now on you can do
$this->soaplibrary->someMethod();
//but also
$test = new Test();
$test->anotherMethod();
CodeIgniter attempts to call the constructor of class SoapLibrary, hence a class with that name must be in there.

Categories