Zend Framework 2 command line scripts - zend-framework2

How would run execute a php script via the command line in Zend Framework 2 that bypasses all of the MVC functionality, but so that the script will have access to resources created by a module, such as database connections or a Doctrine EntityManager?
For reference this is what my entry point index.php looks like
<?php
chdir(dirname(__DIR__));
require_once (getenv('ZF2_PATH') ?: 'vendor/ZendFramework/library') . '/Zend/Loader /AutoloaderFactory.php';
Zend\Loader\AutoloaderFactory::factory(array('Zend\Loader\StandardAutoloader' => array()));
$appConfig = include 'config/application.config.php';
$listenerOptions = new Zend\Module\Listener\ListenerOptions($appConfig['module_listener_options']);
$defaultListeners = new Zend\Module\Listener\DefaultListenerAggregate($listenerOptions);
$defaultListeners->getConfigListener()->addConfigGlobPath('config/autoload/*.config.php');
$moduleManager = new Zend\Module\Manager($appConfig['modules']);
$moduleManager->events()->attachAggregate($defaultListeners);
$moduleManager->loadModules();
// Create application, bootstrap, and run
$bootstrap = new Zend\Mvc\Bootstrap($defaultListeners->getConfigListener()->getMergedConfig());
$application = new Zend\Mvc\Application;
$bootstrap->bootstrap($application);
$application->run()->send();

There are several options for a module to configure resources, for example a database connection. For ZF2, the DoctrineModule and DoctrineORMModule are maintained by Doctrine themselves and the Entity Manager is only created when you want to use it. Instead of a ZF1 approach where database connections are created during bootstrap, these modules have a sort-of just-in-time: create the instance just before you need it.
So: you need to configure the connection and entity manager in a module which is done with a Dependency Injection container. That configuration is done by the module, so you should take care the module is configured properly. Then, in your script you pull the entity manager from the DIC and the EM is instantiated, just what you need.
How to configure modules? First, modules are loaded, then initiated. This is both done in the call $moduleManager->loadModules() because of several listeners listening to the load event, thus instantiating the modules and running the init() method for these modules. There is also a listener to get the modules configuration, so DI can be set up properly. At this time, modules are set up, but not always ready to run. The last step to be ready is bootstrapping which is done by the Zend\Mvc\Bootstrap, bootstrapping the Zend\Mvc\Application.
This means if you copy that index.php script, but only remove the last line ($application->run()->send()), the modules are loaded, the DI container is configured and the application bootstrapped. Now you can get the DI locator and grap the entity manager:
$em = $application->getLocator()->get('doctrine_em');
Be aware of the CLI feature of zf2, coming in some of the next beta releases. The RFC is ready at this moment and when ready for experiments, it will be merged in zf2 master. This makes construction of CLI applications much easier. You have one entry point (eg app.php) and the "real work" is just like http MVC applications done by controllers. Once you have this app.php, it will be extremely easy to add more CLI features because it's as simple as adding some more controllers with actions and (possibly) a route to that point.

Related

Can I define new mustache template variables in swagger-codegen?

