Is it possible to have conditional routing in a Silex app? - silex

I am writing a web application that has a front facing website and then an admin console. I would like to be able to have a setting that when set to true means that a holding or maintenance page is displayed on the front end website.
My routes configuration is currently in a yaml file and is read on on each request. But now I want it to be clever enough to know whether it is in maintenance mode or not and if it is to direct all routes to one specific page. Or it could change the routes so that there is only one.
I have thought that this could be done with different files being loaded based on the setting but then means that all routes are static and cannot be retrieved from a database for example. Additionally I have had problems reading from the database during the setup phase of the request. I configured the system to read from the DB as service but this does not appear to be usable at the setup phase, have i got this wrong?
Any pointers gratefully recieved.
Russell

I often use maintenance page with Silex:
At the same place I define $app['debug'] = true; I also define an other variable $app['maintenance'] = true; that I use for various check.
Among them I define a maintenance page as following:
$app->before(function (Request $request, Application $app) {
if($app['maintenance']){
$subRequest = Request::create('/maintenance', 'GET');
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
});
$app->get('/maintenance', function () use ($app) {
// Here you can return your maintenance page
return $app->render('maintenance.twig');
});
Then when I turn on the maintenance variable, every request is redirected to the maintenance route.
As you can see I don't use any yaml configuration file in my app, but the idea is the same with them.

Related

contao 4.4 - how to congfigure a multilanguage instance

I want to create a multilanguage site in contao.
What I did so far:
At first I copied the Page tree of current language.
At second I added domains like example.com/de and example.com/en in site-structure "Domain name" of both root pages.
Edit: Finally I added app/config/config.yml
contao:
prepend_locale: true
For my assumption it should work now but it doesnt.
What else is necessary to make it work.
In your case you do not configure any DNS names for your website roots, since you are using only one domain. Instead, you should use the following in your app/config/config.yml:
contao:
prepend_locale: true
Clear and warmup the production cache afterwards. This will generate URLs like example.com/de/… and example.com/en/….
See also https://github.com/contao/core-bundle#configuration

Maintain parameter info in the request path for all pages instead of the subdomain

I seek some guidedence here ... ( I'm not sure if this is the best title )
At the moment I prepend a "server name" to the url like this:
server10.example.com
This works fine, except that I need to handle all the subdomains on the IIS and I'm not sure google are happy about jumping around from sub to sub to sub, when it seems the links to the other servers.
I'm kind a hoping for a nice way to archive this wioth asp.net mvc.
Most pages are related to a "server" ... there are however a few info pages, contact, home that dont really need a valid "server" name ... but could just be "na" for not available, but the name need to be maintained, if there is already a selected server, when a user are keeps browsing the site. This needs to be as transparent as possible when I need to create the links to the diffenrent pages.
I could extend the Html Action() extensien to automatically add the selected "server" from the previusly request to the page.
In the format:
/{serverParameter}/{controller}/{action}/{parameterInfo}
And if no server is selected, just add "na" as the {server} placeholder.
I'm not sure if more information is needed, but please let me know if ...
I tired of extracting the selected server from the domain part and the other way also seems better, I just can't think of a good way to structure this ...
Updated
90% of all the pages are about a server that the user select at some point. Could be server10, server9, server20 ... just a name. I want to maintain that information across all pages, after the users has selected it or else I just want it to be f.ex: "empty".
I mostly looking for an easy way of doing this or an alternative ... atm I'm prepending the serverParamter to the url so it ends up being: "serverParameter.example.com".
I want to end up with something like
http://example.com/{server}/{controller}/{action}
instread of
http://{server}.example.com/{controller}/{action}
If I understand your question correctly, you just wish to group different collections of content together above the controller/action level. If that's the case, have you considered using ASP.NET MVC areas?
Just right-click on your project, and choose Add -> Area.... Give it a name (what you're calling "server"), and then you can add content, your own controllers, actions, etc. Under this area. You will automatically be able to access it via /AreaName/Controller/Action/etc.
I went with the already impemented routing in ASP.NET MVC.
{server}/{controller}/{action}
When creating the links it takes the set value for {server} and places the value when generating URL's, so I only need to supply controller and action in the #Html.Action helper method ... this could not have been more easy.
I'm not sure why I did not think about this. One just gotta love routing.

disable an application or a module in Symfony

I have two applications. I want to disable one according a field stored in a database.
Is possible to disable an application (((if it's not posible) a module) by code maybe using a filter) ? I've found a piece of code that executes the project:disable but i think it's not nice enough.
The alternative I think is to check the value stored in the database inside a custom filter and then redirect to an action that inform 'The site is disabled'.
You can create a filter that checks if the current user may access the requested module/action:
if($this->getRequest()->getParameter('module')=='yourmodule' && !$this->getUser()->mayAccess('yourmodule'()){
//redirect to somewhere else
}
In user class:
function mayAccess($module){
$key = $module.'_enabled';
if(!$this->hasAttribute($key)){
$enabled = ... //Fetch permission from database
$this->setAttribute($key,$enabled);
}
return $this->getAttribute($key);
}
Something like that. Maybe you can use the modules security.yml file and override the function that checks the users credentials and permissions, like the hasCredential() method? That actually seems a more clean way to do it.
See: http://www.symfony-project.org/api/1_4/sfBasicSecurityUser
You could dynamically load only the application you want in your index.php file.

Symfony 1.4 and global variables

I've got a very old php application (1999) that has been worked on during the last ten years. At this point the app starts to show it's age so i'm in te progress of migrating to a "new" framework, symfony 1.4. But since the app is very large, i cannot do this at once. So i'm planning to wrap the old app into the new symfony app, and convert functionality by functionality.
First step in this transition was making the old app appear in the new symfony app. So, i've created the "frontend" application, added a "legacy" module, made it the default homepage, and i've put everyhting i had in my index.php (all pages went through this index.php) in the indexSuccess.php file for the indexAction. I've added the code in the "view" because there are also functions in it and changing that setup would take me more time than i want to spend on the old app.
Unfortunately i've now got an issue with global variables. Let me give you an example (i would have never made this register function like this, but it is, so please look past that.
$session = new ps_session;
$demo = "this is a demo variable";
$session->register('demo');
In ps_session i have this method
public function register($var) {
global $$var;
$_SESSION [$var] = $$var;
}
So it should put the content of $demo in a session var named "demo". Clever right :) Anyway, var_dumping shows me the that $$var is "null" and $demo is filled if i var_dump before and after calling the function. Exact same code without symfony and it returns the correct content.
What am i missing? The global call is spread out in all area's of this massive app so i really don't want to switch to something else, so i'm hoping for a quick fix :)
Maybe relevant, the all code except the index.php content are in frontend/lib/legacy/ folder, the index is in frontend/modules/legacy/ (if there is some scope issue i'm missing)
I think that since your indexSuccess.php file is included inside a function (more precisely, here : lib/vendor/symfony/lib/view/sfPHPView.class.php:185 ), this can't work, because $demo is no longer in the global scope. I don't see any easy workaround for this...
I think you should create a legacy folder in /web , and use routing to redirect to it if the url corresponds to something not migrated yet.
I went with putting the entire old site under web/legacy and redirecting from the default index action to the legacy folder. Most of the url's were made by mod_rewrite so easily fixed. The other url's went through a function so fixing was ok, and only a few were hardcoded. To make it totally transparant, i only need to redo the homepage to start from, so i don't have a visible /legacy/ in my url. Thanks for the help!
I agree with greg0ire that this is an issue with the way sfPHPView includes indexSuccess.
Could you simply require index.php in the default/index action?

OutputCache and recording unique views?

Image i have a view that is cached with the OutputCache attribute but i still need to increment a counter that records that the page has been viewed, how could i do it?
I thought about creating my own Custom ActionFilterAttribute, and using Action Filter Order of Execution to record this .. but i'm not sure it will work.
eg.
[IncrementViewCountFilter(Order=1)]
[OutputCache(Duration=60,Order=2)]
public ActionResult Index(int questionId)
{ ... }
Firstly, my assumption here is that if the OutputCache is called, and the page is cached, then the controller code will not be ran.
Next problem i'm guessing is that the IncrementViewCountFilter wouldn't know about the questionId, so how would it know what to increment (because it is executed before the main Index code is executed).
Secondly, if the IncrementViewCountFilter did know the questionId .. and it's getting lots of hits, you wouldn't want it to write all the time to the DB.. but only when it gets to a certain number .. and then u 'flush' the output.
Anyone have any thoughts?
Well, you have a few options.
Donut caching
One server-side option is 'Donut caching'. Donut caching allows most of the page to be cached, and portions of the page to be not cached (the hole in the middle of the donut). Donut caching is described here, and I have used it with great success.
Image-based tracker
Another option is having an image on the page actually load a server-side action that records the hit. This would look like
<img src="/controller/action">
on the page, where the action serves up an empty image at the end.
Client-side tracking
The last option is client-side tracking -- where some script runs on the client side and uses AJAX to call something on the server to record the hit. Google uses something like this for their Analytics package. If you're on the same domain as your tracking mechanism ... like if your main page is:
http://www.domain.com/home/action
and the tracker is on
http://www.domain.com/tracking/action
then you should be fine.
This gets tricky when your tracker is on a different domain (you need to handle this using JSONP or some other mechanism that allows for relatively safe cross-site scripting).
The filter can get the questionId from the ActionExecutingContext.ActionParameters, which is passed to OnActionExecuting. As for caching the hit counts, well, use the cache. :)
You could also use an HttpModule which is a good option because it can be used for pages and other assets that do not use the MVC pipeline. I use a combination of Donut caching,(http://mvcdonutcaching.codeplex.com/), an MVC filter and an HttpModule to record all types of analytics for cached pages.
I don't know about the MVC side but if I was doing this in WebForms this sounds like it would be a candidate for output cache substitution aka donut caching.

Resources