MirthLab » symfony http://blog.mirthlab.com Thu, 15 Jul 2010 21:12:25 +0000 en hourly 1 http://wordpress.org/?v=3.0.1 Extend CSS With Variables, Mixins, Operations and Nested Rules Using LESS http://blog.mirthlab.com/2010/02/09/extend-css-with-variables-mixins-operations-and-nested-rules-using-less/ http://blog.mirthlab.com/2010/02/09/extend-css-with-variables-mixins-operations-and-nested-rules-using-less/#comments Tue, 09 Feb 2010 20:57:52 +0000 Mark Quezada http://blog.mirthlab.com/?p=358 LESS:

LESS extends CSS with: variables, mixins, operations and nested rules.

Best of all, LESS uses existing CSS syntax. This means you can rename your current.css files to .less and they’ll just work.

LESS defines its own extension to CSS syntax which then gets compiled into standard CSS. It’s a really great idea. And there’s a great companion app for Mac OS X called less.app:

This app makes working with LESS a snap by turning it into a graphical interface.

Basically, this standalone app allows you to compile your .less files into CSS with a click of a button. The really nice thing about it though is that it can be set up to monitor changes to your LESS files and then recompile the associated CSS files automatically.

You can also use LESS directly from within Ruby on Rails using the More plugin (which compiles the .less files into .css files automatically).

Update: Konstantin Kudryashov pointed me to a version for Symfony as well. And while we’re at it, here’s a plugin for Django. It’s a little more generic but LESS is one of the compilers it supports.

]]>
http://blog.mirthlab.com/2010/02/09/extend-css-with-variables-mixins-operations-and-nested-rules-using-less/feed/ 2
Migrating from sfSimpleBlog to WordPress http://blog.mirthlab.com/2009/07/19/migrating-from-sfsimpleblog-to-wordpress/ http://blog.mirthlab.com/2009/07/19/migrating-from-sfsimpleblog-to-wordpress/#comments Mon, 20 Jul 2009 09:39:27 +0000 Mark Quezada http://blog.mirthlab.com/?p=275 The sfSimpleBlogPlugin makes adding a simple blogging platform to any Symfony application very easy. It hasn’t really been actively developed for a long while, but it still sees a decent amount of use in the Symfony community simply because it’s so easy to setup and integrate with an existing Symfony project. I developed a site around 3 years ago that used sfSimpleBlog. The requirements for the blog were very minimal at the time so it was a good fit. Since then though, their blog has turned into a central part of the site and now they need something a little less simple.

I found it hard to believe that no one’s ever done this before, but a quick Google search wasn’t much help, so I wrote a pake task to export the sfSimpleBlog articles to an XML format that could be imported using WordPress’s built-in RSS importer. It’s very basic and you should be able to edit it to your needs. It should be noted that this was written for Symfony 1.0 so the format for pake tasks may have changed for Symfony 1.2.

Basic Usage

From the command line:

./symfony blog-export frontend prod

… where “frontend” is simply the application you want to load the config from and “prod” is the environment that should be used.

By default it makes a file called simple_blog_dump.xml in the root of your Symfony project. (You can change this filepath in the code itself if you need.) You can then import this file from your WordPress administration page.

The Code

Download this file and rename it to “myPakeBlogExport.php” inside of your project_root/data/tasks/. The filename must start with myPake since Symfony won’t load the task otherwise. Then run the pake task as mentioned in the section above.

UPDATE: It looks like my WordPress theme is mangling the following code block. Be sure to download and rename it instead. I’ll leave the code block here for reference:

<?php

// Written by Mark Quezada (mark [at] mirthlab dot com)

pake_desc('Export sfSimpleBlogPosts to wordpress xml.');
pake_task('blog-export', 'project_exists');

