Smarty Forum Index Smarty
The discussions here are for Smarty, a template engine for the PHP programming language.

Base Path
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Smarty Forum Index -> Smarty Development
View previous topic :: View next topic  
Author Message
idle0ne
Smarty Rookie


Joined: 16 Oct 2003
Posts: 22
Location: Vermont

PostPosted: Fri Oct 17, 2003 12:22 pm    Post subject: Base Path Reply with quote

Hello Everyone,

i am trying to use smarty and i need to be able to dynamically get the base path for a site. Here is my directory structure

/index.php
/includes/global.php
/includes/all class files here
/smarty/all smarty stuff here

ok what i am doing is in the global.php i have these lines of code

define('INCLUDE_DIR', str_replace('\', '/', dirname($_SERVER['PATH_TRANSLATED']).'/includes'));
define('SMARTY_DIR', str_replace('\', '/', dirname($_SERVER['PATH_TRANSLATED']).'/smarty'));

however i can't seem to get them to work, at this time they do not work, but when they did they would work either using http://localhost and then not work for http://localhost/forum/

the reason it wouldn't work in /forums/ is because it would be setting the constant to

c:\\inetpub\\wwwroot\\forums\includes and that folder doesn't exist

i have tried this using __FILE__ but that doesn't seem to work either, can anyone tell me if there is a way to get c:\inetpub\wwwroot\includes and c:\inetpub\wwwroot\smarty
no matter what directory i am in and this will also be installed on linux so it can't have anything hard coded.

Any help would be appreciated..
Back to top
View user's profile Send private message Visit poster's website AIM Address
alan
Smarty Regular


Joined: 17 Apr 2003
Posts: 43

PostPosted: Sun Oct 26, 2003 11:22 am    Post subject: Reply with quote

In all my sites, I include from every page a 'prepend' file which sets up the various paths:

index.php
Code:

include "../include/prepend.php";


prepend.php
Code:

function path( $filename = null )
{
   static $cache;

   if (!isset($cache))
      $cache = array();

   if (is_null($filename))
      $filename = __FILE__;

   if (!isset($cache[$filename]))
      $cache[$filename] = str_replace("//", "/", str_replace("\\", "/", dirname(realpath($filename))) . "/");

   return $cache[$filename];
}

function root( )
{
   static $cache;

   if (!isset($cache))
      $cache = path(path() . "..");

   return $cache;
}


Using these functions, I can now use the following constructs:

index.php
Code:

include path() . "filename.php"; // relative to where prepend.php is
include root() . "filename.php"; // relative to my root path
include root() . "lib/smarty/smarty.class.php"; // relative to the root path.


Note that I always uses unix style slashes as they work perfectly on Windows (Win98/WinNT/WinXP at least).
Back to top
View user's profile Send private message
idle0ne
Smarty Rookie


Joined: 16 Oct 2003
Posts: 22
Location: Vermont

PostPosted: Sun Oct 26, 2003 8:56 pm    Post subject: Reply with quote

Wow,

thanks for that bit of code, i am not sure i understand it 100% buyt i am gonna analyze it and try Smile
Back to top
View user's profile Send private message Visit poster's website AIM Address
alan
Smarty Regular


Joined: 17 Apr 2003
Posts: 43

PostPosted: Mon Oct 27, 2003 8:31 pm    Post subject: Reply with quote

Sorry for the lack of comments Embarassed, hopefully I can clarify these functions a little...

path() - Returns the fully qualified pathname of the passed filename. Returns the pathname in unix style (i.e. / instead of \, which does work on windows as well as unix). If you don't pass a filename, path() returns the path of the file which declared the function.

root() - Returns the fully qualified pathname of your site's root folder. Note that this assumes you declare this function in a sub-folder of the root folder - say include/prepend.php

Both path() and root() cache the results for speed as I tend to use them rather a lot throughout my sites.
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Oct 27, 2003 10:32 pm    Post subject: Reply with quote

That's pretty slick. My strategy is probably a little bit more convoluted but it avoids function calls by sticking to good old constants and avoids prepends by using a calling convention. I think that even with the lazy reads in alan's code, the constants are just faster--and cleaner.

I don't auto-get the base path because I trust nothing. This could easily be modified to work with the base path, though. Never-the-less, this approach does require some admin maintenance--but I just write scripts to deal with that.

BOOTSTRAP: localize/MYSITE.inc
Each website is given its own special setup file that is named after the website and goes in a directory called "localize" which is in the php include_path.
[php:1:ed0010232f]<?php
define ('MY_ROOT_DIR', '/usr/local/MYSITE/');
require_once MY_ROOT_DIR . '_autoload.inc';
?>[/php:1:ed0010232f]
At minimum, this file sets up a constant MY_ROOT_DIR which points to the base directory for the project. Control is then passed to the local project's bootstrap file (MY_ROOT_DIR.'_autoload.inc'). Note that you can do a variation of alan's code to do checks here to make sure that the localize file for the site is only called from legal locations, for example, from a script that exists in the proper path for the site.

There is not much to the _autoload.inc either--it basically sets up local constants for your app and is useful for autostarting any global scripts for the site or creating global objects, auto-serialization, basic security, etc.

The following is an example with the following directory layout:

MYSITE/
admin/ app/ configs/ data/ libs/ plugins/ templates/ tmp/ www/

I mount the website root at www/ (typically: http://myserver/MYSITE/ or just http://MYSITE/ as appropriate) so the other directories in the project are not accessible via the website. Note that www/ can actually be located anywhere in the existing webroot if that serves your purposes better. app/ is for local php files, libs/ is for 3rd party libraries (eg: libs/smarty/) tmp/ contains cached/ and compiled/ while admin/ contains local protected scripts.

MY_ROOT_DIR.'_autoload.inc'[php:1:ed0010232f]<?php

define ('MY_APP_DIR', MY_ROOT_DIR.'app/');
define ('MY_LIBS_DIR', MY_ROOT_DIR.'libs/');
define ('MY_WWW_DIR', MY_ROOT_DIR.'www/');
define ('SMARTY_DIR', MY_LIBS_DIR.'Smarty/');

require_once MY_APP_DIR . 'util.inc';
?>[/php:1:ed0010232f]

any site page
Finally, any page from within the www/ directory that needs to be localized to the site simply starts with:
[php:1:ed0010232f]require_once 'localize/MYSITE.inc';[/php:1:ed0010232f]
When I need to load some code, I simply use one of the constants:
[php:1:ed0010232f]require_once MY_APP_DIR.'App.inc';[/php:1:ed0010232f]
I'm not showing how I setup my constants for the tmp directory, though Smile

...but otherwise, that is basically all there is to it!

NB. I did hide a few details to make it more readable. EG: In my production code, I tend to use the PHP constant DIRECTORY_SEPARATOR instead of "/".

NB. One last note: this setup implies that any call to a website page (some script in www/) that localizes to the site then does at least two more includes (though of small files). Thus, your performance will be best if you are using some PHP accelerator.
Back to top
View user's profile Send private message
alan
Smarty Regular


Joined: 17 Apr 2003
Posts: 43

PostPosted: Tue Oct 28, 2003 8:46 pm    Post subject: Reply with quote

Nicely done boots - I agree that using defines would be faster even though it requires some admin maintenance (albeit not very often). I originally used defines, but decided to go function calls primarily to limit the amount of junk in the global namespace - and yes, my path() and root() functions are normall static functions within a standard api class.

BTW, why use DIRECTORY_SEPARATOR at all? Windows copes with / just fine...

I'm also interested in how you protect your localize file - Fortunately not something I would normally need as my scripts invariably lie outside of the document root but...
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Oct 29, 2003 1:37 am    Post subject: Reply with quote

alan wrote:
Nicely done boots - I agree that using defines would be faster even though it requires some admin maintenance (albeit not very often).
Thanks for the nice comment, alan Smile

alan wrote:
I originally used defines, but decided to go function calls primarily to limit the amount of junk in the global namespace - and yes, my path() and root() functions are normall static functions within a standard api class.
It's funny because I used to use static class methods as well for this Smile I am using my current approach so as to not limit admin possibilities. For example, the admin now has a scriptable back-door into the site through localize/ without actually touching the site code. Particularly, if you have a project with several responsibility layers, the layered start-up gives you a quick way to delineate them.

I have to agree about polluting the global namespace, but I also think if it is done thoughtfully and with minimal impact that it can be a good thing. In my example, all defined constants are of the type MY_* which limits the chance of collisions. You can also choose to reserve particular prefixes depending on which startup layer defines the constant.

alan wrote:
BTW, why use DIRECTORY_SEPARATOR at all? Windows copes with / just fine...
Well, that's not true as Windows chokes on '/' but PHP manages it okay, at least in current versions. To be honest, I'm not sure about the best practice for this but if you pass paths to native system tools from your script, they will have to be in the native format. I'm interested to hear what others think is most appropriate. It drives me a bit around the bend.

alan wrote:
I'm also interested in how you protect your localize file - Fortunately not something I would normally need as my scripts invariably lie outside of the document root but...
Just to be clear, localize/ exists in the PHP include path and the only directory I expose to the webroot is www/. You are correct that localize/ requires protection, though. There are two issues:

1) particular scripts in lozalize/ need to be accessible only from certain webroots:
- I usually do this by checking against something like $_SERVER['REQUEST_URI'] and I might check for the requested host name as well on virtual servers. Depending on your configuration, you may also achieve this using file group/user permissions.

2) the scripts themselves should not be viewable:
- encoding (for example, using MMCache) is usually the easiest thing to do here.

You can also force pages to automatically localize by creating an appropriate prepend that directs to localize/$site.inc or something similar.

Again, constants aside, this overall approach is somewhat admin centric, though it keeps things fairly neat for the developers. It sort of expects your admin to create or be given proper management scripts. This is why I asked about pwee sometime ago.

Cheers.
Back to top
View user's profile Send private message
tk
Smarty Regular


Joined: 31 Oct 2003
Posts: 49
Location: London, UK

PostPosted: Wed Nov 05, 2003 2:21 am    Post subject: Reply with quote

boots wrote:
alan wrote:

BTW, why use DIRECTORY_SEPARATOR at all? Windows copes with / just fine...


Well, that's not true as Windows chokes on '/' but PHP manages it okay, at least in current versions. To be honest, I'm not sure about the best practice for this but if you pass paths to native system tools from your script, they will have to be in the native format. I'm interested to hear what others think is most appropriate. It drives me a bit around the bend.


/ has always seemed to work fine for me on windoze.. from PHP.. Perl.. console.. etc =)

For these "root dir" definitions etc, I normally use the dirname() function:

[php:1:c3f471bfda]define('SITE_ROOT', dirname(__FILE__));[/php:1:c3f471bfda]

and then a "relative" path to SITE_ROOT. Again, never had a problem either on windoze nor Unix for this method.. and nothing is fixed beyond your own current Web site directory structure.

I also build a 'registry.php' file that I use for including includes (for the likes of functions) and libs (classes). Such as:

[php:1:c3f471bfda]<?php
/* Load libs... */
$libs = array(
'Mysql',
'Sessions',
'Smarty/Smarty'
);
foreach ($libs as $lib) {
@require_once(dirname(__FILE__) . "/../lib/$lib.class.php");
}
?>[/php:1:c3f471bfda]

etc. This way, it's really easy to add / remove / temp comment out any library class or the likes for whatever reason (note: all 3 of these are actually stored within the global includes dir, but used as an example for "local to site" inclusion).

I guess I took this approach as there's less keystrokes involved for loading many libs etc =P
_________________
Certified Code Junkie(tM)
Copyleft (L) two thousand and now, tk
Back to top
View user's profile Send private message Visit poster's website
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Wed Nov 05, 2003 3:01 am    Post subject: Reply with quote

tk wrote:
/ has always seemed to work fine for me on windoze.. from PHP.. Perl.. console.. etc =)

console? I suspect you mean something other than the native command prompt. I love Cygwin Smile but I never used a Cygwin compiled version of PHP on windows--is there a different behaviour there?

This is what I'm getting at:[php:1:9659436fc6]<?php
$a = 'c:/';
echo shell_exec("dir $a"); // does not work on windows (or anywhere!)

$a = 'c:\\';
echo shell_exec("dir $a"); // works on windows
?>[/php:1:9659436fc6]
Same goes for relative paths. It seems that this situation only arises when trying to interface with native tools, so perhaps it is only a system scripting issue which can otherwise be ignored.

tk wrote:

I also build a 'registry.php' file that I use for including includes (for the likes of functions) and libs (classes). Such as:
[..snip..]
etc. This way, it's really easy to add / remove / temp comment out any library class or the likes for whatever reason (note: all 3 of these are actually stored within the global includes dir, but used as an example for "local to site" inclusion).

I guess I took this approach as there's less keystrokes involved for loading many libs etc =P

Nice! I use this a lot for loading libs myself Smile I think you are completey correct about that format (array) making it easier to edit. As a lazy coder who sometimes cuts and pastes too often, I have an additional tip in regards to the format of the array. I haven't run into anyone else who does this, so I'll understand if you think it is atrocious; I think it is very nifty:[php:1:9659436fc6] $libs = array(
'Mysql'
, 'Sessions'
, 'Smarty/Smarty'
);[/php:1:9659436fc6]I do the same thing with SQL columns. I find it is much less prone to syntax errors caused by re-arrangements leading to dangling (or missing) commas.

Cheers!
Back to top
View user's profile Send private message
Marek_mar
Smarty n00b


Joined: 16 Nov 2003
Posts: 3

PostPosted: Mon Nov 17, 2003 6:57 pm    Post subject: Reply with quote

Is there something special about the smarty files becouse I can require a test file (prepend.php) but get an erroe requireing Smarty_Compiler.class.php. Both files are in the same folder and called from the same file. What am I doing wrong?
Back to top
View user's profile Send private message
tk
Smarty Regular


Joined: 31 Oct 2003
Posts: 49
Location: London, UK

PostPosted: Mon Nov 17, 2003 7:07 pm    Post subject: Reply with quote

boots wrote:
tk wrote:
/ has always seemed to work fine for me on windoze.. from PHP.. Perl.. console.. etc =)