I have developed a rest-api client (in java) customised to the needs of my product. I wanted to generate tests using my rest api client using swagger-codegen modules based on yaml-file.
I have already extended DefaultCodegenConfig & even tried implementing the CodegenConfig interface to build my custom jar. I have customized the api.mustache and api_test.mustache files and passing them in the constructor and processOpts() method of my CustomCodeGen that extends DefaultCodegenConfig.
However, I want to use the custom/new mustache template variables that I have added in my customised api.mustache.
For e.g. if refer to standard api.mustache, the template variables it typically uses are
- {{classname}}
- {{#operation}}
- {{#contents}}
- {{#parameters}}
etc.
Now, I want to introduce a new template variable, let's say {{custom_param}}. Now I am not clear how do I integrate this new template variable with the implementation.
Looks like from this Mustache-Template-Variables published here, swagger-codegen does not allow adding new template-variables and perhaps we are restricted to only the variables mentioned on this page.
So, is there some way to make the new template variables work ?
Some time ago I added the uniqueItems parameter for bean validation as it was not getting processed by the engine even though it was a part of the implemented JSR.
So I believe codebase needs to be updated to use your own variable which is only possible if you fork the code.
In case it helps, these two were the PRs:
For query parameters: https://github.com/swagger-api/swagger-codegen/pull/10154.
For body parameters: https://github.com/swagger-api/swagger-codegen/pull/10490.

ColdBox module interface support?

Is there a way to create an interface for a module that any host application can be expected to implement?
We've got a couple apps that have a lot of code that is common that we'd like to refactor into modules, but sometimes the module may need to call runEvent or setNextEvent for a handler method that lives in the host application due to unique behavior and implementation.
Can I specify in the module a contract like "host application must implement the following handlers: 'admin.foo', 'admin.bar', ..."?
I am guessing there's a module load intercept I could do this in manually, but I'm wondering if there's a convention so I can just drop the list in somewhere rather than copy-pasting boilerplate code into every module.
You can specify dependencies within your ModuleConfig.cfc : this.dependencies = [ "myOtherModule" ]. Those dependencies will load before the module. At this time, there is no way to "interface" a module to conform to a collection of handlers.
Typically, though, passing through to other modules this is easily handled by custom routing within the module configuration, rather than by a new implementation:
addRoute(
pattern="/this-module/foo",
moduleRouting="that-module"
)
or
addRoute(
pattern="/this-module/foo",
module="that-module",
handler="oldFoo"
action="bar"
)
More on routing

Different Views for same domain Object in Grails backend and frontend

I've got two grails projects (admin backend and frontend) using the same domain classes from a local plugin.
I need to have different views in the frontend and the backend. E.g. there's a domain class Event. In each of the projects I use GenerateViews. Then I modify the generated gsps. As an example take the list.gsp. In frontend I remove the actions to create a new event from the view and the Controller, in the backend I keep them. That's because in the frontend the users should be only able to see the list of events, while in the backend the admin creates and modifies what is displayed in the frontend. This is the structure I get:
project domain
domain/grails-app/domain/myapp/Event.groovy
project frontend (grails.plugin.location.'domain' = "../domain")
frontend/grails-app/controllers/myapp/frontend/EventController.groovy
frontend/grails-app/views/event/list.gsp (no links to edit / create action)
project backend (grails.plugin.location.'domain' = "../domain")
backend/grails-app/controllers/myapp/backend/EventController.groovy
backend/grails-app/views/event/list.gsp (links to edit/create...)
But when I run my frontend application using run-app, and go to list, the controller is called:
def listEvents(Integer max) {
params.max = Math.min(max ?: 10, 100)
[eventInstanceList: Event.list(params), eventInstanceTotal: Event.count()]
}
and as a result backend/grails-app/views/event/list.gsp is rendered instead of frontend/grails-app/views/event/list.gsp.
The confusion already begins when I'm generating the views. So when I generate views for domain/grails-app/domain/myapp/Event.groovy inside the backend project everything is fine. The views get created inside my backend projectand work as intended.
Then I move ober to the frontend project and generate views for domain/grails-app/domain/myapp/Event.groovy. This time grails will tell me that there already are views, and asks if I want to replace them. If I say yes, it doesn't replace anything, but create the views in my frontend project. Really weird.
I found that there is an older bug report related to this, and I created a new one (http://jira.grails.org/browse/GRAILS-9920).
In the meantime, what should I do to work around this? I could rename my controllers' methods and the views, but I hope that there's a better way. It seems odd, that a view by the same name may override a view in a separate project. Or does something like that only happen when using run-app?
I'm new to Grails, so maybe I missed something obvious, but this really scares me, since it looks like I might accidentally expose actions in one project by modifying the other.

Similar function like getScriptPath from ZF1 in ZF2

I'm currently mapping my ZF1 applications to ZF2 and was wondering if there is a similar function like $this->view->getScriptPath() from ZF1 in ZF2? I spend already my half day, but didn't find a good solution. It would also be fine to get at least the basePath of the Module or the template folder of the Module.
Based on the follow-up questions, what you are really looking for is the path to a given template file. This is actually relatively easy, assuming you're using the default PhpRenderer: you grab the resolver, and resolve the path.
If you're inside a view script already, the following should work:
$path = $this->resolver($templateName);
If you're elsewhere, you need access to either the PhpRenderer, or the ViewResolver. If you have access to the service manager, pull the ViewResolver service, and call resolve() on it:
$resolver = $services->get('ViewResolver');
$path = $resolver->resolve($templateName);
This is superior to knowing where the module lives, as the developer may have chosen to override the template within the application; the resolver will know where even the new location is.

Scaffolding Web Services in Grails

I need to implement a web app, but instead of using relational database I need to use different SOAP Web Services as a back-end. An important part of application only calls web services and displays the result. Since Web Services are clearly defined in form of Operation: In parameters and Return Type it seems to me that basic GUI could be easily constructed just like in the case of scaffolding based on Domain Entities.
For example in case of SearchProducts web service operation I need to enter search parameters as input, so the search page can be constructed. Operation will return a list of products, so I need a page that will display this list in some kind of table.
Is there already some library in grails that let you achieve this. If not, how would you go about creating one?
Probably the easiest approach is to use wsimport on the WSDL files to generate the client-side stubs. Then you can call methods in the stubs from Groovy just as you would have called them from Java.
For example, consider the WSDL file for Microsoft's TerraServer, located at http://terraservice.net/TerraService.asmx?wsdl . Then you run something like
wsimport -d src -keep http://terraservice.net/TerraService.asmx?WSDL
which puts all the compiled stubs in the src directory. Then you can write Groovy code like
import com.terraserver_usa.terraserver.*;
TerraServiceSoap sei = new TerraService().getTerraServiceSoap()
Place home = new Place(city:'Boston',state:'MA',country:'US')
def pt = sei.convertPlaceToLonLatPt(home)
println "$pt.lat, $pt.lon"
assert Math.abs(pt.lat - 42.360000) < 0.001
assert Math.abs(pt.lon - -71.05000) < 0.001
If you want to access a lot of web services, generate the stubs for all of them. Or you can use dynamic proxies instead.
The bottom line, though, is to let Java do what it already does well, and use Groovy where it makes your life easier.
You should be able to use XFire or CXF Plugins. For automatic scaffolding, modify your Controller.groovy template in scaffolding templates so it auto-generates methods you need.

Resources