Archive for the ‘php’ Category

h1

Getting PHP and MSSQL talking on Mac OSX

April 5, 2012

Here is what I had to do to get PHP talking to an MSSQL database on MAC OSX (Lion). Note that I am running Acquia dev desktop for PHP, you’ll have to change the paths to PHP if your setup is different.

Download Free TDS stable source from http://www.freetds.org/software.html and extract from the tarball.

Login as root with

sudo /usr/bin/bash

Go into freetds sources folder and configure freetds

CFLAGS="-arch i386" LDFLAGS="-arch i386" ./configure --prefix=/usr/local/freetds --enable-msdblib --with-tdsver=8.0

Compile freetds with

make && make install

Download and extract PHP sources for your version of PHP from http://php.net/downloads.php

Go into the php sources folder ext/mssql directory and configure

CFLAGS='-arch i386 -isysroot /Developer/SDKs/MacOSX10.7.sdk -mmacosx-version-min=10.7' ./configure --with-php-config=/Applications/acquia-drupal/php/bin/php-config --with-mssql=/usr/local/freetds

This will create a file called libtool

Go back to the freetds sources directory and run

make clean
CFLAGS="-arch i386" LDFLAGS="-arch i386" ./configure --prefix=/usr/local/freetds --enable-msdblib --with-tdsver=8.0

delete the freetds install
rm -rf /usr/local/freetds

copy the libtool file from the php sources ext/mssql directory to the freetds directory
cp /path/to/php-source/ext/mssql/libtool /path/to/freetds-source

Compile and install freetds again
make && make install

Go to the php-sources/ext/mssql directory and compile mssql
make

cp the so file to your php extensions dir
cp modules/mssql.so /Applications/acquia-drupal/php/ext

Edit your php.ini to include the mssql.so extension (e.g. with vim or nano)
vim /Applications/acquia-drupal/php/bin/php.ini

Add the following line in the Dynamic extensions section
extension=mssql.so

Tell the system where the FreeTDS config file is
echo "export FREETDSCONF=/usr/local/freetds/etc/freetds.conf" >> /etc/profile
echo "/usr/local/freetds/lib" >> /etc/ld.so.conf
ln -s /usr/local/freetds/bin/tds /usr/bin

and also run the followig (to save restarting your MAC)

export FREETDSCONF=/usr/local/freetds/etc/freetds.conf

Edit the freetds config file and set the freetds version to 8.0 (others dont seem to work with SQL server properly)
vim /usr/local/freetds/etc/freetds.conf
tds version = 8.0

Restart Web server

If you need help setting up SQLEXPRESS…

The basics…
http://codebetter.com/jefferypalermo/2005/11/04/how-to-use-sql-server-express-wheres-the-ui-level-200/

Setting up SQLEXPRESS for mixed login (windows authentication didn’t work for me from my remote PHP server)
http://eduzine.edujini-labs.com/archives/24-HOWTO-Configure-Microsoft-SQL-Server-for-Mixed-Mode-Authentication.html

Adding a new user account to sql express:
http://msdn.microsoft.com/en-us/library/aa337562.aspx

Let this new account access a db:
http://msdn.microsoft.com/en-us/library/aa337545.aspx

Advertisements
h1

Calculating permutations of a list

January 11, 2012

A recent project found me with the need to calculate all the possible permutations of a list of values. This is the possible order of all the values in the list.

For example, the list

1, 2, 3

Has 6 possible permutations:

1, 2, 3
1, 3, 2
2, 1, 3
2, 3, 1
3, 1, 2
3, 2, 1

My first attempt tried to calculate all the permutations in one go using a recursive function. In PHP, this looks like this:

/**
* Recursive permutations function for calculating the
* possible permutations of an array.
*
* @param array $list
* The list to calculate the pemutations of.
*
* @return array
* An array of arrays. Each sub array is a permutation
* of the originial array.
*/
function permutations(array $list) {

if (count($list) == 1) {
return array($list);
}

$perms = array();

foreach ($list as $key => $value) {
$sublist = $list;
unset($sublist[$key]);
foreach (permutations($sublist) as $subperm) {
array_unshift($subperm, $value);
$perms[] = $subperm;
}
}

return $perms;
}

