Search user agents php array

Here is a php array of all search user agents (Crawlerlist) listed on www.useragentstring.com

public $botAgents = array(
	'008', 'ABACHOBot', 'Accoona-AI-Agent', 'AddSugarSpiderBot', 'AnyApexBot', 'Arachmo', 'B-l-i-t-z-B-O-T', 'Baiduspider', 'BecomeBot', 'BeslistBot', 'BillyBobBot', 'Bimbot', 'Bingbot',
	'BlitzBOT', 'boitho.com-dc', 'boitho.com-robot', 'btbot', 'CatchBot', 'Cerberian Drtrs', 'Charlotte', 'ConveraCrawler', 'cosmos', 'Covario IDS', 'DataparkSearch', 'DiamondBot', 'Discobot',
	'Dotbot', 'EARTHCOM.info', 'EmeraldShield.com WebBot', 'envolk[ITS]spider', 'EsperanzaBot', 'Exabot', 'FAST Enterprise Crawler', 'FAST-WebCrawler', 'FDSE robot', 'FindLinks',
	'FurlBot', 'FyberSpider', 'g2crawler', 'Gaisbot', 'GalaxyBot', 'genieBot', 'Gigabot', 'Girafabot', 'Googlebot', 'Googlebot-Image', 'GurujiBot', 'HappyFunBot', 'hl_ftien_spider', 'Holmes',
	'htdig', 'iaskspider', 'ia_archiver', 'iCCrawler', 'ichiro', 'igdeSpyder', 'IRLbot', 'IssueCrawler', 'Jaxified Bot', 'Jyxobot', 'KoepaBot', 'L.webis', 'LapozzBot', 'Larbin', 'LDSpider',
	'LexxeBot', 'Linguee Bot', 'LinkWalker', 'lmspider', 'lwp-trivial', 'mabontland', 'magpie-crawler', 'Mediapartners-Google', 'MJ12bot', 'MLBot', 'Mnogosearch', 'mogimogi', 'MojeekBot',
	'Moreoverbot', 'Morning Paper', 'msnbot', 'MSRBot', 'MVAClient', 'mxbot', 'NetResearchServer', 'NetSeer Crawler', 'NewsGator', 'NG-Search', 'nicebot', 'noxtrumbot', 'Nusearch Spider',
	'NutchCVS', 'Nymesis', 'obot', 'oegp', 'omgilibot', 'OmniExplorer_Bot', 'OOZBOT', 'Orbiter', 'PageBitesHyperBot', 'Peew', 'polybot', 'Pompos', 'PostPost', 'Psbot', 'PycURL', 'Qseero',
	'Radian6', 'RAMPyBot', 'RufusBot', 'SandCrawler', 'SBIder', 'ScoutJet', 'Scrubby', 'SearchSight', 'Seekbot', 'semanticdiscovery', 'Sensis Web Crawler', 'SEOChat::Bot', 'SeznamBot',
	'Shim-Crawler', 'ShopWiki', 'Shoula robot', 'silk', 'Sitebot', 'Snappy', 'sogou spider', 'Sosospider', 'Speedy Spider', 'Sqworm', 'StackRambler', 'suggybot', 'SurveyBot', 'SynooBot',
	'Teoma', 'TerrawizBot', 'TheSuBot', 'Thumbnail.CZ robot', 'TinEye', 'truwoGPS', 'TurnitinBot', 'TweetedTimes Bot', 'TwengaBot', 'updated', 'Urlfilebot', 'Vagabondo', 'VoilaBot', 'Vortex',
	'voyager', 'VYU2', 'webcollage', 'Websquash.com', 'wf84', 'WoFindeIch Robot', 'WomlpeFactory', 'Xaldon_WebSpider', 'yacy', 'Yahoo! Slurp', 'Yahoo! Slurp China', 'YahooSeeker',
	'YahooSeeker-Testing', 'YandexBot', 'YandexImages', 'YandexMetrika', 'Yasaklibot', 'Yeti', 'YodaoBot', 'yoogliFetchAgent', 'YoudaoBot', 'Zao', 'Zealbot', 'zspider', 'ZyBorg'
);

And this is one way to test if the current request is beeing made by a robot:

foreach($this->botAgents as $agent) {
	if (strstr($_SERVER['HTTP_USER_AGENT'], $agent )) {
		//We have a BOT
	}
}

How do I get javascript

Is the question “How do I get javascript?” the right one

Hello there, you are probably coming from Google. There are approximately two reasons for you to search about “How do I get javascript?”:

  • You want to enable javascript support in your browser.
  • You are curious about what javascript actually is.

Enabling javascript

First of all, make sure that you are using one of the mainstream browsers, and preferably – it’s latest version. If you are not sure how modern and good your browser is, make sure it is not Internet Explorer, but more likely Mozilla Firefox or Google Chrome.

Enabling Java Script in Mozilla Firefox:

  1. At the top of the Firefox window, click on the Edit menu and select Preferences
  2. In the Preferences window, select the Content panel.
  3. Enable JavaScript: Select this option to permit JavaScripts to execute on your computer.
  4. Click Close to close the window.

Edit - Preferences - Content - Enable JavaScript

Enabling Java Script in Google Chrome:

  1. On the web browser menu click on the Customize and control Google Chrome and select Settings.
  2. In the Settings section click on the Show advanced settings…
  3. Under the the Privacy click on the Content settings….
  4. When the dialog window opens, look for the JavaScript section and select Allow all sites to run JavaScript (recommended).
  5. Click on the OK button to close the window.

Customize - Settings - Show advanced - Privacy - Content - JavaScript - Allow

What is JavaScript

JavaScript is a popular scripting language, often built-in in modern browsers. It is being used to add interactive user experience to web sites. With javascript you can make all kinds of interactions, from effects and animations, to dynamically changing content and context switching. The most significant technology based on JavaScript is AJAX (Asynchronous JavaScript and XML) which is designed and dedicated to delivering dynamic content by making asynchronous web requests, without refreshing the current web page, or navigating the browser to a different web page. Take a look at other articles to learn more.

Zend_Service_Twitter and OAuth – How to use twitter API in Zend Framework

Zend_Service_Twitter, OAuth, Twitter API and how the f*ck to do it right..?

Using Zend Framework is a very pleasant thing, but sometimes you may.. sort of.. hit the wall. When you need to use Twitter Applications API in your web application, you may find some lack of information about the best practice and workflow of this subject. The flow is pretty simple actually, and I will explain it in short descriptions and code snippets as examples.

The flow

The first step is to build a method to authorize your application and to request permissions from the user. This is done by using the Zend_Oauth_Consumer library’s mechanism to obtain the so called “request token”. The request token is used later by your application, to authenticate it’s self and to obtain the “access token” needed to initialize the Zend_Service_Twitter.
Here is an example of how to do this:

	protected function _authTwitter()
	{
		$config = array(
			'callbackUrl' => $this->view->serverUrl() . '/tweet/twitter-callback',
			'siteUrl' => 'http://twitter.com/oauth',
			'consumerKey' => "YOUR_APPLICATION_KEY",
			'consumerSecret' => "YOUR_APPLICATION_SECRET"
		);

		$consumer = new Zend_Oauth_Consumer($config);

		$token = $consumer->getRequestToken(); //this may throw an exception if something goes wrong, so don't hesitate to try/catch it

		$this->session->twitter_request_token = serialize($token); //$this->session is an Zend_Session_Namespace instance, we save the request token in the session for later usage in the callback

		$consumer->redirect();
	}

The code above will redirect your application to twitter.com/oauth to request permissions from the user. This requires a “callback” url to land after finishing the process of authentication and authorization.
You should call this method when you don’t have a access token stored and you need to request permissions to perform an API call.

The second step is to implement the callback action method, to do the following tasks:

  1. Check if there is a request token set in the session to continue the OAuth authentication flow
  2. Check if there is an OAuth response in the $_GET
  3. If both conditions are true, initialize the Zend_Oauth_Consumer again and obtain access token, based on the signed request and the request token.
  4. If access token is granted, save it for later usage, if not, handle the exception and fallback
	public function twitterCallbackAction()
	{
		$config = array(
			'callbackUrl' => $this->view->serverUrl() . '/tweet/twitter-callback',
			'siteUrl' => 'http://twitter.com/oauth',
			'consumerKey' => "YOUR_APPLICATION_KEY",
			'consumerSecret' => "YOUR_APPLICATION_SECRET"
		);

		$consumer = new Zend_Oauth_Consumer($config);

		//$this->session is an instance of Zend_Session_Namespace
		if (!empty($_GET) && isset($this->session->twitter_request_token))
		{
			try
			{
				$token = $consumer->getAccessToken(
						$_GET, unserialize($this->session->twitter_request_token)
				);
			}
			catch (Exception $e)
			{
				$this->log("TWITTER SUBMIT TWEET ERROR: ".$e->getMessage());
				//$this->log is an instance of Zend_Log

				$this->_redirect("/tweet");
				
				return;
			}

			//save the access token and clear the request token			

			$this->session->twitter_access_token = serialize($token);

			$this->session->twitter_request_token = null;

			//go back to application

			$this->_redirect("/tweet");
		}
		else
		{
			$this->session->errors = array("Invalid twitter connection...");

			$this->_redirect("/tweet");
		}
	}

If everything goes well you can now implement a form, that will post a message to your application, that will be tweeted in the user’s twitter account. You may do a lot of things actually. Take a look at the official Zend_Service_Twitter API.

Here is a Zend_Service_Twitter example of a twitter API call:

	protected function _sendMessage($message)
	{
		$twitter = new Zend_Service_Twitter(array(
					'accessToken' => unserialize($this->session->twitter_access_token)
				));//use access token from session

		$response = $twitter->status->update($message); //post tweet (less than 140 chars)

		$this->log("TWITTER SUBMIT TWEET RESPONSE: ".$response); //log, just in case of failures
	}

Good luck and happy coding!

LESS CSS tutorial – the beginners guide to a CSS preprocessor. Learn about LESS and save your time repeating CSS code.

LESS CSS tutorial – the beginners guide to a CSS preprocessor.

What is less ?

LESS is a CSS preprocessor. It can solve common code problems, such as code repetition. LESS is crossbrowser friendly. Very intuitive and agile tool.
This is a short tutorial of LESS CSS including some tips.
Before we start i want you to know that there are other CSS preprocessor like SASS, that will be covered in another post.

This tutorial will cover the following:

  • What is the DRY(Don’t repeat yourself) design pattern. How can be implement on CSS using LESS CSS
  • Short introduction to LESS
  • Editors and IDE
  • Getting started with LESS
  • LESS CSS nesting – LESS gives you the ability to use nesting in your CSS!
  • LESS parameters – Finally variables in your CSS
  • LESS functions and operations
  • LESS mixins
  • Final Tips

DRY ( don’t repeat yourself )

DRY is not just a design patter, but it is a way of thinking and a principle of software development. Simple steps to follow, so you can get the idea of DRY.

  1. Identify repetitive and reusable code.
  2. Instead if copy/paste huge blocks of CSS code, you can create a function (Mixin) with LESS to be called when you need those styles
  3. Make use of the Nested Rules – which will cut down some of your repetitive code.
  4. Use variables, color functions, operators and mixins to separate structural code from representational code

By implementing DRY principles in your code you add also the KISS (Keep it simple, stupid!) design principle. When you need to change all the colors or fonts in your website – do it from one place via variables. When you need to change the behavior of all modal windows or popups – do it from one place using a mixin that generates those styles.
Q: Why you should bother with all of this?
A: The code repetion problem will expand in big and growing applications. At some point your code will become unmaintainable.

Short introduction to LESS

LESS expands the capabilities of CSS. It adds more features and agile solutions to common CSS problems. LESS is crossbrowser friendly.

Editors and IDE

A preferred LESS editor – sublime text 2.

LESS syntax is supported by many IDE’s like – VIM, Aptana Studio, Coda 2

Getting started with LESS

First you must download the latest less.js from github – https://github.com/cloudhead/less.js or the official site http://lesscss.org

You will need to create a file with .less extension to put your styles there. Preferred is styles.less

Add the less.js and styles.less to your HTML’s head section:

<link rel="stylesheet/less" type="text/css" href="styles.less">
<script src="less.js" type="text/javascript"></script>

Note the rel attribute of the link element must end with /less in order for LESS to work. You are also required to include the less.js script immediately after the link to the style sheet. If you’re using HTML5 syntax, you can omit the type=”text/css” and the type=”text/javascript”, but do not omit rel=”stylesheet/less”.

Server-side version of LESS – The easiest way to install LESS on the server is with Node Package Manager (NPM). Installations are available for Windows, OSX, UNIX

LESS CSS nesting

// Brand, links, text, and buttons
.navbar {
    text-align: center;
    // Hover and active states
    .brand:hover {
        text-decoration: none;
    }
    .btn-danger{
        float: right;
    }
    // Website or project name
    .brand {
        float: left;
        display: block;
        padding: 8px 20px 8px;
        color: @white;
    }
    // Plain text in topbar
    .navbar-text {
        margin-bottom: 0;
        line-height: 40px;
        color: @navbarText;

        a:hover {
          color: @white;
          background-color: transparent;
        }
    }
    // Buttons in navbar
    .btn,
    .btn-group {
        margin-top: 5px;
    }
    .btn-group .btn {
        margin-top: 0;
    }
}

LESS gives you the ability to use nesting in your CSS!
With the use of & combinator you can nest selector to concatenate the child to its parent selector, instead of acting as a descendant. This is very usefull for pseudo-classes like :hover, :visited and :focus.
With the ability to nest styles your code is more readable and consistent.

LESS parameters

// Accent colors
// -------------------------
@blue:                  #049cdb;
@blueDark:              #0064cd;
@green:                 #46a546;
@red:                   #9d261d;
@yellow:                #ffc40d;
@orange:                #f89406;
@pink:                  #c3325f;
@purple:                #7a43b6;

// Typography
// -------------------------
@sansFontFamily:        "Helvetica Neue", Helvetica, Arial, sans-serif;
@serifFontFamily:       Georgia, "Times New Roman", Times, serif;
@monoFontFamily:        Monaco, Menlo, Consolas, "Courier New", monospace;
@smallFonts:               Helvetica, Arial, sans-serif;

Finally variables!

Variables in LESS are defined via the keyword ‘@’
Variables can have value type of string or number. You can easy separate the presentational part of your layout like colors and fonts. Using variables will help you keep the consistency of your code. When you have all colors defined you don’t need any more to search and scroll for their hex values.

It’s a good practice to define all your variables in separated LESS file and include it on top of your main LESS file

LESS functions and operations

@linkColor:             @blueType;
@linkColorHover:        darken(@blueType, 15%);
@gridColumns1200:            12;      
@gridColumnWidth1200:     90px;
@gridGutterWidth1200:     10px;
@gridRowWidth1200:        (@gridColumns1200 * @gridColumnWidth1200) + (@gridGutterWidth1200 * (@gridColumns1200 + 1));

When using functions and arithmetical operations, the result will be a value
You can add, multiply or divide – pixel, em, %, hex values. Functions are mainly used to help you stick to a color scheme in your coding process. There is no need to go into photoshop and lighten a color with 10% for example.

LESS mixins

// Gradients
#gradient {
  .horizontal(@startColor: #555, @endColor: #333) {
    background-color: @endColor;
    background-image: -moz-linear-gradient(left, @startColor, @endColor); // FF 3.6+
    background-image: -webkit-gradient(linear, 0 0, 100% 0, from(@startColor), to(@endColor)); // Safari 4+, Chrome 2+
    background-image: -webkit-linear-gradient(left, @startColor, @endColor); // Safari 5.1+, Chrome 10+
    background-image: -o-linear-gradient(left, @startColor, @endColor); // Opera 11.10
    background-image: linear-gradient(to right, @startColor, @endColor); // Standard, IE10
    background-repeat: repeat-x;
    filter: e(%("progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)",argb(@startColor),argb(@endColor))); // IE9 and down
  }
}

Mixins are functions that let you implement OOCSS (Object Orientated CSS) principles in your styles. By separating identical styles from elements and using css class inheritance, you can decrease the number of repeated styles. That will help you reduce the CSS file size. This practice is the key foundation of DRY principles and design pattern. You can read more about OOCSS in the following links: http://www.slideshare.net/stubbornella/object-oriented-css, http://www.slideshare.net/stubbornella/what-is-object-oriented-css.

The execution of a mixin will return a block of CSS code. For example all your modal windows will include the .modal-behaviour() and .border-radius() mixins

If you were wondering, can be passed an argument to a mixin? Yes you can. That is another power full feature ot he mixins. You can set default values to your arguments, and pass other to override them. With passing a parameter to a mixin it becomes more flexible and reusable.

// Box sizing Mixin
.box-sizing(@boxmodel) {
  -webkit-box-sizing: @boxmodel;
     -moz-box-sizing: @boxmodel;
          box-sizing: @boxmodel;
}
// Block level inputs
.input-block-level {
  display: block;
  width: 100%;
  min-height: 30px; 
  .box-sizing(border-box); // using a mixin
}

Another good feature of Mixins is to store them in namespaces. For example you want all your font mixins to be stored in #fonts namespace:

// FONTS
// --------------------------------------------------

#font {
  #family {
    .serif() {
      font-family: @serifFontFamily;
    }
    .sans-serif() {
      font-family: @sansFontFamily;
    }
    .monospace() {
      font-family: @monoFontFamily;
    }
  }
  .shorthand(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
    font-size: @size;
    font-weight: @weight;
    line-height: @lineHeight;
  }
  .serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
    #font > #family > .serif;
    #font > .shorthand(@size, @weight, @lineHeight);
  }
  .sans-serif(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
    #font > #family > .sans-serif;
    #font > .shorthand(@size, @weight, @lineHeight);
  }
  .monospace(@size: @baseFontSize, @weight: normal, @lineHeight: @baseLineHeight) {
    #font > #family > .monospace;
    #font > .shorthand(@size, @weight, @lineHeight);
  }
} 

Final Tips

  • Keep your code simple and consistent
  • Use DRY principles where possible
  • For better understanding and implementation of OOCSS use a LESS framework like Bootstrap
  • There are many many more things that can be said about LESS. For example LESS preferred frameworks. Advanced techniques for rapid web development and prototyping. Fluid and fixed layouts. Grid system generator mixins. Best practices for development and production environments. Mobile and tablet development. Quick retina displays enhancements and support. All topics will be featured in a separated advanced LESS CSS tutorial. If you enjoy writing less code, please check out the next tutorial as soon it is available :)

    There are useful links available at the end of the presentation.

    In general – write LESS do more! This is the major feature of LESS.
    The LESS CSS tutorial is formatted as a presentation – LESS presentation

Zend twitter view helper for better user experience

Displaying tweets on a website in the same manner that twitter displays them is a nice user friendly feature to have. Shown bellow is the source for a zend twitter view helper. It should be placed in the “views/helpers” directory in your project in a file named Twitter.php.

<?php
class Zend_View_Helper_Twitter extends Zend_View_Helper_Abstract
{
	public function twitter()
	{
		return $this;
	}

	public function linkifyUsernames($tweet)
	{
		return preg_replace("/@(\w+)/i", "<a href=\"http://twitter.com/$1\" target=\"_blank\">$0</a>", $tweet);
	}

	public function linkifyHashTags($tweet)
	{
		return preg_replace("/#(\w+)/i", "<a href=\"http://twitter.com/#!/search/%23$1\" target=\"_blank\">$0</a>", $tweet);
	}

	public function linkify($tweet)
	{
		$tweet = $this->linkifyUsernames($tweet);
		$tweet = $this->linkifyHashTags($tweet);

		return $tweet;
	}
}

Usage

After you create the file this zend twitter view helper can be used from your view script by calling the twitter() method and then using either linkifyUsernames(), linkifyHashTags() or just linkify() to linkify both usernames and hashtags.

The regular expressions will convert #anystring to

<a href="http://twitter.com/#!/search/#anystring" target="blank">#anystring</a>

and @anyone to

<a href="http://twitter.com/@anyone" target="blank">@anyone</a>

Example

In a view script:

<?php echo $this->twitter()->linkify("Lorem @ipsum dolor #sit amet, consetetur sadipscing @elitr, sed diam nonumyeirmod #tempor invidunt ut #labore et dolore magna"); ?>

will output:
Lorem @ipsum dolor #sit amet, consetetur sadipscing @elitr, sed diam nonumyeirmod #tempor invidunt ut #labore et dolore magna

Numeric only inputs with jQuery

This little jQuery snippet will let you to quickly create a numeric only textbox (input). A nice feature to include for improved user experience.

$.fn.numericOnly = function(decimal, callback) {
	var $el = $(this);
	$el.keydown(function(event) {
		var allowedKeycodes = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 8, 9,
					96, 97, 98, 99, 100, 101, 102, 103, 104, 105];

		if(decimal && $el.val().indexOf('.') == -1) {
			allowedKeycodes.push(190);
			allowedKeycodes.push(110);
		}

		if($.inArray(event.which, allowedKeycodes) == -1) {
			if(callback) callback.call($el);
			event.preventDefault();
		}

		return true;
	});
}

Click Here for the demo.

Making numeric only textbox

To setup the numeric only plugin with its default settings use:

$("#input_id").numericOnly();

And it will disallow entering non numeric characters.

To allow decimal numbers pass true as the first parameter:

$("#input_decimal").numericOnly(true);

And the plugin will allow the input of one “.” decimal point.

For giving a visual feedback effect when user tries to type a illegal character one can use the callback function. The bellow example will make the border of the input red for 300 miliseconds:

$("#numeric_only_callback").numericOnly(true, function(){
	var oldBorder = this.css('border-color');

	this.css('border-color', 'red');

	var el = this;
	setTimeout(function(){
		el.css('border-color', oldBorder);
	},300);
});

This is not a replacement for the server-side validation. Just an easy way to enhance user experience.

Zend Framework Configure Console Tool

The tool

Zend Framework ships with a library folder and bin folder. The library folder contains all the good stuff and the bin folder contains the ZF console tool. This tool is often ignored and unused, which usually leads to statements like “what a stupid framework, I don’t like it”. The tool consists of a launcher (.bat/.sh) that initialized the zf.php file, which actually just facilitates access to the Zend_Tool package and your custom project providers and manifests. Manifests are used to import custom (non-standard) providers and providers are just classes with action methods. Each action method should be named as a verb, that indicates the action that will be taken over the project, in term of the provider name. For example “create controller” is a zf tool command that runs create() method in the controller provider. The main purpose of all this is to be able to add custom automated functionalities to your project, but could also be used for maintenance and scheduled tasks.

The setup

Setting up the ZF console tool is actually pretty easy. As long as you don’t make any preliminary mistakes.
Possible faults are:

  1. Make sure that there is NO .zf.ini inside your home directory (/home/username in linux and C:\Users\Username in.. you know)
  2. Make sure that there is no hardcoded include path that leads to the Zend folder:
      php -r "echo ini_get('include_path').PHP_EOL;"
      
  3. Make sure you have a valid .zfproject.xml file in your project directory. If not, running ./zf.sh create poject in the original bin folder extracted from the archive will create a new empty project with valid .zfproject.xml file. In addition, make sure that the <projectProviderFolder/> in the xml file is enabled.
  4. Make sure you have a copy of Zend Framework in the library folder of your project.
  5. Make sure your library folder is configured as an include path in your project’s application.ini
  6.   includePaths.library = APPLICATION_PATH "/../library"
      

After validating the points above just copy the original bin folder from the extracted archive in your project’s root directory.

Running

To launch the zf console tool simply type in your terminal from your project’s root directory:

./bin/zf.sh

If everything goes well you should see a list of all available providers and their actions. Now you can use the tool to create modules, controllers, actions, dummy dbtable models and etc. You can also write your own project providers to extend the functionalities of the zf console tool.

Zend Framework 1.11 and CRON jobs. Wait, wut?

Setup Zend Framework CRON jobs

Setup CRON jobs for Zend Framework applications? Yes it is possible and actually it’s pretty simple and elegant. Read below to see how to use create zend framework cron jobs.

CRON