function run_blog_export($task, $args)
{
  if(!count($args))
  {
    throw new Exception('You must specify an application to load configuration info from (e.g. frontend).');
  }

  if(count($args) != 2) {
    throw new Exception('Please specify an environment (e.g. prod or dev).');
  }

  $app = $args[0];
  $env = $args[1];
  $con = _file_storage_get_connection($app, $env);


  $posts = sfSimpleBlogPostPeer::doSelect(new Criteria(), $con);

  $lines = array();
  foreach ($posts as $post)
  {
    $lines[] = '<item>';
    $lines[] = '  <pubDate>'.$post->getCreatedAt().'</pubDate>';
    foreach ($post->getsfSimpleBlogTags() as $tag)
    {
      $lines[] = '  <category>'.$tag->getTag().'</category>';
    }
    $lines[] = '  <title>'.$post->getTitle().'</title>';
    $lines[] = '  <content:encoded>'._blog_export_clean_content($post->getContent()).'</content:encoded>';

    foreach ($post->getsfSimpleBlogComments() as $comment)
    {
      $lines[] = '  <wp:comment>';
      $lines[] = '    <wp:comment_author>'.$comment->getAuthorName().'</wp:comment_author>';
      $lines[] = '    <wp:comment_author_email>'.$comment->getAuthorEmail().'</wp:comment_author_email>';
      $lines[] = '    <wp:comment_author_url>'.$comment->getAuthorUrl().'</wp:comment_author_url>';
      $lines[] = '    <wp:comment_date>'.$comment->getCreatedAt().'</wp:comment_date>';
      $lines[] = '    <wp:comment_content>'._blog_export_clean_content($comment->getContent()).'</wp:comment_content>';
      $lines[] = '    <wp:comment_approved>'.$comment->getIsModerated().'</wp:comment_approved>';
      $lines[] = '  </wp:comment>';
    }
    $lines[] = '</item>';
  }


  $handle = fopen("simple_blog_dump.xml", "w");
  foreach($lines as $line)
  {
    fwrite($handle, $line."\n");
  }
  fclose($handle);  
}



function _blog_export_get_connection($app, $env)
{
  // define constants
  define('SF_ROOT_DIR',    sfConfig::get('sf_root_dir'));
  define('SF_APP',         $app);
  define('SF_ENVIRONMENT', $env);
  define('SF_DEBUG',       false);
  require_once SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php';
  $connection = sfContext::getInstance()->getDatabaseConnection('propel');

  return $connection;
}

function _blog_export_clean_content($string)
{
  // check if the string contains html
  if (strlen($string) != strlen(strip_tags($string)))
  {
    // it does, remove newlines as the wordpress importer will automatically convert them (again) to <p> tags
    $string = str_replace("\r\n",'',$string);
    $string = str_replace("\n",'',$string);
    $string = str_replace("\r",'',$string);
  }

  // Note: I'm not removing newlines from posts that *don't* contain html since we want wordpress to add <p> tags in that case

  return $string;
}
]]>
http://blog.mirthlab.com/2009/07/19/migrating-from-sfsimpleblog-to-wordpress/feed/ 0
Adding Subdomain Requirements to Symfony Routing http://blog.mirthlab.com/2009/03/02/adding-subdomain-requirements-to-symfony-routing/ http://blog.mirthlab.com/2009/03/02/adding-subdomain-requirements-to-symfony-routing/#comments Mon, 02 Mar 2009 22:39:57 +0000 Mark Quezada http://blog.mirthlab.com/?p=232 Kris Wallsmith just posted a great tutorial showcasing Symfony 1.2′s flexibility by demonstrating how to add subdomain requirements to routing.yml:

A question came across the mailing list today that provides an excellent opportunity to demonstrate the flexibility of the symfony 1.2 routing system.

Evert Harmeling posed the following:

How can I point sub1.domain.com/test to a different route than sub2.domain.com/test inside the same application?

This is not supported natively by the symfony core, but the routing system can easily be extended to meet Evert’s requirement.

This is a neat extension of Symfony’s core. I’ve written before about using subdomains to load Symfony applications in the same project but this is a bit different as it’s switching subdomains within the same Symfony application.

]]>
http://blog.mirthlab.com/2009/03/02/adding-subdomain-requirements-to-symfony-routing/feed/ 0
One Year and Counting http://blog.mirthlab.com/2008/12/14/one-year-and-counting/ http://blog.mirthlab.com/2008/12/14/one-year-and-counting/#comments Sun, 14 Dec 2008 10:23:59 +0000 Mark Quezada http://blog.mirthlab.com/?p=176 So apparently I missed the One Year Anniversary of this blog. It all started with this post from December 5th, 2007. Here’s a chart of the monthly traffic from Google Analytics:

traffic graph

You can see that in June the traffic started picking up as I began to write more frequently.

Here are the top 5 articles by page views for the same time period:

  1. Parsing jQuery’s sortable(”serialize”) Method with PHP (and symfony)
  2. Using Symfony Partials In DHTML and Ajax
  3. OmniFocus, It’s Not You, It’s me… Really
  4. Simple Symfony Login Form Example
  5. Dynamically Loading Symfony Applications Via Subdomains

I find it interesting that although the Symfony login form example was posted relatively recently, it’s already in the top five. Also, the only article in the top five that doesn’t deal with Symfony is my mini OmniFocus review.

Well, here’s to another year…

]]>
http://blog.mirthlab.com/2008/12/14/one-year-and-counting/feed/ 0
Symfony + Doctrine Book Now Available http://blog.mirthlab.com/2008/12/02/symfony-doctrine-book-now-available/ http://blog.mirthlab.com/2008/12/02/symfony-doctrine-book-now-available/#comments Tue, 02 Dec 2008 19:01:55 +0000 Mark Quezada http://blog.mirthlab.com/?p=165 Hot on the heels of the official Symfony 1.2 Release comes the new Symfony + Doctrine book:

On this day we want to give you another great present, the symfony + Doctrine Book which documents the specific functions of the integration between symfony and Doctrine as well as some commonly used Doctrine functionality.

(Via the Symfony Blog.)

]]>
http://blog.mirthlab.com/2008/12/02/symfony-doctrine-book-now-available/feed/ 1
Symfony 1.2 Released Alongside a New Advent Calendar Tutorial http://blog.mirthlab.com/2008/12/01/symfony-12-released-alongside-a-new-advent-calendar-tutorial/ http://blog.mirthlab.com/2008/12/01/symfony-12-released-alongside-a-new-advent-calendar-tutorial/#comments Mon, 01 Dec 2008 22:13:31 +0000 Mark Quezada http://blog.mirthlab.com/?p=163 Symfony 1.2 stable has been officially released:

As our early Christmas present, we finalized the 1.2 release of symfony after some weeks of hard work.

Be sure to check out what’s new in Symfony 1.2 as well as the upgrade instructions for upgrading from Symfony 1.1. If you’re upgrading from 1.0, it is recommended that you first upgrade to 1.1. Also, the 1.2 documentation and book will be an invaluable resource if you’re new to Symfony 1.2.

Also, those familiar with Symfony will probably remember the Askeet tutorial from several years ago. It was written as an easy, step-by-step tutorial that showcased Symfony and allowed new users to build an application from start to finish while learning about the framework. Over the years the Askeet tutorial has begun to show its age so to celebrate the release of Symfony 1.2 the Symfony team has put together a new Advent Calendar style tutorial called Jobeet. It’s a great way for both Symfony novices and pros to learn about Symfony best-practices right from the creators of Symfony.

(Via the Symfony Blog.)

]]>
http://blog.mirthlab.com/2008/12/01/symfony-12-released-alongside-a-new-advent-calendar-tutorial/feed/ 0
Symfony 1.2 Release Candidate Now Available http://blog.mirthlab.com/2008/11/26/symfony-12-release-candidate-now-available/ http://blog.mirthlab.com/2008/11/26/symfony-12-release-candidate-now-available/#comments Wed, 26 Nov 2008 22:25:57 +0000 Mark Quezada http://blog.mirthlab.com/?p=157 In case you missed it (like I did), the Symfony 1.2 Release Candidate is now available:

Being a release candidate now means that we are no longer doing any changes besides bug fixing and documentation, lots of documentation. Of course with very good reason we do an exception but generally that’s it. This means that you will also have no problems upgrading from this release candidate to the final version. If you haven’t tried 1.2 yet because you were afraid of such changes, you no longer have an excuse.

(Via the Symfony Blog.)

]]>
http://blog.mirthlab.com/2008/11/26/symfony-12-release-candidate-now-available/feed/ 0
Simple Symfony Login Form Example http://blog.mirthlab.com/2008/11/18/simple-symfony-login-form-example/ http://blog.mirthlab.com/2008/11/18/simple-symfony-login-form-example/#comments Tue, 18 Nov 2008 22:25:46 +0000 Mark Quezada http://blog.mirthlab.com/?p=151 There are times when I just need a simple login form that checks for a certain username and password combination in order to lockdown a backend administration interface. The new sfForm sub-framework in Symfony 1.1/1.2 makes it really easy to reuse a Form class for this. If you’re unfamiliar with the new sfForm sub-framework, you should probably start with the Forms Book. Here’s an example form (placed in lib/form):

<?php

class LoginForm extends sfForm
{
  public function configure()
  {
    $this->setWidgets(array(
      'username' => new sfWidgetFormInput(), 
      'password' => new sfWidgetFormInputPassword() 
    ));

    $this->widgetSchema->setNameFormat('login[%s]');

    $this->setValidators(array(
      'username' => new sfValidatorChoice(array('required' => true, 'choices' => array('admin'))), 
      'password' => new sfValidatorChoice(array('required' => true, 'choices' => array('some_password')))
    ));
  }
}

The key here is using sfValidatorChoice to ensure that the input matches some predefined keys (“admin” and “some_password” in this case).

For completeness, here’s the action file:

<?php

class authActions extends sfActions
{
  public function executeLogin(sfWebRequest $request)
  {
    $this->form = new LoginForm();

    if ($request->isMethod('post'))
    {
      $this->form->bind($request->getParameter('login'));
      if ($this->form->isValid())
      {
        // authenticate user and redirect them
        $this->getUser()->setAuthenticated(true);
        $this->getUser()->addCredential('user');
        $this->redirect('home/index');
      }
    }
  }

  public function executeLogout()
  {
    $this->getUser()->clearCredentials();
    $this->getUser()->setAuthenticated(false);
    $this->redirect('@homepage');
  }
}

And the template file loginSuccess.php:

<form action="<?php echo url_for('auth/login') ?>" method="POST">
  <table>
    <?php echo $form ?>
    <tr>
      <td colspan="2">
        <input type="submit" />
      </td>
    </tr>
  </table>
</form>

And of course, you’ll want to turn on security for the application in security.yml:

default:
  is_secure: on
  credentials: user
]]>
http://blog.mirthlab.com/2008/11/18/simple-symfony-login-form-example/feed/ 9
Symfony 1.2 Beta 2 Released http://blog.mirthlab.com/2008/11/10/symfony-12-beta-2-released/ http://blog.mirthlab.com/2008/11/10/symfony-12-beta-2-released/#comments Mon, 10 Nov 2008 22:37:52 +0000 Mark Quezada http://blog.mirthlab.com/?p=133 The second Beta of Symfony 1.2 has been released and adds support for the Doctrine Admin Generator:

We are very happy to announce the symfony 1.2 beta 2 release, which now supports the admin generators for both Doctrine and Propel. No need to use Propel for sexy admin generator anymore.

This will also be the final Beta release before Symfony 1.2 stable is released.

]]>
http://blog.mirthlab.com/2008/11/10/symfony-12-beta-2-released/feed/ 0
sfTaskExtraPlugin Released http://blog.mirthlab.com/2008/11/08/sftaskextraplugin-released/ http://blog.mirthlab.com/2008/11/08/sftaskextraplugin-released/#comments Sat, 08 Nov 2008 19:49:25 +0000 Mark Quezada http://blog.mirthlab.com/?p=131 Kris Wallsmith just released a new plugin that should aid the task of creating and bundling Symfony plugins:

The sfTaskExtraPlugin is a plugin maintained by the symfony core team. It adds a number of useful tasks to your symfony command line to help streamline your workflow. This plugin is relatively young, so I will just be discussing those tasks that we’ll be using for today’s Plugin Developers Day. I should also note this plugin requires symfony 1.2.

]]>
http://blog.mirthlab.com/2008/11/08/sftaskextraplugin-released/feed/ 0