Archive

Archive for the ‘php’ Category

using java style import to include javascript files

May 23rd, 2009 admin No comments

I had used a function and a little bootstrapping trick to solve my problem with including files in PHP and I was happy with it.
But recently while working on a project that has a heavy javascript codebase, I started having trouble managing  all javascript file imports and all those script tags made pages look really ugly.
And also I really longed for java’s clas importing capabilities in javascript such that I could import a single file based on package name or I could import a whole package.
Since some of the pages I’m working requires over 15 script imports, some third-party libraries and some of our own files.
And importing scripts one by one suffers from latency problems as it increases page load time and can contribute to user annoyances.
So I longed for  java’s style of package and class  import and  decided to try my hand on writing some script to emulate imports based on packages.

I jsut used the  similar principle I used with php, but the problem is importing all files in a package isn’t possible in javascript because  javascript cannot read files form disk let alone iterate through a folder and read file content.
For that there was nothing I could do except use some server-side help.

here’s the js file code with  function for importing js file and js files contained in a package(folder).


//create namespace to aviod any present/ future  variable/object/funciton conflicts

if (typeof Anzaan == "undefined" || !Anzaan) {

Anzaan = {};
}

// array to hold all imported files so as not to import them twice
Anzaan.imports = [];

//server side URL for loading whole package content
Anzaan.packageLoaderURL='/Framework/packageLoader/';

//set the base folder for importing files
Anzaan.importBase='js/';

/**
* import a class using the java naming syntax for a class name.
*@param module the module to import
*@param  config object literal with two properties-
* config.packageLoaderURL - the server url for loading all files in a folder/package as a stream
* config.importBase - the base path for importing files
* use config only if necessary otherwise just modify Anzaan.packageLoaderURL and Anzaan.importBase
* of course you can use a different namespace or just use no namespace
*/
function Import(module, config) { //com.anzaan.framework.*

if(config){
if(config.packageLoaderURL)
Anzaan.packageLoaderURL=config.packageLoaderURL;

if(config.importBase)
Anzaan.importBase=config.importBase;
}

// if this import has already happened, don't bother,
if (Anzaan.imports[module] )
return ;

var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';

var src='';
var folders=module.split(".");
for(var i=0;i<folders.length;i++){

if(folders[i].indexOf('*') < 0)
src+=folders[i]+"/";
}
src=src.substring(0,src.length-1);//remove the last slash

if (module.indexOf('*') < 0) { //if not package import
src=Anzaan.importBase+src+".js";
script.src=src;

} else {
script.src=Anzaan.packageLoaderURL+"?package="+Anzaan.importBase+src;
}

head.appendChild(script);
Anzaan.imports[module] = module;
}

The config parameter is optional. It shouldn’t really be used unless you want to load files from locations other tahn the default location of your application and want to use other URL for loading script files.

Just modify the global variables Anzaan.packageLoaderURL and Anzaan.importBase to set the base path and the serverside URL for loading scripts in folder.
And of course rename Anzaan to something more meaningful for you.

Now on the server side here’s a simple php script that services the script file requests.
It loads contents from js flies that reside in folder specified by ‘package’  variable.

packageLoader.php
————————————————

<?php

$folder=$_GET["package"]; // get the package name

$dir = opendir($folder); //open directory

while (($file = readdir($dir)) !== false) {
if (strrpos($file, '.js')) {

echo file_get_contents($folder.'/'.$file); //printout the content of file

}
}

?>

and here’s a Java Servlet for doing the same thing:

JSPackageLoaderServlet.java

public class JSPackageLoaderServlet extends HttpServlet {

@Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {

response.setContentType("text/plain");
ServletOutputStream out = response.getOutputStream();

String packagePath = request.getParameter("package");

StringBuilder sb = new StringBuilder();

File myDir = new File(getServletContext().getRealPath(packagePath));
if (myDir.exists() && myDir.isDirectory()) {
File[] files = myDir.listFiles();
for (int y = 0; y < files.length; y++) {

String line = "";
BufferedReader in = new BufferedReader(new FileReader(files[y]));

while ((line = in.readLine()) != null) {
sb.append(line);

}

}

}
out.print(sb.toString());
}
}

Here’s the usage:

Import('anzaan.event.EvenHandler');

using java style import to include files in php

May 23rd, 2009 admin No comments

