Is it ok to use action helpers not only for controllers? - zend-framework

I'm looking for best way of using session within zf application.
At first I did something like this - in init method of controller superclass I initialized session:
class Vovkin_Controller_Action extends Zend_Controller_Action
{
protected $_session;
public function init()
{
// here I define namespace
// ...
$this->_session = new Zend_Session_Namespace($nameSpace);
parent::init();
}
...
}
after that session in controller was used in this way:
public function someAction()
{
$this->_session->user = $user;
}
but I found this approach not very handy for other parts of system, like plugins, services, etc, because there I had to init session in other way, but I want keep it in one place if it's possible. So I decided to change it to this approach https://stackoverflow.com/a/2506447.
Now I have a few action helpers to provide access for sessions with different namespaces, it works like this:
public function someAction()
{
$this->_helper->session()->user = $user;
}
and so far it looks useful, because I can get access to session namespaces in other parts of system, for example in services, in this way:
class Vovkin_Model_Service_UserLoginService
{
public function login()
{
$session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct();
...
}
....
}
but how much it's correct to use it in this way, from point of architecture and used resources?
Thanks.

The answer you have refereed to is from Rob Allen, one of the main contributors of Zend Framework, so it's right to some extent. You can go with the action helpers on controllers without any problems.
But outside it, it's completely wrong. Services doesn't has nothing with action helpers and the front controller. You can't put a dependency on it (services to action helpers).
So, as the application bootstrap works as a container for initializing the application, it's reasonable to get the necessary values from there. The first thing I would suggest you is to use Zend_Registry. But as far as I cal tell you, it would be the same initializing the session object again, since it will not be wiped, it's just an object referencing the native $_SESSION superglobals. So, simply call
new Zend_Session_Namespace($nameSpace).
But again, this is wrong. You should not let your services know how sessions are handled (thus creating the objects inside it):
$session = Zend_Controller_Action_HelperBroker::getStaticHelper('session')->direct()
or even
$session = Zend_Registry('userSession')
or
$session = new Zend_Session_Namespace('userSession')
With that you are also not using the bootstrap container at all. Instead you should provide a common interface to deal with sessions (it could be $_SESSION or even a database) and inject it into the service as a parameter (e.g. __construct($session)). But that's a whole new subject (Dependency Injection).
So, you have two options considering the current state of the ZendFramework 1.11 (that's already old and full of bad practices):
1) You'll use services through controllers:
So you will get the session through the action helper and then pass it as a parameter to your service.
new Vovkin_Model_Service_UserLoginService($session)
2) You will use services independently of controllers and will get the dependencies through the bootstrap container:
Well, the worst thing is that to get the bootstrap you need to have a frontController dependency.
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
So, avoid it, and go with the first option, injecting the dependency instead. Although, if you really want it in that way, access it directly:
$bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap');
$bootstrap->get('userSession')
Sadly, in the end, it's everything wrong. But it's the best you can do with ZF 1. You should look forward to ZF 2 and Symfony 2 to better understand these concepts.
Here it's a good explanation: http://symfony.com/doc/current/book/service_container.html
(I know that you're using ZF, but it doesn't matter, the concept is the key)

Related

Modifying Autofac Scope to Support XUnit Testing

