Posts Tagged ‘php’
Friday, January 15th, 2010
Many months ago I had asked for help on the symfony forums on how to create a delete button using either the link_to() or button_to() method. I had tried but was always getting validation errors. Today a person asked whether anyone had figured out a solution. It prompted me to do more research into symfony’s core code and found a solution (though the solution wasn’t in the core code).
Original delete text link code:
echo link_to(
'Delete',
'state/delete?id='.$form->getObject()->getId(),
array('method' => 'delete', 'confirm' => 'Are you sure?')
);
New delete BUTTON link code:
echo link_to(
'<button>Delete</button>',
'state/delete?id='.$form->getObject()->getId(),
array('method' => 'delete', 'confirm' => 'Are you sure?')
);
Till Next Time
Tags: delete button, delete link, php, quickie, symfony, symfony 1.2
Posted in programming | No Comments »
Wednesday, January 6th, 2010
Setting the default value for a symfony form field is one of those tasks so simple that it’s impossible to find out how to do it without a good bit of trial and error. So without further ado, here is how to set a DateTime field’s default value:
$this->widgetSchema['start_time']->setDefault(date("m/d/Y", now()));
Till Next Time
Tags: datetime, fields, form fields, forms, php, quickie, symfony
Posted in programming | 1 Comment »
Friday, January 1st, 2010
One thing that’s made programming on symfony very aggravating has been dealing with the forms. Some sections of the forms are not well documented. The main issue that I have with this at work is that we deal with GPS coordinates and the users enter their coordinates in degree-minute-seconds format but the database saves them in degree-decimal format.
I had googled for a solution to this problem before, but had not found anything to guide me to the answer. The couple answers I had found were not very clear on getting it to work. Till I found this. Following these guidelines I got it to work on a test deployment of symfony. Code below:
class Blog extends BaseBlog {
/**
* Initializes internal state of Blog object.
* @see parent::__construct()
*/
public function __construct()
{
// Make sure that parent constructor is always invoked, since that
// is where any default values for this object are set.
parent::__construct();
}
/*
* this function overrides the BaseBlog::save function to allow
* changes to be made to the object before saving to the database
*/
public function save(PropelPDO $con = null)
{
$this->setCommentCount('11');
return parent::save($con);
}
}
Till Next Time
Tags: form update, forms, gps, php, sfForms, symfony
Posted in programming | No Comments »
Tuesday, December 22nd, 2009
The default install on A2hosting’s VPS does not have mbstring or APC installed by default. I became aware of this as I was setting up symfony on the new server. I googled around looking for a quick guide to install them.
mbstring is a straight-forward install:
Easy.
Installing APC is a pretty simple affair with one big caveat at the end. The guide that I found for installing APC is on HowToForge. The last two steps are particular to CentOS on A2hosting’s platform.
1. Install PEAR.
2. Install php-dev & httpd-dev.
yum install php-devel httpd-devel
3. Install group Development Tools
yum groupinstall 'Development Tools'
4. Install group Development Libraries
yum groupinstall 'Development Libraries'
5. Install APC
6. Reboot Apache
7. Error alerts you to SSLRandomSeed error.

SSLRandomSeed Error
8. Fix Centos Dev

Fix CentOS Dev on A2hosting
It took me an hour last night to figure out the last step. Without the last step there is no authentication so there is no SSH access.
Till Next Time
Tags: a2hosting, alternative php cache, apc, centos, centos 5, howtoforge, httpd, httpd-dev, mbstring, php, php-dev, php5, virtual private server, vps, yum
Posted in programming | No Comments »
Tuesday, November 17th, 2009
In the users table at my company’s website there are fields for company, division, region, and location. Since each level of the company organization affects all the lower categories I have to filter out the invalid choices when a higher level choice is selected.
I’ve implemented this on some forms that I’ve created manually on the site but not in any forms that I haven’t heavily modified from the stock symfony creation. I started googling around to find a solution but could not find a simple explanation of how to do it. I expected to find at least some information in one of symfony’s otherwise excellent tutorials, but alas, no.
I had a minor epiphany and went digging through the forms API that symfony provides and realized that I should easily be able to do this through the sfWidgetFormPropelChoice method. The second parameter passed is the html attributes for the form field. I thought I had seen a form post here that said that I could add javascript code to the html attributes and not have it get converted into html entities.
I tried throwing a simple alert() inside the onchange attribute for my company box and wham! it worked! So simple. Code below:
new sfWidgetFormPropelChoice(
array(
'model' => 'Company',
'add_empty' => true
),
array(
'onchange' => "filterBy('company', 'division', this.value, 'sf_guard_user_user_division_id');" .
"filterBy('company', 'region', this.value, 'sf_guard_user_user_region_id');" .
"filterBy('company', 'location', this.value, 'sf_guard_user_user_location_id');"
)
)
Till Next Time
Tags: forms, javascript, onchange, php, sfWidget, symfony, widgets
Posted in programming | 2 Comments »
Tuesday, May 26th, 2009
One of the features of the new platform that I am working on is the ability to automatically retrieve all new seismic activities before the end-user posts that there has been an activity. This will make the data transfer appear instantaneous to our clients and make us look all-around awesome.
So I have a script designed to run whenever I need it to automatically get any new activities and save them to the local database waiting for the end-user. I set it up to run every 15 minutes until I got the multitudes of old data into the new platform. I’m talking ~170,000 activities, and each activity takes about 45-90 seconds to process.
So below is my simple cronjob command to have it run every 15 minutes 24/7/365.
*/15 * * * * php /var/lib/symfony/cron/runcron.php >> /var/lib/symfony/cron/test_cron_log.log
Till Next Time
Tags: cron, cronjob, crontab, linux, php, symfony, ubuntu
Posted in programming | No Comments »
Friday, May 22nd, 2009
I am making progress on my company’s new website. I’m about 3 months in and will be launching the first version of the site in a few weeks. So it was dismaying, to say the least, when I found that when I created the database schema for the symfony project I used the wrong data type for a few fields.
In the current platform these particular fields are stored in MySQL ‘text’ fields. Simple, expands as needed, no problem. I accidentally set these fields in the new schema as varchars. My issue is that for most users, my varchar(32) field would be fine, but for that occasional user who uses lots of explosives & different delays, this would mean a loss of data. Not something I am very keen on.
I googled a bit and could not find any information on doing a reconfiguration of the database fields in symfony and I figured it wouldn’t be too difficult to manually convert the field to a blob and modify all the accessing functions. In the end, I was right! Assuming you don’t make any mistakes it is remarkably simple to change a database field from a varchar to a blob. You only need to modify two files and four functions. So, without further adieu, I give to you the code to make a blob field accessible instead of a varchar field for symfony through propel.
(Original code is commented out for reference)
// lib/model/om/BaseActivityInfo.php
public function getActivityExplosiveType()
{
// return $this->activity_explosive_type;
$content = "";
if(is_resource($this->activity_explosive_type))
{
while(!feof($this->activity_explosive_type))
{
$content .= fread($this->activity_explosive_type, 4096);
}
rewind($this->activity_explosive_type);
return $content;
}
else
return $this->activity_explosive_type;
}
public function setActivityExplosiveType($v)
{
// this is the new code (copied & modified from setActivityExtra1) to set BLOB type
// Because BLOB columns are streams in PDO we have to assume that they are
// always modified when a new value is passed in. For example, the contents
// of the stream itself may have changed externally.
if (!is_resource($v)) {
$this->activity_explosive_type = fopen('php://memory', 'r+');
fwrite($this->activity_explosive_type, $v);
rewind($this->activity_explosive_type);
} else { // it's already a stream
$this->activity_explosive_type = $v;
}
$this->modifiedColumns[] = ActivityInfoPeer::ACTIVITY_EXPLOSIVE_TYPE;
return $this;
/*
// this is the original code for when the field was a simple varchar
if ($v !== null) {
$v = (string) $v;
}
*/
}
public function hydrate($row, $startcol = 0, $rehydrate = false)
{
try {
// ... other field's code ...
// this is the original hydration code for the varchar type activity_explosive_type
// $this->activity_explosive_type = ($row[$startcol + 36] !== null) ? (string) $row[$startcol + 36] : null;
// this is the new hydration code for the blob type activity_explosive_type
if ($row[$startcol + 36] !== null) {
$this->activity_explosive_type = fopen('php://memory', 'r+');
fwrite($this->activity_explosive_type, $row[$startcol + 36]);
rewind($this->activity_explosive_type);
} else {
$this->activity_explosive_type = null;
}
// ... other field's code ...
$this->resetModified();
$this->setNew(false);
if ($rehydrate) {
$this->ensureConsistency();
}
// FIXME - using NUM_COLUMNS may be clearer.
return $startcol + 92; // 92 = ActivityInfoPeer::NUM_COLUMNS - ActivityInfoPeer::NUM_LAZY_LOAD_COLUMNS).
} catch (Exception $e) {
throw new PropelException("Error populating ActivityInfo object", $e);
}
}
if ($this->activity_explosive_type !== $v) {
$this->activity_explosive_type = $v;
$this->modifiedColumns[] = ActivityInfoPeer::ACTIVITY_EXPLOSIVE_TYPE;
}
return $this;
} // setActivityExplosiveType()
// lib/model/map/ActivityInfoMapBuilder.php
public function doBuild()
{
$this->dbMap = Propel::getDatabaseMap(ActivityInfoPeer::DATABASE_NAME);
$tMap = $this->dbMap->addTable(ActivityInfoPeer::TABLE_NAME);
$tMap->setPhpName('ActivityInfo');
$tMap->setClassname('ActivityInfo');
$tMap->setUseIdGenerator(true);
$tMap->addPrimaryKey('ID', 'Id', 'INTEGER', true, null);
// ... other field's code ...
// this is the original code for the varchar type activity_explosive_type field
// $tMap->addColumn('ACTIVITY_EXPLOSIVE_TYPE', 'ActivityExplosiveType', 'VARCHAR', false, 32);
// this is the new code for the blob type activity_explosive_type field
$tMap->addColumn('ACTIVITY_EXPLOSIVE_TYPE', 'ActivityExplosiveType', 'BLOB', false, null);
// ... other field's code ...
} // doBuild()
} // ActivityInfoMapBuilder
UPDATE:
I was doing some work with these form elements and realized that the Validators need to be modified as well. It’s rather simple, all you need to do is change the validator to remove any size limitations and convert the Validator to a sfValidatorString from whatever type of sfValidator it was. Code below:
// lib/form/base/BaseActivityInfoForm.class.php
...other code...
// original code
// 'activity_explosive_type' => new sfValidatorString(array('max_length' => 32, 'required' => false)),
'activity_explosive_type' => new sfValidatorString(array('required' => false)),
// original code
// 'activity_explosive_make' => new sfValidatorString(array('max_length' => 32, 'required' => false)),
'activity_explosive_make' => new sfValidatorString(array('required' => false)),
// original code
// 'activity_explosive_quantity' => new sfValidatorNumber(array('required' => false)),
'activity_explosive_quantity' => new sfValidatorString(array('required' => false)),
...other code...
Till Next Time
Tags: custom code, manual database field changes, modify symfony code, orm, php, propel, symfony
Posted in programming | No Comments »
Wednesday, April 22nd, 2009
A couple weeks ago I came across a query that I needed to write that would only retrieve the records that had the same date as another table’s record. Since I am using propel, I looked for a simple way to format the datetime field to just match the dates in the query so that only the appropriate records would be returned. I googled for a long time, not reaching any solution.
I ended up with a stopgap measure to get me by until I could focus more time on the problem. I iterated through the results and used php to compare the dates and drop the nonequal date records. Today the problem came to a head where I could not move forward with my work until I solved the issue. Since I’m using mysql and propel, I ended up creating a custom criteria using the mysql ‘DATE’ function. I know this is suboptimal in that my query is now tied to mysql, but I really don’t expect to be changing databases soon, or ever.
Most of the solutions that I found online would not work with the DATE function for one reason or another (another = I couldn’t figure it out). I finally found my solution in the symfony forums (can you believe it!?!?!) here. For some reason google failed me on this one. So out of the billions of pages online I had to find the one (1) that had my solution. Luckily time_to_find_solution < losing_my_mind. So the very simple solution is this:
$c->add(ActivityInfoPeer::ACTIVITY_EVENT_TIME, 'DATE('.ActivityInfoPeer::ACTIVITY_EVENT_TIME.')= DATE('.ActivitySeismoInfoPeer::ASI_EVENT_TIME.')', Criteria::CUSTOM);
Till Next Time
Tags: Criteria, Criteria::CUSTOM, custom, date, date function, mysql, php, propel, symfony
Posted in programming | No Comments »
Thursday, April 9th, 2009
I had to do some looking to find how to do an ‘or’ statement in symfony with propel. I found out at a google’s group here and the api documentation from propel is here. Once I found the information it was surprisingly easy. Below is the code I ended up using to select records either updated in the last two weeks OR activities that are delayed AND activities that the posting times are NULL (implying they are not posted yet).
$c = new Criteria();
$c->AddDescendingOrderByColumn(ActivityInfoPeer::ACTIVITY_EVENT_TIME);
$criterion = $c->getNewCriterion(
ActivityInfoPeer::UPDATED_AT, date("Y-m-d H:i:s", time() - 1209600), Criteria::GREATER_THAN)->addOr(
$c->getNewCriterion(ActivityInfoPeer::ACTIVITY_DELAYED, 1, Criteria::EQUAL)
)->addAnd($c->getNewCriterion(ActivityInfoPeer::ACTIVITY_POST_TIME, null, Criteria::ISNULL)
);
$c->add($criterion);
$this->pending_activities = ActivityInfoPeer::doSelect($c);
Till Next Time
Tags: Criteria, Criterion, OR statement, php, propel, symfony
Posted in programming | No Comments »
Thursday, March 12th, 2009
A few days ago my company got our production server for the upcoming website up and running so that I can start working with it. Since this server is being hosted at another office out of state I am learning how to deploy symfony on a server that I don’t have physical access to.
When doing all my previous work (all 3 months!) with symfony, I have either worked on it on my local machine or on a small dev server in our server closet. The main difference on this new server is that I cannot update the php.ini file whenever I choose. I am able to have it modified when there is a long-term need (ie- setting magic_quotes_gpc & short_open_tag to Off). But when running the build commands for the new platform I need a good bit of memory. The propel:build-model action takes more than 32 MB of memory and since I couldn’t change the php.ini file I had to find a way around it.
I discovered that the symfony .bat file that is in the symfony distro has php in it and I was able to simply use the ini_set function to set the memory limit to 64MB while executing any CLI symfony scripts.
Till Next Time
Tags: build-model, cli, ini_set, memory_limit, php, propel, symfony
Posted in programming | No Comments »