Categories
php

File Upload Configuration with PHP and IIS

In php.ini it’s important that these two variables are set right:
upload_max_filesize = 2M
post_max_size = 8M

Very often people will up the upload_max_filesize to something like 20M without updating the post_max_size.

Then if you’re on IIS, there is one more gotcha.

There’s an upload setting in C:\WINNT\system32\inetsrv\MetaBase.xml — the default is 200KB. Up that to what you think is necessary for your web app.

Categories
How-To php WebApps

Symfony Has a Swift Plugin for Sending Gmail

It’s easy to send emails using your gmail account with the Swift Plugin.
Here’s some sample code below


$to          = 'somebody@example.com';

$htmlMessage = "OH HAI!";
$textMessage = "*OH HAI!*";

$connection = new Swift_Connection_SMTP(
  sfConfig::get('app_email_smtp_server'),
  sfConfig::get('app_email_smtp_port'), 
  Swift_Connection_SMTP::ENC_SSL
);

$connection->setUsername(sfConfig::get('app_email_username')); # gmail email
$connection->setPassword(sfConfig::get('app_email_password')); # gmail password

$mailer = new Swift($connection);
$message = new Swift_Message("Your subject goes here. OH HAI!");
 
$message->attach(new Swift_Message_Part($htmlMessage, 'text/html'));
$message->attach(new Swift_Message_Part($textMessage, 'text/plain'));
 
// Send,
// try and catch
try {
  if (!$mailer->send($message, $to, sfConfig::get('app_email_username'))) {
    throw new Exception('mailer error');
  }
} catch (Exception $e) {
    sfContext::getInstance()->getLogger()->info(
      "Caught swift send error exception:\n" .  
      $e->getMessage(). " ".
      $e->getFile() . ": Line ".
      $e->getLine() . "\n", $e->getTraceAsString(), "\n"
  );
}
          
$mailer->disconnect();  
Categories
How-To php WebApps

sfGuardPlugin: The Extra Documentation

Hey Folks,

The Symfony project has a section called sfGuardPlugin Extra Documentation.

It’s worth a read, especially the part about using the sfGuardUserProfile calls.

The docs haven’t been updated since March, so if something isn’t working, please refer to my previous blog post on installing the sfGuardPlugin.

I’d like to state that personally, there isn’t really the right way to do this. Sometimes you already have a table that has a username and password. You can skip using the sfGuardAuth password tables by doing the following:

  sf_guard_plugin:
    algorithm_callable: md5
    success_signin_url: @homepage
    profile_class: sfGuardUserProfile
    profile_field_name: account_id
    check_password_callable: [Account, checkPassword]

The important line here is check_password_callable, where you are telling symfony to use the Account table and to use your own checkPassword method.

Categories
php

Wow, PHP has a wordwrap function!

http://www.php.net/wordwrap

picture of php wordwrap

Woot!

Categories
How-To php WebApps

Installing Swift in symfony 1.1 — The missing manual

There’s one little gotcha with installing Swift in symfony 1.1. The directions are correct but do not mention how to get around the error that outputs:


Fatal error: Class ‘Swift_Connection_SMTP’ not found

The solution is quite simple and involves creating an autoload.yml file in your project’s config directory. Here it is:

autoload:
  swift_mailer_classes:
    name: swift classes
    ext:  .php
    path: %SF_PLUGINS_DIR%/swift
    recursive: on

What I really like about Swift is how you can use your gmail account to send messages.

Categories
How-To php WebApps

Installing sfGuardPlugin in symfony 1.1 — A Guide for the Perplexed

Like the verbally creative barfly, who is a dead ringer for a 21+ Juno, that you picked up during last call on a Friday night, symfony 1.1 starts to grow on you. Nevermind your friends, who found Erlang in some higher-scale, hipster, hippy hang out. They tell you it’s time to leave symfony 1.1. You’re perversely drawn to this framework and don’t mind racking up the future therapy bills.

God is dead, and so everything is permitted, unless you can install something like symfony 1.1’s sfGuardPlugin to add logins and login protection to web pages. Like the initiation rites into the Eleusinian mysteries or the Freemasons, not everything is articulated on how to do the install. But below, for the first time, it is.

Note: I use psymfony as an alias which really just means ‘php symfony’.

  • psymfony generate:app backend

