Slim3 telling me that callable route can't be found - slim-3

I'm new to slim. I ran into an error telling me the callable controller does not exist. However my other controller (HomeController) does work. I'm sure I am doing something stupid but I can't figure out what.
Error Message
Type: RuntimeException
Message: Callable JoeyD473\RPG_Tools\controllers\traveller\UniverseCreationControllercreateUniverse does not exist
File: C:\Users\Joey\Web\JRD_Traveller_Tools\vendor\slim\slim\Slim\CallableResolver.php
Line: 90
Project Structure
\public
index.php
.htaccess
\src
\app
\controllers
BaseController.php
HomeController.php
\traveller
UniverseCreationController.php
\model
\views
config.php
container.php
routes.php
composer.json
"autoload": {
"psr-4": {
"JoeyD473\\RPG_Tools\\models\\": "src/app/model",
"JoeyD473\\RPG_Tools\\controllers\\": "src/app/controllers"
}
},
container.php
$container = $app->getContainer();
$container['view'] = new \Slim\Views\PhpRenderer(APP.'views/');
$container['db'] = function($c){
$settings = $c->get('settings')['db'];
$db = new \Aura\Sql\ExtendedPdo($settings['vendor'].':host='.$settings['host'].';dbname='.$settings['db_name'],$settings['username'],$settings['password']);
return $db;
};
$container['HomeController'] = function($container){
return new \JoeyD473\RPG_Tools\controllers\HomeController;
};
$container['UniverseCreationController'] = function($container){
return new \JoeyD473\RPG_Tools\controllers\traveller\UniverseCreationController;
};
routes.php
$app->get('/',JoeyD473\RPG_Tools\controllers\HomeController::class.':home');
$app->get('/api',JoeyD473\RPG_Tools\controllers\HomeController::class.':sw_api');
$app->get('/temp',JoeyD473\RPG_Tools\controllers\HomeController::class.':temp');
$app->get('/universe/create_new_universe',JoeyD473\RPG_Tools\controllers\traveller\UniverseCreationController::class.'createUniverse');
UniverseCreationController.php
namespace JoeyD473\RPG_Tools\controllers\traveller;
use JoeyD473\RPG_Tools\controllers\BaseController;
use JoeyD473\RPG_Tools\models\traveller\universe\Universes;
class UniverseCreationController extends BaseController
{
public function createUniverse($request,$response)
{
return $this->container->view->render($response,'travellers/universe/create_universe.phtml');
}
public function generateUniverse($request,$response)
{
$universe = new Universes($this->db);
return 'generateSector';
}
}

You've missed a colon (:) in your last route
\traveller\UniverseCreationController::class.'createUniverse');
^^^
You could also use the array syntax for this.
[YourClass::class, 'yourMethod']

Related

Codeigniter autocheck db depending on session value

I'm trying to force my app to check every time it loads a model or controller depending on which is my session value.
This is actually running, but just when I get throw this model.
class News_model extends CI_Model {
public function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}
But I do not war to include that __construct code to all my models or controllers.
I've tried to add on my autoload.php
$autoload['model'] = array('General');
Where my General code is something like this.
class General extends CI_Model {
function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
}
How can I do it?
You can do it by creating a base model which will be extended by your models that require the database check.
I have simplified the checking and loading code. A simple ternary determines the string to use and stores it in the variable $dbname. That variable is used to load the database, i.e. $this->load->database($dbname);.
I don't believe you need the second argument to load::database() which means you don't need to set $this->db explicitly. If I'm wrong, use
$this->db = $this->load->database($dbname, TRUE);
Below is the "base" model. The prefix of the file name is determined in config.php with the setting $config['subclass_prefix'] = 'MY_'; Adjust your base model's file and class name to match the 'subclass_prefix' you use.
/application/core/MY_Model.php
<?php
class MY_Model extends CI_Model
{
public function __construct()
{
parent::__construct();
$dbname = $this->session->dbname == 'db1' ? 'db1' : 'db2';
$this->load->database($dbname);
}
}
Use the above to create other models like so...
class News_model extends MY_Model
{
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}

SONATA generate pdf with knpSnappy

