Aug 31
Digg
Stumbleupon
Technorati
Delicious

Symfony’s super puper cache plugin

You know.. I was never had a chance to speed up symfony project performance. I always knew there are a bunch of cache plugins but also always performance was enough good even without any type of caching.
And now I had a chance to investigate this question. I googled for “sfSuperCache” and found some performance measurements which says that it’s faster than sfMemcached, not sure if that’s true but I liked the logic of how supercache plugin would work. So I went and installed this plugin..

But then story is not ending :-)

I added super cache filter to filters.yml, I modified .htaccess like instructions says. I launched my app and.. nothing.. (it’s time to say it has to store static html files in web/cache folder). I googled again and found a thread in symfony’s forum where guy is asking actually the same - “I installed the plugin and is it working?” - no man, it does not work. I started to debug plugin and figured out not obviously things which are though pretty obvious (which proves that this plugin only for real Gurus ;-) )

So take your pen and write following me (of course these things should be done after you did the changes to filters.yml and .htaccess like written in plugin instruction):

1. Go to your apps/frontend/settings.yml and uncomment if you did not yet:

.settings:
cache: on # Enable the template cache

2. Go to your apps/frontend/cache.yml and write if you did not yet:

default:
enabled: on
with_layout: true
lifetime: 86400

Here key phrase is with_layout: true

And only now you can go and drink some beer: you did it man, huzza!


Author: admin
Jul 27
Digg
Stumbleupon
Technorati
Delicious

What Google Gears may offer to Symfony ?

Hi all,

I’m pretty sure you’ve already heard of Google Gears (now it’s just “Gears” as the other companies along with Google joined to the development process), so just to remind Gears is a browsers plug-in which makes possible your site works offline on users machines. This technology incudes 3 main core elements:

  • LocalServer Cache and serve application resources (HTML, JavaScript, images, etc.) locally
  • Database Store data locally in a fully-searchable relational database
  • WorkerPool Make your web applications more responsive by performing resource-intensive operations asynchronously

I’d mention at least 2 ways for how you can use this technology in your symfony application. Btw, I was trying to find anything about gears on symfony forum and it’s mostly unresponded stuff like this:

http://www.symfony-project.org/forum/index.php/m/34645/?srch=gears#msg_34645

So first way is a simple way which Wordpress has chosen. You can simply add caching stuff to your application via using LocalServer component. This way is pretty simple you add standard initial code for gears

<?php use_javascript(’gears_init’) ?>
<script>
if (!window.google || !google.gears) {
location.href = “http://gears.google.com/?action=install&message=” +
“&return=“;
}
</script>

and then use something similar to what Google proposes in samples:

// Change this to set the name of the managed resource store to create.
// You use the name with the createManagedStore, and removeManagedStore,
// and openManagedStore APIs. It isn’t visible to the user.
var STORE_NAME = “my_offline_docset”;

// Change this to set the URL of tha manifest file, which describe which
// URLs to capture. It can be relative to the current page, or an
// absolute URL.
var MANIFEST_FILENAME = “tutorial_manifest.json”;

var localServer;
var store;

// Called onload to initialize local server and store variables
function init() {
if (!window.google || !google.gears) {
textOut(”NOTE: You must install Gears first.”);
} else {
localServer = google.gears.factory.create(”beta.localserver”);
store = localServer.createManagedStore(STORE_NAME);
textOut(”Yeay, Gears is already installed.”);
}
}

// Create the managed resource store
function createStore() {
if (!window.google || !google.gears) {
alert(”You must install Gears first.”);
return;
}

store.manifestUrl = MANIFEST_FILENAME;
store.checkForUpdate();

var timerId = window.setInterval(function() {
// When the currentVersion property has a value, all of the resources
// listed in the manifest file for that version are captured. There is
// an open bug to surface this state change as an event.
if (store.currentVersion) {
window.clearInterval(timerId);
textOut(”The documents are now available offline.\n” +
“With your browser offline, load the document at ” +
“its normal online URL to see the locally stored ” +
“version. The version stored is: ” +
store.currentVersion);
} else if (store.updateStatus == 3) {
textOut(”Error: ” + store.lastErrorMessage);
}
}, 500);
}

// Remove the managed resource store.
function removeStore() {
if (!window.google || !google.gears) {
alert(”You must install Gears first.”);
return;
}

localServer.removeManagedStore(STORE_NAME);
textOut(”Done. The local store has been removed.” +
“You will now see online versions of the documents.”);
}

// Utility function to output some status text.
function textOut(s) {
var elm = document.getElementById(”textOut”);
while (elm.firstChild) {
elm.removeChild(elm.firstChild);
}
elm.appendChild(document.createTextNode(s));
}

where tutorial_manifest.json should contain information about cached files:

{
“betaManifestVersion”: 1,
“version”: “my_version_string”,
“entries”: [
{ "url": "go_offline.html"},
{ "url": "go_offline.js"},
{ "url": "../gears_init.js"}
]
}

So this way even when user goes offline he still is able to work with cached pages.
As for me more interesting feature is Database module. This way along with cached pages you are able to allow user to store locally database (Gears uses SQLite for storing data). Here is a proposed sample:

<?php use_javascript(’gears_init’) ?>
<script type=”text/javascript”>
var db = google.gears.factory.create(’beta.database’);
db.open(’database-test’);
db.execute(’create table if not exists Test’ +
‘ (Phrase text, Timestamp int)’);
db.execute(’insert into Test values (?, ?)’, ['Monkey!', new Date().getTime()]);
var rs = db.execute(’select * from Test order by Timestamp desc’);

while (rs.isValidRow()) {
alert(rs.field(0) + ‘@’ + rs.field(1));
rs.next();
}
rs.close();
</script>

Disadvantage is you need to clone your mysql / pgsql stuff for sqlite but thanks God common SQL commands are mostly the same so it wont be too complicated.
Interesting if the other companies proposes similar mechanism to what Gears proposes. I’m sure making sites to work in online/offline mode still has big perspectives.


Author: admin
Jul 22
Digg
Stumbleupon
Technorati
Delicious

use YML for storing data in db

Sometimes you may need to store complicated data with non-fixed fields/data types in table. There are different ways for that but if we use symfony where YML is so native and good known - why dont store data in table as YML-formed value.

It’s pretty straightforward with using of Spyc class and its methods YAMLLoad, YAMLDump to convert YAML from/into array but some things worth mentioning:

YML usually contains more information that may fit simple varchar so you may want to use “longvarchar” type for storing this kind of info and then I faced with the problem that in order to access this value from $data object you may need to use additionally getContents method, e.g. $data_object->getValue()->getContents().
The other thing - dont forget to decode your text before printing it with YAMLLoad by calling html_entity_decode method, so it finally looks like to dump YAML into PHP array:

Spyc::YAMLLoad(html_entity_decode($data_object->getValue()->getContents()))

and to store text field as YAML well-formed object use this:

Spyc::YAMLDump($this->getRequestParameter(’some_value’))

The other non-ordinary thing is that you may want to prepare fixture YML files for batch processing, in this case the problem you may expect is how to prepare YAML file which contains text field with break lines. I found the solution in sfSimpleForumPlugin (see using content field in this sample):

post_12:
topic_id: topic_7
content: |
If you see no alert, it means that your output escaping is turned on

user_id: tarzanman

That’s it.


Author: admin
Jul 15
Digg
Stumbleupon
Technorati
Delicious

Flex + Symfony = ?

I must say the older I’m getting the more pessimistic I’m about new technologies. All this buzz around RIA .. I was never tried to understand what is going on there, technologies are changing one other: Laszlo, OpenLaszlo, Flex, AIR, Silverlight. Last thing I’ve heard was that Flex with AMFPHP is something worth of my attention and I decided it’s finally time to look into that. I killed whole weekend looking into this and passed full path from euphoria (”wow that’s the best thing i’ve ever seen”) to deep disappointment (”shit i’ll never use it in real life project”). But a few good conclusions I made for myself:

1. Flex is the most perspective technology compared to the others (of course it’s subjective opinion but I know that I have good feeling on such things and I dont want to explain here why I think so but I’d be happy to read here another opinions)

