Archive for the ‘Symfony’ Category
Google chart over HTTPS/SSL
The google charts API does not support the https protocol. If your website is being delivered through a secure connection, the chart will cause a SSL error. Here's a quick way to deliver google chart images over ssl.
To start off with, the chart image must be delivered from a secure connection. Google doesn't allow this plain and simple, so we need to figure out how to host it from our own site. We accomplish this by fetching the image from google using the standard API, writing it to a file, and then calling it on our own script. We basically make a image handling proxy.
Let's take a simple google chart to experiment with.
-
$chart_image = 'http://chart.apis.google.com/chart?chs=500x50&chf=bg,s,ffffff&cht=ls&chd=t:23.52,20.58,26.47,23.52,23.52,23.52,100.00,0.00,23.52,23.52,27.94,20.58,23.52&chco=0066ff';
Next we need to make a function to fetch and save the google chart locally. It will check the chart against the local copy and save it if the chart doesn't exist, or the image has changed. This way we aren't re-writing the same chart on every request, but if the chart changes, it will be updated appropriately.
-
{
-
}
-
-
return $file_name;
-
}
Lastly we tie it all together so that it is usable in our application. Im using this within a class, but this could just be used as a function as well. Your image directory will need to be writable for this to work.
-
public function doSomething()
-
{
-
-
$local_image_path = '/path/to/images/charts/';
-
$image_name = 'some_chart_image.png';
-
$chart_url = 'http://chart.apis.google.com/chart?chs=500x50&chf=bg,s,ffffff&cht=ls&chd=t:23.52,20.58,26.47,23.52,23.52,23.52,100.00,0.00,23.52,23.52,27.94,20.58,23.52&chco=0066ff';
-
-
$image = self::saveImage($chart_url ,$local_image_path,$image_name);
-
-
}
You'll need to implement your own error handling, and adjust this to meet the paths and specifics of your server, but the image can now be called from:
<img src="/images/charts/some_chart_image.png" alt="" />
If you need help creating your base chart image, this tool is a great place to start.
Symfony 1.2 redirect specific modules and actions to HTTPS (SSL)
Post Symfony 1.1, the sfSslRequirementPlugin will no longer work.
Having needed a way to force a SSL connection for certain pages, I modified a few scripts that I found online, and created a very simple filter to handle this. This was inspired by this script, and the unacceptably poor example in the Symfony 1.2 book.
To start off with, we need to modify our app.yml file to specify what modules and/or actions need to be secure. Leave the action completely blank if you want the entire module secure. Also change ignore_non_secure to true if you don't care if non specified pages are server over a ssl connection. Basically, from the app.yml below, setting this to false, will redirect any module/action to the non-secure version if it is not specifically defined under secure_actions. Setting it to true will allow a user to request any page over https, even if it is not listed in app.yml. Let me know if this is confusing in any way.
-
//app.yml
-
all:
-
ssl:
-
ignore_non_secure: false
-
secure_actions:
-
- { module: shopping_cart}
-
- { module: services action: apply}
Next we add this filter. Save this under MyProject/apps/MyApp/lib/sfSslFilter.php
-
<?php
-
-
class sslFilter extends sfFilter
-
{
-
/**
-
* Execute filter
-
*
-
* @param FilterChain $filterChain The symfony filter chain
-
*/
-
public function execute ($filterChain)
-
{
-
-
$context = $this->getContext();
-
$request = $context->getRequest();
-
-
$ssl_actions = sfConfig::get('app_ssl_secure_actions');
-
$allow_ssl = sfConfig::get('app_ssl_ignore_non_secure');
-
-
/*
-
* Uncomment For Debugging
-
*
-
* echo '<pre>';
-
* print_r($ssl_actions);
-
* echo '</pre>';
-
* exit();
-
*
-
*/
-
-
if (!$request->isSecure())
-
{
-
//Redirect to the Secure Url
-
//If the module and/or action match $ssl_actions set in app.yml
-
foreach($ssl_actions as $action)
-
{
-
-
if($action['module'] == $context->getModuleName() && !$action['action']){
-
-
//The entire module needs to be secure
-
//Redired no matter what the action is.
-
-
return $context->getController()->redirect($secure_url, 0 , 301);
-
-
-
} else if($action['module'] == $context->getModuleName() && $action['action'] == $context->getActionName())
-
{
-
-
//Redirect if the module and action need to be secure
-
-
return $context->getController()->redirect($secure_url, 0 , 301);
-
}
-
}
-
-
} else if($request->isSecure() && !$allow_ssl)
-
{
-
$redirect = true;
-
-
//Redirect to the Non-Secure Url
-
//If the module and/or action are not in $ssl_actions set in app.yml
-
foreach($ssl_actions as $action)
-
{
-
if(($action['module'] == $context->getModuleName() && !$action['action']) || ($action['module'] == $context->getModuleName() && $action['action'] == $context->getActionName()))
-
{
-
$redirect = false;
-
}
-
}
-
-
if($redirect)
-
{
-
return $context->getController()->redirect($non_secure_url, 0 , 301);
-
}
-
}
-
-
$filterChain->execute();
-
-
}
-
}
Finally, add to the MyProject/apps/MyApp/config/filters.yml file:
-
sslFilter:
-
class: sslFilter
Clear the cache (symfony cc), and there you have it. Let me know if you have a better or different way of dealing with this on a per-module or per-action basis. Hopefully sfSslRequirementPlugin will get ported to work with Symfony 1.2, as the method above will not alter routes on your application.
Additionally, I specifically used 301 redirects to make this more search engine friendly, in case Google or another bot gets on a ssl page. This will help prevent getting duplicate pages indexed due to http and https versions of the same page.
Symfony and Modalbox
ModalBox is a cool inline-popup script that can be used to create interactive Web 2.0 dialogs. Modalbox uses the Prototype javascript framework, which is coincidentally the same that Symfony uses for its included Javascript and Ajax functions.

Unfortunately Modalbox uses a more recent version of Prototype, and there is no track on when we can expect Symfony to upgrade it's included version of Prototype. However, this doesn't prevent us from using Modalbox in a Symfony development. We do have to trick symfony into using the correct Propel version for us. Once Symfony updates their Prototype version, using modalbox should become substantially easier.
To start out we need to download modalbox, and upload the newer prototype, scriptaculous, and modalbox.js scripts to our web/js directory.
Querying with Propel Criteria using “NOT IN” (criteria::not_in)
It's fairly common to use "NOT IN" database queries in web development.
Symfony when using Propel does not have native support for using NOT IN queries in reference to another tables. You can use NOT IN and an array, but cannot use NOT IN with reference to another table.
Here's how to use NOT IN other_table with Propel and Symfony. Let's pretend we need to run this query.
-
SELECT * FROM my_table_1 WHERE id NOT IN (
-
SELECT id FROM my_table_2
-
);
Using Propel and Criteria, there is no native way of running this query. But, with the Criteria::CUSTOM modifier, we can force this query through propel.
It's actually very easy.
-
$c = new Criteria;
-
-
$not_in_query = 'my_table_1.id NOT IN (
-
SELECT id
-
FROM my_table_2)';
-
-
$c->add(MyTable1Peer::ID, $not_in_query, Criteria::CUSTOM);
-
-
$result = MyTable1Peer::doSelect($c);
You can add whatever other Criteria to the query as well. So far this is the only reliable way to run these sort of queries that I've found.
If you want to keep this more true to the Propel ORM, you would use something like this:
-
$c = new Criteria;
-
-
$not_in_query = "
-
%s NOT IN (
-
SELECT %s
-
FROM %s)";
-
-
$not_in_query,
-
MyTable1Peer::ID,
-
MyTable2Peer::ID,
-
MyTable2Peer::TABLE_NAME
-
);
-
-
$c->add(MyTable1Peer::ID, $not_in_query, Criteria::CUSTOM);
-
-
$result = MyTable1Peer::doSelect($c);