I want to integrate a PDF export into my SONATA ADMIN application. For that, I installed the KnpSnappy Bundle and SonataExporterBundle.
I followed an old tutorial found on google, but in the end it does not work.
config.yml:
knp_snappy:
pdf:
enabled: true
binary: /usr/local/bin/wkhtmltopdf
options: []
image:
enabled: true
binary: /usr/local/bin/wkhtmltoimage
options: []
temporary_folder: %kernel.cache_dir%/snappy
services.yml:
sonata.admin.exporter:
class: AppBundle\Export\Exporter
calls:
- ["setKnpSnappyPdf", ["#knp_snappy.pdf"]]
- ["setTemplateEngine", ["#templating"] ]
in my ModelAdmin, I added it:
public function getExportFormats() {
return array_merge(parent::getExportFormats(), array('pdf'));
}
I created AppBundle/Export/Exporter.php:
namespace AppBundle\Export;
use Exporter\Source\SourceIteratorInterface;
use Symfony\Component\HttpFoundation\Response;
use Sonata\AdminBundle\Export\Exporter as BaseExporter;
class Exporter extends BaseExporter
{
protected $knpSnappyPdf;
protected $templateEngine;
public function getResponse($format, $filename, SourceIteratorInterface $source)
{
if ('pdf' != $format) {
return parent::getResponse($format, $filename, $source);
}
$html = $this->templateEngine->renderView('AppBundle:Export:pdf.html.twig', array(
'source' => $source
));
$content = $this->knpSnappyPdf->getOutputFromHtml($html);
return new Response($content, 200, array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => sprintf('attachment; filename=%s', $filename)
));
}
public function setKnpSnappyPdf($service)
{
$this->knpSnappyPdf = $service;
}
public function setTemplateEngine($service)
{
$this->templateEngine = $service;
}
}
error:
RuntimeException:
Invalid "pdf" format, supported formats are : "csv, json, xls, xml"
at vendor/sonata-project/exporter/src/Exporter.php:52
at Exporter\Exporter->getResponse('pdf', 'export_model_2018_04_20_15_44_05.pdf', object(DoctrineORMQuerySourceIterator))
(vendor/sonata-project/admin-bundle/src/Controller/CRUDController.php:952)
at Sonata\AdminBundle\Controller\CRUDController->exportAction(object(Request))
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:151)
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), 1)
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php:68)
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), 1, true)
(vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php:202)
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
(web/app_dev.php:31)
at require('/var/www/html/acianovintra/web/app_dev.php')
(vendor/symfony/symfony/src/Symfony/Bundle/WebServerBundle/Resources/router.php:42)
Can you tell me what I did wrong?
In a project I had to export some data in docx format.
To do that, I wrote a custom writer :
<?php
namespace App\MyBundle\Utils\Exporter\Writer;
use Exporter\Writer\TypedWriterInterface;
class DocxWriter implements TypedWriterInterface
{
/**
* {#inheritdoc}
*/
final public function getDefaultMimeType()
{
return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
}
/**
* {#inheritdoc}
*/
final public function getFormat()
{
return 'docx';
}
//...
}
Then I had to create a service for the writer and add a tag :
// service.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="app.exporter.writer.docx" class="App\MyBundle\Utils\Exporter\Writer\DocxWriter">
<argument>php://output</argument>
<tag name="sonata.exporter.writer"/>
</service>
</services>
</container>
In the ExporterCompilerPass of the exporter bundle, sonata get all the services tagged with sonata.exporter.writer and pass them to the addWriter of the Exporter class.
To integrate this new writer in sonata admin, you'll have to override the sonata.admin.exporter like you already did, except that you will call this new writer :
<?php
namespace App\MyBundle\Export;
use Exporter\Source\SourceIteratorInterface;
use Sonata\AdminBundle\Export\Exporter as BaseExporter;
use App\MyBundle\Utils\Exporter\Writer\DocxWriter;
use Symfony\Component\HttpFoundation\StreamedResponse;
class Exporter extends BaseExporter
{
public function getResponse($format, $filename, SourceIteratorInterface $source)
{
switch ($format) {
case 'docx':
$writer = new DocxWriter('php://output');
$contentType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
break;
default:
return parent::getResponse($format, $filename, $source);
}
$callback = function () use ($source, $writer) {
$handler = \Exporter\Handler::create($source, $writer);
$handler->export();
};
return new StreamedResponse($callback, 200, array(
'Content-Type' => $contentType,
'Content-Disposition' => sprintf('attachment; filename="%s"', $filename),
));
}
}
With this, you should be able to add your pdf format in your admin overriding the getExportFormats method.
Hpe this helps

List all controllers/actions in Cakephp 3

