Practice for storing files for classes - php

How do you store files that are to be used in a class.
For example the class file itself, then images used in that class. Or do you not use images in the class, but just return an output to the main page which in turn uses the images?
Recently I have been problems deciding whether to put the images used by a class in the global directory for the website or to create its own directory. This has just stricken me as I realised that a class such as for image manipulation or db manipulation can be used with other projects and it might be hard to try and find the related images in the global folder when migrating them.
So how do you store the images used in your classes? Or do you not return a printed output ever from a class?
The programming language used in this case is PHP.

Images are stored in a separate folder. For one, images must be reached by the client (browser), while the php files (except for a couple that are actually used in urls) can be kept outside the document folder.
The exact path of images and others files is stored in a configuration. This is just a small PHP file that keeps a list of settings. You should not hardcode the path to your images folder in your classes.

this is the structure I use
/includes
All the clases that you have
/logs
Log files
/public_html
All the pages visible to the user
/css
/javascript
/images
You can have a config.php file where you have something like this
define("LIB_PATH", '/includes/');
define("IMG_PATH", '/public_html/images/');
etc.
That gives you the benefit of using absolute paths in a short, simple and understandable way

Related

Including a folder and accessing images in the folder

I am trying to access to a folder using "include $path" inside a php file.
Inside the folder, it includes a lot of images, and in php, it includes many tags of img that accesses to the images inside the folder.
Is there any way to access to a image's path inside folder using "include"?
That is not what include is for.
Include let you include another piece of PHP (some class, some functions, whatever), it is not for 'accessing' some folder.
If you want to see the contents (images) of that folder, try scandir:
https://secure.php.net/manual/en/function.scandir.php
Also make sure your webserver has rights to read those files.
On *nix/apache this user is often named www-data (I have seen 'nobody' and 'apache' too as usernames). On IIS it is typically something like IUSR.

What filepath to use with ffmpeg_php?

I'm using ffmpeg-php to extract thumbnails from user uploaded videos for a site I'm building. Previously the videos were stored in a subdirectory of the directory containing the relevant php files and it worked fine. However I have now altered my directory structure and can't work out what filepath to supply ffmpeg_movie() with. The relevant files are:
/app/classes/class_lib.php
location of the class that calls ffmpeg_movie() and extracts/saves the thumbnail.
/app/upload.php
the php file that requires the above class, instantiates it and calls the relevant method.
And the videos are stored in:
/videos/encodes/
All those paths are relative to the sites public root (public_html). I have trieda number of different paths but keep getting a "cannot open movie file [Attempted video path]". I've tried paths relative to the site root /video/encodes/movie.mp4, relative to the executed php file ../video/encodes/movie.mp4, relative to the php class file ../../video/encodes/movie.mp4 and even the server root /srv/www/sitename.com/public_html/video/encodes/movie.mp4. No luck with any of them.
Any other ideas?
Server is Apache running on Ubuntu and directory permissions haven't changed since it was previously working (the encodes folder is globally readable)
I've ended up using the full url http://somesite.com/video/encodes/movie.mp4. It actually works, but it feels like the wrong way to do it. Unfortunately nothing else seems to work.
Still, if you're having the same problem then this is at least a working solution.

PHP url functions and subdomains