console? I suspect you mean something other than the native command prompt. I love Cygwin :) but I never used a Cygwin compiled version of PHP on windows--is there a different behaviour there?


Was actually referring to the 'cmd.exe' as "console".. that'll teach me to over-generalise =)

Quote:
This is what I'm getting at:[php:1:ca7b839f42]<?php
$a = 'c:/';
echo shell_exec("dir $a"); // does not work on windows (or anywhere!)

$a = 'c:\\';
echo shell_exec("dir $a"); // works on windows
?>[/php:1:ca7b839f42]
Same goes for relative paths. It seems that this situation only arises when trying to interface with native tools, so perhaps it is only a system scripting issue which can otherwise be ignored.


Hmm.. whenever using the cmd.exe console, I always used to use commands such as:

Code:
> cd /WINNT/system32


for example. '/' would be assumed as the root directory of the current drive.

Quote:
Nice! I use this a lot for loading libs myself :) I think you are completey correct about that format (array) making it easier to edit. As a lazy coder who sometimes cuts and pastes too often, I have an additional tip in regards to the format of the array. I haven't run into anyone else who does this, so I'll understand if you think it is atrocious; I think it is very nifty:[php:1:ca7b839f42] $libs = array(
'Mysql'
, 'Sessions'
, 'Smarty/Smarty'
);[/php:1:ca7b839f42]I do the same thing with SQL columns. I find it is much less prone to syntax errors caused by re-arrangements leading to dangling (or missing) commas.

Cheers!


This actually makes logical sense to me as the commas are more clearly defined etc.. does look "strange" at first glance (because I'm used to 'value,') but would seem an easy method to read and understand =)



Regards,

tk
_________________
Certified Code Junkie(tM)
Copyleft (L) two thousand and now, tk
Back to top
View user's profile Send private message Visit poster's website
tk
Smarty Regular


Joined: 31 Oct 2003
Posts: 49
Location: London, UK

PostPosted: Mon Nov 17, 2003 7:09 pm    Post subject: Reply with quote

Marek_mar wrote:
Is there something special about the smarty files becouse I can require a test file (prepend.php) but get an erroe requireing Smarty_Compiler.class.php. Both files are in the same folder and called from the same file. What am I doing wrong?


Marek,

Forgive me if I'm wrong.. but I thought the Smarty_compiler.class.php file was called _from_ Smarty.class.php itself, thus meaning you don't need to =)

Try:

[php:1:2593e6d3e4]<?php include('Smarty.class.php');?>[/php:1:2593e6d3e4]

instead and see what happens =)

Please feel free to correct me anyone =)



Regards,

tk
_________________
Certified Code Junkie(tM)
Copyleft (L) two thousand and now, tk
Back to top
View user's profile Send private message Visit poster's website
Marek_mar
Smarty n00b


Joined: 16 Nov 2003
Posts: 3

PostPosted: Mon Nov 17, 2003 7:16 pm    Post subject: Reply with quote

Sorry im stupid. It is Smarty.class.php. Embarassed
Back to top
View user's profile Send private message
boots
Administrator


Joined: 16 Apr 2003
Posts: 5611
Location: Toronto, Canada

PostPosted: Mon Nov 17, 2003 7:25 pm    Post subject: Reply with quote

@tk: you are correct about the compiler class--except in two cases: 1) it is the only class he wants; 2) there are no templates processed that require compilation (smarty only loads the compiler class on as-needed basis).

tk wrote:
Hmm.. whenever using the cmd.exe console, I always used to use commands such as:
Code:
> cd /WINNT/system32

for example. '/' would be assumed as the root directory of the current drive.

I severely doubt that. Going back to the initial days of DOS, CMD.exe and its predecessors have never accepted the forward slash as a directory delimiter. Indeed, it is used to denote parameters in the windows world. Look at it this way tk, you are at the point that your FreeBSD usage has utterly and completely erased your memory of windows--not too regretable Wink

Finally, tk, since I continually harass you about your signature line, can you please copyleft your current one? Tee Hee.
Back to top
View user's profile Send private message
tk
Smarty Regular


Joined: 31 Oct 2003
Posts: 49
Location: London, UK

PostPosted: Mon Nov 17, 2003 7:55 pm    Post subject: Reply with quote

boots wrote:
@tk: you are correct about the compiler class--except in two cases: 1) it is the only class he wants; 2) there are no templates processed that require compilation (smarty only loads the compiler class on as-needed basis).


Thanks for that boots.. interesting info (that I hadn't obviously read in the "fine" manual) =)

Quote:
tk wrote:
Hmm.. whenever using the cmd.exe console, I always used to use commands such as:
Code:
> cd /WINNT/system32

for example. '/' would be assumed as the root directory of the current drive.

I severely doubt that. Going back to the initial days of DOS, CMD.exe and its predecessors have never accepted the forward slash as a directory delimiter. Indeed, it is used to denote parameters in the windows world. Look at it this way tk, you are at the point that your FreeBSD usage has utterly and completely erased your memory of windows--not too regretable ;)


I stand corrected, heh =)

I just had it tested for me.. would seem I used to just ignore the drive letter and use:

Code:
> cd \WINNT\system32


As you say though.. at least I've been brainwashed in the right direction =D

Quote:
Finally, tk, since I continually harass you about your signature line, can you please copyleft your current one? Tee Hee.


LOL!

Will do ;)
_________________
Certified Code Junkie(tM)
Copyleft (L) two thousand and now, tk
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Smarty Forum Index -> Smarty Development All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP