Redirect sub-sub-domains to dynamically configured virtual hosts on the localhost.

0

A colleague (thanks Danny) pointed me to this solution to host multiple development environments under a single sub-domain name.

Step 1. Configure a type A domain record by using a wildcard and a fixed sub-domain name like:

*.lab    A    127.0.0.1

( why didn’t I think of that x_X )

Step 2. Enable mod_vhost_alias in Apache if not already active.

Step 3. Configure a virtual host and use the wildcards from mod_vhost_alias to your liking, for example

<VirtualHost 127.0.0.1:80>
    ServerName lab.yourdomain.com
    VirtualDocumentRoot /var/my_flexible_friends/%1
</VirtualHost>

would redirect myproject.lab.yourdomain.com to 127.0.0.1 and serve pages from /var/my_flexible_friends/myproject but would also redirect jquery.lab.yourdomain.com to 127.0.0.1 and serve pages from /var/my_flexible_friends/jquery.

Just look at the mod_vhost_alias documentation for more possibilities.
Also a nice consistent setup to share in development teams.

If you happen to stumble upon apache error messages like ‘Request exceeded the limit of 10 internal redirects due to probable configuration error.’, just change your .htaccess file by added the rule RewriteBase /. This will most likely happen when you are using the windows hosts file instead of a real domain.

See also Stackoverflow Infinite Rewrite Loop

SetEnv APPLICATION_ENV development
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteBase /
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

I guess PhpStorm does not love OpenJDK

0

OpenJDK Runtime Environment (IcedTea6 1.9.10) (6b20-1.9.10-0ubuntu1~10.04.2)
OpenJDK Client VM (build 19.0-b09, mixed mode, sharing)
WARNING: You are launching IDE using OpenJDK Java runtime

THIS IS STRICTLY UNSUPPORTED DUE TO KNOWN PERFORMANCE AND GRAPHICS PROBLEMS

NOTE: If you have both Sun JDK and OpenJDK installed
please validate either WEBIDE_JDK or JDK_HOME environment variable points to valid Sun JDK installation

Ubuntu Sun (Oracle) Java Installation Guide

sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo apt-get update
aptitude install sun-java6-jdk
sudo update-alternatives --config java

Donating my upper lip to fight cancer (Movember Time!), please donate too!

0


Movember!

Disable Apache 404 ErrorDocument HTML

0

While implementing a REST service, Apache started to append HTML 404 error HTML to my custom 404 application/json response.
It seems the Windows Apache version which comes with Zend Server requires a httpd.conf entry to disable the HTML to be appended to the response:

To disable it for a 404 error:
ErrorDocument 404 ” ”

So in general:
ErrorDocument ” ”

It’s weird though that the Linux version does not append this HTML error code by default.

PHPDoc an Array Param (in Zend Framework)

0

I found this code snippet which shows how array based parameters should be documented with PHPDoc (in ZF projects). The topic came up because I’m always nagging about those magic functions and magic properties in ZF and how poorly they are documented. It seems we’ve been neglecting adding PHPDoc tags a bit because PHPDoc does have support to document magic methods and magic class properties:

@method Magic Properties

@property Magic Methods

/**
* $args may contain the following keys:
* - var1:
* - var2:
*
* @param array @args
* @return void
*/

Items prefixed with a ‘- ‘ will be treated as bullets by phpDocumentor.

source: zend framework community

I’m currently piloting PhpStorm because I had some issues with Zend Studio, it’s interesting to notice that a phpdoc line like:

/*
 * @return Foo[]
 */
function getList() {
   $f = array();
   $f[] = new Foo();
   ...
   return $f;
}

triggers auto-completion in PhpStorm when looping over the return value like:

$list = $this->getList();
foreach($list as $l) {
    $l->(starts auto-completion ...)
}

Zend Tool Cheat Sheet (v1.11.10)

1
Zend Framework Command Line Console Tool v1.11.10
Usage:
zf [--global-opts] action-name [--action-opts] provider-name [--provider-opts] [provider parameters ...]
Note: You may use “?” in any place of the above usage string to ask for more specific help information.
Example: “zf ? version” will list all available actions for the version provider.Providers and their actions:

Version
zf show version mode[=mini] name-included[=1]
Note: There are specialties, use zf show version.? to get specific help on them.Config
zf create config
zf show config
zf enable config
Note: There are specialties, use zf enable config.? to get specific help on them.
zf disable config
Note: There are specialties, use zf disable config.? to get specific help on them.

Phpinfo
zf show phpinfo

Manifest
zf show manifest

Profile
zf show profile