I have a website thenoblesite.com. It has some subdomains i.e.
download.thenoblesite.com
wallpaper.thenoblesite.com
etc.
Pages for subdomains are present in the main htdocs folder i.e.
httpdocs/download <- download.thenoblesite.com
httpdocs/wallpaper <- wallpaper.thenoblesite.com
Problem is that I am using $_SERVER['DOCUMENT_ROOT'] . '/css'; for css folder and other common folders(graphics, includes, script etc). However in the subdomain page download.thenoblesite.com, $_SERVER['DOCUMENT_ROOT'] will refer to download.thenoblesite.com root folder, not the main thenoblesite.com root folder where css,graphics and includes folders are present.
I have to place the same graphics, css and includes folders separately on all subdomains. Every time I update the website I have to copy the common folders to all subdomains folders.
Another related problem is that i have to use absolute linking for the large sized downloads folder for e.g. VLC media player I have to use thenoblesite.com/download/vlc.exe or i also have to duplicate the large size download folder in all subdomain folders. This method unnecessarily increases the website size , creates confusion when I update the site and doesn't look good programming practise. Is there any possible PHP solution so that i can use the same css, images, downloads and includes folder for all subdomains....
I am not sure if this is something you might be interested in, but you could always create a new subdomain and call it something like style.[domain] and create a new variable in your config file and point it to that. this way you have all the images and css files etc stored in one place and if your traffic spikes you can always move that subdomain to a CDN etc so its really customizable.
UPDATE
ok so you can simply use a new variable in your config file like below :
$_config['http'] = 'http://www.yousite.com/';
now you can just use this variable to point to all your downloads etc on the main site rather than each pointing to the subdomain's folder. and if you want to be more flexible you can also add a few more css or js folders like :
$_config['http'] = 'http://www.yousite.com/';
$_config['css'] = $_config['http']."css";
$_config['js'] = $_config['http']."js";
the solution above will also help you if you decided to move the files around or just move a certain folder around etc. this is a good practice if you can adopt it.
You might be able to use an alias in htaccess (or the server config) :
Alias /images /home/username/public_html/images
If that's not possible, you could rewrite all requests to /images via htaccess:
# Untested - should get you on the right track though
RewriteEngine On
RewriteRule ^/images/(.*)$ http://yourdomain.com/images/$1 [R=301,L]

How to correctly link files?

