Integrating external scripts with Zend Framework - php

What is the best way to integrate an external script into the Zend Framework? Let me explain because I may be asking this the wrong way. I have a script that downloads and parses an XML file. This script, which runs as a daily cron job, needs to dump its data into the database.
I am using Zend Framework for the site which uses this script and it seems to me that it would be best to use my subclassed model of Zend_Db_Abstract to do the adding and updating of the database. How does one go about doing this? Does my script go in the library next to the Zend Components (i.e. library/Mine/Xmlparse.php) and thus have access to the various ZF components? Do I simply need to include the correct model files and the Zend DB component in the file itself? What is the best way to handle this sort of integration?

Yes, you should put your own classes that maybe inherit Zend Framework classes or add further classes into your own folder next to the Zend Framework folder in library.
When you have Zend_Loader s auto-loading enabled, the class names will automatically map to the class you created, e.g.:
My_Db_Abstract will map to My/Db/Abstract.php .

In your library directory you should have your own library next to the Zend library folder. Whatever you call it (Mylib, Project, ...) you should include it into the Zend Autoloader and that's done as follows:
require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->registerNamespace('Project_');
$loader->setFallbackAutoloader(true);
if ($configSection == 'development')
{
$loader->suppressNotFoundWarnings(false);
}
In order for you library to integrate nicely with ZF and the Autoloader you should stick to the ZF naming conventions. This means two things:
if you extend an existing ZF class, replicate the ZF folder structure so that your file has the same path and name except for the library name. E.g. /library/Zend/Db/Abstract.php => /library/Project/Db/Abstract.php.
if you write your own classes, still stick to the ZF naming conventions for the autoloader to find them.

I just came across something that may be germane to this question. This IBM developerWorks article.
The author recommends simply creating a scripts folder in the ZF hierarchy and the using it as one normally would within ZF (though he does set the ini path and call autoload). Is it that simple? Does simply being in the hierarchy of the framework and including the path and autoloader grant your script access to all of the goodies?

I'm not 100% sure what you're trying to ask but I will try to help. If at any point you add a reference to "/path/to/zend/framework" into your php include path then you have in essence enabled the Zend Framework. From there if you do:
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();
Then at any point in your script you can pretty much just create new Zend Framework objects and Zend_Loader will handle the rest.
One of the big things about the Zend Framework though is not forcing you to do things a certain way. That's why sometimes there are several ways to accomplish the same thing. So, if you feel you need to make your script use the Zend Framework just for the sake of doing so this is not really necessary. But if you think it may improve your script in some way then go for it.

I usually put custom stuff that I think could be used across projects in a custom folder in the library. So I have a library/Ak33m folder that has scripts that may be outside of the framework.

As a ZF noob myself, I think I understand some of what the OP is trying to figure out. So, I'll just explain a bit of what I understand in the hope that it is helpful either to the OP (or more likely, to a future reader, since the original question is so old and I imagine that OP is now a ZF guru).
I understand that ZF claims to be largely "use at will", so that you need no buy into an entire structure, like the Zend_Application, the Zend_Bootstrap class, the entire MVC approach, etc.
Further, I understand conventions for class naming and file locations that enable easy autoloading. Ex: class App_Model_User resides in a folder App/Model/User.php
I think what can be potentially confusing is that in the script context, where you have not yet
done the .htaccess magic that pushes all request to public/index.php
set your APPLICATION_PATH and include paths in public/index.php
created your Application or Bootstrap object tied to a config file
it can be a little bit unclear how best to avail yourself of most of the ZF goodness we get in that context and want in another context.
I guess my answer to the original question would be that the usual entry point sequence of
http request -> .htaccess -> index.php -> config
sets up much of our environment for us, we would need to duplicate some of that for different entry path.
So, for your script, my first instinct would be to create a common include file that mirrors much of what happens in index.php - set the include paths, the APPLICATION_PATH, instantiates and calls a bootstrap, and then does your script-specific processing.
Even better, it might be desirable to create a single entry point for all your scripts, like we do in the http/web context. Extend Zend_Application for your own script purposes so that $application->run(); no longer starts up the MVC router-controller-dispatch processing, but rather does your own stuff. In that way, this single script entry point would look almost identical to the web entry point, the only difference being which application object gets instantiated. Then pass the name of your desired Application class as a command line parameter to the script.
But here I confess to being less confident and just throwing out ideas.
Hope all this helps someone. It actually helped me to write it all down. Thanks and cheers!
Update 2009-09-29: Just ran across this article: Using Zend Framework from the Command Line
Update 2009-11-20: And another article: Cron jobs in Zend Framework | GS Design
Update 2010-02-25: Easy command line scripts with Zend Application - David Caunt

