Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "batch"

Batch script to populate city and state tables

Add this to your schema.yml

  state:
    id:
    name:          varchar(50)
  city:
    id:
    state_id:
    name:          varchar(50)
 

Create a batch/load_citystates.php

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'frontend');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG',       true);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
sfContext::getInstance();
 
// initialize database manager
$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();
 
echo 'Loading States - ';
 
$page = file_get_contents('http://www.citytowninfo.com/places');
 
preg_match_all('@<tr><td><a href="http://www.citytowninfo.com/places/[^"]*"><strong>([a-z-A-Z ]*)</strong></a></td><td>[^<]*</td><td><a href="http://www.citytowninfo.com/places/[^/]*/[^"]*">[^<]*</a></td></tr>@i', $page, $states, PREG_SET_ORDER);
 
echo count($states). "\n";
 
for ($i = 0; $i < count($states); $i++)
{
    $state = new State();
    $state->setName($states[$i][1]);
    $state->save();
 
    $page  = file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/a-d');
    $page .= file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/e-h');
    $page .= file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/i-l');
    $page .= file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/m-p');
    $page .= file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/q-u');
    $page .= file_get_contents('http://www.citytowninfo.com/places/' . str_replace(' ', '-', strtolower($state->getName())) . '/alphabetically/v-z');
 
    preg_match_all('@<tr><td><a href="/places/[^/]*/[^/]*"><strong>([a-z-A-Z ]*)</strong></a></td><td>[^<]*</td><td>[^<]*</td></tr>@i', $page, $cities, PREG_SET_ORDER);
?>
Getting cities for <?php echo $state->getName(); ?> - <?php echo count($cities); ?>
 
<?php
    for ($j = 0; $j < count($cities); $j++)
    {
        $city = new City();
        $city->setName($cities[$j][1]);
        $city->setStateId($state->getId());
        $city->save();
    }
}
 
by Brandon Nason on 2008-02-27, tagged batch  city  state 
(1 comment)

CLI and Symfony with complex arguments

I create a script to use complex arguments while runing script from command line.

It also allow to switch SF_ENVIRONMENT, SF_APP and SF_DEBUG directly from command line.

Just create configBatch.php in your project's config directory and paste this :

<?php
define('SF_ROOT_DIR',    realpath(dirname(__file__).'/..'));
 
$argv = array();
for ($i = 1; $i < $_SERVER["argc"]; $i++) {
    if ($_SERVER["argv"][$i]{0} === '-') {
        // argument
        $value =  (
            isset($_SERVER["argv"][$i+1]) 
            && 
            $_SERVER["argv"][$i+1]{0} !== '-'
            ?
            $_SERVER["argv"][$i+1]
            :
            true
        );
 
        if ($_SERVER["argv"][$i]{1} === '-') {
            // long argument
            $argv[substr($_SERVER["argv"][$i], 2)] = $value;
        }
        else {
            foreach (str_split($_SERVER["argv"][$i]) as $arg) {
                if (ereg('[a-zA-Z0-9]', $arg)) {
                    $last_arg   = $arg;
                    $argv[$arg] = true;
                }
            }
            $argv[$last_arg] = $value;
        }
    }
}
 
define('SF_APP',         (isset($argv['app'])?$argv['app']:'www'));
define('SF_ENVIRONMENT', (isset($argv['env'])?$argv['env']:'prod'));
define('SF_DEBUG',       (isset($argv['debug'])?1:0));
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 

Then, start your batch file with :

<?php
 
require_once(realpath(dirname(__file__).'/..').DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'configBatch.php');
 
// Your script start here
 

Now, you can pass arguments to you script :

php -f /path/to/project/batch/my_batch.php -rf some_value --help --foo bar
 

Here is the generated $argv :

$argv = array (
  'r' => true,
  'f' => 'some_value',
  'help' => true,
  'foo' => 'bar',
);
 

You can also change the SF_ENVIRONMENT with the --env argument, the SF_APP with the --app argument and the debug flag with --debug argumnent

Enjoy

by Romain Cambien on 2007-11-22, tagged argv  batch  cli 

Environment in batch files

Normally, there is a controller for each environment in your app. However, batch scripts have only one controller, and hence you have to set the environment manually.

This code allows you to set the environment to 'dev' while developing, and to 'prod' when your batch script has to run on the production server. The clever thing here is that this is done transparently on the production server (whoever calls your scripts do not have to make a choice of environment).

Create a file batchConfig.php (eg. in config folder):

$env = (((count($argv) >= 2) && ($argv[1] == 'dev')) ? 'dev' : 'prod');
 
define('SF_ROOT_DIR',    realpath(dirname(__file__).'/..'));
define('SF_APP',         'frontend');
define('SF_ENVIRONMENT', $env);
define('SF_DEBUG',       true);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
// Initialize database manager.
$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();
 

(The first line does all the work.) In all your batch files, just include it with:

require_once('config/batchConfig.php');
 

and leave out all the usual definitions and database connection code.

In dev, just call:

php myscript.php dev
 

and do as usual in prod:

php myscript.php
 

As an added benefit, your batch files will only contain actual business logic.

by Martin Kock on 2007-10-04, tagged batch 

Doctrine-build-all(-load) workaround

It's very annoying that the pake tasks @doctrine-build-all@ and @doctrine-build-all-load@ don't work. So I've thought, why don't write a shell script which executes the single steps for me.

Just create a new file in your batch directory. For example 'build' or 'doctrine'

#!/usr/bin/env bash
 
symfony doctrine-drop-db <your app>
symfony doctrine-build-db <your app>
symfony doctrine-build-model <your app>
symfony doctrine-build-sql <your app>
symfony doctrine-insert-sql <your app>
 
php batch/<your load-data-batch-file>.php
by Halil Köklü on 2007-07-25, tagged batch  doctrine  model 

package.xml file structure generator for plugins

It can be a hassle to write a package.yml for a plugin if it contains many files. Fortunately, with the help of the sfFinder class and a bit of programming, you can automate the generation of the <content> part in a batch.

Create a batch/package_generator.php with the following code:

<?php
 
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'frontend');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',       false);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
$line          = array();
$lines         = array();
$previous_dirs = array();  
$files         = sfFinder::type('file')->relative()->in('path/to/plugin/files');
 
// Prepare the list of files for nice hierarchy
foreach($files as $file)
{
  $file = str_replace('\\', '/', $file);
  $dirs = explode ('/', $file);
  $line['filename'] = array_pop($dirs);
  $temp_dirs = $dirs;
  foreach($dirs as $dir)
  {
    if($previous_dirs && $dir == $previous_dirs[0])
    {
      array_shift($previous_dirs); 
      array_shift($dirs);
    } 
  }
  foreach($dirs as $dir)
  {
    $line['open'][] = $dir;        
  }
  foreach($previous_dirs as $dir)
  {
    $line['close'][] = $dir;        
  }
  $lines[] = $line;
  $line = array();
  $previous_dirs = $temp_dirs;
}
$blanks = 0;
?>
 
<?php foreach($lines as $line): ?>
<?php if(isset($line['close'])): ?>
<?php foreach($line['close'] as $dir): ?>
<?php echo str_repeat('  ', --$blanks) ?></dir>
<?php endforeach; ?>
<?php endif; ?>
<?php if(isset($line['open'])): ?>
<?php foreach($line['open'] as $dir): $counter++ ?>
<?php echo str_repeat('  ', $blanks++) ?><dir name="<?php echo $dir ?>">
<?php endforeach; ?>
<?php endif; ?>
<?php echo str_repeat('  ', $blanks) ?><file name="<?php echo str_replace('\\', '/', $line['filename']) ?>" role="data"/>
<?php endforeach; ?>

Just run it with

> php batch/package_generator.php

and paste the output in your package.xml. That's all.

by Francois Zaninotto on 2007-01-04, tagged batch  package  plugin 
(2 comments)

simple console options for batch scripts

I was looking for this type of functionality:

'php batch/mybatch.php app=batch env=dev'

The following allows me to use the same batch scripts for different environments and applications. It also keeps batch scripts lean by only requiring one line.

batch/run_me.php:

require_once('lib/batch.php');
 
//
// begin batch scripting here
//

batch/lib/batch.php:

set_time_limit(0);
 
$app = get_app($argv[1]);
$env = get_env($argv[2]);
$debug = get_debug($argv[3]);
 
//
// initialize symfony
//
 