2. Symfony could easily be tied with Flex (however there is really luck of information regard this, mostly non-responded questions on forum like this http://www.symfony-project.org/forum/index.php/m/46982/ or plugin bridge for amfPHP http://trac.symfony-project.org/wiki/sfAmfphpPlugin)

I was half way to start doing this integrating but before that I decided to figure out what is its perspectives and the result is my disappointment.. Why? There is real luck of good samples for Flex 3/PHP. Right now I keep in mind that it might be good to built RIA backend and I’d need for this datagrid with ability to paginate results and filter them and also I’d need authorization component with credentials and easy way to restrict access for different type of users. I did not find such sample. Flex Builder 3 generates CRUD code but without paginating/filtering (why what is the sense of datagrid which is not able to paginate data and which is slowly dying because of 1K records in table), there are also some paginating samples but not tied to mysql, there are simple authentification samples but they are too simple to be used in real projects. I have nothing to start with.. They show me cool charts and zoom animation but all I need is good working sample. And what is bad there is no open-source projects where I can look how this can be done (there are some but they are mostly not about Flex/PHP - http://ntt.cc/2008/04/09/over-30-useful-as3-open-source-projects.html). I know I want too much but how I can start using it (I really want) without these little bricks. Or maybe Flex is wrong decision and I need to look more into Silverlight or so. Is there anyone who could help me to solve this puzzle?


Author: admin
May 24
Digg
Stumbleupon
Technorati
Delicious

Another one constants management plugin

Hi all,

We were happy to see that our plugins are usefull and used in following articles about symfony theme:

http://www.symfony-framework.com/2008/05/22/themes-management-system-with-symfony-step-by-step-tutorial/

Therefore we decided to add to symfony repository the other plugin which we already announced and described on our site a long time ago (see this: http://www.symfonylab.com/sfadvancedconstplugin/

So from now on this plugin is officially added to symfony repository and can be installed via pear:

http://trac.symfony-project.com/wiki/sfAdvancedConstPlugin

We hope you’ll find it usefull and wait for your proposals and comments!


Author: admin
Apr 30
Digg
Stumbleupon
Technorati
Delicious

Backend generator theme

Hi,

I’m wondering if there are available admin themes somewhere. It’s really strange but simple googling and search on symfony forum does not give me anything new.

What I knew before is good Joomla-like theme available here (this one is easy to use and integrate):

http://www.symfony-project.org/forum/index.php/m/16515/

also there is available plugin based on ExtJs but it seems in early development (and it’s pretty slow at least when I tested it out):

http://trac.symfony-project.com/wiki/sfExtjsThemePlugin

There is also plugin which provide distinct configurations between create and edit actions:

http://trac.symfony-project.com/wiki/sfAdvancedAdminGeneratorPlugin

And that’s all? I bet there must be guys who has own themes ( themesholders ;-) )

Why I’m started to talk about all this stuff. I found today in my RSSs this link and thought how good it would be if someone integrates such theme for symfony:

http://webresourcesdepot.com/wp-content/uploads/file/admin-template/index.html

Maybe someday me..


Author: admin
Apr 19
Digg
Stumbleupon
Technorati
Delicious

So what symfonians are talking about?

Hi,

as you know we propose 2 additional services along with writing about symfony. First one is articles voting service and the other one is twitter symfony community.

Voting one is a good chance to read usefull articles and dont waste time on the other ones. We aggregate most of articles and then we personally vote only for the best ones.

Community on twitter helps you to have some fun from reading what are talking symfony developers about. This community exists more than month and it’s slowly growing each day. Guys are talking about food, movies, new projects, share links.
Here is a screenshot so you can get a better idea of how it looks like:

symfonians1.png

I think it’s not surprise that most of the time symfonians are reading feeds, responding emails, cooking, eating, watching movies, and backing home :-)

As for me, I’m going to sleep a bit. And what are you doing? ;-)


Author: admin
Apr 12
Digg
Stumbleupon
Technorati
Delicious

How to handle page representation dynamically

Hi all,

Lets say you want to allow each user’s group to see different page style. You may need to change page layout and css file for this dynamically. Lets imagine we have very similar functionality for a few user groups but we want their dashboard pages look different. Here is the code sample which setup for buyer group separate layout and stylesheet and default layout / stylesheet for default user:

public function preExecute() {
if ($this->getContext()->getUser()->hasCredential(’buyer’)) {
$this->setLayout(’layout_buyer’);
$this->getResponse()->addStylesheet(’style_buyer.css’);
} else {
$this->setLayout(’layout’);
$this->getResponse()->addStylesheet(’style.css’);
}
}

The other approach - we can modify view.yml file for each separate action (so for buyers actions we can have separate layout / stylesheet), e.g.

indexSuccess:
layout: layout_buyer
stylesheets: [ -style, style_buyer ]

Interesting thing is that we can use “-style” syntax which means that we stop using “style.css” for this specific action. Please note that we can use it only from view.yml, if you’d like to remove stylesheet from php code - there is no way to do that, i.e. we have

$this->getResponse()->addStylesheet(’style_buyer.css’)

but we dont have

$this->getResponse()->removeStylesheet(’style_buyer.css’);

Actually removeStylesheet is added to symfony tickets but I dont think it was implemented until now.


Author: admin
Apr 04
Digg
Stumbleupon
Technorati
Delicious

How to customize login action for sfGuardPlugin

Actually, we are going to raise here 2 topics:

  • how to customize login action
  • how to fix referer problem for sfGuardPlugin

Both are quite often using in real life projects. For instance, on logging in user stage you may want to store some extra information which is not provided by sfGuardPlugin by default. Lets say you want to store referer information.

So first of all you would need to override login handler for default sfGuard plugin. For this create a sfGuardAuth module in your application (don’t use the init-module task, just create a sfGuardAuth directory). And copy into lib folder BasesfGuardAuthActions.class.php and into actions directory actions.class.php (take these files from sfGuardPlugin original folder).

Now we are going to edit BasesfGuardAuthActions.class.php, it contains public function executeSignin which is responsible for actual signing in mechanism. Most functionality for actual logging was actual performed so this is the only lastest steps before redirecting user to tha login success/failure steps.

So lets add into this function some code (we assume using of sfGuardUserProfile class along with sfGuardUser so we actually work with extended version of guard plugin. We reffer you to our previous articles “Extending sfGuardPlugin part 1 part 2):

if ($profile = $user->getProfile()) {
$profile->setReferer($referer);
$profile->save();
}

The same way we may handle here the places where should be redirected user after success logging in (as you know sfGuardUser provides singin url success parameter but sometimes we need more than one place to redirect after login, e.g. based on referer we may login user to different locations of dashboard or so).

Next interesting thing is about redirecting user to the page from where he tried to login. Basically, sfGuardPlugin supports this and provides referer parameter for it. Originally this piece of code looks like:

$referer = $user->getAttribute(’referer’, $this->getRequest()->getReferer());

But it never worked for me. There is a ticket opened currently for guard plugin where is proposed to use:

$referer = $user->getAttribute(’referer’) ? $user->getAttribute(’referer’) : $this->getRequest()->getReferer();

This approach looks better and the other guys confirmed it works but I could nto figure out why it does not work for me.
So finally we came to decision that the following code should be added into the template from where is requesting login mechanism. Lets say you have the site where visitors are browsing some data and you have vote link per each data item. And when user clicks on vote you want to popup login form and when user enters in required information you want him to be logged in and stay on the same page. So for it we add the following code to this “browse data” template:

$sf_user->setAttribute(’referer’, $sf_request->getUri());

which basically setup referer in forced way. In our understanding this stuff had to be built into guard plugin but somehow it does not work or works wrong way. Hopefully this is going to be resolved or documented on official sfGuardPlugin page).

We are really sure there must be the other workarounds for it and if you know them share with us so the other guys know how this can be done in easier maner.

Guys, have a great weekend!


Author: admin
Mar 28
Digg
Stumbleupon
Technorati
Delicious

One backend, many sites

It’s good regularly to read through symfony forum. Sometimes there can be found pearls. It makes me feel I’m ready to keep using symfony if such problems are already solved :-)

So here is the one:

I have a homegrown CMS that I use for my clients that I want to port over to the Symfony framework eventually. I have a fair amount of experience using Symfony, but I’m wondering if it can accommodate what I’m looking for.

Right now, I have one instance of a backend that all my clients log into. I do this so that when I make changes to the backend, I only have to roll it out once, instead of making updates to dozens of sites. When a client logs into the CMS, it fetches his/her associated “site_id” and manages only pages associated with that site by filtering every query. Likewise, on the frontend, a local config file tells the controllers to only get records in the CMS that are associated with that site_id…

It seems like Symfony and most other MVC frameworks would rather I have one backend and one frontend, but in this case I have one backend and many frontends… Although they all share the same modules (blog, imagegallery, etc..), so it’s really only one frontend with just the templates and local files changing from site to site.

One thing I considered was setting up a backend application for every site and giving it a symbolic link to the shared backend, but that doesn’t seem like the best solution. Any ideas?

And here is Guru’s response:

I think your problem is easy to solve. You just need to configure connection for each of the databases in your config/databases.yml (unfortently we still need to set default ‘propel’ connection):


all:
propel-client1:
class: sfPropelDatabase
param:
dsn: pgsql://client1.host/client1-db
propel-client2:
class: sfPropelDatabase
param:
dsn: pgsql://client2.host/client2-db
propel-client3:
class: sfPropelDatabase
param:
dsn: pgsql://client3.host/client3-db
propel:
class: sfPropelDatabase
param:
dsn: pgsql://@localhost/default-db

While logging user in you could define his database connection name and store it in the session (depending where you’ll do it code could look different):

sfContext::getInstance()->getUser()->setAttribute('connection', 'propel-client2');

You will then get proper connection and save your object with something like:


$conName = sfContext::getInstance()->getUser()->getAttribute('connection');
$con = Propel::getConnection($conName);
$article = new Article();
$article->setTitle("Test article");
$article->setBody("Blah blah blah");
$article->save($con);

You could also override your Article’s save() method to set connection automagically.

As for me I’d really preffer to keep everything in single shared db (it is implemented e.g. in WPmu) instead of keep cloning databases. In this case backend manage would be easier to implement. But one think and the other happens. So good to know exists solution like this.

Btw, forum posting url is http://www.symfony-project.org/forum/index.php/m/40347/


Author: admin