Project
zf create project path name-of-profile file-of-profile
zf show project
Note: There are specialties, use zf show project.? to get specific help on them.

Application
zf change application.class-name-prefix class-name-prefix

Model
zf create model name module

View
zf create view controller-name action-name-or-simple-name module

Controller
zf create controller name index-action-included[=1] module

Action
zf create action name controller-name[=Index] view-included[=1] module

Module
zf create module name

Form
zf enable form module
zf create form name module

Layout
zf enable layout
zf disable layout

DbAdapter
zf configure db-adapter dsn section-name[=production]

DbTable
zf create db-table name actual-table-name module force-overwrite
Note: There are specialties, use zf create db-table.? to get specific help on them.

ProjectProvider
zf create project-provider name actions

Examples (Windows):

zf create project ./
zf create module test
zf create controller Test index-action-included=1 test

Remarks:
- The Zend Tool will maintain a xml based configuration file called ‘.zfproject.xml’, do not remove!
- Zend Tool is case sensitive, thus “zf create module blog” and “zf create module Blog” are different commands, running them both will create 2 modules (in Windows it will only result in 1 module directory though!)
- The create module command did not create a module Bootstrap file
- The bootstrap file in the tests directory has a lowercase ‘b’ which probably needs to be an uppercase like ‘Bootstrap.php’
- Note: PHPUnit is required in order to generate controller test stubs.
- For a module Bootstrap to work, the application.ini needs resources.modules = ""

A simple module Bootstrap looks like:

<?php
class Yourmodulename_Bootstrap extends Zend_Application_Module_Bootstrap {
	protected function _initSomething () {
    }
}

ZF ReCaptcha Inline Configuration Code Snippet

0

Somehow it’s always a pain to find the right configuration parameters and proper format in ZF which makes me reverse engineer them.

$this->captcha = new Zend_Form_Element_Captcha('captcha',
	array(
		'captcha'=>array ('ReCaptcha'),
		'captchaOptions'=>array (
			'pubkey'=>'...',
			'privkey'=>'...'
		)
	)
);

Show the LIVE Status from an OWN3D.TV Livestream with a jQuery Plugin

4

Demo
jQuery plug-in source at BitBucket

Examples of how to use the plug-in.

// global configuration options
$.own3d.liveurl = 'http://ingol.nl/own3d/live.php';
$.own3d.channelurl = 'http://ingol.nl/own3d/channel.php';

// A single stream
$('#own3d-cowclan').own3d({liveid:'1213', title:'COWCLAN'});
// A single stream with HD
$('#own3d-rebootgpf').own3d({liveid:'1208', title:'REBOOTGPF', hd:true});
// A single stream without title
$('#own3d-1208').own3d({liveid:'1208', hd:true, embed:true, channelid: 'orlissenberg'});
// A single channel, live streams only
$('#channel').own3d({channelid:'clgame', hd:true, embed:true});
// A single channel, live and offline streams
$('#channel-all').own3d({channelid:'clgame', hd:true, showall:true});

The jQuery OWN3D Plug-in Code.

(function($){
  $.own3d = {
    liveurl : 'live.php',
    channelurl : 'channel.php'
  };

  $.fn.own3d = function(options) {
    return this.each(function(){
      var self = $(this);
      self.data('liveid', options.liveid);

      if (options &amp;amp;&amp;amp; options.liveid) {
        $.ajax({
            type: &amp;quot;GET&amp;quot;,
            async: true,
            data: {live_id:options.liveid},
            url: $.own3d.liveurl,
            dataType: &amp;quot;jsonp&amp;quot;,
            success: function(data){
              var title = (options.title) ? options.title : 'OWN3D CHANNEL ['+options.liveid+']';
              var liveclass = (options.hd) ? 'own3d-live-hd' : 'own3d-live';

              self.empty();
              self.addClass('own3d');

              var link = $('&amp;lt;a/&amp;gt;')
                  .attr('href','http://www.own3d.tv/live/'+options.liveid)
                  .attr('target','_blank');

              if (data.isLive &amp;amp;&amp;amp; data.isLive == 'true') {
                link.html(title+' - LIVE (viewers: '+data.liveViewers+' - duration: '+Math.round(parseInt(data.liveDuration) / 60)+' minutes)');

                if ((options.showthumbnail || options.embed) &amp;amp;&amp;amp; options.channelid) {
                  $.ajax({
                      type: &amp;quot;GET&amp;quot;,
                      async: true,
                      data: {channel_id : options.channelid, stream_guid : 'http://www.own3d.tv/live/'+options.liveid},
                      url: $.own3d.channelurl,
                      dataType: &amp;quot;jsonp&amp;quot;,
                      success: function(data){
                        if (options.showthumbnail &amp;amp;&amp;amp; data.thumbnail) {
                          var table = $('&amp;lt;table/&amp;gt;');

                          var status = $('&amp;lt;td/&amp;gt;').append($('&amp;lt;div/&amp;gt;').addClass(liveclass).append(link));
                          table.append($('&amp;lt;tr/&amp;gt;').append(status));

                          var thumbnail = $('&amp;lt;td/&amp;gt;').append($('&amp;lt;img/&amp;gt;').attr('src',data.thumbnail));
                          table.append($('&amp;lt;tr/&amp;gt;').append(thumbnail));

                          self.append(table);
                        } else if (options.embed &amp;amp;&amp;amp; data.title) {

                            var e = '&amp;lt;iframe height=&amp;quot;360&amp;quot; width=&amp;quot;640&amp;quot; frameborder=&amp;quot;0&amp;quot; src=&amp;quot;http://www.own3d.tv/liveembed/'+self.data('liveid')+'&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;';
                            var table = $('&amp;lt;table/&amp;gt;');

                            var status = $('&amp;lt;td/&amp;gt;').append($('&amp;lt;div/&amp;gt;').addClass(liveclass).append(link));
                            table.append($('&amp;lt;tr/&amp;gt;').append(status));

                            var embeddedplayer = $('&amp;lt;td/&amp;gt;').html(e);
                            table.append($('&amp;lt;tr/&amp;gt;').append(embeddedplayer));

                            self.append(table);
                        };
                      },
                      error: function(XMLHttpRequest, textStatus, errorThrown){
                        // console.debug(errorThrown);
                      }
                  });
                } else {
                  self.append(link);
                  self.addClass(liveclass);
                }
              } else {
                link.html(title+' - OFFLINE');
                self.removeClass(liveclass);
                self.append(link);
              }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
                // console.debug(errorThrown);
            }
        });
      } else if (options &amp;amp;&amp;amp; options.channelid) {
        var ajaxdata = {
          channel_id : options.channelid
        };
        if (options.showall) { ajaxdata.showall = 1; };

        $.ajax({
            type: &amp;quot;GET&amp;quot;,
            async: true,
            data: ajaxdata,
            url: $.own3d.channelurl,
            dataType: &amp;quot;jsonp&amp;quot;,
            success: function(data){
              self.empty();

              var embedded = true;
              for(var i=0;i&amp;lt;data.streams.length;i++) {
                var stream = data.streams[i];

                var plugindata = {
                  liveid : stream.liveid,
                  title : stream.title,
                  channelid : options.channelid,
                  // embed the first, thumbnail the rest
                  showthumbnail : (options.showthumbnail) || (!(options.showthumbnail) &amp;amp;&amp;amp; options.embed &amp;amp;&amp;amp; !embedded) ? true : false,
                  embed : (options.embed) ? true &amp;amp;&amp;amp; embedded : false
                };

                // prevent opening multiple embedded players
                embedded = false;                

                self.append($('&amp;lt;div/&amp;gt;').own3d(plugindata));
              }
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
              // console.debug(errorThrown);
            }
        });
      }
    });
  }
})(jQuery)

A simple PHP – Zend Framework script to enable a cross domain request to the OWN3D API (the full project contains two, one for the live status and one for the channel information).

&amp;lt;?php

// Define path to application directory
define('APPLICATION_PATH', realpath(dirname(__FILE__)));

// Ensure library/ is on include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../../apps/library'),
    get_include_path(),
)));

$liveid = isset($_GET['live_id']) ? intval($_GET['live_id']) : 0;

require_once 'Zend/Http/Client.php';
$client = new Zend_Http_Client('http://api.own3d.tv/liveCheck.php?live_id='.$liveid, array('adapter' =&amp;gt; 'Zend_Http_Client_Adapter_Socket'));

$xmlstr = $client-&amp;gt;request()-&amp;gt;getBody();
$xml = new SimpleXMLElement($xmlstr);

require_once 'Zend/Json/Encoder.php';
header('Content-Type: application/json');

// JSONP
if (isset($_GET['callback'])) {
        echo $_GET['callback'].'('. Zend_Json_Encoder::encode(array(
        'isLive'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;isLive,
        'liveViewers'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;liveViewers,
        'liveDuration'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;liveDuration,
    )).')';
}
// JSON
else {
    echo Zend_Json_Encoder::encode(array(
        'isLive'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;isLive,
        'liveViewers'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;liveViewers,
        'liveDuration'=&amp;gt;(string)$xml-&amp;gt;liveEvent-&amp;gt;liveDuration,
    ));
}
Go to Top