define('SF_ROOT_DIR',         realpath(dirname(__FILE__).'/../..'));
define('SF_APP',              $app);
define('SF_ENVIRONMENT',      $env);
define('SF_DEBUG',            $debug);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
sfContext::getInstance();
 
//
// initialize doctrine (just an example)
//
 
$connection = sfDoctrine::connection();
 
//
// parse command line args
//
 
function get_app($argv)
{
  preg_match('@app=(\w+)@', $argv, $match);
 
  return isset($match[1]) ? $match[1] : 'batch';
}
 
function get_env($argv)
{
  preg_match('@env=(\w+)@', $argv, $match);
 
  return isset($match[1]) ? $match[1] : 'dev';
}
 
function get_debug($argv)
{
  preg_match('@(true|false)@', $argv, $match);
 
  return isset($match[1]) ? $match[1] : true;
 
}
by Roger Stanton on 2006-09-25, tagged batch  cli 

Sending batch emails

Sending a large volume of emails using symfony's built-in email support can be problematic because of memory overhead involved in calling the sendEmail action for every email to be sent. In order to overcome this, we will have to use another way. In essence, instead of making multiple symfony mail calls, we will grab the presentation for the email action, then use sfMail directly to send our emails.

In an action

// Get the presentation only for the actual email.
// email/newsletter is the module/action pair that will
// generate the template for the actual email in this example.
$raw_email = $this->getPresentationFor('email', 'newsletter');
 
require_once sfConfig::get('sf_symfony_lib_dir') . '/addon/sfMail/sfMail.class.php';
$mail = new sfMail();
$mail->setMailer('sendmail');
$mail->setCharset('utf-8');
$mail->setContentType('text/html');
 
$mail->setFrom($sender_email, $sender_name);
$mail->setSubject($newsletter_title);
$mail->setBody($raw_email);
 
// To further ensure that we don't choke up on the
// emails, we introduce a throttle. In this example,
// we use 100, which we will use to sleep for a period
// of time for every 100 emails sent.
 
$throttle = 100;
$i = 0;
 
// Now, run a loop through all the email addresses in the mailing list.
 
foreach($email_addrs as $email_addr)
{
    if ($i % $throttle == 0)
    {
        sleep(10); // Here, we sleep for 10 seconds for every $throttle emails sent.
    }
 
    $mail->addAddress($email_addr);
    $mail->prepare();
    $mail->send();
    $mail->clearAllRecipients();
    $i++;
}

That's it! Now, just go ahead and set up the email/newsletter pair which will set up the template for the actual email.

Update: In order to beat the maximum execution time limit in PHP, I also use

set_time_limit(0);

to remove the limit at the start of my actual script. In addition, it may also be a good idea to run the action as a batch script in the background so that the mass mailing can occur in the background.

by Ron Lim on 2006-06-26, tagged batch  email 
(3 comments)

Sending email from a batch script

It can be tricky sending email from a batch script (e.g. for cron use), here's how to do it. Start with your usual batch setup:

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'app_name');
define('SF_ENVIRONMENT', 'environment');
define('SF_DEBUG',       true);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
sfContext::getInstance();

You can set attributes directly from the batch script if you wish:

sfContext::getInstance()->getRequest()->setAttribute('key', $value);

Then forward on to another module/action to handle processing and forwarding to mail as usual:

sfContext::getInstance()->getController()->forward('action', 'module');
by James McGlinn on 2006-06-22, tagged batch  cli  email 

Use the model in a batch or a test

To use database connections defined in the databases.yml configuration file, you can use the following snippet:

// initialize database manager
$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();
by Fabien Potencier on 2006-05-21, tagged batch  configuration  propel  test 
(2 comments)

Load data batch

Create a batch/load_data.php script with:

<?php
 
define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'frontend');
define('SF_ENVIRONMENT', 'dev');
define('SF_DEBUG',       true);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
// initialize database manager
$databaseManager = new sfDatabaseManager();
$databaseManager->initialize();
 
$data = new sfPropelData();
$data->loadData(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'fixtures');
 
?>

Call it with:

$ cd batch
$ php load_data.php

It will load the data contained in all the .yml files of the data/fixtures/ directory.

by Francois Zaninotto on 2006-05-20, tagged batch  data  propel 
(4 comments)