From my previous experience, I've almost always had problems with linking files with my website projects.
For example, linking CSS styles, Javascript files and including files in PHP. The problem is, that on my PC, the directory of my project was /www/project-name/ and when I put the project on a server, the directory would be just /www/. When I uploaded the project to a server, images wouldn't show, styles wouldn't work, database connections wasn't set, functions were not defined etc...
So my question is: What is the best and most efficient way to link/include files?
Something that will work no matter what the directory of the project is, and possibly, if I include project/includes/mysql.class.php in file1.php, and I move that file to a different directory, it would still properly include project/includes/mysql.class.php
You should use relative paths.
Instead of specifying the full path ('/www/project-name/includes/whatever.php'), use a path relative to the current location:
'./includes/whatever.php'
you can define the document root directory of project and then, include all files depending on it
put
define(DOC_ROOT, realpath(direname(__FILE__));
in your front controller, and when you have to include a file
include(DOC_ROOT . "/includes/file.php");
all frameworks uses this method
I'd suggest using a relative path (eg ../style.css or ../../style.css)
The ../ references the parent directory to the current file.
This is what I do, in general.
I use root relative urls inside html (e.g. src="/images/logo.jpg"). This way I can just copy the html from one page and past it in another without having to worry about the link not working becase the other page is inside a folder.
I relative urls in css, because all the resources I use inside the css, like images, I keep in the same folder as the css file (or a sub-directory of it). I mostly do this because it is shorter (url(img/background.jpg); vs. url(/css/img/background.jpg);). Minor added bonus is you could just copy the css folder to create a new theme based on the old one, without having to change all the urls in the css.
In PHP I use include($_SERVER['DOCUMENT_ROOT'] . '/includes/mysql.php');. You can just copy past the code into another file in another folder and it will still work.
The only time I rarely need to hardcode paths is inside htaccess.

PHP include file strategy needed

I'm in the process of setting up a php project, but am not very familiar with how to properly use php's include/require commands. My layout currently looks like this:
/public --apache points into this directory
/public/index.php
/public/blah/page.php
/utils/util1.php -- useful classes/code are stored in other directories out here
/dbaccess/db1.php
dbaccess/db1.php
require '../utils/util1.php
public/index.php
require '../dbaccess/db1.php'
public/blah/page.php
require '../../dbaccess/db1.php'
The problem is this from the php 'include' documentation:
If filename begins with ./ or ../, it is looked only in the current working directory
So public/blah/page.php fails because it includes dbaccess/db1.php which blows up when it tries to include util1.php. It fails because it's relative path is from the original script in public/blah/, not from dbaccess/
This seems pretty stupid -- db1.php has to just know where it's being included from which isn't going to work.
I've seen strategies like this:
require_once dirname(__FILE__) . '/../utils/util1.php');
That apparently works since now the path is an absolute path, but just seems really bizarre to me.
Is that normal? Should I continue down that path or am I missing something obvious here?
Usually, the standard conventions are thus: like #grepsedawk said, you'll want to define a constant that contains the root of your project folder and if you can the root of your includes folder:
define('APP_ROOT', dirname(__FILE__));
define('INCLUDE_ROOT', APP_ROOT . "/includes");
Note: the constant name needs to be a string!
Also, you'll notice I'm using dirname(__FILE__);. If you place your constants definition file in a subdirectory, you can do a dirname(dirname(__FILE__));, which is the equivalent of a ../.
Now some other caveats. While PATH_SEPARATOR is a cool constant, it is not needed. Windows accepts / or \ in path names, and since Linux only users / as a path separator, go ahead and always use a / instead of mucking up your code with repeated references to PATH_SEPARATOR.
Now that you have your root constants defined, what you'll do when you need a configuration file included is a simple:
include INCLUDE_ROOT . '/path/to/some/file.php';
You'll probably want your constant definitions (the define(...)'s above) in a bootstrap script in your root directory:
www_root/
index.php
bootstrap.php
The bootstrap will contain the defines (or an include of the constants file), as well as an include of any files that will be required by EVERY page.
And finally the last standard convention you may not use, but if you start doing object oriented programming, the most common method (the PEAR standard) is to name your classes by using an _ to separate namespaces:
class GlobalNamespace_Namespace_Class
//...
And then organizing your file structure mapping name spaces to subdirectories (literally replacing all _'s with /'s):
include_dir/
GlobalNamespace/
Namespace/
Class.php
And using __autoload() functions to load your classes, but that's another question.
Have a configuration script that sets the "INSTALL ROOT" of your project and then use absolute paths. Relative path with multiple includes is a headache in php.
DEFINE("INSTALL_ROOT", "/path/to/www/project")
require_once(INSTALL_ROOT . '/util1.php')
in my config / setup file, i do something like
define('MYAPP_BASEDIR',realpath('.'));
then i reference everything relative to that.
... if your include directory relates specifically to class files and you are able to name them so that the include file name could be derived from the class, you might like to look into spl_autoload_register().
this latter part isn't a direct answer to your question, but it's very handy if you're doing includes for each class you use.
Keep in mind, it starts in the current working directory and then looks through the include paths. If you want to reference all of your paths from some central root directory (or many) you can add that directory in the php.ini file or you can do it programatically with set_include_path( $path.PATH_SEPERATOR.get_include_path());
I suggest an abstraction strategy.
In your application page area, have a single file that all pages include.
This "local" include file has one job: find the include file that is outside the application page area. It then includes that. It can probably be as simple as <?php include dirname(__FILE__).'/../include/include.php/'; ?>
This second file is the single entry point into your library structure. It, or something else it includes, has the job of finding where everything is and including it.
This structure means you have just one file as your library's entry point and how it finds the rest of the library is not the application pages' problem. It also means you have just one file in your application area which knows how to find your library's entry point.
If you need a way for different application pages to load different things, I would suggest a modularisation approach. This can either be a global array you set before the master include, or a function you can call to request libraries by name. Yes, this is a slightly fancier way of your master library file declaring a constant of where everything is -- but it removes the temptation of doing include LIBRARY_DIR.'/utils/util.php'; which straightaway makes it unnecessarily difficult to move util.php out of utils and into misc/util at a later date.
The other advantage of the chained files is that it is then much easier to make your codebase relocatable, which makes it possible for multiple versions to be runnable. And it makes it possible to have one tree for the application and another for your library. Which means another application could use your library. In fact, you could extend the chaining a bit more if you want to help with the isolation further.
You're right, your scripts doesn't have to know the physical path where your includes are.
IMO the location where the includes are should be configured in the PHP.INI file (or .htaccess if you preffer).
Suponse your includes (utils and database are stored here /home/scott/php_includes/).
PHP.INI:
include_path=.:/home/scott/php_includes/
Now your scripts can include the libraries in this way:
dbaccess/db1.php:
require_once 'utils/util1.php';
public/index.php
require_once 'dbaccess/db1.php';
public/blah/page.php:
require_once 'dbaccess/db1.php';
A lot of people have provided good solutions, but I've just got one performance-related remark while talking about includes and requires.
If you start include'ing and require'ing a lot of files, it can be tempting to use include_once or require_once. Cachegrinds of scripts that use a lot of _once's have shown that they really slow down performance as the script has to stop what its doing to scan and make sure the file hasn't been included already. Eliminating as many of the _once's as you can will help a lot.
There was perfect solution - pecl extension called "pwee" - it allowed user define his/her own extern superglobal constants / variable using XML file. Thus you were able to use absolute path as I recomend in such form:
require_once APP_ROOT."/path/to/your/script.php";
The advantage of such solution was:
accessible from everywhere
no server load - everything in server memory
The XML file contained
<Environments>
<Application name="www.domain.com" namespace="">
<Constants>
<Constant name="APP_ROOT" value="/full/path/to/project/source" />
</Constants>
<Constants>
<Constant name="WEB_ROOT" value="/full/path/to/project/public" />
</Constants>
</Application>
</Environments>
link to pwee project
You should distinguish these cases of inclusion:
standalone library - all includes should be relative - to let user integrate it to his/her project easily
executable scripts in your public directory - contain absolute includes to project files and to standalone libraries public files (which has relative includes inside - transparent to user). Using the APP_ROOT constant is elegant way.
a,link,script, form html elemets and header forwards should use relative path when diving into tree hierarchy and absolute path when using common files from higher levels of hierarchy
In case of relative path use this form:
require_once "./relative/path/to/script.php";
Why do I use past tense? Because the project is not more supported - works only with Php4. If anyone knows similar solution with support, please let me know.
The best way to do that is to build flexible autoload system.
Simple map of classnames and proprietary patches. Then any internal require_* or include_* is not needed.
There is of course matter of relative/absolute path for autoloader. Well, absolute is most system-efficient, so in the array I mentioned before u can prepend some kind of variable {I have used Phing-style variable} e.g.
<map>
<path classname="MyClass">${project_directory}/libs/my_classes/MyClass.php</path>
<path classname="OtherClass">${project_directory}/libs/some_new/Other.php</path>
<!-- its so flexible that even external libraries fit in -->
<path classname="Propel">${project_directory}/vendors/propel/Propel.php</path>
<!-- etc -->
</map>
This is xml (think about ini or yaml as well) file and requires compile to php during first start, but after that any path is absolute.
Oh, as you can see no file naming convention or file layout is mandatory - its huge advantage.
Cheers, Alan.
It seems that every time I move my simple scripts from one server to another I have to redefine where things are.
I set up a test environment at home, built a few things, and deployed them to a shared host. The result was that the $_server['DOCUMENT_ROOT'] was two folders higher than the public_html folder on one server, and on another server it was one folder higher.
That skewed all my references. So I tried $_server['WEB_ROOT'] and failed again. I was thinking that the web root was a reference to the root of publicly-accessible folders on the server, but I was wrong.
I have one to throw in the pile that did something really simple without adding a lot of code I don't understand (I don't understand a lot of this code either, I just kept adding as I read rules and got it to work).
This gave me a reference to the publicly-accessible web root on all three servers I tried it on. Now I can move my folder anywhere and it just works, no config file necessary!
pub-doc-root.php:
<?php
//You only need to paste the following line into your script once,
//and it must come before you reference the public document root of your website.
//Use $pubroot.'/path_from_public_document_root_to_file/filename.php
$pubroot = (str_replace(($_SERVER['PHP_SELF']), '', (str_replace('\\', '/', (realpath(basename(getenv("SCRIPT_NAME"))))))));
//uncomment the next line to show the calculated public document root
//relative to the document root.
//echo ("$pubroot");
?>
My test environment:
php 5.3.1
Apache 2.2.14 (Win32) mod_ssl 2.2.14 OpenSSL 0.9.8k
ZendServer-CE-5.0.0GA_RC181-5.3.1-Windows_x86
Why not require it based on it's full path?
For example, /sharedhost/yourdomain.com/apache/www is your document root, so why not use
require('/sharedhost/yourdomain.com/apache/www/dbutils.php');
This also has the advantage of you being able to store your includes outside of your wwwroot so they are far less likely to be inadvertenly exposed via the web.
You could also set up a global variable equal to the /sharedhost/yourdomain.com/apache/ part of it so you can move the site around.
require(WWWROOT . '/dbutils.php');
I use
require '../path/to/file.ext';
without problems.
Also require is a statement not a function so it should be used as
require '/path/to/file.ext';
not
require('/path/to/file.ext');

Categories