Every serious web application demands large and/or heavy amounts of calculations to be made, or data to be prepared outside the client flow. Probably the best solution for this is to run CRON jobs. Running CRONs is sometimes pretty easy, just execute a .php file, it does what it does and that’s it, but when it comes to ZF, you may need to use more than just custom initialized PDO and files I/O. If you need to run Zend_Db, Zend_Db_Table models, Zend_Cache, or other Zend Framework libraries in your CRON, you will need to do it The Zend Way.

How

Just create a project provider in your project’s directory, using your ZF console tool. To do so, make sure you have a working ZF tool and run:

./bin/zf.sh create project-provider MyCron run

You can verify the results of this operation by taking a look inside your project’s “providers” directory and by running the ZF tool again to list the available providers and actions:

./bin/zf.sh

The next step is to open the provider file in the “providers” directory and add an init() method as a private or protected method, depending on whether you are going to extend this provider or not. Public methods are visible in ZF tool, so the init method should never be public.

    /**
     * @var Zend_Db_Adapter_Abstract
     */
    private $db;
    
    /**
     *
     * @var array 
     */
    private $config;

    private function init()
    {
	$this->_loadProfile(self::NO_PROFILE_THROW_EXCEPTION); //load .zfproject.xml

	$bootstrapResource = $this->_loadedProfile->search('BootstrapFile'); //get application bootstrap

	/* @var $zendApp Zend_Application */
	$zendApp = $bootstrapResource->getApplicationInstance(); //initialize application instance

	try
	{
	    //bootstrap resource plugins for later usage
	    $zendApp->bootstrap('log');
	    $zendApp->bootstrap('cachemanager');
	    $zendApp->bootstrap('db');

            //new Zend_Session_Namespace(); //uncomment if you are going to use Facebook API, prevents from session_start bug
        }
	catch (Zend_Application_Exception $e)
	{
	    throw new Zend_Tool_Project_Provider_Exception($e->getMessage());
	}
        
	$this->db = $zendApp->getBootstrap()->getResource('db')->getConnection(); //get database instance for later usage

	$this->config = $zendApp->getOptions(); //get the contents of application.ini as array
    }

Now, you can use the init() method inside your action methods to configure the povider.

    public function run()
    {
	$this->init();

	//awsome stuff go here
    }


CRONTAB Setup

The final step is to setup your crontab to execute the ZF console tool and your project provider at predefined time intervals or events. To do this, edit the file, opened by “crontab -e” command

* * * * * cd /path/to/project && ./bin/zf.sh run my-cron

This for example will execute the project provider’s run() method each and every minute. For more information about CRONTAB settings, see here or run “man crontab

Zend Framework Cheat Sheet

Zend Framework is very powerful, and many people do not use it at it’s full potential. This Zend Framework Cheat Sheet serves as a guide to supper often used build in methods, helpers and classes.

The Zend Framework Cheat Sheet is designed to live on the developer’s bookmarks bar, to make life a bit easier. A description of what is on the cheat sheet follows, or if you are impatient, you can go straight to the full size Zend Framework cheat sheet.

PNG, 314kb
HTML Version

The request object

The request object is very heavily used in action controllers for various tasks. The cheat sheet includes the most common ones like getting params, determining the HTTP method or retrieving information about the current controller/action.

Action Helpers

Again action helpers are something that is constantly used. Some tend to ignore them and write beautiful code:

//at the end of some action
die(json_encode($response));

The included action helpers are the ones that can be used with just copying and pasting. For more complex usage and full reference you can check out the official guide.

View Helpers From the controller

This section provides snippets for accessing the view helpers from the controller. These actions can be done from the view also, but in a lot of cases the controller is a bit more “aware” of what has to be added to the head of the page.

The response object

The response object is the logical counterpart to the request object. Typically is not used as much as the request object, but it would be a loss to not include some of it’s methods in the cheat sheet.

Recommended Project Directory Structure

Since Zend Framework is so liberal (and highly configurable) about where files are stored, developers can find themselves wondering where is the “right” place for a particular resource. The cheat sheet includes the project structure as proposed by the official guide

View Helpers

The problem with view helpers is that a lot of IDE’s can’t autocomplete them. Having a quick peak at the cheat sheet will quickly save you from having to digg it out from the official documentation. Some of the included helpers are the action helper, partial helper, placeholder helper, doctype helper, all the head-Stuff helpers and some more.