Related

php - Autoloader implementation, preload all the classes

I'm new to php and inherited a website project with hundreds of pages, all procedural (when I do a text search of the files, there isn't even a function definition anywhere). I'm coming from the c# and Java worlds. I'm looking for a way to incrementally add OOP. (They want me to update the front end and I am trying to convince them of fixing the backend at the same time and they don't want to use a framework (dammit)).
While looking into autoloader... Well, here's my understanding. It's a method of registering folders where classes are stored and when you instantiate a class, trait, etc. it searches the folder based on the class/filename/namespace and loads the appropriate definitions.
I have a few questions:
Does autoloader search the folder and load the appropriate definitions on every page lifecycle (or does it cache them)?
Pre-loading:
Is there a way to use autoloader, or some alternative, to pre-load ALL class definitions into memory and make them available across all sessions?
If so, when updating class files, how would I tell this mechanism to reload everything to memory when I make changes to class files?
UPDATE TO QUESTIONS:
Thank you both for your answers and it helps a little, but... I do have a bad habit of posing the wrong question(s) on StackOverflow.
The thing I want to avoid is slowing down pages by adding classes. So let's say I add a library and register the paths with autoloader. A page instanciates a class with multiple dependencies. Let's say that the dependency graph includes 15 files. For each request lifecycle, the server loads the page and 15 other files just on that one page.
Since I am coming from compiled languages, I feel a little strange not loading these classes into memory. All the classes together should not be over say 5MB.
(Or maybe I should just create a RAM Disk and copy all the files in there on boot and just have a symlink?)
Auto loaders in PHP are lazy. When PHP encounters a the use of a class it doesn't know about, it will ask the registered autoloader (or chain of autoloaders) to go find it. It's the autoloader's job to figure out where to get the file the class is defined in and include it. Having some sort of convention for naming your classes and organizing your class files is key to having a useful autoloader, and several conventions have arisen in the PHP community, such as PSR-4.
Does autoloader search the folder and load the appropriate definitions on every page lifecycle (or does it cache them)?
The autoloader(s) is(are) called on every request, but only when the need to autoload a class arises.
Pre-loading: Is there a way to use autoloader, or some alternative, to pre-load ALL class definitions into memory and make them available across all sessions?
I don't believe so, but as the number of classes grow, this becomes more and more wasteful.
Welcome to the wonderful[citation needed] world of legacy PHP, I highly recommend you check out Modernizing Legacy Applications In PHP. It's like a strategy guide for getting from Mordor back to the Shire.
I think you may misunderstand the purpose of autoloading. It is simply instructions on what to do when your code calls for a class that PHP doesn't recognize. That's it. The autoloader just calls requires /path/to/classfile so that PHP will see the class.
Does autoloader search the folder and load the appropriate definitions
on every page lifecycle (or does it cache them)?
There is no caching across requests, so if you make a change to file, the next http request will incorporate those changes. It's just as if you changed any other instruction in your script, for example change echo 1 to echo 2
Pre-loading: Is there a way to use autoloader, or some alternative, to
pre-load ALL class definitions into memory and make them available
across all sessions?
There is no need for this. A well written autoloader has instructions for where to find any class, so loading all possible classes ahead of time is wasteful. If you're still running into undefined classes errors, you need to either improve the autoloader or place the class files in accordance with the current autoloader instructions.
If you really want to preload all your classes, use the auto_prepend_file setting in php.ini. The docs say
Specifies the name of a file that is automatically parsed before the
main file
Set it to an initialization script. In that script have something like:
//put all your class files in this folder
$dir = '/path/to/classes/folder';
$handle = opendir($dir);
//require all PHP files from classes folder
while (false !== ($item = readdir($handle))){
$path = $dir.'/'.$item;
if(is_file($path) && pathinfo($path,PATHINFO_EXTENSION)==='php')
require_once $path;
}
This is simplified. There is significant risk in just including all files in any directory into your script so I would not do this. You would also need to adjust this if you want to include files in subdirectories.
Basically, don't do this. Just have a good autoloader.
No one posted what I was looking for but it seems the best route is the OptCache that's prebuilt into php 5.5 and above (my client is using 5.3 so I didn't know about it).
https://github.com/zendtech/ZendOptimizerPlus
The Zend OPcache
The Zend OPcache provides faster PHP execution through opcode caching
and optimization. It improves PHP performance by storing precompiled
script bytecode in the shared memory. This eliminates the stages of
reading code from the disk and compiling it on future access. In
addition, it applies a few bytecode optimization patterns that make
code execution faster.

Kohana classes and cascading file system

I'm just new to Kohana and its cascading file system.
From what I understand, using the cascading file system allows extending of core classes and making your module use the subclass in place of the original core class (kind of like monkey patching). What I don't quite understand is why we need to create blank sub classes and put all the logic on Kohana classes. It just seems like a hack and the duplicate classes makes it very hard to trace the calls.
Based from this doc on cascading file system, it will always check for application path first before modules, so is it possible to just completely overwrite the core classes with new versions on the application path? I'm not sure where the blank classes fit in here. An actual concrete example would help, thanks.
I've never really understood the need for the empty classes extending the core Kohana ones either, so you're not alone.
I have often created classes with the same names as the empty ones in order to overwrite them completely. This would be done in either the modules or the application folders.
Kohana compiles the files in this order: system -> modules -> application...so if you were to create a class with the same name within the application directory, it would overwrite any class with the same name in system or modules.
I often create re-usable classes within my own modules and then overwrite certain methods within other modules if I need them to behave slightly differently. You can specify the order that the modules load in by changing your bootstrap.php file in the application directory.
Pretty much the only reason I'm still using Kohana is because of the Hierarchical MVC (HMVC) capabilities, for which I can't seem to find equivalent functionality in any of the other frameworks. It is massively powerful and flexible, especially for large projects.
However, if you are only just getting in to Kohana you may want to reconsider, as it does seem to be a dying framework - the devs seem to have lost interest, which is a real shame because it has so much potential. It is a stable enough framework as it stands though.
Hope this helps you.

Can I use zend translate, date and cache as standalone class in my project?

I'm going to use Zend framework but just some tool of Zend like translate, date and cache. Can I use it as standalone class? My project has it own structure and I don't want use the whole Zend fw. If yes, which files should I include in my project? Is there a docs for using each Zend fw tool as standalone?
And remember, to use various Zend Framework components in another project, you just need to have the Zend library somewhere on your include_path. Copying the whole thing may seem overkill to use one component, but it's only disk space. Having those files there doesn't affect performance unless they are called upon. And this way, you don't have to sweat the dependencies, like Zend_Exception and its various component-specific subclasses.
So, for example, if you have a folder myapp/lib to contain your external libraries, you simply make sure that your include path contains that lib folder and copy the Zend folder into it as myapp/lib/Zend.
Then to use a component like Zend_Translate, all you have to do is something like the following:
require_once 'Zend/Translate.php';
$options = array(
// your options here
);
$translate = new Zend_Translate($options);
With some kind of autloading mechanism in place, you can avoid even the require_once call. Setting up autoloading is as easy as putting the following in some kind of common/bootstrap file:
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
Then any classes that follow the PEAR 1-class-1-file naming convention can be loaded without explicitly adding any require/include statements.
If disk-space really is a concern and you really don't want the whole Zend library, then you could investigate a packageizer, like Jani Hartikainen's Packageizer.
As an answer i could say Yes of course.
for example if u want to use Zend_Translate copy Translate.php and Translate folder to your library directory.
some times inside a class some other classes have been used. u have to copy them too. i find them by reading raised errors. ;)

PHP Bootstrapping Basics

I'm writing my first PHP app. Everyone talks about having a bootstrap.php to initialize your app. This makes sense and I've put together one that I'm happy with. There's two things I don't understand, and which no one seems to mention:
Where do I call my boostrap from? Do I include it in every page? Please tell me there's a better way...
How do I make it so my bootstrap is not called more often than needed? I assume it only needs to be called either at the start of the app or the start of a new session.
1: Generally the bootstrap is in the "application" directory. It is called from the "public" directory which is in the same level as application (not inside of it). The index.php inside the public folder should include the bootstrap.php and that is where your Document_Root should be set to (note you may need to change / add some include paths for it to work)
2: It should only be included once via the index.php file in the public folder. Just including it there should be enough, if it was done correctly.
Hope that helps.
It depends on your application architecture.
If your architecture is the good old "flock of php scripts" - PHP scripts called directly from the browser - then you'll be including it at the top of each script, one way or another.
Most developers (and frameworks) these days marshall all their requests through /index.php one way or another, usually with some URL rewriting going on to make nice, pretty URLs for users to see.
In this day and age, you should probably be doing the latter, or at least thinking about it. It leads to much better organization, and even more importantly, allows you to keep all your code outside of the web server's document root, which is a good security practice for several reasons that are outside the scope of this answer.
Have a look at the singleton pattern. You can double your bootstrap class as a resource container, e.g.:
$bootstrap = Bootstrap::getInstance();
$dbConn = $bootstrap->getPdoDbh();
You can include or require the file, or use the autoloader and make sure you have a call to instantiate the object on all your pages. You might even have a call to getInstance() on the bottom of the file, after the class definition.
Or you might use URL-based routing and have all your requests go through a single index.php file, like Zend Framework does. Or better yet, use Zend Framework.
This answer assumes you're doing OOP w/ PHP >=5, which really is the way to go.
One of the more elegant means by which to bootstrap a PHP application is to do so using Composer.
Almost every PHP library uses Composer nowadays, and requiring a Bootstrap.php-like file is as simple as:
"autoload": {
"psr-4": {
"Acme\\Rocket\\": "src/"
},
"files": ["src/Bootstrap.php"]
},
Note the second property, files. (The first, psr-4, is standard PSR-4 boilerplate auto-loading, and is included only to make the example more real-world.)
Including the bootstrap file in this way doesn't make the naive assumption that the PHP application is executed in a web-server context, via index.php, or similar; the application could very well be a command-line application (or both, like Laravel/Artisan). Bootstrapping via the auto-loader makes this distinction a non-issue.
it depends on what your bootstrap file does. If it's just a file that sets some ini settings and such to create a sane execution environment and establish a database connection, then simply including it with require_once in your scripts should be enough. If it's more of a single-point of entry then you can configure your server to filter all requests to it and have it dispatch to appropriate controller scripts.

Integrate Zend translator into my app

I wish to use the Translator classes of Zend framework in my app, but I don't want to include the whole framework. I grabbed the:
Locale folder
Translate folder
Exception.php
Loader.php
Locale.php
Registry.php
Translate.php
and copied into a custom folder named zend.translator.
Obviously I had to edit all them to adjust the includes to the new path...
Is this the way to go? I'm worried to have to edit all those files every time
a new version is released.
You could use the Zend_Loader_Autoloader to include only the classes from Zend Framework that you actually use. So you wouldn't have to check all the dependencies yourself. Just put the complete Framework on your include_path and the Autoloader will take care of it.
That way, you don't have to edit all the files. And autoloading can also give you a significant performance boost.
No. That's definitely not the way to go.
First of all, grab the whole framework. It does not add any overhead to your application besides occupying some more diskspace. Should you find out later you want to use some more components, you have everything in place already. ZF will not instantiate anything you don't use, so it won't impact performance to have the whole thing.
Second, don't change the files. ZF uses a naming convention you can easily use with autoloading. You can either use the Zend_Autoloader or roll your own. Basically, you just have to replace underscores in a filename with slashes and add '.php'.

Categories