I canĀ“t get CakePdf to work, If I would get an error, I could work with it. But nothing really shows up.
CakePhp: 3.1.6
CakePdf: current Version
I added an InvoicesController with this code
<?php
namespace App\Controller;
class InvoicesController extends AppController
{
// In your Invoices controller you could set additional configs, or override the global ones:
public function view($id)
{
$this->pdfConfig = array(
'orientation' => 'landscape',
'download' => true,
'filename' => 'invoucne.pdf'
);
}
}
?>
Also added this to my bootstrap.php
use Cake\Event\EventManager;
EventManager::instance()
->on(
'Controller.initialize',
function (Cake\Event\Event $event) {
$controller = $event->subject();
if ($controller->components()->has('RequestHandler')) {
$controller->RequestHandler->config('viewClassMap.pdf', 'CakePdf.Pdf');
}
}
);
Plugin::load('CakePdf', ['bootstrap' => true, 'routes' => true]);
Configure::write('CakePdf', [
'engine' => 'CakePdf.dompdf',
'margin' => [
'bottom' => 15,
'left' => 50,
'right' => 30,
'top' => 45
],
'orientation' => 'landscape',
'download' => true
]);
This to my routes.php
Router::extensions(['pdf']);
Also I go my default.ctp in the src/Template/Layout/pdf
<h2>Rendered with default layout</h2>
<?php echo $this->fetch('content'); ?>
And my views in my Template/Invoices/pdf
<html>
<body>
<h1>test</h1>
</body>
</html>
My url looks like:
http://localhost/caketest/invoices/view/1.pdf
I installed it with composer and my plugins lie in vendor/dompdf and vendor/friendsofcake/cakepdf
I had this problem before the solution is to put
Router::extensions(['pdf']);
before
Router::scope('/', function ($routes) { //some code}
not after it
Related
I am creating a REST Api using cakephp-jwt-auth But the AppController I create in subfolder is not called.
My App controller code inside Ca/Api code
<?php
namespace App\Controller\Ca\Api;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'storage' => 'Memory',
'authenticate' => [
'Form' => [
'fields' => ['username' => 'email'],
],
'ADmad/JwtAuth.Jwt' => [
'parameter' => 'token',
'userModel' => 'Users',
'fields' => [
'username' => 'id'
],
'queryDatasource' => true
]
],
'unauthorizedRedirect' => false,
'checkAuthIn' => 'Controller.initialize'
]);
$this->loadComponent('BryanCrowe/ApiPagination.ApiPagination', [
'key' => 'paging',
'aliases' => [
'page' => 'currentPage',
'current' => 'resultCount'
],
'visible' => [
'currentPage',
'resultCount',
'prevPage',
'nextPage',
'pageCount',
'page',
]
]);
}
public function beforeFilter(Event $event) {
parent::beforeFilter($event);
}
}
And my route file:
Router::prefix('ca/api', function ($routes) {
$routes->setExtensions(['json']);
$routes->connect('/login', ['controller' => 'Login', 'action' => 'login', "prefix" => "ca/api"]);
$routes->connect('/dashboard', ['controller' => 'Dashboard', 'action' => 'home', 'prefix' => "ca/api"]);
$routes->fallbacks('InflectedRoute');
});
My app controller class is not called and I don't understand where I am doing wrong.
you can create controller like this
<?php
namespace App\Controller\Api;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Auth', [
'storage' => 'Memory',
'authenticate' => [
'Form' => [
'scope' => ['Users.group_id' => 1]
],
'ADmad/JwtAuth.Jwt' => [
'parameter' => 'token',
'userModel' => 'Users',
'fields' => [
'username' => 'id'
],
'queryDatasource' => true
]
],
'unauthorizedRedirect' => false,
'checkAuthIn' => 'Controller.initialize'
]);
}
}
And other controller like this
<?php
namespace App\Controller\Ca;
use Cake\Event\Event;
use Cake\Http\Exception\UnauthorizedException;
use Cake\Utility\Security;
use Firebase\JWT\JWT;
use Cake\Http\ServerRequest;
use Cake\I18n\Time;
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;
use Cake\Http\Exception\NotFoundException;
class DashboardController extends AppController
{
public function initialize()
{
parent::initialize();
}
public function home()
{
pr("hiiih");
}
}
Remember do not use
**
use App\Controller\AppController;
**
When you are creating AppController in sub folder
for more information read this tutorial :- https://trinitytuts.com/secure-cakephp-web-services-using-jwt/
The AppController isn't called magically someplace internally in CakePHP. The Routes you define call a specific controller, which should simply extend your AppController.
Following convention you'd typically only ever use a single AppController for your entire application, in /src/Controller/AppController. It looks based on the authentication methods listed in your example, this is the approach your taking, but you don't need to move it into a subfolder to make prefix routing work.
Based on your routes:
Router::prefix('ca/api', function ($routes) {
... This will look for a classes that match connections inside /src/Controller/Ca/Api, and for matches like:
// Note, the "prefix" item you listed on this line is not required I'd remove it:
$routes->connect('/login', ['controller' => 'Login', 'action' => 'login', "prefix" => "ca/api"]);
.. This will look for a class called LoginController, at /src/Controller/Ca/Api/. This class should simply reference your existing default AppController in it's default location:
<?php
namespace App\Controller\Ca\Api;
use App\Controller\AppController; // The namespace declaration is how your subclass locates it's parent class
class LoginController extends AppController
{
If you have some particular need to have multiple AppControllers (which I'd not recommend) then just change what version you're referencing with use namespace.
See for more information:
PHP Namespaces
Prefix Routing
The AppController
I'm writing tests for a controller in a plugin (Assets plugin).
This is the controller:
namespace Assets\Controller;
use Cake\Controller\Controller;
class AssetsController extends Controller
{
public function asset($filename, $type)
{
$this->response->type($type);
$this->response->file(ASSETS . DS . $filename);
return $this->response;
}
}
As you can see, it only sends an asset files.
This is the route:
Router::plugin('Assets', ['path' => '/assets'], function ($routes) {
$routes->connect(
'/:type/:filename',
['controller' => 'Assets', 'action' => 'asset'],
[
'type' => '(css|js)',
'filename' => '[a-z0-9]+\.(css|js)',
'pass' => ['filename', 'type'],
]
);
});
And this is the test class:
namespace Assets\Test\TestCase\Controller;
use Assets\Utility\AssetsCreator;
use Cake\TestSuite\IntegrationTestCase;
class AssetsControllerTest extends IntegrationTestCase
{
public function testAsset()
{
//This is the filename
$filename = sprintf('%s.%s', AssetsCreator::css('test'), 'css');
$this->get(sprintf('/assets/css/%s', $filename));
$this->assertResponseOk();
}
}
Running the test, however, this exception is generated (full test here):
1) Assets\Test\TestCase\Controller\AssetsControllerTest::testAsset
Cake\Routing\Exception\MissingControllerException: Controller class could not be found. in /home/mirko/Libs/Plugins/Assets/vendor/cakephp/cakephp/src/Http/ControllerFactory.php:91
I do not think is a problem of broken, because the same exception is generated by doing so:
$url = \Cake\Routing\Router::url([
'controller' => 'Assets',
'action' => 'asset',
'plugin' => 'Assets',
'type' => 'css',
'filename' => $filename,
]);
$this->get($url);
Where am I doing wrong? Thanks.
Solved! On my tests' bootstrap, I missed:
DispatcherFactory::add('Routing');
DispatcherFactory::add('ControllerFactory');
Now it works.
I have installed CakePdf plugin in app/plugins folder and followed all the documentation possbile, thus my settings are as following:
// config/bootstrap.php
Plugin::load('CakePdf', ['bootstrap' => true, 'routes' => true]);
Configure::write('CakePdf', [
'engine' => 'CakePdf.WkHtmlToPdf',
'binary' => '/wkhtmltopdf/bin/wkhtmltopdf',
'margin' => [
'bottom' => 15,
'left' => 50,
'right' => 30,
'top' => 45
],
'orientation' => 'landscape',
'download' => true
]);
// config/routes.php
Router::extensions(['pdf']);
// controller/AppController.php
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authenticate' => ['Form' => ['fields' => ['username' => 'email', 'password' => 'password']]],
'loginAction' => ['controller' => 'Users', 'action' => 'login'],
'loginRedirect' => ['controller' => 'Users', 'action' => 'index'],
'logoutRedirect' => ['controller' => 'Users', 'action' => 'login'],
'authorize' => 'Controller'
]);
}
Here is how a sample agendaPdf action looks like:
function agendaPdf(){
$agenda = 'sample agenda';
$this->viewBuilder()->options([
'pdfConfig' => [
'orientation' => 'portrait',
'filename' => 'agenda_123'
]
]);
$this->set('agenda', $agenda);
}
I have PDF layouts done, as well as a PDF folder inside the templates folder for the model's actions, however, if I go to app/users/agendapdf.pdf, I am given the following messages:
The action agendapdf.pdf is not defined in UsersController
Error: Create UsersController::agendapdf.pdf() in file: src/Controller/UsersController.php.
I would really like to know what could have went wrong and how I can fix it to work.
CakePdf does not include any of the supported PDF engines, so i tried wkhtmltopdf( Refered Link).
Step by Step process:
1. Install wkhtmltopdf binary file in your local or server system (Ubuntu, Window, Mac) - Download link : [wkhtmltopdf][2]
2. Check the installed location of wkhtmltopdf binary file - (i am using ubuntu so installed location is /usr/local/bin)
3. configure the wkhtmltopdf with cakephp:
- in : config/bootstrap.php like below:
Plugin::load('CakePdf', ['bootstrap' => true, 'routes' => true]);
Configure::write('CakePdf', [
'engine' => 'CakePdf.WkHtmlToPdf',
'margin' => [
'bottom' => 15,
'left' => 50,
'right' => 30,
'top' => 45
],
'orientation' => 'landscape',
'download' => true
]);
- Create a folder name "pdf" under your working template view folder:
* for ex: src/template/(working view folder)/pdf (src/template/budget/pdf)
- Create a file name "view.ctp" under newly created pdf folder under working directory:
* for ex: src/template/(working view folder)/pdf/view.ctp (src/template/budget/pdf/view.ctp)
- use below code in working controller - action(view - method)
$this->viewBuilder()->options([
'pdfConfig' => [
'orientation' => 'portrait',
'filename' => 'Invoice_' . $id
]
]);
* for ex:
public function view($id = null)
{
$budget = $this->budget->get($id);
$this->viewBuilder()->options([
'pdfConfig' => [
'orientation' => 'portrait',
'filename' => 'Invoice_' . $id
]
]);
$this->set('budget', $budget);
}
- Hit the controller and action to download as PDF.
* for ex: http://localhost:8765/projects/view/1.pdf
- if you are facing "wkhtmltopdf binary is not found or not executable" error. copy your wkhtmltopdf file from "/usr/local/bin" to "/usr/bin"
* cd /usr/local/bin
* sudo cp wkhtmltoimage /usr/bin/wkhtmltoimage
* sudo cp wkhtmltopdf /usr/bin/wkhtmltopdf
I have a form of uploading a file and everything works. I just need to set the folder into which files will be thrown.
My files: http://wklej.org/id/1756722/
Just add filter RenameUpload to Your FilesFilter:
Form/FilesFilter:
<?php
namespace DynamicAppModuleFiles\Form;
use Zend\InputFilter\InputFilter;
class FilesFilter extends InputFilter
{
public function __construct()
{
$this->add(array(
'name'=> 'upload',
'required'=> true,
'validators' => array(
array('name'=>'NotEmpty')
),
'filters' => array(
array(
'name' => 'File/RenameUpload',
'options' => array(
'target' => 'path/to store/files'
)
)
)
));
}
}
More options you can find here: http://framework.zend.com/manual/current/en/modules/zend.filter.file.html#renameupload
EDIT:
Also make sure that you're calling $form->getInputFilter()->getValues(); after $form->isValid()
I have a following Link in zf2
<?php echo $this->translate('Enquiries') ?>
and this router in zf2
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
which convert above link into
Enquiries
which is fine.
I am using angularjs, which uses anchor fragments a lot.
How can I add achor "#/active" on above zf2 link url, so target url look something like this.
Active Enquiries
do you have a reason why you are not just adding the anchor manually after the url definition url(...).'#/active' ?
if you have, try this:
'route' => '/[:controller[/:action[#/:anchor]]]',
UPDATE:
I checked the source for router and uri and url , it seems that url view helper accepts a 'fragment' key for the third option so try this :
url('[route]',array([params]),array('fragment'=>'/active'));
Zend/View/Helper/Url
Zend/Mvc/Router/Http/TreeRouteStack
Zend/Uri/Uri
Create following view Helper by extending Url
namespace Application\View\Helper;
use Zend\View\Helper\Url;
class MyUrl extends Url {
public function __invoke($name = null, $params = array(), $options = array(), $reuseMatchedParams = false) {
if (isset($params['anchor']) && !empty($params['anchor'])) {
$anchor = $params['anchor'];
unset($params['anchor']);
} else {
$anchor = '';
}
$link = parent::__invoke($name, $params, $options, $reuseMatchedParams);
return $link . $anchor;
}
}
In Module file add following in factory to add newly created helper
public function getViewHelperConfig() {
return array(
'factories' => array(
'myUrl' => function($sm) {
$locator = $sm->getServiceLocator();
$helper = new \Application\View\Helper\MyUrl;
$router = \Zend\Console\Console::isConsole() ? 'HttpRouter' : 'Router';
$helper->setRouter($locator->get($router));
$match = $locator->get('application')
->getMvcEvent()
->getRouteMatch();
if ($match instanceof RouteMatch) {
$helper->setRouteMatch($match);
}
return $helper;
},
),
);
}
Add anchor in URL as parameter
<?php echo $this->translate('Enquiries') ?>