This worked great for small lists of up to about 8 elements but past 8 the number of permutations grows great and you start to run out of memory in the recursive calculations. Incidentally, the total number of permutations is always given as the factorial of the number of elements. So, for 3 elements the total number is 3! or 3 x 2 x 1 = 6.

Here is a short piece of code for calculating the factorial of a positive integer.

/**
* Factorial function. For calculating some of the numbers
* of possible combinations.
*/
function nfact($n) {
if ($n == 0) {
return 1;
}
else {
return $n * nfact($n - 1);
}
}

So, my second attempt was to come up with a relationship between the permutation number and the order of the elements in a list given the starting order. I came up with this (in PHP again)

/**
* Given a list in it's initial state workout the
* i'th permutation.
*
* @param array $initial_state
* The initial state of the array.
* @param int $i
* The permutation of the initial state to find. Initial state is 0.
*
* @return array
* The i'th permutation of the initial state.
*/
function permutation(array $initial_state, $i) {

$n = count($initial_state);

// Requires all keys to be numeric in ascending order.
$initial_state = array_values($initial_state);

if ($n == 1) {
return $initial_state;
}

$t = nfact($n);

$first_value_position = floor($i / ($t / $n));
$first_value = $initial_state[$first_value_position];

// Setup the args of for the next value in the permutation.
unset($initial_state[$first_value_position]);
$i = $i % ($t / $n);

return array_merge(array($first_value), permutation($initial_state, $i));
}

To get all permutations you can then loop $i from 0 to the total number of permutations for the list.

$initial_state = array(1, 2, 3, 4, 5, 6, 7, 8);
$permutations = array();

for ($i = 0; $i < nfact(count($initial_state)); $i++) {
$permutations[] = permutation($initial_state, $i);
}

h1

Timing out PHP SOAP Calls

June 22, 2011

PHP has a bug when making SOAP calls over HTTPS. If the other end picks up but then does not send any data (as can happen if the SOAP server is behind a proxy or load balancer or the like) then its supposed to timeout after a specified amount of time. However, all current versions of PHP do not seem to allow this.

Thanks to Rob Ludwick for providing a workaround using CURL as the transport mechanism instead until PHP fix this. You can read about it on his blog here:
http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls

There is a PHP bug reported here for reference: http://bugs.php.net/bug.php?id=48524

h1

Put your Content Types with CCK fields into code [Drupal]

April 18, 2011

Putting a content type into code is a good thing to do since it then follows your module and means you don’t have to recreate content types on each instance of the site (e.g. dev, test and live)

To create basic content types in code, you can use the following code pattern in your mymodule.install file:

function mymodule_install() {
_mymodule_install_content_types();
}

function _mymodule_install_content_types() {
// Create Video Content type
$video_node_type = array(
'type' => 'vzaar_video_page',
'name' => t('Vzaar Video Page'),
'module' => 'node',
'description' => t('A Page containing a video stored on Vzaar'),
'custom' => TRUE,
'modified' => TRUE,
'locked' => FALSE,
);
node_type_save((object)_node_type_set_defaults($video_node_type));
}

Now on installation of the module, mymodule, you will get a new content type called Vzaar Video Page. This only has the Title and Body fields though so isn’t very useful. Using CCK we can add new fields in the interface but how do we get those fields out into code?

One way is to use the content_fields function to get an instance of a field as an array. You can then use that array in your install file to recreate the content. However, running this function is hardwork becaue you’ll need to run it in drupal then copy and paste the data into your file. An alternative is to use Drush, which is a full drupal environment on the command line to execute the function for you, then redirect the output into you install file.

drush ev "var_export( content_fields( 'field_myfield_name' ) );" >> mymodule.install

Now edit mymodule install and you’ll see the array at the end of the file. Move it into your install function and wrap it in the function content_field_instance_create. To test it works, make an update function as well in your install file, delete the content type from your drupal and then run update.php (or drush updb)

You’re final install function might look something like this …

/**
* Implementation of hook_update_N
*
* Add Vzaar Video content type
*/
function mymodule_update_6201() {
_mymodule_install_content_types();
}

