You are on page 1of 82

Contents

[hide]

1 Initial Setup

2 Tutorials

3 Video Tutorials

4 Developers Documentation

Initial Setup

Requirements

File Structure

Installing the Product

o

Preparation & Uploading of phpFox

o

CHMOD & File Permissions

o

Using the Web-Installer

Upgrading the Product

o

Preparation & Uploading of phpFox

o

CHMOD & File Permissions

o

Using the Web-Installer

Post Install & Upgrade

o Web Site Administration

Troubleshooting

Tutorials

Change site logo

Create a "Welcome Intro"

Adding FTP Support

Installing/Upgrading a Theme

Installing/Upgrading a Style

Installing/Upgrading a Product

How to add an Announcement

Create an Advertisement/Ad/Banner

Disable Double Login for AdminCP

Change photo size limit

Translating Categories, Pages & Blocks

Show genres for non musicians

Install Branding Removal

Remove phpFox Twitter And/Or Updates Block From AdminCP

Video Tutorials

Change site logo

Change site SEO setting

Create a "Welcome Intro"

Change Favicon

Installing a Theme

Change photo size limit

Install a language package

Developers Documentation

Welcome to the phpFox2 developers manual. This manual will help you get started with how to develop new modules and plug-ins for phpFox2. phpFox2 is based on a modular system, which runs all of the common features we as users see when we visit a phpFox2 website. It also contains libraries or libs as we will call it, which is the engine that runs the skeleton of phpFox2 and its modules. The products core is designed to be a CMS (Content Management System). If you were only to include the core engine and the few required Core modules to run the product it would simply by a CMS. We bring in modules to introduce other features, which once packed with a heap of them turn the CMS into a Social Networking Solution. With this in mind we leave it up to the client to decide what sort of a site they would like to run and what sort of features they really need to get their crowd interested in their site and what it has to offer. Since the core can be stripped away from modules this leaves a lot of freedom for the script to evolve into other products such as a Software Licensing System or a Bug Tracker.

The modules are based on a MVC (Model View Controller) architectural pattern. phpFox2 is developed under a OOP (Object-oriented programming) environment, which will give future developers an easier time to enhance the product to their benefits.

Requirements for the product have become more flexible when dealing with PHP related requirements such as safe_mode or open_base_dir. Using those as an example the product can work with whatever those are set to allowing clients not to worry about if their server has a specific setting enabled or not. Our goal is to have a product that is as flexible as possible to make sure it works on all of the popular hosts today. There is one strict requirement and that in order to run the product you must have PHP5. Past requirements have been PHP 4.3.3, however since PHP5 introduced a wave of improvements when it comes down to OOP we decided it was time we move forward. As for MySQL the same 4.1 is required, although phpFox2 will support other database drivers and not just MySQL.

When reading this manual it is wise to read everything in order and not skip ahead as items that we cover later on will require knowledge of something you have learned earlier in the manual.

Introduction & Usage

Coding Guidelines

o

Naming

o

Coding Layout

o

SQL Layout

Libraries

o Classes

Products

o

Introduction

o

Creating a New Product

Modules

o

Introduction

o

File & Folder Structure

o

Creating a Module

o

Creating a Controller

o

Creating a Block

o

Working with a Controller

o

Working with a Block

o

Module Services

Plugins

o

Introduction

o

Creating a Plugin via the AdminCP

Completed Product

Retrieved from "http://wiki.phpfox.com/guide/V2"

Server Requirements

PHP Version 5+

MySQL Version 4.1+

Web Server Apache

Operating System Linux

GD complied with your PHP Build Yes

PHP memory_limit 32M

Optional Server Requirements

Notice: In order to run the music module:

PHP file_uploads 1

PHP post_max_size 40M

PHP max_input_time "1"

PHP upload_max_filesize 38M

Notice: In order to run the video module:

FFmpeg

FFmpegPHP (optional)

Mplayer + Mencoder

flv2tool

Libogg + Libvorbis

LAME MP3 Encoder

PHP file_uploads "1"

PHP post_max_size "75M"

PHP max_input_time "1"

PHP upload_max_filesize "75M"

Web Browser Requirements

The requirements for a web browser depends on what theme you are using for your site. The default theme we release has been tested to work on the latest versions of all the most common web

browsers (eg. Firefox, IE8, Opera, Chrome etc

version 7 or higher installed in order to properly use all the features provided with v2.

).

For those that use Internet Explorer must have

File Structure

Log in / create account

Search
Search

/file/ Stores files that are either uploaded or written to the server by the script, which requires folders within this folder to be writable.

o

/cache/ Stores all files cached by the script.

o

/pic/ Stores images uploaded by users using the script.

/attachment/ Stores all attachments uploaded by users.

/emoticon/ Stores all emoticons added by admins via the AdminCP.

/user/ Stores all of the users profile images.

o

/static/ Stores static JavaScript and CSS files cached by the script.

/include/ Stores all PHP files that are included in the script.

o

/cron/ Stores PHP files used for cron jobs.

/source/ Stores PHP files used when a specific cron job is executed, in other words it holds all the actual cron jobs.

exec.php PHP file that is executed when running or calling a cron job.

o

/library/ Stores the phpFox 2 engine library and any other 3rd party libraries that do not belong to a specific module.

/phpfox/ Stores all the classes that belong to the phpFox 2 engine.

o

/plugin/ Stores temporary plugin files being developed before they are exported for deployment.

o

/setting/ Stores all the configuration files.

common.sett.php Includes all the common variables needed for the script to run but should not be modified.

constant.sett.php Includes all constants.

server.sett.php Includes the database configuration and is created via the Installer. This file may be modified at a later time by the Admin if they were moving to another server for example.

validator.sett.php Includes all regex used when validating forms.

o

/xml/ Stores XML data which is used when installing or upgrading the product.

/install/ Is the core Installer and handles the install and upgrade of the product.

/module/ Stores all the core and 3rd party modules.

/static/ Stores static data such as JavaScript and CSS files which do not need to be modified and do not belong to a specific theme or style.

/theme/ Stores HTML files which control the themes provided with the product.

o

/adminpanel/ Stores themes & styles for the AdminCP

o

/frontend/ Stores themes & styles for the Front End.

o

/install/ Stores themes & styles for the Installer.

favicon.ico Default favicon image.

htaccess.txt Sample .htaccess file which has information on how to enable the Short URL feature.

index.php First file that is called when a user visits a phpFox 2 site and controls the action of the entire script from this file.

robots.txt Used to allow/deny bots to visit certain folders on a site.

Install

Log in / create account

Search
Search

This guide will help you through the installation process of phpFox. Installation is very straight forward, only taking about 15 minutes from uploading the files to logging into your Administration Control Panel (AdminCP).

We advise that you read this entire documentation to get a greater idea on how to handle the package and solve any issues should they occur.

You will need an FTP (File Transfer Protocol) client, if you do not have one you can download Filezilla for Windows/Linux or InterArchy for Macintosh. You do not need an in-depth knowledge of PHP programming to install phpFox, but a working knowledge of FTP functions is a plus.

This guide assumes that you have successfully downloaded the latest release from phpFox and have the ZIP file "unzipped".

Contents

[hide ]

1 Preparation & Uploading of phpFox

2 CHMOD & File Permissions

3 Using the WebInstaller

o

3.1 Step 1: Verification

o

3.2 Step 2: License

o

3.3 Step 3: Requirement Check

o

3.4 Step 4: Configuration

3.4.1 Video Module Configuration

o

3.5 Step 5: Installer

o

3.6 Step 6: Administrators Account

o

3.7 Step 7: Complete

Preparation & Uploading of phpFox

At this point you should have the zip archive "unzipped", which should have contents similar to those shown in this structure guide:

tools/

upload/

readme.html

Go into the folder "upload/", which should have contents similar to those shown in this structure guide:

file/

include/

install/

module/

static/

theme/

favicon.ico

htaccess.txt

index.php

robots.txt

Rename the file

include/setting/server.sett.php.new

to

include/setting/server.sett.php

Next, upload the files and folders within the "upload/" folder to your site using an FTP client. Be sure to overwrite any old files.

Once that is completed we can move on to the next step.

CHMOD & File Permissions

With the phpFox package there are certain folders and files that need write permission in order to execute certain tasks.

Below you will find the files and folders that must have full write permission and set to 0777 in order for the script to be installed:

file/attachment/

file/cache/

file/css/

file/log/

file/music/

file/pic/ad/

file/pic/emoticon/

file/pic/emoticon/default/

file/pic/event/

file/pic/group/

file/pic/icon/

file/pic/marketplace/

file/pic/music/

file/pic/photo/

file/pic/poll/

file/pic/quiz/

file/pic/subscribe/

file/pic/user/

file/pic/video/

file/pic/watermark/

file/static/

file/video/

include/setting/server.sett.php

Once you have completed CHMODING all the needed files and folders continue to the next step.

Using the Web-Installer

An installer is provided to assist you in entering the information phpFox2 needs to connect to your SQL database.

Run the installer file through your web browser by entering the URL into your browser address bar (if you have followed our example, type in http://www.domain.com/install/, naturally substituting 'domain.com' for your web address.)

Then follow these steps:

Step 1: Verification

We first check if the domain you are attempting to install the product on currently has a valid product license. There are several ways you can run a licensed product. You can run it on a licensed domain, which you provide the full path to where the software will be installed. You can also run a test site only for development purposes in a folder, sub-domain or localhost. The folder or sub- domain name must be called "phpfoxdev" or "development" and must be access protected. Here are some examples:

http://www.yoursite.com/phpfoxdev/ or http://www.yoursite.com/development/ (Live Development Server)

http://phpfoxdev.yoursite.com/ or http://development.yoursite.com/ (Live Development Server) http://localhost/ or http://127.0.0.1 (Local Server) http://209.85.135.104/ (IP to Your Development Server)

Step 2: License

Abide to the License Agreement to continue to the next step.

Step 3: Requirement Check

Step 3 will consist of checking your server if it meets the software requirements and the correct file permission layout.

Step 4: Configuration

This step is where you will need to know your SQL username and password. If you do not know it, please ask your web host - in most cases it is different from the FTP log in information.

The form is very straightforward, with only the following points needing closer examination. If you do not know what your "SQL Host" is, try "localhost" (without the quotes). If the SQL server is on the same server as your website (and in most cases it is) this will suffice. If you have created a new database for phpFox2, or wish to use an existing database, enter the name of the database in the appropriate field.

Video Module Configuration

These settings are optional and only should be filled if you plan to use the video module. The script will attempt to find the correct paths for both FFMPEG and MENCODER, however you should verify if they are correct with your host. If at any time these settings are incorrect you can change them directly from the AdminCP at a later time.

Step 5: Installer

The installer will now be automated until the final step. It will install all the required database tables and insert any data into each of the tables depending on what modules are being installed.

Step 6: Administrators Account

Fill out the form to create your administrators account.

Step 7: Complete

Congratulations phpFox2 is installed!

Post Install

Log in / create account

Search
Search

Installing Short URLs with mod_rewrite

In order to enable short URL's with phpFox2 you will need mod_rewrite, most servers today have support for this. To enable this feature open the file on your server:

htaccess.txt

Look for:

RewriteBase /

If you have installed phpFox2 in a sub-folder you will need to change the trailing slash with the sub-folder path. For example if you installed your site on:

http://www.yoursite.com/folder/

Yuo will need to change the RewriteBase to:

RewriteBase /folder/

If you installed your phpFox2 in your sites root directory (eg. http://www.yoursite.com) you can leave this setting as it is.

Next lets rename the file

htaccess.txt

to

.htaccess

Once you have done that open the file

/include/setting/server.sett.php

and look for

$_CONF['core.url_rewrite'] = '2';

and replace that with

$_CONF['core.url_rewrite'] = '1';

Save and close the file. You should now have short url's enabled on your site.

Enabling the Video Module

Since our video module relies on 3rd party scripts the ability to upload and convert videos is disabled by default. This feature needs to be enabled. First, we need to verify if FFMPEG and MENCODER is installed and we can find the correct path to them. During the install process we attempt to find these paths for you, however if these paths were wrong you can change them direct from the AdminCP.

Navigate to

AdminCP >> Settings >> Manage Settings >> Video

Look for

Path to FFMPEG

and

Path to MENCODER

Make sure the full path to these scripts are correct. If you are unsure you can ask your web host or connect to your server via SSH.

If you have connected to your server via SSH execute this command

whereis ffmpeg

It would output something like this:

ffmpeg: /usr/bin/ffmpeg /usr/X11R6/bin/ffmpeg /usr/bin/X11/ffmpeg /usr/local/bin/ffmpeg /usr/share/man/man1/ffmpeg.1.gz

The full path would then be:

/usr/bin/ffmpeg

This same method needs to be done for mencoder.

Once you have entered the correct path enable this option

Enable Uploading of Videos

Once enabled submit the form and the script will attempt to connect to both scripts and if successful it will enable this feature. If unable to connect to the scripts a set of error message(s) will appear to guide you on what is wrong.

Troubleshooting

Log in / create account

Search
Search

Contents

[hide ]

1 Install & Upgrade

o 1.1 Error Log Reporting

2 General

o 2.1 Enabling Debug Mode

2.1.1 Enabling from AdminCP

2.1.2 Enabling from Your Server

3 Music Section

o 3.1 The "Musician" User Group Only Allowed Within Custom Fields

4 Video Section

o 4.1 Video remains "in process"

[ edit ] Install & Upgrade

[edit] Error Log Reporting

During both the install & upgrade procedures we log all the activity within the folder "/file/log/". All the files themselves are secure so no 3rd party can view them unless accessed via the server using an FTP client for example. Currently the product is not supported and the only form of help can be reporting any problems to our developers by submitting a bug report.

Submitting bug reports at this stage of the product is crucial so feel free to report any problems here.

When submitting a bug report we ask that you ZIP the folder:

/file/log/

Note we ask only to ZIP the folder "log" and not the entire "file" folder. If you do not have SSH access to your server you can access your server via an FTP client and browse to the folder:

/file/

From there download the folder:

/log/

Once the folder is on your computer you can right click and on most operating systems there should be an option to create a ZIP archive. Once a ZIP archive has been created feel free to submit the bug report and attach the ZIP and we can have all the details to help solve the problem.

[ edit ] General

[edit] Enabling Debug Mode

If you encounter problems on your site, enabling Debug Mode in many cases helps answer the question on what is causing a problem. By default all errors are suppressed so end-users do not see such errors. To enable Debug Mode this can be done either by enabling it from your AdminCP or accessing your web server. If you encounter a problem that does not cause a blank white screen you can enable debug mode from your AdminCP, however if your problem is due to a blank white screen you must enable debug mode by accessing your server and creating a PHP file.

[edit] Enabling from AdminCP

To enable debug mode from AdminCP, navigate to your AdminCP and go to

Settings >> System Settings >> Manage Settings >> Debug

For the setting

Debug Level

change the value from "Level 0" to any of the other levels.

[edit] Enabling from Your Server

To enable debug mode from your server you need to access your site via an FTP client or a hosting file manager. Once you have reached your sites root directory navigate to the folder

include/setting/

Create a new file:

dev.sett.php

Open the file and add the following:

<?php define('PHPFOX_DEBUG', true); ?>

Save and close the file.

[ edit ] Music Section

[edit] The "Musician" User Group Only Allowed Within Custom Fields

When you are adding custom fields you will notice you can only select the user group "Musician" from the "User Group" selection drop down. This is because the "Musician" user group is allowed to have custom fields, while other user groups by default do not have this option enabled. This feature can be enabled by editing the settings for each user group and enabling the option:

Can have special custom fields?

[ edit ] Video Section

[edit] Video remains "in process"

If when you upload certain videos these remain in process it is possible that the database connection is timing out. To confirm this case you need to make sure that the video is being converted properly (as that is the first step in the uploading routine). This problem should also happen with some longer videos. The actual setting on mysql is called wait_timeout, it is measured in seconds and it tells how long to wait before it kills a connection. The connection is open since the user opens up "this" page, for example if they log in, check their private messages and then they go to the video section a connection is established since they got to the video section, not since they logged in. The video upload routine uploads and converts the video while the database session is still active, so if the conversion takes 40 seconds and your wait_timeout is set to 30 you will have this problem. In phpmyadmin you can check the value for wait_timeout by going to Variables and scrolling all the way down.

If you have enough permissions you can change this value by executing: set

@@global.wait_timeout=3000

In a linux default installation this value is set to 28800, but you should judge if this value is appropriate for your site as it may affect other features (it uses memory for longer time so accepting new connections may run your database server out of memory).

Please note that using persistent connections will not help in this case.

You should also change this value in the mysql ini file

Official mysql documentation on this value found here

Developers Documentation

Welcome to the phpFox2 developers manual. This manual will help you get started with how to develop new modules and plug-ins for phpFox2. phpFox2 is based on a modular system, which runs all of the common features we as users see when we visit a phpFox2 website. It also contains libraries or libs as we will call it, which is the engine that runs the skeleton of phpFox2 and its modules. The products core is designed to be a CMS (Content Management System). If you were only to include the core engine and the few required Core modules to run the product it would simply by a CMS. We bring in modules to introduce other features, which once packed with a heap of them turn the CMS into a Social Networking Solution. With this in mind we leave it up to the client to decide what sort of a site they would like to run and what sort of features they really need to get their crowd interested in their site and what it has to offer. Since the core can be stripped away from modules this leaves a lot of freedom for the script to evolve into other products such as a Software Licensing System or a Bug Tracker.

The modules are based on a MVC (Model View Controller) architectural pattern. phpFox2 is developed under a OOP (Object-oriented programming) environment, which will give future developers an easier time to enhance the product to their benefits.

Requirements for the product have become more flexible when dealing with PHP related requirements such as safe_mode or open_base_dir. Using those as an example the product can work with whatever those are set to allowing clients not to worry about if their server has a specific setting enabled or not. Our goal is to have a product that is as flexible as possible to make sure it works on all of the popular hosts today. There is one strict requirement and that in order to run the product you must have PHP5. Past requirements have been PHP 4.3.3, however since PHP5 introduced a wave of improvements when it comes down to OOP we decided it was time we move forward. As for MySQL the same 4.1 is required, although phpFox2 will support other database drivers and not just MySQL.

When reading this manual it is wise to read everything in order and not skip ahead as items that we cover later on will require knowledge of something you have learned earlier in the manual.

Introduction & Usage

Coding Guidelines

o

Naming

o

Coding Layout

o

SQL Layout

Libraries

o Classes

Products

o

Introduction

o

Creating a New Product

Modules

o

Introduction

o

File & Folder Structure

o

Creating a Module

o

Creating a Controller

o

Creating a Block

o

Working with a Controller

o

Working with a Block

o

Module Services

Plugins

o

Introduction

o

Creating a Plugin via the AdminCP

Completed Product

Introduction

Log in / create account

Search
Search

While you are developing there are certain constants to make things a lot easier for all of us. Many aspects of the script is cached into flat files. This can be from data we pull out from the database, templates files that are converted into PHP code or JavaScript files that are gzipped. While we are developing we always enable debug mode to make sure we don't have any errors in our code. The constants we are about to show you is a list of constants that do not all have to be set. You can choose which constants you want. If you do not want a certain constant simply remove it from the file. Note then when certain constants are enabled your site will run much slower. You have to consider that the site is not caching any data and this is very risky on a live community. Remember never have any of these settings on a live community.

To enable this settings first create a file

include/setting/dev.sett.php

You can then add the following:

<?php

// Enable debug define('PHPFOX_DEBUG', true);

// Debug level define('PHPFOX_DEBUG_LEVEL', 1);

// Force templates re-cache on each page refresh define('PHPFOX_NO_TEMPLATE_CACHE', true);

// Force browsers to re-cache static files on each page refresh define('PHPFOX_NO_CSS_CACHE', true);

// Override default email define('PHPFOX_DEFAULT_OUT_EMAIL', 'your_email@email.com');

// Skip sending out of emails define('PHPFOX_SKIP_MAIL', true);

// Use live templates and not those from the database define('PHPFOX_LIVE_TEMPLATES', true);

// Add user_name in the title of each page. Great for when working with many browsers open define('PHPFOX_ADD_USER_TITLE', true);

// Cache emails to flat files define('PHPFOX_CACHE_MAIL', true);

// Log error messages to XML flat file within the cache folder define('PHPFOX_LOG_ERROR', true);

// Skip the storing of cache files in the DB define('PHPFOX_CACHE_SKIP_DB_STORE', true);

?>

Coding Guidelines

Log in / create account

Search
Search

Contents

[hide ]

1 Naming

o

1.1 Variables

o

1.2 Classes

o

1.3 Functions/Methods

o

1.4 Function Arguments

o

1.5 Properties

o

1.6 Constants

o

1.7 phpFox Parameters

o

1.8 phpFox Phrases

o

1.9 Folders

o

1.10 Filenames

2 Coding Layout

o

2.1 Include Braces

o

2.2 Brace Positions

o

2.3 Use Spaces Between Tokens

o

2.4 Operator Precedence

o

2.5 Quoting Strings

o

2.6 Associative Array Keys

o

2.7 Magic Numbers

o

2.8 Don't Use Uninitialized Variables

o

2.9 Switch Statements

o

2.10 elseif or else if

o

2.11 Control Structures

3 SQL/SQL Layout

o

3.1 Common SQL Guidelines

o

3.2 Prefix

o

3.3 Database Abstraction Layer

o

3.4 SQL Code Layout

3.4.1 SELECT

3.4.2 INSERT

3.4.3 UPDATE

3.4.4 DELETE

3.4.5 SELECT with JOINS

3.4.6 ORDER BY

3.4.7 LIMIT

3.4.8 GROUP

3.4.9 HAVING

o

3.5 Escape

o

3.6 SQL Quotes

Naming

Variables

Variable names should define what type of data it holds by adding a lower case letter after the dollar sign. Example:

$iFoo = 1;

In the above example you will notice the letter i after the dollar sign ($). The signifies that this specific variable holds an integer. Use the following letters to define the data the variable is holding:

// i = integer $iFoo = 1;

// a = array $aFoo = array(1, 2, 3);

// b = boolean $bFoo = true;

// h = resource $hFoo = opendir('/var/www/phpfox/');

// s = string

$sFoo = 'bar';

// o = object $oFoo = new Bar();

By doing this will give other developers an idea of what a certain variable holds without having to back trace the variable. Remember after you define what the variable holds you must start with an uppercase letter.

Variables cannot contain underscores and must be separated by an uppercase character to signify that a new word is starting. Here are some wrong and right examples.

Wrong

$variable_name = 'bar'; $aBar_name = array(1, 2, 3); $_new_name = 1;

Right

$sVariableName = 'bar'; $aBarName = array(1, 2, 3); $iNewName = 1;

When naming a variable try not to make the variable name too long or too short. Also don't simply make up words, try to name the variable by making a connection to what the variable holds. If for an example the variable you are creating is an array and it holds information for a user you could name it:

$aUser = array();

This way another developer has an idea that the variable $aUser is holding an array with user information. If a variable is holding an array that has numerous values you should create a plural variable name. Example:

$aUsers = array(

'user1',

'user2',

'user3'

);

If an array holds only one value or is a string for example you can create a singular name. Example:

$aUser = array('user1'); $sUser = 'user name';

Classes

To understand how to name classes you will have to know more about how modules and libraries work with phpFox2. Since naming the class has very specific rules with how phpFox2 is designed its best to wait till we get to those sections to fully understand how these classes are named.

Functions/Methods

Naming a function/method is similar to naming a variable except we don't need to define what sort of data it will return. All functions/methods must start with a lower case letter and cannot contain any underscores unless its a private method, then and only then can it start with an underscore. Much like the variable naming you must separate words with an uppercase letter. If a method is not private and is either public or protected it still cannot start with an underscore. Here are some wrong and right examples.

Wrong

function name_of_function($sFoo)

{

}

private function name($sBar)

{

}

Right

function nameOfFunction($sFoo)

{

}

private function _name($sBar)

{

}

If you are creating a method you must declare if its public, protected or private. When creating a function/method try to create a name that has something to do with what will actually be done in the function/method. If for example we are calling a method that will get an array for a specific menu you could name it:

public function getMenu()

Function Arguments

Arguments are subject to the same guidelines as variable names. We don't want a bunch of functions like:

doStuff($a, $b, $c)

Instead it should be:

doStuff($aUser, $bUpgrade, $iFriendId)

Properties

Properties are subject to the same guidelines as variable names. You must declare if a property is public, protected or private. If a property is private it must being with an underscore like so:

private $_bFoo = true;

Constants

All constants must be uppercase and must have a PHPFOX_ prefix. When naming a constant make sure its related to the data its holding. Here are some wrong and right examples:

define('my_constant', true); define('NEW_CONSTANT_NAME', true);

Right

define('PHPFOX_MY_CONSTANT', true); define('PHPFOX_NEW_CONSTANT_NAME', true);

phpFox Parameters

Certain Settings which can be found in the AdminCP are used throughout the script. The reason these variables are located in the AdminCP instead of being defined in the actual PHP script is Admins may need to edit some of these variables at a later time and its a lot easier for non- developers to edit variables from the AdminCP then it is from the source code. We won't go into much detail on how to add a parameter at the moment as we will go into that later once we reach that section. The variable name for such settings have all lowercase characters and spaces are separated by an underscore (_) and must contain the module ID.

If for example we had a parameter that held a setting for the sites title it could be named core.site_title and getting the value via a PHP script can be done by calling the following static method:

echo Phpfox::getParam('core.site_title');

Notice where we have core, this is the module ID so the variable site_title belongs to the core module. If this setting belonged to the user module the call would be:

echo Phpfox::getParam('user.site_title');

Note that phpFox parameters are stored in the database table setting and is automatically cached once the script is executed.

phpFox Phrases

Phrase variables is what we use to get a phrase from the language package being used. This gives us the ability to provide a Multilingual product. We use all lowercase letters and replace spaces with underscores. This is actually automatically done when you create a new variable from the AdminCP so not much thought has to go into creating a variable for phrases. The only thing you can consider is making sure the name of the variable is somewhat related to what sort of information it holds. For example if a phrase holds information that a user has just logged out it could look something like this when trying to call the phpFox static method:

echo Phpfox::getPhrase('user.you_have_logged_out');

Notice that we have user as this specific phrase belongs to the user module. Similar to how settings work and much of the actual script, phrases belong to a module and if its a global phrase then it belongs to the core module.

Folders

All folders must be named with lowercase characters. It cannot contain any other characters other then those from A-Z. All folders must be named singular. Here are some wrong and right examples.

Wrong

/my_folder/

/newFolder/

/Folder/

Right

/my/folder/

/new/folder/

/folder/

Filenames

All filenames must be lowercase and cannot contain any other characters other then those from A-Z. All filenames must be singular. If a PHP file contains a class it must have the following .class.php suffix. If a PHP file contains PHP data it must end with a .php.

Here are some wrong and right examples.

Wrong

Foo.php

Foo.class.inc

foo_bar.php

Right

foo.php

foo.class.php

/foo/bar.php

Coding Layout

Include Braces

You must always include braces. There are a few ways on how to include your braces and this is usually up to how your personal coding style is, however to make sure we all understand the product we must all use the same style of coding. Below are some wrong and right examples of how to add braces.

Wrong

if (condition) doStuff();

if (condition) doStuff();

if (condition) { doStuff();

}

while (condition) ddoStuff();

for ($i = 0; $i < size; $i++) doStuff($i);

Right

if (condition)

{

doStuff();

}

while (condition)

{

doStuff();

}

for ($i = 0; $i < size; $i++)

{

doStuff();

}

Brace Positions

Braces always go on their own line. The closing brace should also always be at the same column as the corresponding opening brace, examples:

if (condition)

{

 

while (condition2)

{

}

}

else

{

}

for ($i = 0; $i < $iSize; $i++)

{

}

while (condition)

{

}

function doStuff()

{

}

Use Spaces Between Tokens

This is another simple, easy step that helps keep code readable without much effort. Whenever you

write an assignment, expression, etc

code as if it was English. Put spaces between variable names and operators. Don't put spaces just

after an opening bracket or before a closing bracket. Don't put spaces just before a comma or a semicolon. This is best shown with a few examples, examples:

Always leave one space between the tokens. Basically, write

Notice: Each pair shows the wrong way followed by the right way.

$i=0;

$i = 0;

if($i<7)

if ($i < 7)

if ( ($i < 7)&&($j > 8) ) if ($i < 7 && $j > 8)

doStuff( $i, 'foo', $b ); doStuff($i, 'foo', $b);

for($i=0; $i<$size; $i++) for ($i = 0; $i < $size; $i++)

$i=($j < $size)?0:1; $i = (($j < $size) ? 0 : 1);

Operator Precedence

Always make it obvious by using brackets to force the precedence of an equation so you know what it does. Remember to not over-use this, as it may harden the readability. Basically, do not enclose single expressions. Examples:

What's the result? Who knows.

$bBool = ($i < 7 && $j > 8 || $k == 4);

Now you can be certain what I'm doing here.

$bBool = (($i < 7) && (($j < 8) || ($k == 4)));

But this one is even better, because it is easier on the eye but the intention is preserved

$bBool = ($i < 7 && ($j < 8 || $k == 4));

Quoting Strings

There are two different ways to quote strings in PHP - either with single quotes or with double quotes. The main difference is that the parser does variable interpolation in double-quoted strings, but not in single quoted strings. Because of this, you should always use single quotes unless you specifically need variable interpolation to be done on that string. This way, we can save the parser the trouble of parsing a bunch of strings where no interpolation needs to be done.

Also, if you are using a string variable as part of a function call, you do not need to enclose that variable in quotes. Again, this will just make unnecessary work for the parser. Note, however, that nearly all of the escape sequences that exist for double-quoted strings will not work with single- quoted strings. Be careful, and feel free to break this guideline if it's making your code easier to read, examples:

Wrong

$sStr = "This is a really long string with no variables for the parser to find.";

Right

$sStr = 'This is a really long string with no variables for the parser to find.';

Notice: In SQL Statements mixing single and double quotes is partly allowed (following the guidelines listed here about SQL Formatting), else it should be tried to only use one method - mostly single quotes.

Associative Array Keys

In PHP, it's legal to use a literal string as a key to an associative array without quoting that string. We don't want to do this -- the string should always be quoted to avoid confusion. Note that this is only when we're using a literal, not when we're using a variable, examples:

Wrong

$sFoo = $assocArray[blah];

Right

$sFoo = $assocArray['blah'];

Wrong

$sFoo = $assocArray["$sVar"];

Right

$sFoo = $assocArray[$sVar];

Magic Numbers

Don't use them. Use named constants for any literal value other than obvious special cases. Basically, it's ok to check if an array has 0 elements by using the literal 0. It's not ok to assign some special meaning to a number and then use it everywhere as a literal. This hurts readability AND maintainability. The constants true and false should be used in place of the literals 1 and 0 -- even though they have the same values (but not type!), it's more obvious what the actual logic is when you use the named constants. Typecast variables where it is needed, do not rely on the correct variable type (PHP is currently very loose on typecasting which can lead to security problems if a developer does not have a very close eye to it).

Don't Use Uninitialized Variables

For phpFox 2, we intend to use a higher level of run-time error reporting. This will mean that the use of an uninitialized variable will be reported as a warning. These warnings can be avoided by using the built-in isset() function to check whether a variable has been set - but preferably the variable is always existing. For checking if an array has a key set this can come in handy though, examples:

Wrong

if ($iBlog)

Right

if (isset($iBlog))

Right

if (isset($iBlog) && $iBlog == 1)

The empty() function is useful if you want to check if a variable is not set or being empty (an empty string, 0 as an integer or string, NULL, false, an empty array or a variable declared, but without a value in a class). Therefore empty should be used in favor of isset($aArray) && sizeof($aArray) > 0 - this can be written in a shorter way as !empty($aArray).

Switch Statements

Switch/case code blocks can get a bit long sometimes. To have some level of notice and being in- line with the opening/closing brace requirement (where they are on the same line for better readability), this also applies to switch/case code blocks and the breaks. An example:

Wrong

switch ($sMode)

{

 

case 'mode1':

// I am doing something here

break;

case 'mode2':

// I am doing something completely different here

break;

default:

// Always assume that the case got not catched

break;

}

Right

switch ($sMode)

{

case 'mode1':

// I am doing something here break;

case 'mode2':

// I am doing something completely different here break; default:

}

break;

Even if the break for the default case is not needed, it is sometimes better to include it just for readability and completeness.

elseif or else if

This depends on how you code but to make sure we are all on the same page we will just use elseif. Here is a wrong and right example.

Wrong

if (condition)

{

}

else if (condition)

{

}

Right

if (condition)

{

}

elseif (condition)

{

}

Control Structures

All control structures must be lower case. Here is a wrong and right example:

Wrong

IF (condition)

{

}

ELSEIF (condition)

{

}

Right

if (condition)

{

}

elseif (condition)

{

}

SQL/SQL Layout

Common SQL Guidelines

All SQL should be cross-DB compatible, if DB specific SQL is used alternatives must be provided which work on all supported DB's (MySQL4/5, MSSQL (7.0 and 2000), PostgreSQL (7.0+), SQLite, Oracle8.

All SQL commands should utilize the Database Abstraction Layer and not use the conventional methods of executing SQL queries.

Prefix

All of your queries must use the method we provide to allow sites that use a different prefix. In order to use a prefixed table you can use the following method:

Phpfox::getT('user');

If their prefix is phpfox_ then the above method will output

phpfox_user

Database Abstraction Layer

phpFox2 uses a database abstraction layer to make sure we can work with all the database drivers we support. In order to connect to this object there are several ways to accomplish this. At first sight these methods may look rather odd but once you get a clearer understanding of how we connect to phpFox2 libraries you will fully understand. This is something we will cover shortly after we look over the guidelines.

If you would like to connect to the database from anywhere in the script you can do the following:

Phpfox::getLib('phpfox.database')->query('SELECT user FROM ' . Phpfox::getT('user'));

If you plan to use the database object more then once you can do the following:

$oDb = Phpfox::getLib('phpfox.database'); $oDb->query('SELECT user FROM ' . Phpfox::getT('user'));

If you are within a module service class you can do the following:

$this->database()->query('SELECT user FROM ' . Phpfox::getT('user'));

Notice: In many of the examples that are coming up we will be using the first method we displayed, however any of the above methods will work depending on where you are calling it from.

You can use the conventional method of using mysql_query() anywhere in the script, however this will cause problems if for example another user is using an Mssql driver.

SQL Code Layout

Since we use a database abstraction layer for all our SQL queries this will take some getting used to especially if you are used to writing the conventional SQL query. However, once you learn the methods used it will be a lot easier and faster to get things down. Below we have listed examples of the common SQL queries and the abstraction layer method we provide.

SELECT

An example of how we perform a simple SELECT query that will pull out a users user name.

Wrong

$hRes = mysql_query("SELECT user_name, email FROM " . Phpfox::getT('user') . " WHERE user_id = 1"); $aRow = mysql_fetch_array($hRes);

Right

$aRow = Phpfox::getLib('phpfox.database')->select('user_name, email') ->from(Phpfox::getT('user')) ->where('user_id = 1') ->execute('getRow');

As you will notice the methods used are similar to that of a query so there won't be too much of a confusion for those that are new to this. You will also notice the execute method. This is the method we use to specify what sort of a query we plan to execute. In this case we used getRow, which simply put gets one row from the database.

With phpFox2 we also provide an alternative to getRow, which is getSlaveRow. What this does is if you are for example using MySQL as your database driver and since it supports the ability to setup multiple slave servers the query will attempt to connect to one of the slave servers thus lowering the load off the main server. If your database driver does not have slave support then getSlaveRow will automatically default back to getRow. Note that you should use getSlaveRow wisely as if a users server as some sort of a delay before one of the slave servers is populated with the new data it could cause some server problems. So only use this if you feel the information that we are getting does not need to be "live". An example of when not to use this is during a login routine. This sort of information needs to be fully up-to-date at all times and if not it could cause the user problems when trying to login.

If you wanted to select multiple rows you can execute the getRows method. An example of the wrong and right way are:

Wrong

$hRes = mysql_query("SELECT user_name, email FROM " . Phpfox::getT('user') . " WHERE user_id = 1"); while ($aRow = mysql_fetch_array($hRes)

{

}

Right

$aRows = Phpfox::getLib('phpfox.database')->select('user_name, email') ->from(Phpfox::getT('user')) ->where('user_id = 1') ->execute('getRows');

foreach ($aRows as $aRow)

{

}

Much like how the method getRow has getSlaveRow you can instead use getSlaveRows instead of getRows. The same rules of caution apply to this method as it does withgetSlaveRow.

Another useful method is getField and getSlaveField. This method will return the specific field and is very useful when trying to count how many total rows there are for a specific query. Here is an example:

$iCnt = Phpfox::getLib('phpfox.database')->select('COUNT(*)') ->from(Phpfox::getT('user')) ->execute('getField');

$iCnt will return the total number of members found in the user table.

INSERT

We also provide an easy way to insert data into the database. Here is an example of the wrong and right way.

Wrong

mysql_query("INSERT INTO " . Phpfox::getT('user') . " SET user_name = 'natio', email = 'natio@phpfox.com'");

Right

Phpfox::getLib('phpfox.database')->insert(Phpfox::getT('user'), array('user_name' => 'natio', 'email' => 'natio@phpfox.com'));

Another method we provide is if you would like to process the data before its added into the database. This is useful as sometimes we allow all the data being posted from a form to pass directly to the insert method. This can be dangerous as sometimes you do not want to insert injected data, however this method will check to make sure the data being posted matches what you want to store in the database. For example if the data for a users birthday needed to be a numeric value you can specify that this field is an int thus it makes sure its numeric before entering it into the database. If you do not specify a field in the database then this field will not have any data inserted into it thus protecting the field from any sort of SQL injection that might be attempted. Here is an example of how to utilize this feature:

Phpfox::getLib('phpfox.database')->process(array('user_id' => 'int', 'email', 'user_name'), $_POST)->insert(Phpfox::getT('user'));

With the query above it will only allow us to insert the user_id, email and user_name into the database; it also makes sure that the user_id is a numeric value.

One final method we provide is the multi-insert as we call it. This will allow you to insert a lot more information with just one query. One downside with this method is not all database driver support this, however since you will be using the database abstraction layer there is nothing to worry about as for those drivers that don't support this method we simply do the conventional method within the layer. This sort of query won't be used as often but it can be rather handy in some occasions. Take the routine we use to check if any new phrases are found and if they are it lets us insert them into the database so the site has all the latest phrases for a language package. This is something we use during an upgrade of a site. Since we are upgrading and new phrases might have been added we need to find out which ones are new as users can be running very different versions.

$aInsert = array(); $aPhrases = Phpfox::getLib('phpfox.locale')->getPhrases(); $aRows = Phpfox::getLib('phpfox.database')->select('phrase') ->from(Phpfox::getT('language_phrase')) ->execute('getSlaveRows');

foreach ($aRows as $aRow)

{

if (isset($aPhrases[$aRow['phrase']]))

{

}

continue;

$aInsert[] = array( $aRow['language_id'], $aRow['phrase']

}

);

if (count($aInsert))

{

$this->database()->multiInsert(Phpfox::getT('language_phrase'), array('language_id', 'phrase'), $aInsert);

}

By using this method it allows you to insert a lot more data with just one SQL insert.

UPDATE

Updating is similar to that of inserting data. Here is an example of the wrong and right way.

Wrong

mysql_query("UPDATE " . Phpfox::getT('user') . " SET user_name = 'natio', email = 'natio@test.com' WHERE user_id = 1");

Right

Phpfox::getLib('phpfox.database')->update(Phpfox::getT('user'), array('user_name' => 'natio', 'email' => 'natio@test.com'), 'user_id = 1');

Just like inserting data you can use a process method to update information which would be:

Phpfox::getLib('phpfox.database')->process(array('user_id' => 'int', 'email', 'user_name'), $_POST)->update(Phpfox::getT('user'), 'user_id = 1');

DELETE

For deleting a query we provide a very short method. Here is an example of the wrong and right way.

Wrong

mysql_query("DELETE FROM " . Phpfox::getT('user') . " WHERE user_id = 1");

Right

Phpfox::getLib('phpfox.database')->delete(Phpfox::getT('user'), 'user_id = 1');

SELECT with JOINS

Most of the queries you will come across in the script include a joined query. To accomplish this you can do the following:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email') ->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->where('b.blog_id = 1') ->execute('getSlaveRows');

In the query above you will notice we added the following

->join(Phpfox::getT('user'), 'u', 'u.user_id = b.user_id')

with this we can JOIN another table. The first parameter is the table name. The 2nd parameter is the table alias for that join. The 3rd parameter is the index connection for that table. Its important to remember that these field(s) must be indexed or it could cause severe problems later on. If we were to translate this query into the conventional method it would look like the following:

Phpfox::getLib('phpfox.database')->query(' SELECT b.blog_id, u.user, u.email FROM ' . Phpfox::getT('blog') . ' AS b JOIN ' . Phpfox::getT('user') . ' AS b ON(u.user_id = b.user_id) WHERE b.blog_id = 1

');

If you were to use a LEFT JOIN instead of a JOIN the query would then look like this:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email') ->from(Phpfox::getT('blog'), 'b') ->leftJoin(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->where('b.blog_id = 1') ->execute('getSlaveRows');

You can also use an innerJoin() which would be:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email')

->from(Phpfox::getT('blog'), 'b') ->innerJoin(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

ORDER BY

->where('b.blog_id = 1') ->execute('getSlaveRows');

Ordering a query we use the order() method and the command we use is standard SQL. Here is an example:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email') ->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->where('b.blog_id = 1') ->order('b.time_stamp DESC') ->execute('getSlaveRows');

If you were to translate this query to its conventional form it would look like the following:

Phpfox::getLib('phpfox.database')->query(' SELECT b.blog_id, u.user, u.email FROM ' . Phpfox::getT('blog') . ' AS b JOIN ' . Phpfox::getT('user') . ' AS b ON(u.user_id = b.user_id) WHERE b.blog_id = 1 ORDER BY b.time_stamp DESC

');

LIMIT

Limiting a query we use the limit() method. Here is an example:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email') ->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->where('b.blog_id = 1') ->order('b.time_stamp DESC') ->limit(0, 5) ->execute('getSlaveRows');

If you were to translate this query to its conventional form it would look like the following:

Phpfox::getLib('phpfox.database')->query(' SELECT b.blog_id, u.user, u.email FROM ' . Phpfox::getT('blog') . ' AS b JOIN ' . Phpfox::getT('user') . ' AS b ON(u.user_id = b.user_id) WHERE b.blog_id = 1 ORDER BY b.time_stamp DESC LIMIT 0,5

');

With the limit() method we also provide a feature that will get the correct limit by calculating the offset, mainly used on page that display numerous items and only a certain amount can be viewed on that page. Here is an example of how this query could look like:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email')

->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->where('b.blog_id = 1') ->order('b.time_stamp DESC') ->limit($iPage, $sLimit, $iCnt) ->execute('getSlaveRows');

You will notice the following part:

->limit($iPage, $sLimit, $iCnt)

The 1st parameter is the current page we are on (eg 1, 2, 3 etc

can be displayed on one page. The 3rd parameter is how many total items or in this case how many blogs we have. Using this method the script will automatically calculate the offset and return the

correct LIMIT for you. This will be explained in more detail once we reach how pagination works, however this should get you a head start in that area.

).

The 2nd parameter is how many

GROUP

Notice: Mssql has a different way of processing grouped fields as it requires everything selected to be defined in the group clause and it also does not allow TEXT fields so use this with caution. In many cases we felt to deal with this problem with Mssql we used PHP logic to group queries instead. It unfortunately will cause a slight overhead but it is a route we must take.

You can group a query by using the group() method. Here is an example:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email, COUNT(blog_id) AS total_blogs') ->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->group('b.blog_id, u.user, u.email') ->order('b.time_stamp DESC') ->execute('getSlaveRows');

If you were to translate this query to its conventional form it would look like the following:

Phpfox::getLib('phpfox.database')->query(' SELECT b.blog_id, u.user, u.email, COUNT(blog_id) AS total_blogs FROM ' . Phpfox::getT('blog') . ' AS b JOIN ' . Phpfox::getT('user') . ' AS b ON(u.user_id = b.user_id) GROUP BY b.blog_id, u.user, u.email ORDER BY b.time_stamp DESC

');

HAVING

If you would like to use HAVING you can use it with the having() method. Here is an example:

$aRows = Phpfox::getLib('phpfox.database')->select('b.blog_id, u.user, u.email, u.view')

->from(Phpfox::getT('blog'), 'b') ->join(Phpfox::getT('user'), 'u', 'u.user_id =

b.user_id')

->having('u.view > 1') ->order('b.time_stamp DESC')

->execute('getSlaveRows');

If you were to translate this query to its conventional form it would look like the following:

Phpfox::getLib('phpfox.database')->query(' SELECT b.blog_id, u.user, u.email, u.view FROM ' . Phpfox::getT('blog') . ' AS b JOIN ' . Phpfox::getT('user') . ' AS b ON(u.user_id = b.user_id) HAVING u.view > 1 ORDER BY b.time_stamp DESC

');

Escape

Escaping queries is very important. This is to prevent any sort of SQL injections at a later time. To make things a little easier for us we automatically escape data when inserting or updating data that is passed within the array. For example in this update:

Phpfox::getLib('phpfox.database')->update(Phpfox::getT('user'), array('email' => $aVals['email']), "user_name = '" . $aVals['user_name'] . "'");

In the example above $aVals['email'] will automatically be escaped since its within the update array. However, $aVals['user_name'] will not be automatically escaped so this is up to you to protect the script from any sort of SQL injections by using the method escape() like so:

Phpfox::getLib('phpfox.database')->update(Phpfox::getT('user'), array('email' => $aVals['email']), "user_name = '" . Phpfox::getLib('phpfox.database')- >escape($aVals['user_name']) . "'");

SQL Quotes

Double quotes where applicable. Since SQL standard is to use single quotes within queries you must sometimes use double quotes especially when dealing with strings that need to be escape. Here is a wrong and right example:

Wrong

$aRows = Phpfox::getLib('phpfox.database')->select('phrase') ->from(Phpfox::getT('language_phrase')) ->where('phrase = "' . $aRow['var'] . '"') ->execute('getSlaveRows');

Right

$aRows = Phpfox::getLib('phpfox.database')->select('phrase') ->from(Phpfox::getT('language_phrase')) ->where('phrase = \'' . $aRow['var'] . '\'') ->execute('getSlaveRows');

Libraries

Log in / create account

Search
Search

Contents

[hide ]

1 Classes

o

1.1 Phpfox

1.1.1 run()

1.1.2 getLib()

1.1.3 getService()

1.1.4 getT()

1.1.5 getUserId()

1.1.6 getUserBy()

1.1.7 isUser()

1.1.8 getUserParam()

1.1.9 isAdminPanel()

1.1.10 getPhrase()

1.1.11 getParam()

1.1.12 addMessage()

1.1.13 setCookie()

1.1.14 getCookie()

o

1.2 Cache

1.2.1 set()

1.2.2 get()

1.2.3 save()

1.2.4 close()

1.2.5 remove()

1.2.5.1 name

1.2.5.2 sub string

1.2.5.3 all

1.2.6 isCached()

o

1.3 Request

1.3.1 get()

1.3.1.1 URL String ($_GET)

1.3.1.2 Form ($_POST)

1.3.2 getInt()

1.3.3 getArray()

1.3.4 getServer()

1.3.4.1 SERVER_NAME

1.3.4.2 HTTP_HOST

1.3.4.3 REMOTE_ADDR

1.3.4.4 PHPFOX_SERVER_ID

1.3.5 getBrowser()

1.3.6 send()

Classes

We will now go over the most used classes. We have listed the classes in order of its importance and by the frequency it is used.

Phpfox

Our main class is phpfox.class.php and can be found in the lib folder:

/include/library/phpfox/phpfox/

This class holds only static methods and is the most used class as it is what we use to connect to all libraries and modules. Below you will find the most common methods we use.

run()

We execute the script using the static method run(). If you check the /index.php file you will find the following:

Phpfox::run();

This calls the run() method and this is where all the magic happens.

getLib()

We discussed this method a little earlier and it is what we use to call other libraries.

getService()

We use this method to call a module service. More information regarding what a module service is and does will be mentioned later on. For the time being the method to call them is as follows:

Phpfox::getService('blog');

This would then require the following class and initiate the object

/module/blog/include/service/blog.class.php

To call a method from that class you could do:

Phpfox::getService('blog')->getBlogs();

This will then call the getBlogs() method. However if you are in a for loop or you plan to use the object more then once it might be a good idea to do the following:

$oServiceBlog = Phpfox::getService('blog');

$oServiceBlog->getBlogs();

$oServiceBlog->displayBlogs();

You may noticed we created the variable $oServiceBlog. It is important to prefix this variable with $oService so other developers know that this variable is an object and it is part of a service class. The variable ended with Blog and this will be easy to understand that the service class was blog.

If you were to get another class within the blog service folder you could do the following

Phpfox::getService('blog.process');

This would then require the following class and initiate the object

/module/blog/include/service/process.class.php

or

/module/blog/include/service/process/process.class.php

Similar to how libs get included the script will try to find the correct service file for you. Remember to name the variable connected with the service with the same name of the service being called. So with the above example the variable should be $oServiceBlogProcess.

getT()

It is the method used to get a database table name with the prefix specifically used for a site. It is very important to use this method with all database interactions which require the table name. You must use this method as sites have different prefixes and if you use the default prefix or none at all when you develop, this will cause severe problems for those that will use your module in the future. This method only has one parameter and that is the name of the database table. Here is an example of how it is used:

Phpfox::getLib('phpfox.database')->select('user_name')

->from(Phpfox::getT('user'))

->execute('getRows');

As you can see from the query above we used this method to get the table name user.

getUserId()

This method will retrieve the user_id for the current user that is logged in. This is useful when inserting or updating data for a specific user as many tables require the users user_id, which is what connects many tables to the user table. An example is:

Phpfox::getLib('phpfox.database')->update(Phpfox::getT('user'), array('email' => $aVals['email']), 'user_id = ' . Phpfox::getUserId());

This database query will update the users email and it does a check on the user_id, which you can see at the end. This method does not have any parameters and it will return 0 if a user is not logged in.

getUserBy()

This method retrieve specific data for the user that is logged in. Much like the getUserId() method, this method uses the first and only parameter to return the field we need. The supported fields that are returned are session_hash, id_hash, captcha_hash, user_id, server_id, user_id, user_name, user_image, password, password_salt, user_group_id and hide_tip. There are many more fields that could be returned from the user table, however these are the only ones we need on every page. So if we wanted to get the user name for the user that is logged in we could do the following:

Phpfox::getUserBy('user_name');

This will then return their user name.

isUser()

This is useful if you are creating a page that only allows members access to it. If for example you have created a new page and you only want members to view this page you could add the following:

if (!Phpfox::isUser())

{

exit('Need to be logged in!');

}

If a user is not logged in the script will exit and output the following on a blank white page:

Need to be logged in!

If you have properly created a phpFox controller, which you will learn shortly:

if (!Phpfox::isUser())

{

return Phpfox_Error::display('Need to be logged in!');

}

This will then use the phpFox template and display the message on the site instead of a blank white page. These 2 options are good but the best way to exit a controller that does not allow access to guests is to simply send them to the login page, which will also automatically redirect them back to the last page they visited thus making it a lot more user friendly. In order to do this you can add this instead:

Phpfox::isUser(true);

You may have noticed that this method did not require an if statement and was only one line of code. We simply used the first parameter, which when set to true (bool) it will redirect the user if they are not logged in.

getUserParam()

We have two types of settings that control how many of the features function. Some of these settings are global and anything changed from those settings will effect all users, however there is another setting group which controls settings for a specific user group. Since phpFox2 supports numerous user groups you can specify exactly how a user group should behave. In order to get the

value for a specific setting that controls how a user group behalves we use the method getUserParam. From the name you can understand that we will be getting a users parameter. The return value could be Strings, Arrays, Integers or Boolean. It really depends on the setting itself and what sort of information it holds. The most common return value is boolean and it returns either true or false. Lets take for example the Guest user group. Lets say we do not want them to view blogs and the variable name for this setting is blog.can_wiew_blogs (Note that the variable name can be found in the AdminCP and is defined by the one that created the setting). You can then do the following:

if (!Phpfox::getUserParam('blog.can_wiew_blogs'))

{

return Phpfox_Error::display('Not allowed to view blogs!');

}

From the example above you can see we used the first parameter for this method to identify which setting we would like returned. If it returned false we returned the script with an error message which will output the message:

Not allowed to view blogs!

If you do not want to display an error message and simply redirect them to the generic page that informs them that the feature they are trying to view/use is only allowed for certain user groups you can do the following:

Phpfox::getUserParam('blog.can_wiew_blogs', true);

As you can see we did not need an if statement any longer and we did everything in one line by adding a true (bool) to the 2nd parameter. Note that if the site allows subscriptions it will display a page guiding the user to upgrade their membership and if they are not logged in it will auto redirect to the login page.

Just like how other params work we always identify a param with what module it belongs to and in this case it would be the blog module.

isAdminPanel()

It may come up that you need to identify if a page you are viewing is being viewed from the AdminCP. This is very rare as this is usually required in the core source code, but in case you need such a function this will return a boolean true or false with the latter confirming that its not currently being viewed from the AdminCP.

getPhrase()

phpFox2 has multilingual support and because of this it is very important to use the Language Package. More detailed information regarding the language package will be looked over later however getPhrase() is the method we use to return a phrase from the current language package that is being used. If for example we have a phrase with the variable name user.user_not_logged_in and the phrase value was

You are not logged in!

In order to display the phrases value we can call this method from anywhere in the script by doing the following:

Phpfox::getPhrase('user.user_not_logged_in')

There are some phrases that have values that need to be replaced by new values. For example if we had the following phrase with the variable name user.welcome_back_user:

Hello, {user_name}. Welcome back!

Since each user has a different user name we need PHP to identify what the user name is and since phrases are stored in a language package and mass distributed we would need to create a system to allow certain words to be replaced with PHP variables. Using the above example you can replace {user_name} with the user name for the current user logged in by doing the following:

Phpfox::getPhrase('user.welcome_back_user', array('user_name' => Phpfox::getUserBy('user_name')))

Notice we added the following:

array('user_name' => Phpfox::getUserBy('user_name'))

Since we use an array you can replace as many strings as you need as long as they are surrounded by { and }.

getParam()

Similar to the method getUserParam() this method returns a global setting. These settings are found in

AdminCP >> Settings >> Manage Settings.

If for example we had a variable name core.site_title which holds the value for the sites name we could get this value by doing the following:

Phpfox::getParam('core.site_title')

addMessage()

You may find that you need to notify a user with a quick message at times. It requires extra work if you do this via the template so adding a message with the method addMessage is rather easy as it requires only one parameter and that is the actual message you want to pass. Note that this message will be displayed after you have called the method and its mostly used when sending the user to another page or refreshing the page after a posted form. To display this message on top of the main content under the main menu (depending on the template being used) you can do the following:

Phpfox::addMessage('Your blog has been added.');

This will then display the message:

Your blog has been added.

Note when redirecting users which you will learn how to do shortly has a parameter which you can pass a messages with thus leaving this method obsolete in many instances.

setCookie()

Cookies are really yummy and you can set them using this method. We allow 3 parameters with the first being the name of the cookie. The 2nd being the value of the cookie and the 3rd being how long the cookie should last. Note that 0 will expire after the user closes their browser and -1 will destroy the cookie. Here is an example of how to set a cookie:

Phpfox::setCookie('cookie_name', 'cookie_value');

From the example you can see we did not add a 3rd parameter as it defaults to 0.

getCookie()

In order to return the value of the cookie we us the method getCookie(). There is only one parameter and that is the first one which is used to identify the cookies name. Here is a working exmaple:

Phpfox::getCookie('cookie_name');

Cache

Class file: /include/library/phpfox/cache/cache.class.php

With phpFox2 we have focused greatly on caching a lot of the data that is being viewed but not constantly updated or the need to display live information not required. If we come across data that has the possibility of being cached we make sure we cache it and follow up on updating the cached data once it needs to be updated. We provide support for 3 different methods of caching. File, Memcache and APC. We recommend using both APC or Memcache, however flat file caching is the commonly used method as the other 2 requires configuring your server. Most of the data we cache is what we pull out from the database. Since pulling loads of information from the database can be very costly with memory consumption and overall performance of the script there are methods to help with this and caching is one of the most effective methods. The supported storage engines can be found in the folder:

/include/library/phpfox/cache/storage/

By default we automatically use the file storage engine. If using the file storage engine cached files are stored in flat files in the folder:

/file/cache/

The cache folder needs to be writable, however the file folder does not. All cached files have a check at the beginning of the file to make sure no direct access can be done. During development you can see the file names of the cached files, however during a live environment all cached files have an MD5() hashed name with a unique salt.

You can cache Strings, Integers, Boolean values or Arrays. You cannot store objects, sessions or sensitive information. Here is a working example of how to cache data being pulled from the database:

$oCache = Phpfox::getLib('phpfox.cache');

$sCachedId = $oCache->set('module'); if (!($aModules = $oCache->get($sCachedId)))

{

$aModules = Phpfox::getLib('phpfox.database')->select('m.module_id,

m.name')

->from(Phpfox::getT('module'), 'm') ->join(Phpfox::getT('product'), 'p', 'm.product_id = p.product_id AND p.is_active = 1') ->where('m.is_active = 1') ->order('m.name') ->execute('getRows');

$oCache->save($sCachedId, $aModules);

}

Now lets dissect the above example line by line.

First we call the cache object.

$oCache = Phpfox::getLib('phpfox.cache');

Next we set the unique name of the cache file to module. Make sure to pick a unique name that is related to what is being stored. In most cases we try to use the database table name. This method will return the unique cache id which we created the variable $sCachedId.

$sCachedId = $oCache->set('module');

Next we do an if statement to make sure not to run the query within the statement as that would be a waste of resources since the data is already cached.

if (!($aModules = $oCache->get($sCachedId)))

If the data is not cached then inside the if statement we first run an SQL query.

$aModules = Phpfox::getLib('phpfox.database')->select('m.module_id, m.name') ->from(Phpfox::getT('module'), 'm') ->join(Phpfox::getT('product'), 'p', 'm.product_id = p.product_id AND p.is_active = 1') ->where('m.is_active = 1') ->order('m.name') ->execute('getRows');

Once we ran the query we save the data using the save method. Remember for the first parameter you must add the unique cache id which you created a variable for with the set method. The 2nd parameter is what is used to store the data which in this case was an array.

$oCache->save($sCachedId, $aModules);

After the if statement, if you wanted to get all the modules which is what we pulled from the database you can use the variable $aModules which is what we created with the get method and if not cached it was then created by the SQL query. So the entire script would look like this:

$oCache = Phpfox::getLib('phpfox.cache'); $sCachedId = $oCache->set('module'); if (!($aModules = $oCache->get($sCachedId)))

{

$aModules = Phpfox::getLib('phpfox.database')->select('m.module_id,

m.name')

->from(Phpfox::getT('module'), 'm') ->join(Phpfox::getT('product'), 'p', 'm.product_id = p.product_id AND p.is_active = 1') ->where('m.is_active = 1') ->order('m.name') ->execute('getRows');

$oCache->save($sCachedId, $aModules);

}

foreach ($aModules as $aModule)

{

echo $aModule['name'];

}

set()

This method is used to create a unique name of the cache file. This must be a name that only uses characters from a-z and must be lowercase and cannot contain any other characters other then the

underscore

Here are some wrong and right examples:

Wrong

cacheName

another name

new-name

Right

cache_name

another_name

new_name

There is only one parameter and that is the name of file we plan to cache. Here is a working example:

$sCachedId = Phpfox::getLib('phpfox.cache')->set('module');

This method will return a unique string id.

get()

Use the get method to return the cached value. If the data has not yet been cached it will return a Boolean false. This method has 2 parameters with the first being the unique cache id which you created with the method set. The 2nd is an optional parameter and that is used if you want to limit how long the cached data can be cached before it has to be re-cached. Here is a working example without a time limit:

$aModules = Phpfox::getLib('phpfox.cache')->get($sCachedId);

Make sure to create a return variable otherwise you will not be able to retrieve your cached data which we created with the variable $aModules. Here is an example using this method with a time limit:

$aModules = Phpfox::getLib('phpfox.cache')->get($sCachedId, 15);

Notice we added a 15 for the 2nd parameter which stands for 15 minutes before the data has to be re-cached.

save()

You can save your data with the save method. This method has 2 parameters with the first being the unique cache id you got from the set method and the other the data we are going to cache. You can cache Strings, Integers, Boolean and Arrays. Here is a working example:

Phpfox::getLib('phpfox.cache')->save($sCachedId, $aModules);

Your cache connection is automatically closed once you have saved the data so there is no need to use the close method.

close()

You can close the cache connection you have open which was created with the set method. This method has one parameter which needs to pass the unique cache id.

remove()

Once you have cached data without a time limit then it will not get updated until you clear the cache which can be done with the remove method. This method provides the ability to remove cached data based on the name, sub string of a name or all of the cached data.

name

Pass the name of the unique ID you created earlier with the set method. So far we have used the name module as our unique cache name so using this as an example you can remove this cache file by doing the following:

Phpfox::getLib('phpfox.cache')->remove('module');

sub string

Pass the sub string of a name you created earlier with the set method. For example we cache several

types of language arrays which use the prefix language we can do a sub string remove like so:

So instead of removing these one by one

Phpfox::getLib('phpfox.cache')->remove('language', 'substr');

From the above example you can see we now used the 2nd parameter to pass the command we need to run which in this case was substr.

all

If you want to clear all the cached data you can do the following:

Phpfox::getLib('phpfox.cache')->remove();

This will remove every cached item.

isCached()

The isCached method is used to check if a file is cached. We don't use this method in public calls mainly because the method get has this method built in to it so you would end up running it twice and thus wasting resources. However, there are times when we must use this when trying to simply check if something is cached without the need to get it and if this is the case you can do the following:

if (!Phpfox::getLib('phpfox.cache')->isCached($sCacheId))

{

// Add stuff we need to cache.

}

With the above example you can see we used an if statement to check if a cache was set for the ID $sCacheId. It will return a Boolean true or false with the latter identifying that the data was not cached.

You can also check if a file has passed a certain time limit you have set which is handy to automatically update data without having to manually remove it. You can do this with the following method:

if (!Phpfox::getLib('phpfox.cache')->isCached($sCacheId, 15))

{

// Add stuff we need to cache.

}

We now added a 15 to the 2nd parameter which checks if the data is older then 15 minutes and it will return a Boolean false otherwise true if under or on the 15 minute mark.

Request

Class path: /include/library/phpfox/request/request.class.php

In order to get information from users we must understand the requests they are sending and to do this we use the Request class. Requests can be sent via a URL string or a form that is being posted.

get()

To get a request either from a URL string ($_GET) or passed via a form ($_POST and/or $_FILES) you can use the get method.

URL String ($_GET)

Getting from a URL string is a little different from the conventional method that would look something like this:

index.php?action=blog&id=1

Since we have a special way of creating short URLs that are easy to read and both user friendly the above would end up as:

index.php?do=/action_blog/id_1/

This example does not use the short URL method but you can get the idea of how to pass requests via a URL string. If you have short URLs setup it would look like this:

/action_blog/id_1/

Now to get the value of action the conventional method would be:

$_GET['action']

With phpFox2 you can get the value for action by using the following method:

Phpfox::getLib('phpfox.request')->get('action')

Usually its better to create a variable for the object since you will probably use the request object more then once. Here is an example:

$oRequest = Phpfox::getLib('phpfox.request'); $oRequest->get('action'); $oRequest->get('id');

So why use our method instead of the conventional method? The reason for this is since we provide

a special way to create short URLs this is the best way to pass values via a URL string and all data

being passed is parsed before you get the value so its safe before you even use it. Another problem we face with the conventional method is PHPs Magic Quotes, which will be removed with PHP6.

Using this method will fix this problem and if a server has this feature enabled or disabled it will function the same way. Another benefit is since we code in strict conditions you won't have to check if a request has been set thus adding more work for you to check each request with isset(). If

a request has not been set because it was not passed via the URL the method will return a Boolean

false and if you were to pass a 2nd parameter it will return that value as the default value. For example if we did not pass the action request via the URL and we wanted the variable that will be

set for this request to have a default value you can do the following:

$sAction = Phpfox::getLib('phpfox.request')->get('action', 'blog');

You will notice in the 2nd parameter we added blog and this method will return the string value blog if the action request was not set.

Form ($_POST)

Everything that applies to the URL String method of getting requests applies to this method other then the way it is passed. Since the URL String method uses the URL to pass requests the form method passes it via a form. For example if we had the following form:

<form method="post" action="index.php"> <input type="text" name="user_name" /> <input type="text" name="email" /> </form>

If you were to post the above form the requests would then be user_name and email. This works much like using the conventional method:

echo $_POST['user_name'];

Instead we use:

echo Phpfox::getLib('phpfox.request')->get('user_name');

getInt()

The method getInt works identical to the get method other then the fact that it only allows integers to be passed. Meaning if you were to pass a string or array it will default the value to 0. If an integer was passed it will then allow it and pass it to you.

getArray()

The getArray method works somewhat identical to that of the get method other then the fact that it only allows arrays to be passed. This is something we never use with the URL String method of passing requests. This is generally used with forms. Notice that most of our forms are built around the array val[] and as a rule if building a module or add-on for phpFox2 and if you are going to be passing more the one request via a form it must use the val[] array. Here is a wrong and right example of how a form should look when passing requests:

Wrong

<form method="post" action="index.php"> <input type="text" name="user_name" /> <input type="text" name="email" /> </form>

Right

<form method="post" action="index.php"> <input type="text" name="val[user_name]" /> <input type="text" name="val[email]" /> </form>

In order to get this request when being passed is to use the getArray method like so:

$aVals = Phpfox::getLib('phpfox.request')->get('val');

The variable we created $aVals will hold the array value for val[] so to echo the user_name and email you could do the following:

echo $aVals['user_name']; echo $aVals['email'];

Note that it is important to name the variable $aVals for requests you are retrieving via a posted form and if the form uses the val[] method. This way we all know that $aVals is a variable that is holding data that is being passed by a form.

getServer()

Instead of using $_SERVER[] we use our own method getServer(). The reason for this is some server environments might not have a variable you are looking for which will lead to a ugly PHP notice which we don't want to have. Plus we have added some of our own server variables. Note

that you can call anything via this method if its supported by $_SERVER[] and we will return it if it exists.

Below we have added some of our own variables that might be useful.

SERVER_NAME

Instead of using the default SERVER_NAME' we check if HTTP_X_FORWARDED_HOST is set because of our Server Load Balancing feature this needs to return the correct server. If HTTP_X_FORWARDED_HOST is not set then it will return SERVER_NAME as normal.

HTTP_HOST

Instead of using the default HTTP_HOST' we check if HTTP_X_FORWARDED_HOST is set because of our Server Load Balancing feature this needs to return the correct server. If HTTP_X_FORWARDED_HOST is not set then it will return HTTP_HOST as normal.

REMOTE_ADDR

Instead of using the default REMOTE_ADDR we try to find and return the users IP, which we try to find if they are hiding behind a proxy.

PHPFOX_SERVER_ID

If you have the Server Load Balancing feature enabled this is a variable we use to find out what server the user is currently on so we can use that information for benefits of the Server Load Balancing feature.

getBrowser()

It will return the browser that the user is using but will return it in a very short format such as

Firefox 3

or

IE 7

send()

At times we may need to send information to another server and at the same time retrieve the information from that server depending on the parameters we have sent. To do this you can use the send method. This method supports curl (POST & GET), file_get_contents (GET) and fsockopen (POST & GET). We use curl by default however some servers do not have support for this so we then try file_get_contents and for our last resport we use fsockopen.

This method has 3 parameters with only the first being required and is the full path to where you will be sending the request. The 2nd parameter is optional and is setup to allow an array of requests you plan to pass. These will end up as POST or GET requests depending on the 3rd parameter. For the 3rd parameter which is also optional is used to identify how you want to send the request and this can be POST or GET and defaults to POST if this parameter is left empty.

Here is a working example:

Phpfox::getLib('phpfox.request')->send('http://api.phpfox.com/', array( 'foo' => 'bar', 'var' => 'value'

));

Once the other server gets this request it can for example echo the following requests that were sent:

echo $_POST['foo']; echo "<br />"; echo $_POST['var'];

This output will be:

bar

value

Since we did not create a variable or echo the call from our side we won't see anything, however the other server will get the request and can handle the information without the user even knowing. If you want to return the value simply create a variable for the call like so:

$sRequest = Phpfox::getLib('phpfox.request')->send('http://api.phpfox.com/', array(

'foo' => 'bar', 'var' => 'value'

));

You could then use the variable $sRequest and if you were to echo it you would see the following output:

bar

value

Products

Log in / create account

Search
Search

[hide ]

1 Introduction

2 Creating a New Product

o

2.1 Product ID

o

2.2 Title

o

2.3 Description

o

2.4 Version

o

2.5 Product URL

o

2.6 Version Check URL

o

2.7 Active

Introduction

When you develop a module or plug-in it must belong to a product. Since you would be releasing your module or plug-in publicly it needs to be part of your unique product. Everything you create

within the AdminCP requires that it be part of a product. All the menus, phrases, settings etc

is provided with the script when you first install it is part of our product, which has the unique ID

phpfox. If you add menus or settings for example to your product and once you export your product it will be included in an XML file. From there you can release this as your product for others to install on their site.

that

Creating a New Product

Follow the guide below to create your first product. When creating your product add the values we added as we plan on using our sample product throughout this manual.

Log into your AdminCP and navigate to:

Extensions >> Product >> Create New Product

Next we need to fill out the form.

Product ID

This is the unique product ID you must create. It can have alphanumeric characters and the underscore (_). It must be lowercase. If you plan to release your product publicly it is vital you