I really like the way java handles packages and the way it import classes based on package description.
Last year while  developing  a php  based CMS application, I faced shitload of trouble when it came to file including.
The problem was if I was making a normal page request, realtive URL’s  worked this way:
“../framework/service/DataService.php” and I used

inlcude_once("../framework/service/DataService.php")

to include a script.

But for accessing files using AJAX request for some weird reason I had to use single dot at the start of the path – instead :

inlcude_once("./framework/service/DataService.php").
<pre>

And as such I hit a kind of brick-wall because say I have a script that I need to accesss normally and via AJAX call, and the file included some other files, then what do i do?  I either have to put duplicate includes one with single dot and one with double dots at the begining and there was no way I was going to do such stupid things.
So I set out to solve this truely annoying problem.
I found some scripts in the net that did what I needed, almost….
I stole a script from the net and modified to suit my need. And since then my life has been so easy  you won’t believe.
with that scrip all I had to do was import files just the way I do in good old Java.
Even better I started using the same conventions as java.

So my imports look like this nowaday:

import("com.barahisolutions.cms.model.MenuPermission");

and if I want to import all files in a package I use the same comvention as java and
and use ‘*’ instead of file name.

import("com.barahisolutions.cms.model.*");

The code looks very neat and all my scripts are neatly organised in packages and life has been good ever since.

I divide all my scripts into two main folders. One classses to hold all project specific classes and one lib to hold all my library files. and i set these folders as include path using ini_set. I just have to do one inculde_once statement to include the file that has the import function and for the rest I use import function to include the required classes and files.

Of course its not all that simple. Because relative path to the classes and lib folders may be different depending on where the page/script that uses the import function is located. so instead of using ini_set in every place I want to use the import function, I used a little trick to solve the problem. I created one more function bootstrap and used it to calculate the relative path to the classes and lib folder before doing the ini_set.
From there all I have to do is include this file as a bootstrap for my applicaitons and I was ready use the import function for all my file include needs.

Here’s a stripped down version of the bootstrap file with the required funcitons.

bootstrap.php.

// array to keep track of all the already included files
$_imports = array();

// set the include path to the classes and lib folder
function bootstrap(){

//get the current script's path  relative to the applicaiton root folder
$rel_paths=explode('/',$_SERVER['SCRIPT_NAME']);
$path="";

// calculate the depth relative to the root folder
if(sizeof($rel_paths)>2){
for($i=2; $i< (sizeof($rel_paths)-1); $i++){
$path.="../";
}
}
// set the include path for our application's library and class files
ini_set('include_path', $path.'lib' . (DIRECTORY_SEPARATOR == '/' ? ':' : ';') .
$path.'classes'.(DIRECTORY_SEPARATOR == '/' ? ':' : ';') );

}
//just execute the funciton.
bootstrap();

/**
* Import a class using the java naming syntax for a class name.
* use * to include all files in a package
* @param string $name The name of the package to be imported
* @return void
*/

function import($import) {

// if this import has already happened, don't bother,
if (isset($_imports[$import]) )
return true;

// seperate import into a package and a class
$lastDot = strrpos($import, '.');
$class = $lastDot ? substr($import, $lastDot + 1) : $import;
$package = substr($_import, 0, $lastDot);

// create a folder path out of the package name
$folder = '' . ($package ? str_replace('.', '/', $package) : '');
$file = "$folder/$class.php";

if ($class != '*') {
// add the class and it's file location to the imports array

include_once($file);

} else {
// add all the classes from this package and their file location to the imports array
// first log the fact that this whole package was alread imported
$_imports["$package.*"] = 1;
$dir = opendir($folder);
while (($file = readdir($dir)) !== false) {
if (strrpos($file, '.php')) {
include_once("$folder/$file");
}
}
}

$_imports[$import] = $import;
}

That’s all that is required.

Now if you include this file, you  can simple use the import statement to import files that you need in your script.

samle usage: (its assumed that the file that actually uses MenuController class has already included the bootstrap.php file.
class MenuController.php

//import all the required classes
import('com.barahisolutions.cms.model.Menu');
import('com.barahisolutions.cms.dao.MenuDAO');
import('com.barahisolutions.cms.dao.UserPermissionDAO');
import('com.barahisolutions.framework.menu.VerticalMenu');

class MenuController {

// your business logic here

}
Categories: Software Development, php Tags: