I'm pretty new to Laravel, I've spent some time reading about it and doing some tutorials. Lately, I've been following this tutorial about creating an authentication bundle:
http://net.tutsplus.com/tutorials/php/build-your-first-admin-bundle-for-laravel/
Basically, it's creating a simple custom auth driver extending the default auth one. Everything works quite nicely.. inside the bundle. My problem is more about how to use/access this admin/login bundle in my main application. I feel a bit ashamed asking this, I guess it has something to do with loading/starting the admin bundle in my application controller(s), but i can't get it to work.
Thank you
You have a couple of options, you can either start the bundle manually from within your application controllers each time by calling:
Bundle::start("<Your Bundle Name>");
Or when you register the bundle with Laravel (when you add it to /application/bundles.php) you can also choose to autoload it:
return array(
// ... other bundles
"<Your Bundle Name>" => array("auto" => true),
);
From looking at the tutorial this might look something like:
'admin' => array('handles' => 'admin', 'auto' => true)
Once you have either started the bundle manually, or autoloaded it, you can then call the bundle classes directly (make sure you use the proper namespace when calling the class).
You can also check out Laravel's documentation.
Related
I'm on the way of creating a Laravel package for our internal use, that's why it's not in packagist, and not in vendor/ directory. Instead it's in packages/ directory - a custom directory of ours - a similar approach we used for another package of our internal use.
Issue is, in the blades from the package we used action('MyPackageController#method') to produce links. After publishing the view files to the application the current path of the views are like resources/views/vendor/mypackage/one-directory/index.blade.php.
With a global access to the controller it simply is working:
action('\MyVendor\MyPackage\App\Controllers\MyPackageController#edit', ['id' => $item->id])
But issue is, when I'm trying to impose aliases for the controller[s], they are not working. In config/app.php aliases, I mentioned:
'XYZ' => MyVendor\MyPackage\App\Controllers\MyPackageController::class,
'ABC' => MyVendor\MyPackage\App\Controllers\MyPackageSecondController::class,
and in index.blade.php I tried using:
action('ABC#edit', ['id' => $item->id])
but it's not working. Because it's trying to find the controller in App\Http\Controllers\:
ErrorException (E_ERROR)
Action App\Http\Controllers\ABC#edit not defined. (View: D:\laragon\www\test-laravel\resources\views\vendor\mypackage\one-directory\index.blade.php)
Aren't package controllers be aliased?
PS. I tried clearing all types of caching.
As even after a long time, Martin Bean did not add any answer to the thread, here I'm posting one for future record:
As Martin Bean said in his comment:
You’d used a named route instead of action(): laravel.com/docs/master/routing#named-routes
What I found is: the action() function has its own caveat, it cannot take other namespaces other than App\Http\Controllers. So named route did it for me: route('my_name', ['id' => $item->id]);.
Thanks to Martin Bean for his clue.
First of all, you have to register your routes in the service provider of your package.
boot() {
require __DIR__ . '/Http/routes.php';
}
__DIR__ would point to the root of your package folder. This is assuming your routes are registered in your packages' Http directory. If this is done, make sure you use a unique name for your route and just call your action like so:
action="{{route-name}}"
That's all you have to do.
I am trying to use Symfony to replicate behavior in an existing Framework (zikula). This framework is extensible using modules which are basically extended symphony bundles. The old framework had urls like so
index.php?module=foo&type=bar&func=zip
which in symfony speak roughly translates to
index.php?bundle=foo&controller=bar&method=zip
The framework has an AbstractController which has a magic method like:
public function __call($method, $args)
{
$event = new \Zikula\Core\Event\GenericEvent($this, array('method' => $method, 'args' => $args));
$this->eventManager->dispatch('controller.method_not_found', $event);
if ($event->isPropagationStopped()) {
return $event->getData();
}
}
so, if you created a url with a method that didn't exist in the bundle, you could create a listener to capture it and send a response that looks like and behaves like it came from the specified bundle. We use this to call module services that are available to all modules and provided in a separate module but look like they are served by the 'host' module.
Now I am trying to replicates this using symfony and routing.
the first problem is generating a route that doesn't technically exist. Is this possible?
The second problem is capturing the RouteNotFoundException (which I know how to do, we already have listeners for other exceptions).
The last problem is making it appear that the bundle is serving up the response when it is actually being served by an event listener (or something else). This last part is important because other content in the response needs to come from the module/bundle.
I have tried changing the current listener to a controller, and also tried adding a method to our extension of symfony's AbstractController, but haven't yet achieved what I am hoping to achieve. I'm hoping for some suggestions on new ideas or methods to try.
I gave up trying to replicate the exact behavior as it seems impossible (it is also pretty difficult to describe). So I have resorted to a normal controller with standard route, but I found a way to make it appear to belong to the original 'host' module. Thanks to Gerry, ggioffreda and DerStoffel for offering ideas.
I have some basic ZF2 knowledge for creating normal projects. Now I want to create a module which is extendable by user community by creating plugins for its features.
I have created basic architecture like
ModuleName
src
Service
MyService.php
Factory
Fun1Factory.php
Fun2Factory.php
Plugins
Fun1Plugins
PluginA.php
PluginB.php
Fun2Plugins
PluginC.php
PluginD.php
I have created two factory classes ( not from zf2 factoryinterface) for handling each type of functionality like Fun1Factory.php & Fun2Factory.php. They both are registered in module.config.php through invokables.
'invokables' => array (
'Fun1Factory' => 'ModuleName\Factory\Fun1Factory',
'Fun2Factory' => 'ModuleName\Factory\Fun2Factory',
)
Now MyService actually calling them with arguments for specific plugins. Like below.
$fun1Factory = $this->getServiceLocator()->get('Fun1Factory');
$fun1Factory->setSettings($settings['fun1']);
$this->fun1Plugin = $fun1Factory->getPlugin();
$this->fun1Plugin->init();
$fun2Factory = $this->getServiceLocator()->get('Fun2Factory');
$fun2Factory->setSettings($settings['fun2']);
$this->fun2Plugin = $fun2Factory->getPlugin();
$this->fun2Plugin->init();
So code can be called like that
$service = $this->getServiceLocator()->get('ModuleName\Service\MyService');
$service->init(array('fun1' => 'pluginA', 'fun2' => 'pluginD'));
I earlier built similar using basic MVC + Factory Pattern. But I don't know how it should be build into ZF2. ZF2 give factory interface, but that look like a very similar to autoload some service/controllers. If their are any guide how to create a such module ?
UPDATE : I can do factory code also in MyService class. But I am thinking of "ZF2 WAY" to doing this.
MORE DETAILS : I have update question wtih more details. The closest I found at https://samsonasik.wordpress.com/2014/01/29/zend-framework-2-getting-closer-with-pluginmanager/ . But I still need to dynamically register plugin to factory instead of statically in there like below.
protected $invokableClasses = array(
//represent invokables key
'xls' => 'Tutorial\Plugin\Xls',
'pdf' => 'Tutorial\Plugin\Pdf'
);
If you do not want plugin creators having to modify the service_manager at the module.config.php then you have two options:
An option is creating a Factory for MyService that will look for its dependencies in those plugin folders.
Other option would be creating an invoke method for MyService passing the plugin as an argument and then you create the plugin instance.
But the way zf2 works is using module.config.php to register instances in the service_manager. So if the plugin creators can use the service_manager will be better.
[UPDATE]
Zend FactoryInterface is used for creating instances which have dependencies, so those dependencies are created or extracted from the ServiceManager and then they are injected via constructor to the instance the factory has been created for.
In your case your plugin developers would have to create factories for their plugins and register those factories in the service_manager. If they didn't then you need a way to know if a plugin has dependencies.
Hope this helps
Ismael Trascastro
In L3 i managed to make a module system where i was able to install/uninstall modules from an admin area.
if(!Bundle::exists($name))
{
// Load the bundle
// If a routes file exists then we'll assume it handles routes of it's own name.
// Remember, if you need it to handle a custom route you should manually add
// the bundle in application/bundles.php.
Bundle::register($name, array(
'handles' => File::exists($path.DS.'routes.php') ? $name : null,
'location' => 'path: '.$path,
'auto' => true)
);
// autobundle is already in the loop that's starting bundles so we
// can't let the normal mechanism start it. We'll start it here.
Bundle::start($name);
}
How i can do it in L4? L4 it looks very different for me, i started using L3 2 months ago (first framework)
Or if you still want modules that are more app specific you can check out my tutorial at: http://creolab.hr/2013/05/modules-in-laravel-4/
I'll expand on that article soon to explain how to build a simple interface to activate/deactivate these modules.
Bundles are now Packages, which are actually libraries of reusable PHP code stored on various locations and indexed by Packagist (installable with Composer).
In order to do Laravel based package development you'll need to checkout this documentation: http://laravel.com/docs/packages which should help you out.
Starting from the skeleton application using beta3 how would you resolve the view path for a new module called Foo?
I have added below to the di config and now both modules action's render Foo's views.
'Zend\View\Resolver\TemplatePathStack' => array(
'parameters' => array(
'paths' => array(
'foo' => __DIR__ . '/../view',
),
),
),
I would expect Application\Controller\IndexController::indexAction() to render the views in Application and for Foo\Controller\IndexController::indexAction() to render Foo's views.
Note that questions like this help shape the direction of the stable framework. :)
One idea I've been toying with is to use the module as part of the view script resolution. Right now, the default used is "/"; my proposal is to use "//", as this would help prevent naming conflicts between modules; it also makes it much simpler to understand exactly what view script you are overriding if you use template maps.
You can use this approach today, but it will require manually setting the template on the view models you return from your controllers.
This doesn't currently work in ZF2 as there is no concept of taking the namespace into account when resolving view scripts. Discussions are currently ongoing on how best to tackle this.
For the time being, you have to name each controller differently. In general, we are recommending that you name the "primary" controller within a module after the module name. That is, the primary controller in the Foo module would be FooController.
You actually can do this; and it is not too bad....
Rob Allen himself had a blog post that basically makes this work... Notice you have to basically handle it as a module based loader that separates much of the work out so that we don't have controllers utilizing it: http://pastie.org/3824571