How do I list all the controllers/actions on my site? Configure::listObjects('model') doesnt seem to exist anymore. I am trying to write a function to generate/add to the ACO's in my ACL setup. Thanks.
So here is what I did. In my Resource Controller:
Include the reflection class/method libraries
use ReflectionClass;
use ReflectionMethod;
To get the controllers:
public function getControllers() {
$files = scandir('../src/Controller/');
$results = [];
$ignoreList = [
'.',
'..',
'Component',
'AppController.php',
];
foreach($files as $file){
if(!in_array($file, $ignoreList)) {
$controller = explode('.', $file)[0];
array_push($results, str_replace('Controller', '', $controller));
}
}
return $results;
}
And now for the actions:
public function getActions($controllerName) {
$className = 'App\\Controller\\'.$controllerName.'Controller';
$class = new ReflectionClass($className);
$actions = $class->getMethods(ReflectionMethod::IS_PUBLIC);
$results = [$controllerName => []];
$ignoreList = ['beforeFilter', 'afterFilter', 'initialize'];
foreach($actions as $action){
if($action->class == $className && !in_array($action->name, $ignoreList)){
array_push($results[$controllerName], $action->name);
}
}
return $results;
}
Finally, to tie them boths together:
public function getResources(){
$controllers = $this->getControllers();
$resources = [];
foreach($controllers as $controller){
$actions = $this->getActions($controller);
array_push($resources, $actions);
}
return $resources;
}
I hope that helps some people.
It doesn't look like anything similar to this is still available in Cake3, nor is it still needed because of the namespaces I think.
So in short you can try to do this:
Read all controllers from the app level controller folder
Read all plugin controller folders (Get the plugin folder via Plugin::path())
Iterate over the controllers you've collected in the previous steps (You'll need to use App::uses())
Use reflections to get the public methods from each controller
I am using CakePHP 3.x and had problems with the function "getActions"
The correct syntax for "ReflectionClass" and "ReflectionMethod" is:
public function getActions($controllerName) {
$className = 'App\\Controller\\'.$controllerName.'Controller';
$class = new \ReflectionClass($className);
$actions = $class->getMethods(\ReflectionMethod::IS_PUBLIC);
$results = [$controllerName => []];
$ignoreList = ['beforeFilter', 'afterFilter', 'initialize'];
foreach($actions as $action){
if($action->class == $className && !in_array($action->name, $ignoreList)){
array_push($results[$controllerName], $action->name);
}
}
return $results;
}
Warning for "\" before ReflectionClass and ReflectionMethod.

CakePHP Custom Helper not working

MY first time creating a custom helper. I'm getting an error in my Controller Code that I"m calling a a method on a non existed object (helper). Yet i believe my helper "BM" is being loaded successfully because i'm not getting any errors on loading helpers.
Error: Call to a member function mcpGetActiveMerchantID() on a non-object
File: C:\wamp\www\bm\app\Controller\MCPController.php
Line: 412
I have placed BMHelper.php into my View\Helper\ directory.
<?php
class BMHelper extends AppHelper{
public function mcpGetActiveMerchant(){
return $this->Session->read('Auth.ActiveMerchant');
}
public function mcpGetActiveMerchantID() {
$activemerchant = $this->Session->read('Auth.ActiveMerchant');
foreach($activemerchant as $key => $value) {
$merchant_id = $key;
}
return $merchant_id;
}
}
?>
Then in my Controller I have this:
<?php
class MCPController extends AppController {
public $helpers = array('Html', 'Form', 'Session','BM','Js' => array('Jquery'));
public function walkinadd() {
$test = $this->BM->mcpGetActiveMerchantID(); //Line 412
}
}
?>
HEre is the error again (same as the error I pasted at the top)
Error: Call to a member function mcpGetActiveMerchantID() on a non-object
File: C:\wamp\www\bm\app\Controller\MCPController.php
Line: 412
Anyone know what is wrong?
Helpers are to be used in Views not Controllers, though you could do:
public function walkinadd() {
$view = new View($this);
$bm = $view->loadHelper('BM');
$test = $bm->mcpGetActiveMerchantID();
}

Symfony 2 how to call the renderView method in FormHandler?

I try to do a contact form with Symfony 2.4.1. My form is a simple contact one without an entity.
The following error happens in my handler :
FatalErrorException: Error: Call to undefined method Symfony\Component\Form\Form::render() in C:\Program Files\wamp\www\sf2\src\Open\OpcBundle\Form\Handler\ContactHandler.php line 75
And the form handler code :
<?php
// src/Open/OpcBundle/Form/Handler/Handler.php
namespace Open\OpcBundle\Form\Handler;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
class ContactHandler {
protected $request;
protected $form;
protected $mailer;
public function __construct(Form $form, Request $request, $mailer) {
$this->form = $form;
$this->request = $request;
$this->mailer = $mailer;
}
public function process() {
if ('POST' == $this->request->getMethod()) {
$this->form->handleRequest($this->request);
$data = $this->form->getData();
$this->onSuccess($data);
return true;
}
return false;
}
protected function onSuccess($data) {
$message = \Swift_Message::newInstance()
->setContentType('text/html')
->setSubject($data['sujet'])
->setFrom($data['courriel'])
->setTo('me#gmail.com')
->setBody($this->render('OpcOpenBundle:Opc:Mails/contact.html.twig',
array('ip' => $request->getClientIp(),
'nom' => $data['nom'],
'msg' => $data['msg'])
)
);
$this->get('mailer')->send($message);
$request->getSession()->getFlash()->add('success', 'Your email has been sent! Thanks!');
return $this->redirect($this->generateUrl('contact'));
}
}
So the problem is that I don't have an object/instance for the renderView() method to call the template mail with setBody in the function onSuccess()
Which object/instance should I use for ?
Thanks
PS: sorry for my english, i'm French!
It's Symfony\Bundle\TwigBundle\TwigEngine class. service name is 'templating'.
BTW, why is you handler is not service?

Resources