I use Autofac extensively. Recently I've gotten interested in tweaking the lifetime scopes when registering items for XUnit testing. Basically I want to register a number of standard components I use as "instance per test" rather than what I normally do for runtime (I've found a useful library on github that defines an instance-per-test lifetime).
One way to do this is to define two separate container builds, one for runtime and one for xunit testing. That would work but it gets increasingly expensive to maintain.
What I'd like to do (I think) is modify the registration pipeline dynamically depending upon the context -- runtime or xunit test -- in which it is being built. In pseudocode:
builder.RegisterType<SomeType>().AsImplementedInterfaces().SingleInstance();
...
void TweakPipeline(...)
{
if( Testing )
{
TypeBeingRegistered.InstancePerTest();
}
else
{
TypeBeingRegistered.SingleInstance();
}
}
Is this something Autofac middleware can do? If not is there another capability in the Autofac API which could address it? As always, links to examples would be appreciated.
This is an interesting question. I like that you started thinking about some of the new features in Autofac, very few do. So, kudos for the good question.
If you think about the middleware, yes, you can probably use it to muck with lifetime scope, but we didn't really make "change the lifetime scope on the fly" something easy to do and... I'll be honest, I'm not sure how you'd do it.
However, I think there are a couple of different options you have to make life easier. In the order in which I'd do them if it was me...
Option 1: Container Per Test
This is actually what I do for my tests. I don't share a container across multiple tests, I actually make building the container part of the test setup. For Xunit, that means I put it in the constructor of the test class.
Why? A couple reasons:
State is a problem. I don't want test ordering or state on singletons in the container to make my tests fragile.
I want to test what I deploy. I don't want something to test out OK only to find that it worked because of something I set up in the container special for testing. Obvious exceptions for mocks and things to make the tests actually unit tests.
If the problem is that the container takes too long to set up and is slowing the tests down, I'd probably troubleshoot that. I usually find the cause of this to be either that I'm assembly scanning and registering way, way too much (oops, forgot the Where statement to filter things down) or I've started trying to "multi-purpose" the container to start orchestrating my app startup logic by registering code to auto-execute on container build (which is easy to do... but don't forget the container isn't your app startup logic, so maybe separate that out).
Container per test really is the easiest, most isolated way to go and requires no special effort.
Option 2: Modules
Modules are a nice way to encapsulate sets of registrations and can be a good way to take parameters like this. In this case, I might do something like this for the module:
public class MyModule : Module
{
public bool Testing { get; set; }
protected override void Load(ContainerBuilder builder)
{
var toUpdate = new List<IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle>>();
toUpdate.Add(builder.RegisterType<SomeType>());
toUpdate.Add(builder.RegisterType<OtherType>());
foreach(var reg in toUpdate)
{
if(this.Testing)
{
reg.InstancePerTest();
}
else
{
reg.SingleInstance();
}
}
}
}
Then you could register it:
var module = new MyModule { Testing = true };
builder.RegisterModule(module);
That makes the list of registrations easier to tweak (foreach loop) and also keeps the "things that need changing based on testing" isolated to a module.
Granted, it could get a little complex in there if you have lambdas and all sorts of other registrations in there, but that's the gist.
Option 3: Builder Properties
The ContainerBuilder has a set of properties you can use while building stuff to help avoid having to deal with environment variables but also cart around arbitrary info you can use while setting up the container. You could write an extension method like this:
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle>
EnableTesting<TLimit, TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registration,
ContainerBuilder builder)
{
if(builder.Properties.TryGetValue("testing", out var testing) && Convert.ToBoolean(testing))
{
registration.InstancePerTest();
}
return registration;
}
Then when you register things that need to be tweaked, you could do it like this:
var builder = new ContainerBuilder();
// Set this in your tests, not in production
// builder.Properties["testing"] = true;
builder.RegisterType<Handler>()
.SingleInstance()
.EnableTesting(builder);
var container = builder.Build();
You might be able to clean that up a bit, but again, that's the general idea.
You might ask why use the builder as the mechanism to transport properties if you have to pass it in anyway.
Fluent syntax: Due to the way registrations work, they're all extension methods on the registration, not on the builder. The registration is a self-contained thing that doesn't have a reference to the builder (you can create a registration object entirely without a builder).
Internal callbacks: The internals on how registration works basically boil down to having a list of Action executed where the registrations have all the variables set up in a closure. It's not a function where we can pass stuff in during build; it's self-contained. (That might be interesting to change, now I think of it, but that's another discussion!)
You can isolate it: You could put this into a module or anywhere else and you won't be adding any new dependencies or logic. The thing carting around the variable will be the builder itself, which is always present.
Like I said, you could potentially make this better based on your own needs.
Recommendation: Container Per Test
I'll wrap up by just again recommending container per test. It's so simple, it requires no extra work, there are no surprises, and it "just works."

Is it possible to implement a module that is not a WPF module (a standard class library, no screens)?

I am developing a modular WPF application with Prism in .Net Core 5.0 (using MVVM, DryIoc) and I would like to have a module that is not a WPF module, i.e., a module with functionality that can be used by any other module. I don't want any project reference, because I want to keep the loosely coupled idea of the modules.
My first question is: is it conceptually correct? Or is it mandatory that a module has a screen? I guess it should be ok.
The second and more important (for me) is, what would be the best way to create the instance?
This is the project (I know I should review the names in this project):
HotfixSearcher is the main class, the one I need to get instantiated. In this class, for example, I subscribe to some events.
And this is the class that implements the IModule interface (the module class):
namespace SearchHotfix.Library
{
public class HotfixSearcherModule : IModule
{
public HotfixSearcherModule()
{
}
public void OnInitialized(IContainerProvider containerProvider)
{
//Create Searcher instance
var searcher = containerProvider.Resolve<IHotfixSearcher>();
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterSingleton<IHotfixSearcher, HotfixSearcher>();
}
}
}
That is the only way I found to get the class instantiated, but I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
For modules that have screens, the instances get created when navigating to them using the RequestNavigate method:
_regionManager.RequestNavigate(RegionNames.ContentRegion, "ContentView");
But since this is only a library with no screens, I can't find any other way to get this instantiated.
According to Prism documentation, subscribing to an event shoud be enough but I tried doing that from within my main class HotfixSearcher but it does not work (breakpoints on constructor or on the event handler of the event to which I subscribe are never hit).
When I do this way, instead, the instance is created, I hit the constructor breakpoint, and obviously the instance is subscribed to the event since it is done in the constructor.
To sum up, is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
Thanks in advance!
Or is it mandatory that a module has a screen?
No, of course not, modules have nothing to do with views or view models. They are just a set of registrations with the container.
what would be the best way to create the instance?
Let the container do the work. Normally, you have (at least) one assembly that only contains public interfaces (and the associated enums), but no modules. You reference that from the module and register the module's implementations of the relevant interfaces withing the module's Initialize method. Some other module (or the main app) can then have classes that get the interfaces as constructor parameters, and the container will resolve (i.e. create) the concrete types registered in the module, although they are internal or even private and completely unknown outside the module.
This is as loose a coupling as it gets if you don't want to sacrifice strong typing.
is there a way to get rid of that var searcher = containerProvider.Resolve<IHotfixSearcher>(); and a better way to achieve this?
You can skip the var searcher = part :-) But if the HotfixSearcher is never injected anywhere, it won't be created unless you do it yourself. OnInitialized is the perfect spot for this, because it runs after all modules had their chance to RegisterTypes so all dependencies should be registered.
If HotfixSearcher is not meant to be injected, you can also drop IHotfixSearcher and resolve HotfixSearcher directly:
public void OnInitialized(IContainerProvider containerProvider)
{
containerProvider.Resolve<HotfixSearcher>();
}
I am not a hundred per cent comfortable with creating an instance that is not used, I think it does not make much sense.
It is used, I suppose, although not through calling one of its methods. It's used by sending it an event. That's just fine. Think of it like Task.Run - it's fine for the task to exist in seeming isolation, too.