Now you can start following the guide written on the symfony website. Below is just from my shell’s history log:

  • psymfony plugin:install sfGuardPlugin
  • psymfony propel:build-model
  • psymfony propel:build-sql
  • psymfony propel:insert-sql — this didn’t work for me so I ended up just doing: mysql -uusername -p < data/sql/plugins.sfGuardPlugin.lib.model.schema.sql
  • follow the instructions in the guide above for fixtures
  • psymfony propel:data-load frontend
  • psymfony propel:data-load backend
  • vim apps/frontend/config/settings.yml
  • vim apps/backend/config/settings.yml
  • psymfony cc

But you’re not done yet. Are you running into a propel connection error? Then you might have to edit some yaml files based on this blog post.

In my case, I ended up having to edit config/databases.yaml by adding the following below:

   propel:
     class:          sfPropelDatabase
     param:
       phptype: mysql
       host: localhost
       database: dev_starster
       username: writes
       password: some_wicked_sick_password
       dsn:          mysql://writes@localhost/dev_starster
       datasource: propel

Are we out of the woods yet?

Unfortunately, symfony 1.1 has a signout bug, where sessions are not entirely cleared. Thanks to this blog post, I was able to hack something together.

In apps/yourapp/modules/sfGuardAuth/actions/actions.class.php write:

public function executeSignout()
{
if (sfConfig::get('sf_environment') != 'test')
{
session_destroy();
session_write_close();
session_regenerate_id();
}
parent::executeSignout();
}

You might have to link the sf_guard_user table to an account table, if you want the account table to do the authorization instead. If so edit apps/modulename/config/app.yml by adding something that looks like this:

  sf_guard_plugin:
    algorithm_callable: md5
    success_signin_url: @homepage
    profile_class: sfGuardUserProfile
    profile_field_name: account_id
    check_password_callable: [Account, checkPassword]

In the lib/model/Account.php you should add code that looks like this:

  public static function checkPassword($username, $password) {
  	$c = new Criteria();
  	$c->add(AccountPeer::EMAIL, $username);
  	$c->add(AccountPeer::PASSWORD, md5($password));
  	$rac = AccountPeer::doSelect($c);
  	//print_r($rac) ; die();
  	if ($rac == TRUE) {
  		return TRUE;
  	} else {
  		return FALSE;
  	}
  }

Here is a list of links that made getting the plugin working possible:

Categories
php WebApps

sfValidatorCompare Is Now sfValidatorSchemaCompare

I’ve been running into other folks that have been having trouble with symfony 1.1 on Twitter. One common stumbling block is sfValidatorSchemaCompare.

I’m just gonna paste code here, because I’m now a week behind schedule working with symfony 1.1 because I didn’t pad time for having to read a good chunk of the source of symfony 1.1:

<?php

    $this->validatorSchema->setPostValidator(new sfValidatorAnd(array(
	  new sfValidatorSchemaCompare('email', '==', 'email_confirm',
		    array(),
		    array('invalid' => 'The email adresses must match')
		  ),
	  new sfValidatorSchemaCompare('password', '==', 'password_confirm',
		    array(),
		    array('invalid' => 'The passwords must match')
		  ),
	    )));

?>

Anyway it’s been cool getting props for posting code like the above. 😀

Good luck!

Categories
php TechBiz WebApps

Does Core Developer Think Symfony 1.1 Alienates PHP Developers?

Have you ever coded in a framework and then woke up one day to find that all your code broke when you upgraded? That’s exactly what happened when symfony 1.1 was released without backwards compatibility. A core symfony developer, François Zaninotto, shares his thoughts about the non-launch of symfony 1.1.

A couple key phrases, that he uses to describe the symfony core developers attitude to us mortals, are pretty disturbing:

  • If you just used symfony for one project, and left if afterwards because it lacked some feature that you needed, then you don’t deserve to be informed that this new release does have this feature.
  • Symfony 1.1 is so good, that it should not be left in everybody’s hands. Think of it as a forbidden manuscript of the middle ages, that only a few copyists ever read and got a fair picture of.
  • …there is no “First Project tutorial” at all for symfony 1.1.

Caveat: Do not use symfony 1.1 unless you want to pour through source code.

Problem: You’re working on symfony 1.1 and it doesn’t work as advertised.

Solution: You have to pad your estimates on symfony based projects by at least a hundredfold. A form that should have taken me no more than an hour at Dogster ended up taking 4 days! Read this blog for important symfony 1.1 updates.

So does François think that PHP developers are being alienated? It’s strongly suggested through his use of irony, and analogy of symfony to a medieval text, but does he say abandon symfony?

Not at all. Rather his frustration noted in a follow up blog post has to do with the fact that he cares a great deal about symfony. If you were thinking about leaving symfony, François is enough reason to stay.

Categories
How-To php WebApps

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.
Categories
php

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].”