Tag: php

  • Symfony 1.1 Validation — Gotchas

    1. sfValidatorAnd requires a patch to work with Propel.

    Get the patch here.

    Read the trac ticket for more details.

    2. A huge difference between 1.0 and 1.1 in form validation deals with error handling.

    1.0 puts the error handling right in the action. In 1.1 you use code in a lib/forms file that looks like this for validation / error handling and corresponds usually to the object being validated. In the example below the code is in lib/forms/AccountForm.class.php

    $this->setValidators(array(
        'username' => new sfValidatorString(array('max_length' => 30))
    ));
    

    3. sfForm::setDefaults doesn’t work quite right with CSRF values.
    you’ll need to patch up code based on this google groups post.

    The documentation right now for 1.1 isn’t updated. E.G. The chapter on forms for the 1.1 documentation as of 12 August 2008 will lead you down the wrong path.

    To keep up to date on what’s going on with symfony, I totally consider doing the following mandatory and not optional:

    • Join the google group, symfony-users
    • Join the irc channel in irc.freenode.net #symfony any time you’ve got a question that needs asking
    • Since the docs might be off, it’s best to just read the source.
  • print_r in PHP-5.2.6 Doesn’t Print the Whole SimpleXML Object

    There’s an interesting SimpleXML related bug in PHP 5.2.6 . print_r is unable to print all the contents of a SimpleXML object. The bug is reported on the php.net site.

    The reproduction of the code is below:

    Reproduce code:
    ---------------
    <?php
    $xmlstr=<<<EOXML
    <?xml version='1.0' standalone='yes'?>l;
    <products>
        <product order_id="0001"></product>
        <product order_id="0002">PHP book</product>
        <product order_id="0003">
            <name>PHP book</name>
        </product>
    </products>
    EOXML;
    
    $xml=new SimpleXMLElement($xmlstr);
    print_r($xml);
    ?>
    
    Expected result:
    ----------------
    @attributes array for second item as well
    
    Actual result:
    --------------
    SimpleXMLElement Object
    (
        [product] => Array
            (
                [0] => SimpleXMLElement Object
                    (
                        [@attributes] => Array
                            (
                                [order_id] => 0001
                            )
    
                    )
    
                [1] => PHP book
                [2] => SimpleXMLElement Object
                    (
                        [@attributes] => Array
                            (
                                [order_id] => 0003
                            )
    
                        [name] => PHP book
                    )
    
            )
    
    )
    
    [13 May 1:29pm UTC] felipe@php.net
    
    The attribute can be accessed, however toString really doesn't show it.
    
    print_r($xml->product[1]);
    
    SimpleXMLElement Object
    (
        [@attributes] => Array
            (
                [order_id] => 0002
            )
    
        [0] => PHP book
    )

    It’s been pretty interesting going through the code in php-5.2.6/ext/simplexml . A note in the README file provides a clue:

    “Due to engine problems it is currently not possible to access a subelement by index 0: $object->property[0].”

  • #php on irc.he.net harbors a racist coder

    16:43 < barce> @niklas` i’m writing a connect4 game, and noticed that when i traverse
    diagonals acutely or gravely, the only diff between the functions is their
    operators: “>=” or “<=". 16:43 < barce> “++” or “–”
    16:44 < barce> so instead of if ($x < $limit) $x++; i want to define an operator before hand. 16:44 < barce> e.g. $op = “++”; if ($x < $limit) $x{$op}; 16:44 <+impl> so you save one line of code?
    16:45 <@horros> Now why the hell would you want to do that?
    16:45 <@feti> i’m successfully confused
    16:45 < barce> ya. why not?
    16:45 <+impl> because it’s stupid
    16:45 < barce> why is it stupid?
    16:45 <+impl> Because you would have to implement runtime operator resolution so that you
    don’t have to have an else { } block
    16:45 < barce> not being curious is stupid.
    16:46 < barce> right.
    16:46 < barce> that would be pretty hard to do.
    16:46 <@horros> No, being curious is good.
    16:46 < barce> so i’m asking if there’s a language like that.
    16:46 <+impl> I’m sure you could nigger rig it in ruby

    Please, come on down to #php irc.he.net and let this impl dude know what a blight to humanity he is.

  • How to Make Your Own PHP Extension… Quick and Dirty

    This is a cheat sheet on how to extend PHP. I’m learning how to fix bugs in C within the PHP source code right now using what’s google-able, the #php chat room in irc.freenode.net and “Extending and Embedding PHP” by Sara Goleman.

    Preliminaries: make sure you have the right tools for building php from source. Right now these tools are:

    • autoconf: 2.13
    • automake: 1.4+
    • libtool: 1.4.x+ (except 1.4.2)
    • bison: 1.28, 1.35, 1.75, 2.0 or higher
    • flex: 2.5.4 (not higher)
    • re2c: 0.9.11+ (0.12.0+ for HEAD)
    • Get the latest php stable version. as of this blog posting it’s php-5.2.6
    • unpack the file using something like bunzip2 -c < php-5.2.6.tar.bz2 | tar xvf -
    • ./configure –prefix=/usr/local –enable-debug (I’m really old school and like to put my stuff in /usr/local . YMMV.)
    • make ; make install

    If that worked now we’re ready to make a module. Feel free to substitute barce or BARCE in the code below with whatever you want the module name to be.

    • cd ext (if you type ls you’ll see the extensions that come with php.)
    • mkdir barce (I’m a narcissistic, buddhist, nihilist.)
    • create a config.m4 file with this code:
    PHP_ARG_ENABLE(barce,
            [Whether to enable the "barce" extension],
            [  --enable-barce       Enable "barce" extension support])
    
    if test $PHP_BARCE != "no"; then
            PHP_SUBST(BARCE_SHARED_LIBADD)
            PHP_NEW_EXTENSION(barce, barce.c, $ext_shared)
    fi
    
    • then create a php_barce.h file:
    #ifndef PHP_BARCE_H
    /* Prevent double inclusion */
    #define PHP_BARCE_H
    
    /* Define extension properties */
    #define PHP_BARCE_EXTNAME "barce"
    #define PHP_BARCE_EXTVER "1.0"
    
    /* Import configure options
     * when building outside of the 
     * PHP source tree */
    #ifdef HAVE_CONFIG_H
    #include "config.h"
    #endif
    
    /* Include PHP standard Header */
    #include "php.h"
    /*
     * define the entry point symbole
     * Zend will use when loading this module
     */
    extern zend_module_entry barce_module_entry;
    #define phpext_barce_ptr &barce_module_entry
    
    #endif /* PHP_BARCE_H */
    
    
    • create a barce.c file with your functions that you are creating for PHP
    #include "php_barce.h"
    
    PHP_FUNCTION(barce_thinks_youre_cool)
    {
            char *name;
            int name_len;
    
            if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", 
                    &name, &name_len) == FAILURE)
            {
                    RETURN_NULL();
            }
    
            php_printf("Barce thinks you're cool, ");
            PHPWRITE(name, name_len);
            php_printf("!\n");
    }
    
    
    static function_entry php_barce_functions[] = {
            PHP_FE(barce_thinks_youre_cool, NULL)
            { NULL, NULL, NULL }
    };
    
    zend_module_entry barce_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
            STANDARD_MODULE_HEADER,
    #endif
            PHP_BARCE_EXTNAME,
            php_barce_functions, /* Functions */
            NULL, /* MINIT */
            NULL, /* MSHUTDOWN */
            NULL, /* RINIT */
            NULL, /* RSHUTDOWN */
            NULL, /* MINFO */
    #if ZEND_MODULE_API_NO >= 20010901
            PHP_BARCE_EXTVER,
    #endif
            STANDARD_MODULE_PROPERTIES
    };
    
    #ifdef COMPILE_DL_BARCE
    ZEND_GET_MODULE(barce)
    #endif
    
    

    Now let’s build this puppy.

    • phpize
    • ./configure –enable-barce
    • make
    • there should now be a modules directory. copy it to /usr/local/lib/php/modules/ .
    • edit php.ini and add two lines:
      • extension_dir = “/usr/local/lib/php/modules”
      • extension = “barce.so”

    Let’s test and see if it worked:

    php -r “barce_thinks_youre_cool(‘Put your name here’);”

  • Algorithms in PHP

    I started coding algorithms in PHP in order to beef up my coding knowledge. It’s been an interesting exercise so far because when I coded algorithms in college it was great using C pointers.

  • Migrating to the Newest Youtube API

    You’ve got until August 30th, 2008 to migrate your code to the latest Youtube API. After that date, your current code base might not work.

    I used 3 important coding concepts while working on migrating my Youtube Facebook App to the newest Youtube API:

    Youtube

    The strategy pattern allows you to define common behaviors that will be shared among your set of classes. In this case, I’ve got a class for the old Youtube API, and a class for the new Youtube API. Although the URLs used for accessing the two APIs are different, I’ll define a method common to each class for accessing URLs. In this case it’s the setURL method.

    In PHP I do this like so:


    interface apiCalls
    {

    public function setUrl();

    }

    The factory pattern allows me to create an instance of an object for using the old API or the new API on the fly. Factory methods just return the new instance of an object.

    $dynamic_fave = FaveFactory::Create(“cyphgenic”, ‘yes’, 2, ‘on’, ‘2.0’);
    $dynamic_fave->setUrl();
    print $dynamic_fave->url . “\n”;

    $dynamic_fave = FaveFactory::Create(“cyphgenic”, ‘yes’, 2, ‘on’, ‘1.0’);
    $dynamic_fave->setUrl();
    print $dynamic_fave->url . “\n”;

    If you take a look at the code I’ve got and compare the old version with the new one, you can also see that I’ve cleaned up the nested if-else statements with arrays.

    BAD NESTED IF-ELSE:

          if ($showUploaded == 'on') {
            $method   = "youtube.videos.list_by_user";
          } else {
            $method   = "youtube.users.list_favorite_videos";
          }
    

    YAY! NO IF-ELSE:

          $h_method['on'] = "youtube.videos.list_by_user";
          $h_method['off'] = "youtube.videos.list_by_user";
          $method = $h_method[$this->showUploaded];
    

    Below are the links to the bits of the code that I had to migrate. I just use one particular method, setUrl() as an example.

    You might be wondering why two classes for the old and new API. If any new features need to be coded, or bugs need to be fixed in either API, I can do so within a particular class, and not add more obfuscation to the code. The two classes don’t violate the DRY principle because each models a particular thing.