Getting stuff anywhere

Often one finds himself in a file far far away in a need of an object. What follows is a web search “zend, how can i get {insert class name here} anywhere”. The cheat sheet includes static calls for retrieving often used objects such as the request, response, view, database adapter, the bootstrap, configuration options, auth instance and a particular cache instance.

Download

So now that you know what it does, please feel free to bookmark/download/print out the Zend Framework cheat sheet:

PNG, 314kb
HTML Version

Please note: If you wish to link to the Zend Framework cheat sheet from elsewhere, please link to this page so others find the description, rather than linking directly to the sheet.

Keep application.ini in version control without conflicting

The Problem with application.ini

One of the most common problems when working on large projects with several people are the different configurations. For example: every developer may have different application.ini configuration settings or different include paths on his system, moreover on the staging and live environment the configuration will differ for sure from what is being kept in version control.

One way I’ve seen this being handled is to use the configuration extending functionality provided by Zend, so there is a [production] section, [development : production] section, and from there every developer defines it’s own section (ex. [samurai : development]) and so on. This is a working approach to the problem but it has several drawbacks:

  • Everybody sees everybody’s database login credentials and other configuration setting that may be private in some way (ex. passwords)
  • The application.ini becomes a huge sheet full with sections overriding one another that have nothing to do with the actual project.

Keeping the configurations out of version control is also a bad idea when it comes to deployment of the project on a server or on another developer machine since someone will have to send the latest copy of his configuration to the person doing the deployment. Also if a certain task requires adding a new configuration option it will be inefficient sending the change to the other team members by mail, chat or some other means of communication.

The Solution

A very practical solution is to have two configurations – one that stays in version control and one that every developer creates manually on his machine. Then regardless of what section of the application.ini the project is currently using (development, production, etc.) the values from the local non-versioned configuration override the values from the “official” application.ini that stays under version control.

For example the project’s application.ini looks like this:

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0

resources.db.adapter = "mysqli"
resources.db.params.host = "localhost"
resources.db.params.username = "production_db_username"
resources.db.params.password = "production_db_password"
resources.db.params.dbname = "production_db_name"
resources.db.isDefaultTableAdapter = true
resources.db.params.charset = "utf8"

;... imagine other configuration stuff here ...

[staging : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 0

resources.db.params.username = "staging_db_username"
resources.db.params.password = "staging_db_password"
resources.db.params.dbname = "staging_db_name"

And everyone can create in the “application/configs” directory a file called application.local.ini that looks like this:

phpSettings.display_errors = 1

resources.db.params.username = "staging_db_username"
resources.db.params.password = "staging_db_password"
resources.db.params.dbname = "staging_db_name"

And override the settings in the currently loaded section.

This functionality doesn’t come built in Zend, but it isn’t difficult at all adding it. Just edit the application/Bootstrap.php file and override the __construct method like this:

public function __construct($application)
{
    /* @var $application Zend_Application|Zend_Application_Bootstrap_Bootstrapper */

    $applicationConfig = new Zend_Config($application->getOptions(), true);

    // overriding default configs with default configurations
    $applicationLocalConfigPath = APPLICATION_PATH . '/configs/application.local.ini';
    
    if(is_readable($applicationLocalConfigPath))
    {
        $applicationLocalConfig = new Zend_Config_Ini($applicationLocalConfigPath);
        $applicationConfig->merge($applicationLocalConfig);
    }

    $this->setApplication($application);
    $options = $applicationConfig->toArray();
    $this->setOptions($options);

    if($application->hasOption('resourceloader'))
    {
        $this->setOptions(array(
            'resourceloader' => $application->getOption('resourceloader')
        ));
    }
 
    $this->getResourceLoader();

    if(!$this->hasPluginResource('FrontController'))
    {
        $this->registerPluginResource('FrontController');
    }
}

And it will search for application.local.ini file in application/configs and will merge the currently loaded section of the application.ini with the local settings. Also it’s a good idea to configure the project repository to ignore the application.local.ini file if someone accidentally tries to add/commit it.