Autofac - dynamic Resolve based on registered provider

I'm having problems finding proper solution for my problem, namely:
Let's consider workflow:
Application starts
Main components are registered in Autofac
Application loads plugin assembly and registers modules within it
Container is being build
Plugin handling logic is run
Plugin can add its own controllers. To properly handle that I had to prepare interface which will provide me types of custom controllers:
interface ICustomControllerProvider
{
IEnumerable<Type> GetControllerTypes();
}
Based on the above my app knows how to integrate specified types as controllers.
All controllers are also defined as services, so Autofac deals with their creation, and so...
Problem:
I want to avoid specifying custom controller type twice
public PluginControllerProvider : ICustomControllerProvider
{
public IEnumerable<Type> GetControllerTypes()
{
// 1st type specification
// controller types are specified here, so they could be integrated with app
yield return typeof(ControllerX);
yield return typeof(ControllerY);
}
}
public class PluginModule : Module
{
protected override void Load(ContainerBuilder builder)
    {
builder.RegisterType<PluginControllerProvider>().As<ICustomControllerProvider>();
// 2nd type specification
// controllers have to be register in module as well
builder.RegisterType<ControllerX>();
builder.RegisterType<ControllerY>();
}
}
Is there any way how ControllerX and ControllerY could be managed by Autofac, where I specified them only in PluginControllerProvider?
I tried achieving that by providing custom registration source and resolving ICustomControllerProvider, however I cannot resolve ICustomControllerProvider based on arguments provided by IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<ServiceRegistration>> registrationAccessor) from IRegistrationSource
Autofac does not offer the ability to inject a list of types registered with Autofac. You'll have to get that yourself by working with the lifetime scope registry.
Before I get into how you might solve this, I should probably note:
Listing the types registered is not a normal thing from a DI perspective. It'd be like listing all the controllers in your MVC application - you don't normally need to do that, and if you did, you'd likely need to build a whole metadata structure on top of it like the ApiExplorer that was built to do that on top of ASP.NET Core. That structure wouldn't be supported or involved with the DI system because you're querying about the system, not injecting live instances into the system.
If you are relying on DI to resolve controllers, you probably don't need a whole separate controller provider. Once you know what type you need for the request, you'd just resolve it.
All that's to say, while I'll answer the question, the way the design here is posed may be something you'd want to look at. What you're doing, trying to involve DI with listing metadata about the app... seems somewhat backwards (you'd feed the DI container based on the list of types, not get the list of types from the DI container).
But let's just go with it. Given:
There are controllers registered with Autofac
The controllers have no common base class or interface
There's no attributes on the controllers you could query
What I'd do is register all the controllers with some metadata. You need something to be able to locate the controllers in the list of all the types in the container.
builder.RegisterType<ControllerX>().WithMetadata("controller", true);
builder.RegisterType<ControllerY>().WithMetadata("controller", true);
Now in the plugin controller, you need to inject an ILifetimeScope because you have to query the list of stuff registered. The ILifetimeScope that gets injected into the controller will be the same scope from which the plugin controller itself was resolved.
You can use the injected scope to query things in the component registry tagged with your metadata.
public class PluginControllerProvider : ICustomControllerProvider
{
private readonly Type[] _controllerTypes;
public PluginController(ILifetimeScope scope)
{
_controllerTypes = scope
.ComponentRegistry
.Registrations
.Where(r => r.Metadata.ContainsKey("controller"))
.Select(r => r.Activator.LimitType)
.ToArray();
}
public IEnumerable<Type> GetControllerTypes()
{
return _controllerTypes;
}
}
Now, disclaimers:
If you are registering more controllers in child lifetime scopes (e.g., during a BeginLifetimeScope() call), you will need a controller provider from that scope or it won't get all the controller types. The provider needs to come from the scope that has all the registrations.
If you're using registration sources (like the AnyConcreteTypeNotAlreadyRegisteredSource), this won't capture things that come from the registration sources. It'll only capture things that come from direct registrations of a type (or lambda) on a ContainerBuilder.
But it should work.

Initiating objects in Zend Framework?

How can I eliminate to write $object = new Application_Model_Database() in every controller?
For example for an article controller, I have to type $articles = new Application_Model_Articles() for every controller. Should I put it under viewer controller, action helpers, or any other way?
Your question almost sounds like an OOP best practices question as opposed to a Zend Framework specific question. Regardless of whether or not I'm using a framework, and regardless of what framework I choose, I base when and where I create new objects on testability how many times I have to write $object = new My_Random_Object();.
Speaking specifically to the Zend Framework: Objects I'm going to use everywhere, or almost everywhere, get created in Bootstrap.php. These objects generally include a database adapter, logger, view object, and any plugins I might use. To access these across the application, I'll create private properties in the appropriate controllers and assign the objects to those properties in the controller's init() method.
class ExampleController extends Zend_Controller_Action
{
public function init()
{
$bootstrap = $this->getInvokeArg('bootstrap');
$this->_db = $bootstrap->getResource('db');
$this->_log = $bootstrap->getResource('log');
// and so on, and so forth
}
}
Ideally, models, services, daos, etc, will all be relatively tightly grouped by controller and by action. In my experience, and this is speaking generally, if I have the same model or service class showing up across all of the controllers in my application, I have an organization problem. That being said, any model that shows up in only one action gets created in that action. If it's across actions in a controller, it gets created in the init() method and assigned to a property. If it shows up across multiple controllers, it gets created in my Bootstrap.php.
(Ideally, everything gets created in the Bootstrap.php, so you can swap out that bootstrap for testing purposes. Sadly, I don't always do that, and I most often use the principles I outlined above.)
Well do you really need it in every controllers? Because that's pretty much by design. You implement models when you need them. Its not that much code really.
Now if its to be used across actions from a controller you could always:
class MyController extends Zend_Controllers{
$protected $_articleModel;
...
and in your constructor or __init() function initialize it so you can use it in every action thru $this->_articleModel
If you REALLY want it everywhere in your application just initialize it in your bootstrap and store it in the registry.
public function __initModels(){
$articles = new Application_Model_Articles()
Zend_Registry::set('articles', $articles );
}
And access it in your controllers like so:
Zend_Registry::get('articles')->fetchAll();
But then your still writing a couple of characters.
Hope this help!
IF you want to use models in the controllers you must call it..anyway some shortcuts are here
1.You can initialize it in the init section of your controller like
public function init(){
$this->object = new Application_Model_Database();
}
So that the this->object is available in all the actions of that particular controller
2.Use Zend_registry as suggested in the above answer
Another possibility is to use a Dependency Injection container, such as the Symfony DI component. It takes care of instantiating your objects, and you get some additional benefits:
Separation of concerns. You have a component devoted to create your object tree.
Easier testability of the objects.
Last, but not least, the performance benefits given by lazy instantiation (objects are created only when you ask for them). Thus, if some object is not used by the particular controller serving your request, it's not instantiated).
It's a bit more laborious than the above solutions, but much more flexible if you need to maintain and extend your application in the future.
Hope that helps,
If you are using this object to just display data in your view and are using your controller to grab the data and assign it to your view, like so:
//someControllerAction
$object = new Application_Model_Articles();
$object->fetchAll();
//assign to view
$this->view->articles = $object;
You might be better off making a view helper similar to:
//Articles.php put in /application/views/helpers
class Zend_View_Helper_Articles extends Zend_View_Helper_Abstract {
public function Articles() {
$articles = new Application_Model_Articles();
$articles->fetchAll();
//return rowset object
return $articles;
Then in your view (phtml) you could do something like:
//someView.phmtl
<?php $articles = $this->Articles(); ?>
<h1><?php echo $this->escape($articles->title); ?></h1>
<p><?php echo $this->escape($articles->body); ?></p>
building a view helper allows you to bypass the controller completely if you just need to display data from the model. This is a very simple example and can be used with partials and partialLoops.
REF:ZF reference Custom View Helper
ZF partial view helper reference

Autofac Session Scope

I am investigating the use of Autofac in our web application having previously used Castle Windsor in the past.
The thing that I really like with Autofac is being able to express dynamic component construction through lamda expressions, as opposed to creating DependancyResolvers etc. in Windsor.
One scenario I have is that I want a particular component to be registered at ASP.NET session level scope. With Windsor I would create/source a new LifestyleManager, however with Autofac I came up with this:
//Register SessionContext at HTTP Session Level
builder.Register(c =>
{
HttpContext current = HttpContext.Current;
//HttpContext handes delivering the correct session
Pelagon.Violet.Core.Interfaces.SessionContext instance = current.Session["SessionContext"] as Pelagon.Violet.Core.Interfaces.SessionContext;
if (instance == null)
{
instance = c.Resolve<Pelagon.Violet.Core.Interfaces.SessionContext>();
current.Session["SessionContext"] = instance;
}
return instance;
})
.FactoryScoped();
Which at some point I might be able to turn into an extension method. I accept this implemtation will bomb if the HttpContext.Current.Session is null as it should only be used in a web app.
The question is:
What is the best practice for such a registration in Autofac. I have seen a lot of mention about the use of nested containers etc. but no concrete examples, and I am keen to understand what might be wrong with the above approach (only thing I can think of is the automatic disposal stuff).
Thanks.
This looks fine.
Marking the component 'ExternallyOwned()' will ensure that Autofac doesn't call Dispose() on it.
The only gotchas here are that your session-scoped component could resolve dependencies of its own via the current container, and thus hold references to things that may belong to the current request (for instance.) This should be easy to spot in testing though.