MuratYaman.co.uk

..a Turkish programmer in London..
RSS icon Email icon Home icon
  • Class Library as DLL for Business Model to be used in PHP

    Posted on February 12th, 2010 murat No comments

    Just an idea, possibly not a new one, and I promise, it is not another “framework”:

    Is it worth to create a class library as a DLL for a business model and use that DLL in PHP?
    What are the advantages and disadvantages?

    As soon as we say DLL, it is a solution that can be used only in Windows :(

    First, let us discuss what we mean about this class library.
    1. For proof of concept, our classes will be very primitive. Here is a sample C# namespace:

    using System;
     
    namespace myClassLib
    {
     
    	public class Class1
    	{
    		public string s1;
     
    		public Class1(){
    			s1 = "default s1";
    		}
    	}
     
    	public class Class2
    	{
    		public string s2;
    		public Class1 c1;
     
    		public Class2(){
    			s2 = "default s2";
    			c1 = new Class1();
    		}
     
    		public bool changeData(){
    			s2 = "who did it?";
    			c1.s1 = "s1 did it";
    			return true;
    		}
    	}	
    }

    There is nothing fancy about it; only 2 related classes with string properties.

    2. Compile the class library and copy the myClassLib.dll into the Apache binary folder, next to the httpd.exe, start Apache.

    3. Write a simple PHP code, load the library (DOTNET) and refer to the classes in it:

    <?php
    $obj2 = new DOTNET("myClassLib,Version=1.0.3695.2377,Culture=neutral", "myClassLib.Class2");
    $obj1 = $obj2->c1;
    echo 'obj2->s2 = ' . $obj2->s2 . '<br>';
    echo 'obj2->c1->s1 = ' . $obj2->c1->s1 . '<br>';
    echo 'obj1->s1 = ' . $obj1->s1 . '<br>';
    $obj2->changeData();
    echo 'obj2->s2 = ' . $obj2->s2 . '<br>';
    echo 'obj2->c1->s1 = ' . $obj2->c1->s1 . '<br>';
    echo 'obj1->s1 = ' . $obj1->s1 . '<br>';
    $obj1->s1 = "No, I didn't!";
    echo 'obj2->s2 = ' . $obj2->s2 . '<br>';
    echo 'obj2->c1->s1 = ' . $obj2->c1->s1 . '<br>';
    echo 'obj1->s1 = ' . $obj1->s1 . '<br>';
    unset($obj2);
    ?>

    The output should be like:

    obj2->s2 = default s2
    obj2->c1->s1 = default s1
    obj1->s1 = default s1
    obj2->s2 = who did it?
    obj2->c1->s1 = s1 did it?
    obj1->s1 = s1 did it?
    obj2->s2 = who did it?
    obj2->c1->s1 = No, I didn’t!
    obj1->s1 = No, I didn’t!

    Please note if you came across the problem of loading the assembly, I changed my file called AssemblyInfo.cs and set type visibility to true.

     
    //some code
     
    // This sets the default COM visibility of types in the assembly to invisible.
    // If you need to expose a type to COM, use [ComVisible(true)] on that type.
     
    [assembly: ComVisible(true)]
     
    //some code

    Advantages:
    1. You can see the business model or logic is in a compiled and secure state inside a DLL.
    2. I think the library is loaded for every request, but I expect it to be faster than loading PHP classes in text files.
    3. Instead of writing a PHP extension in C with difficulty, you can do it with one of many programming languages supported by .Net easily.

    Disadvantages:
    1. You have to re-compile the DLL after each modification.
    2. There may be overhead of loading the DLL. There are PHP caching tools as well.
    3. Stability: I noticed that Apache has crashed a few times.
    4. You may be forced to learn another programming language.

    So, it can be done.

    Next steps:
    1. Testing and sorting out stability issues.
    2. Testing with many classes, more complex classes and types, with more interaction with PHP (passing data in and out).
    3. Finding a way of loading the DLL only once when Apache (web server process) is started, such as OLE Automation Servers, Word, Excel.
    4. Benchmarking.
    5. Optionally, moving the database operations from PHP to the DLL
    + an ORM (Object-relational Mapping) functionality could be ideal

    6. Porting: We can achieve all using Java and JVM which can run on operating systems other than Windows
    + also there are JPA (Java Persistence API) tools for Java ready to use

    PHP can also load Java classes. Here are some examples.

    Happy coding!

  • Minimum Apache/PHP Maximum Performance

    Posted on January 18th, 2010 murat No comments

    The idea is simple: why don’t we turn off all the modules of Apache HTTPD server and PHP which we do not use at all? Hopefully, we should get the light version of the application platform. Surely, there may be various ways to optimize Apache and PHP, monitor it, and then fine tune it again for your needs. This is an on-going process.

    For this exercise, I used XAMPP 1.7.3 which comes with:

    Apache Httpd 2.2.14 and PHP 5.3.1

    After installing XAMPP with the default settings, I have turned off PERL (mod_perl) support as well as IPv6 and SSL (mod_ssl) by following the command line prompts during the installation.

    After this step, the main victim modules are … (come on, they have just been turned off!)

    # mod_actions
    # mod_alias
    # mod_asis
    # mod_auth_basic
    # mod_auth_digest
    # mod_authn_default
    # mod_authn_file
    # mod_authz_default
    # mod_authn_file
    # mod_authz_default
    # mod_authz_groupfile
    # mod_authz_user
    # mod_cgi
    # mod_dav
    # mod_dav_fs
    # mod_dav_lock
    # mod_include
    # mod_info
    # mod_rewrite
    # mod_autoindex_color

    Then, I commented out the lines related to alias_module (including ScriptAlias), cgi-bin configurations, and XAMPP file (httpd-xampp.conf).

    I had to enable mod_authz_host to give IP specific access permissions to my clients.

    On the contrary, I wanted to enable modules which could be useful for performance such as:

    + mod_deflate

    I would like to check the contribution of the caching modules for static content like images, CSS files and JavaScript files which tend to change rarely in our applications:

    ~ mod_cache
    ~ mod_mem_cache

    Some recommend to setup a separate web media server by using lightweight web server applications such as lighttpd and thttpd, which forces us to look at alternatives and compare.

    On the PHP side (php.ini), I did not need the following libraries (modules):

    ; php_exif
    ; php_imap
    ; php_soap
    ; php_sockets
    ; php_xmlrpc
    ; php_zip
    ; php_ming
    ; php_pdflib

    On the other hand, we need to check the following modules if they work and do not crash our web application:

    ~ php_apc or
    ~ php_eaccelerator

    Happy coding!

  • Creating a CV indexing facility using Oracle Text

    Posted on January 7th, 2010 murat No comments

    Recently, I have struggled to get Oracle Text working on Linux. It was supposed to be a simple addon based on a very simple idea:

    + already installed Apache 2.2, PHP 5.3, Firebird 2.0; which are working fine

    + install Oracle 10g Express Edition
    + create a simple table to store candidate ID and document itself
    – binary contents of Word document (.doc) or PDF document (.pdf)

    I had to download the RPM file for Oracle 10g XE (Western Europe charset) and install it using yum. Then, run its configuration command (/etc/init.d/oracle-xe configure) to finish the setup.

    After connecting with sqlplus, I created the table:

    CREATE TABLE mytable (
      id NUMBER PRIMARY KEY,
      cvfile BLOB DEFAULT EMPTY_BLOB()
    );
     
    CREATE INDEX mytable_cvfile_idx ON mytable (cv_file)
      INDEXTYPE IS CTXSYS.CONTEXT
      PARAMETERS ('SYNC (ON COMMIT)')
    );

    “How can I populate BLOB column of the table?”

    1. You can save files in the table as usual using PHP OCI functions (PHP documentation).

    2. Or you can create/execute a custom procedure that refers to your files inside a specific directory and let it do the rest using DBMS_LOB package.

    The issue I experienced was that indexing failed with errors. When I looked at view (select * from CTX_USER_INDEX_ERRORS) I saw errors such as:

    “DRG-11207: user filter command exited with status 1″
    “DRG-11222: Third-party filter does not support this known document format”

    However, the same structure worked perfectly on a Windows server (with ifilters installed).

    Then, I tried another method. First, I added a CLOB column into my table, and created similar index on the new column:

    ALTER TABLE mytable
    ADD cvtxt CLOB DEFAULT EMPTY_CLOB();
     
    UPDATE mytable SET cvtxt = EMPTY_CLOB();-- if there are records
     
    CREATE INDEX mytable_cvtxt_idx ON mytable (cv_file)
      INDEXTYPE IS CTXSYS.CONTEXT
      PARAMETERS ('SYNC (ON COMMIT)')
    );

    I had to populate the new column with text. I thought while I was saving the files in the database, I might as well extract text from Word documents and PDF documents and save the text in the CLOB column.

    Here comes the new challenge!

    Thanks to the open source world, we can find free solutions:

    + Antiword MS-Word reader (“.. converts the documents from Word 2, 6, 7, 97, 2000, 2002, and 2003 to text, Postscript, and XML/DocBook”)

    Installation is easy:

    yum install antiword

    + XPDF PDF viewer (“.. includes a PDF text extractor called pdftotext, PDF-to-PostScript converter, and various other utilities”)

    Download the version for your system (mine was Extra Packages for Linux 5 aka EPEL5 x86_64)

    cd /usr/local/src/
    wget ftp://195.220.108.108/linux/epel/5/x86_64/xpdf-3.02-15.el5.x86_64.rpm
    yum install ./xpdf-3.02-15.el5.x86_64.rpm

    In PHP, you can exec the following commands and extract text from your Word and PDF files:

    <?php
    //extract text from Word document
    $myfile_path_and_name = "/tmp/abc.doc";
    $cmd = "antiword $myfile_path_and_name";
    $output_lines = array(); $return_value = 0;
    $last_line = exec($cmd, $output_lines, $return_value);
    $doc_text = implode("\n", $output_lines);
     
    //extract text from PDF file
    $myfile_path_and_name = "/tmp/def.pdf";
    $cmd = "pdftotext -q $myfile_path_and_name -"; // "-q" no messages, "-" no output file but stdout
    $output_lines = array(); $return_value = 0;
    $last_line = exec($cmd, $output_lines, $return_value);
    $pdf_text = implode("\n", $output_lines);
    ?>

    I could use text taken from these utilities in my PHP/OCI function like saving BLOBs, but this time it is a CLOB column.

    That’s all! Happy searching CVs!

    SELECT id, SCORE(1) AS myrank
    FROM mytable
    WHERE CONTAINS (cvtxt, 'php sql', 1) > 0;
  • Emergency check on command-line for Oracle XE

    Posted on December 30th, 2009 murat No comments

    Go to your Oracle binaries folder and export environment variables, if they are not set already. Then, run SQL*Plus command line utility with option /nolog .

    [root@localhost /]# cd /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/bin/
     
    [root@localhost bin]#. ./oracle_env.sh
     
    [root@localhost bin]# sqlplus /nolog
     
    SQL> connect myuser/mypassword@localhost/xe
     
    Connected.
     
    SQL> select count(*) as c from mytablespace.mytable
      2    /
             C
    ----------
           123

    I hope this helps some beginners.

  • Setting up a web application on CentOS (continued)

    Posted on December 30th, 2009 murat No comments

    Before continuing the rest of the installation process we started (/wp/index.php/2009/07/setting-up-a-web-application-on-centos-5-3/), I must mention my appreciation for the “yummy” tool Linux developers provided: yum (.. an automatic updater and package installer/remover for rpm systems). I love using webmin (.. a web-based interface for system administration for Unix) as well. The other day I only clicked on a button to upgrade almost all the packages in our CentOS box; this facility is using yum in the background. It took almost 2 hours: just be patient :)

    The main problem I have experienced was the create the link between PHP and Oracle 10g Express Database server. Thanks to Google I was able to find people on the net that had the similar issues.

    I downloaded 2 (free) packages from Oracle’s website (into folder /usr/src/):

    oracle-instantclient-basic-10.2.0.3-1.x86_64.rpm
    oracle-instantclient-devel-10.2.0.3-1.x86_64.rpm

    Then, I ran:

    cd /usr/src/
    rpm -ivh oracle-instantclient-basic-10.2.0.3-1.x86_64.rpm
    rpm -ivh oracle-instantclient-devel-10.2.0.3-1.x86_64.rpm

    Development packages and a compiler were needed, as far as I understood from the error messages.

    yum install gcc
    yum install php-devel
    yum install php-pecl-* --skip-broken
    yum install php-oci8
    pecl install oci8

    When it asks for the ORACLE_HOME or Oracle Instant Client, type:

    instantclient,/usr/lib/oracle/10.2.0.3/client64/lib

    [root@localhost src]# pecl install oci8
    downloading oci8-1.3.5.tgz ...
    Starting to download oci8-1.3.5.tgz (137,987 bytes)
    ............................done: 137,987 bytes
    10 source files, building
    running: phpize
    Configuring for:
    PHP Api Version:         20090626
    Zend Module Api No:      20090626
    Zend Extension Api No:   220090626
    Please provide the path to the ORACLE_HOME directory. Use 'instantclient,/path/to/instant/client/lib' if you're compiling with Oracle Instant Client [autodetect] : instantclient,/usr/lib/oracle/10.2.0.3/client64/lib

    By the way, I did not need all the pecl libraries installed. I simply went into /etc/php.d/ and commented out the lines for extensions (to disable them):

    [root@localhost php.d]# ls
    apc.ini       gmagick.ini    lzf.ini        oci8.ini          pdo_sqlite.ini        sphinx.ini  z-mailparse.ini
    curl.ini      imap.ini       mbstring.ini   pdf.ini           phar.ini              sqlite.ini
    fileinfo.ini  interbase.ini  memcached.ini  pdo_firebird.ini  php-pecl-imagick.ini  ssh2.ini
    gd.ini        json.ini       memcache.ini   pdo.ini           pspell.ini            xdebug.ini
    geoip.ini     ldap.ini       ncurses.ini    pdo_oci.ini       radius.ini            zip.ini
     
    [root@localhost php.d]# nano xdebug.ini
    ; Enable xdebug extension module
    ; zend_extension=/usr/lib64/php/modules/xdebug.so

    So, far the packages installed help us run our bespoke web application on Apache (httpd 2.2.3), PHP 5.3.1, Firebird 2.1.2, Oracle 10g XE.

    Check the following useful extras:

    yum install aspell
    yum install php-pspell
    yum install php-imap

    Reading emails from an IMAP server, parsing structured content, preparing emails using by TinyMCE with spellchecker and sending email using PHPMailer class are all fun!

    Happy coding!