Archive for category Symfony

Simple Logging Utility Class for Symfony

Here’s a little gem I’ve been using for quite some time. Sometimes during your development process you simply want to see the contents of a variable while it’s being used or want to know when a certain bit of code is firing. In my PHP programming infancy I would simply dump such data on screen with functions like echo and print_r. This was an ugly and brutish way of doing it.

Since one of the nice features Symfony sports is it’s logging features, I started dumping such data to the log. I quickly found out that depending on what part of the code I was working on, the syntax of my logging was different and became quite cumbersome in some cases.

In comes the following class, the Logging class, or L class for short.  It simplifies logging and dumping a variable to the log.  I also found it helpful when I was first learning Symfony to know what methods a class had. I’ve also included that function as well.

Here are some examples:

        L::log('Something happened.');
 
        $array = array('1', '2', 'Tom' => 'Jones', 'Richard' => 'Smith',
            'Harrold' => 'Jackson');
        L::dump($array, 'Example Array', 'info');
 
        $config = new sfConfig();
        L::methods($config);

Output:

Jul DD HH:MM:SS symfony [debug]
***********************
* Something happened. *
***********************

Jul DD HH:MM:SS symfony [info]
*******************************
* Variable Dump Example Array *
*******************************
array (
 0 => '1',
 1 => '2',
 'Tom' => 'Jones',
 'Richard' => 'Smith',
 'Harrold' => 'Jackson',
)
Jul DD HH:MM:SS symfony [debug]
************************
* Methods for sfConfig *
************************
sfConfig::get
sfConfig::has
sfConfig::set
sfConfig::add
sfConfig::getAll
sfConfig::clear

Here is the code. Simply drop it into a file in your project’s lib directory (I placed it into a util subdirectory) and clear your cache to start using it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<?php
/**
 * Pretty Simple Logger
 *
 * @package util
 * @author Phazeon Phoenix <phoenix@phazeon.com>
 * @copyright 2009 Phazeon.com
 * @version 1
 */
class L {
 
    static public $allowedMessageLevels = array('notice', 'emerg', 'alert',
                         'crit', 'info', 'debug', 'err', 'warning');
    /**
     * Log a message.
     *
     * @param mixed $message
     * @param string $level
     * @param boolean $pretty Does not add the star header if false.
     * @return void
     */
    static public function log($message, $level = 'debug', $pretty = true)
    {
        if (sfConfig::get('sf_logging_enabled')) {
            if ( ! in_array($level, self::$allowedMessageLevels))
                $level = 'debug';
            if ($pretty)
                $output = self::prettyHeader($message);
            else
                $output = $message;
            sfContext::getInstance()->getLogger()->$level($output);
        }
    }
 
    /**
     * Dump a variable to the log.
     *
     * Known Limitation: Variables that are too large, such as many of the
     * Symfony core classes, will cause this function to fail. This is a
     * limitation of var_export(). If you need to dump such a variable, use
     * print_r(). It's ugly but it'll work no matter how large the variable is.
     *
     * @param mixed $var
     * @param mixed $message
     * @param string $level
     * @return void
     */
    static public function dump($var, $message = null,  $level = 'debug')
    {
        if (sfConfig::get('sf_logging_enabled')) {
            $output = self::prettyHeader("Variable Dump $message");
            $output .= var_export($var, true);
            L::log($output, $level, false);
        }
    }
 
    /**
     * Output all publicly accessable methods of a class.
     *
     * @param mixed $class
     * @param mixed $message
     * @param string $level
     * @return void
     */
    static public function methods($class, $message = null,  $level = 'debug')
    {
        if (sfConfig::get('sf_logging_enabled')) {
            $class = get_class($class);
            $output = self::prettyHeader("Methods for $class $message");
            $methods = get_class_methods($class);
            foreach($methods as $method) {
                $output .= "$class::$method\n";
            }
            L::log($output, $level, false);
        }
    }
 
    /**
     * Build a string padded and surrounded by stars.
     *
     * @param mixed $text
     * @return string
     */
    static public function prettyHeader($text) {
        $stars = '';
        $text = "* " . trim($text) . " *";
        $stars = str_repeat('*', strlen($text));
        return "\n" . $stars . "\n" . $text . "\n" . $stars . "\n";
    }
}

, , ,

No Comments

Symfony Template and Component Templates

Today I’ve got a pair of small templates.

The first is a comment header for the Symfony template files.  Due to the shear number of these template files you can create if you’re partial and component happy, sometimes just the filename isn’t enough to really describe what file your editing. My motto is you can never have too much documentation.

1
2
3
4
5
6
7
8
9
10
11
<?php
/**
 * Template Template
 * 
 * @author Phazeon Phoenix <phoenix@phazeon.com>
 * @version 1
 * @package Templates
 * @copyright 2009 Phazeon.com
 */
?>
<h2>My Template</h2>

Next is a template for new components.  This is the sort of thing that I always had trouble remembering. I had to track down the exact syntax for the component class declaration each time.  Now in my IDE (phpDesigner) I can define user entered variables in my snippets/templates.  It prompts me for the model name and the method name minus the “execute” prefix.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
/**
 * Component Template
 * 
 * @author Phazeon Phoenix <phoenix@phazeon.com>
 * @version 1
 * @package Components
 * @copyright 2009 Phazeon.com
 */
 
class templateComponents extends sfComponents
{
    public function executeSomething()
    {
 
    }
}

, , , , ,

No Comments

Symfony 1.1+ Form Template

In my work with Symfony I’ve started collecting a library of code snippets that I use to speed up my creation of different objects in the Symfony tree. Since most of them are cut and splices of other people’s code (especially the Symfony documentation) I’m going to start posting some of the better ones on my blog.

The one that I’m going to share today involves the creation of a form class for the new form handling classes added in Symfony 1.1.  I found myself constantly having to go back to the form and adding the sections that I needed but forgot the list time I was working it. I created this template and included all of the options I felt I’d need to declare to correctly implement a nice looking and behaving form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?php
/**
 * Template Form
 * 
 * @author Phazeon Phoenix <phoenix@phazeon.com>
 * @version 1
 * @copyright 2009 Phazeon.com
 * @package Forms
 */
class templateForm extends sfForm
{
    public function configure()
    {
        $this->setWidgets(array(
 
        ));
 
        $this->setValidators(array(
 
        ));
 
        $this->setDefaults(array(
 
        ));
 
        $this->widgetSchema->setLabels(array(
 
        ));
 
        $this->widgetSchema->setFormFormatterName('list');
 
        $this->widgetSchema->setNameFormat('template[%s]');
    }
}

, , , , ,

1 Comment

New Symfony Project Woes

Generating a new Symfony framework project is as simple as a single command. But as with many things it rarely works the way you want out of the box. I’ve documented every step and every command that I end up running on a new project to ensure that it behaves the way it should and I ended up with a 30 point list! I have to initialize the project, modify several files to enable things such as the Doctrine ORM plugin, install several plugins such as the sfDoctrineGuard authentication plugin, SVN version control taking careful steps to avoid placing the cache, logs, and the base model classes under revision, and set up my development environment for the new project.

I need to work on a way to automate as much as I can of the process. The tricky thing is that certain commands need to be executed as root (inlcuding rebooting the web server) and that throws a monkey wrench in the gears of that idea.  Certainly one could create a script and SUID root, but that is going to require extensive care to ensure that the process is handled gracefully if it fails for whatever reason.  It’s a large undertaking to say the least. I guess I have to weigh the time spent each new project vs. coding such a script.

, , , ,

2 Comments

actAs: Accountable Doctrine Behaviour

It was fairly easy to create a Signable behaviour and it was done within a couple days.  I soon realized though that the behavior of the SoftDelete behaviour wasn’t quite what I wanted. It only adds a “deleted” boolean field to the DB. I also wanted to know who deleted it and what time it was deleted.  I decided to expand SoftDelete and make it use a timestamp instead of a boolean. That part worked too.

The problem I soon ran into was with when I combined SoftDelete and Signable with it’s new preDelete hook.  Seems since SoftDelete stops the preDelete event it doesn’t let the Signable code execute properly.  I decided that the correct answer to the problem was to create a whole new behaviour which would combine not only SoftDelete and Signable but also Timestampable.  I called it Accountable since it’s primary function is to keep record of who touched an object.

I did a manual test and so far it’s worked as planned.  I’m not yet sure of the SoftDelete filters… I made a change to preDqlDelete and preDqlSelect and I’m not quite sure if it still works. Time will tell I’m sure. Once I’m more certain this code is solid I’ll give more information on it.

, , , , ,

No Comments

Doctrine Behaviours

I’m finding that I need to write a couple behaviors that for some reason are not in the default distribution.  The features I’m needing in particular are “Signable” to add created_by, updated_by and deleted_by to each table, and “Commentable” to handle the comments that you’re going to be able to post on almost every single object.

Thankfully the best way for me to learn is to find an example.  I’m going to modify the code for “Timestampable” for “Signable” and I think I’m going to look at csDoctrineActAsAttachablePlugin for how it behaves and build from it to make “Commentable”.  I might even release it to the community.

Doctrine Behaviours are fairly new to me but I understand what’s going on for sure.  Behaviours allow you to modularize your reusable database code.  In my examples, I need to be able to keep track of who created, updated, and/or deleted an item.  Instead of adding that bit of code to each model by hand, I can cut it out and make a Behaviour that I then attach to each model.

, , , ,

No Comments

Database Schema and Doctrine Model planning

Today I did some major database planning for a major project I’m working on and it’s quite an interesting process. You have to take such a large concept as every bit of information your application might need to store and slicing that into smaller pieces to create the tables and models needed to access and process them.

I’m finding the best way to plan them out is to grab a piece of paper and something to write with and start scribbling.  Maybe it is low tech but whatever works you know.  I found myself creating what could have easily have been a flow chart spanning several pages. I started in one small area and quickly expanded to other less obvious and obscure tables I’d need. All while relaxing on my bed.

I started writing my schema file. This being my first real application of the Doctrine ORM it was a bit slow going. The syntax for the schema.yml is a bit new to me. It took me a couple tries to get the correct relationships to form exactly the way I wanted. But so far so good.

, , , , ,

No Comments

Authenticating to an Active Directory Domain

I’ve a project that needs to authenticate itself against a Windows Active Directory.  I’ve done this before and it’s not exactly the simplest thing to do.  I’ve used adLDAP before and it’s worked relatively well in my stand alone projects before I discovered MVC frameworks.  Now that I’m using symfony I’ve become quite fond at how easy sfGuardPlugin made authentication.  The problem is there isn’t a symfony plugin that allows for AD/LDAP authentication.

My next task is going to be integrating the adLDAP code into a plugin to expand sfGuardPlugin. The point isn’t to create a seemless authentication scheme, simply to be able to sign in with a domain username and password. I’m going to need not only authentication but also group membership for permission maintenance. This is either going to be something simple or something complex.  I have done it before and I’m fairly certain I’ll be able to do it again.

, , , ,

No Comments