function mymodule_install() {
_mymodule_install_content_types();
}

function _mymodule_install_content_types() {
// Create Video Content type
$video_node_type = array(
'type' => 'vzaar_video_page',
'name' => t('Vzaar Video Page'),
'module' => 'node',
'description' => t('A Page containing a video stored on Vzaar'),
'custom' => TRUE,
'modified' => TRUE,
'locked' => FALSE,
);

node_type_save((object)_node_type_set_defaults($video_node_type));

// Create CCK field for media_vzaar
$vzaar_media_field = array (
'field_name' => 'field_vzaar_video_url',
'type_name' => 'vzaar_video_page',
'display_settings' =>
array (
'label' =>
array (
'format' => 'above',
'exclude' => 0,
),
'teaser' =>
array (
'format' => 'default',
'exclude' => 0,
),
'full' =>
array (
'format' => 'default',
'exclude' => 0,
),
4 =>
array (
'format' => 'default',
'exclude' => 0,
),
),
'widget_active' => '1',
'type' => 'emvideo',
'required' => '0',
'multiple' => '0',
'db_storage' => '1',
'module' => 'emvideo',
'active' => '1',
'locked' => '0',
'columns' =>
array (
'embed' =>
array (
'type' => 'text',
'size' => 'big',
'not null' => false,
'sortable' => true,
),
'value' =>
array (
'type' => 'varchar',
'length' => 255,
'not null' => false,
'sortable' => true,
),
'provider' =>
array (
'type' => 'varchar',
'length' => 255,
'not null' => false,
'sortable' => true,
),
'data' =>
array (
'type' => 'text',
'size' => 'big',
'not null' => false,
'sortable' => false,
),
'status' =>
array (
'description' => 'The availability status of this media.',
'type' => 'int',
'unsigned' => 'TRUE',
'not null' => true,
'default' => 1,
),
'version' =>
array (
'description' => 'The version of the provider\'s data.',
'type' => 'int',
'unsigned' => true,
'not null' => true,
'default' => 0,
),
'title' =>
array (
'type' => 'varchar',
'length' => 255,
'not null' => false,
'sortable' => true,
),
'description' =>
array (
'type' => 'varchar',
'length' => 255,
'not null' => false,
'sortable' => true,
),
'duration' =>
array (
'description' => 'Store the duration of a video in seconds.',
'type' => 'int',
'unsigned' => true,
'not null' => true,
'default' => 0,
),
),
'widget' =>
array (
'video_width' => '425',
'video_height' => '350',
'video_autoplay' => 0,
'preview_width' => '425',
'preview_height' => '350',
'preview_autoplay' => 0,
'thumbnail_width' => '120',
'thumbnail_height' => '90',
'thumbnail_default_path' => '',
'thumbnail_link_title' => 'See video',
'meta_fields' =>
array (
'title' => 0,
'description' => 0,
),
'providers' =>
array (
'vzaar' => 'vzaar',
),
'default_value' =>
array (
0 =>
array (
'embed' => '',
'value' => '',
),
),
'default_value_php' => NULL,
'label' => 'Vzaar Video URL',
'weight' => '28',
'description' => '',
'type' => 'emvideo_textfields',
'module' => 'emvideo',
),
);

// Add the new content type to drupal
content_field_instance_create($vzaar_media_field);

}

h1

Print windows line endings with PHP

March 11, 2011

To print windows line endings when writing to a file using php you can use \r\n escape characters. e.g.

print "some line \r\n";

For unix/linux style line endings you just use \n;

h1

PHP Html Forms (QuickForm)

November 11, 2010

Good tutorial on using the QuickForm form builder and validator for PHP. This is used in Moodle.

http://www.midnighthax.com/quickform.php

h1

Character encoding with PHP and MySQL

September 21, 2010

Today had a problem reading UTF-8 encoded characters from MySQL using PHP. After connecting to the MySQL database I needed to explictly set the character encoding standard, PHP MySQL driver did not seem to automatically know what the db was set to. I am using the PDO method with PHP and MySQL…

$PDO = new PDO('mysql:host=myhost;dbname=db', $username, $password);
$PDO->exec('SET CHARSET SET utf8');