Hi I am having problem while matching Kohana 3 custom route, it seems like every thing is correct but URL doesnot match with route. Following are settings in my bootstrap.php file:
Kohana::init(array(
'base_url' => '/basepath/',
'index_file' => 'index.php'
));
/**
* Attach the file write to logging. Multiple writers are supported.
*/
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
/**
* Attach a file reader to config. Multiple readers are supported.
*/
Kohana::$config->attach(new Config_File);
/**
* Enable modules. Modules are referenced by a relative or absolute path.
*/
Kohana::modules(array(
'auth' => MODPATH.'auth', // Basic authentication
// 'cache' => MODPATH.'cache', // Caching with multiple backends
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
'database' => MODPATH.'database', // Database access
'image' => MODPATH.'image', // Image manipulation
'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'unittest' => MODPATH.'unittest', // Unit testing
'userguide' => MODPATH.'userguide', // User guide and API documentation
));
/**
* Set the routes. Each route must have a minimum of a name, a URI and a set of
* defaults for the URI.
*/
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
Route::set('category_images', 'cat/<category>', array('category'=>'[a-z\-_\.]+'))
->defaults(array(
'controller' => 'categoryimages',
'action' => 'index',
));
Route::set('user_images', '<username>/images(/<pageid>)', array('username'=>'[a-z\-_\.]+', 'pageid'=>'[1-9][0-9]*'))
->defaults(array(
'controller' => 'userimages',
'action' => 'index',
));
Route::set('dynamic_image', 'image/thumbnail/<size>/<id>/<image>', array('size'=>'s|m|z', 'id'=>'[0-9]+', 'image'=>'.+'))
->defaults(array(
'controller' => 'image',
'action' => 'thumbnail'
));
Attached is the error mesage:
Here is target controller, to show naming conventions if there is problem in that:
<?php
class Controller_Categoryimages extends Controller_Template {
public $template = 'template';
public $images_per_page = 15;
// show images of a user
public function action_index() {
//code here
}
Please tell if some one have any idea that why it is not matching the URL.
thanks in advance guys.
Your default route should be last, as it's a catch all. I'd recommend you delete it completely. It's currently matching default first, and trying to load the Contoller_Cat class with action sky.
Related
I've got a simple user registration form where a user can choose their own user type. The user type maps to a role. This is part of a zf2 application using the doctrine2 module.
The relevant part of the init() method of my user fieldset looks like this:
public function init()
{
// ... other field definitions ...
$roleRadio = new ObjectRadio('role');
$roleRadio->setLabel('What type of user are you?')
->setOptions(
array(
'object_manager' => $this->objectManager,
'target_class' => 'MyUser\Entity\Role',
'property' => 'roleId',
'is_method' => true,
'find_method' => array(
'name' => 'findBy',
'params' => array(
'criteria' => array('userselectable' => true),
'orderBy' => array('displayorder' => 'ASC'),
),
),
)
);
$this->add($roleRadio);
// ... more stuff ...
}
I'm using Doctrine's ObjectRadio class for this element to automatically populate the value options. Is there any way to set the default selected value?
I know I can just do something like this:
$form->get('user')->get('role')->setValue(3);
But I don't want to hard code this and I also don't want to put that kind of logic in my controller.
Any suggestions?
I don't know what do you mean by "I don't want to hard code this", but you can do it as you said in your controller, or you can do it in the form definition by setting attributes as the following:
$roleRadio->setAttributes(array('value' => 3));
I use doctrine2 with ZF2, some of my libraries work with Zend\Db\Adapter\Adapter, others with doctrine2. Now, they connect to database twice. Is it possible to use one db connection in doctrine and standard ZF2 db adapter?
The DoctrineORM module accepts a PDO resource or a service name where the instance can be located in the service manager instead of the usual connection params.
First step is to create a service factory which retrieves the PDO resource from the Zend\Db\Adapter\Adapter service
<?php
namespace Application\Db\Service;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\Exception\ServiceNotCreatedException;
class PdoResourceFactory implements FactoryInterface
{
/**
* #param ServiceLocatorInterface $serviceLocator
* #return \PDO resource
*/
public function createService(ServiceLocatorInterface $services)
{
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
}
}
Once you have the factory, it's just a case of adding it to the service manager, configuring the db params for Zend\Db\Adapter\Adapter and telling doctrine to use the existing PdoResource from the service manager to connect.
Assuming you did this all in one file, let's say dbconn.local.php...
<?php
return array (
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// include the pdo resource factory
'PdoResource' => 'Application\Db\Service\PdoResourceFactory',
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
),
),
),
);
Sorry for posting this as new answer but I am not able to add a comment to Crisp's answer since my reputation is too low because I only registered to stackoverflow for writing this comment:
In the dbconn.local.php that Crisp posted be sure to set dbname to null like in the following snippet:
Addition to Crisp's answer:
<?php
return array(
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
// the lazy way of Crisp's PdoResourceFactory:
'PdoResource' => function (ServiceLocatorInterface $services) {
$dbAdapter = $services->get('Zend\Db\Adapter\Adapter');
$pdo = $dbAdapter->getDriver()->getConnection()->getResource();
if (!$pdo instanceof \PDO) {
throw new ServiceNotCreatedException('Connection resource must be an instance of PDO');
}
return $pdo;
},
),
),
// db adapter config
'db' => array(
'driver' => 'pdo',
'dsn' => 'mysql:dbname=database;host=127.0.0.1',
'username' => 'username',
'password' => 'password',
),
'doctrine' => array (
'connection' => array (
'orm_default' => array (
'driverClass' => 'Doctrine\DBAL\Driver\PDOMySql\Driver',
// use the resource from the zend adapter
'pdo' => 'PdoResource',
// important addition to Crisp's answer:
'params' => array(
'dbname' => null,
),
),
),
),
);
And now here is why this is important:
When calling
$em->getConnection()->getDatabase();
on your EntityManager without having set the dbname to null you will get "database" as the name of your database because this is the default value which is set by the module.config.php of the DoctrineORMModule as you can see here. Setting the dbname to null will cause your Doctrine\DBAL\Driver\PDOMySql\Driver which extends Doctrine\DBAL\Driver\AbstractMySQLDriver to load the name of the database via SELECT DATABASE() from the database itself as you can see here.
Also not setting the dbname to null (or to the correct database name) will cause the schemaInSyncWithMetadata() function of the Doctrine\ORM\Tools\SchemaValidator to always return false since it cannot load the current database setup because it uses the Doctrine\ORM\Tools\SchemaTool which uses the EntityManager's Connection which thinks that the database being used is called "database".
So I hope someone can use this information to save some time. I wasted half the day to figure that out.
And many thanks to Crisp again for his answer that saved me a lot of time.
I am developing a module for prestashop (basically, it's a very custom import of data and the only thing I need is to have a form and process data). I have created controller class derived from the ModuleAdminController but the problem is where should I put the tpl file containing the look of my custom form?
I realize that I can put tpl file to the templates but I want to keep all files within my module folder, is it possible (probably somewhere like "/views/templates/admin")?
This is the most easy method to create a basic admin controller / action in Prestashop 1.6
Create basic configuration :
./config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>foo</name>
<displayName><![CDATA[Foo]]></displayName>
<version><![CDATA[2.1.3]]></version>
<description><![CDATA[Bar.]]></description>
<author><![CDATA[your-name]]></author>
<tab><![CDATA[administration]]></tab>
<is_configurable>0</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>
./foo.php
if (!defined('_PS_VERSION_'))
exit;
class BarcodeEasyPrint extends Module
{
public function __construct()
{
$this->name = 'foo';
$this->tab = 'administration';
$this->version = '1.0.0';
$this->author = 'your-name-here';
$this->need_instance = 0;
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('Foo');
$this->description = $this->l('Bar.');
if ((int)Tools::getValue('p'))
$this->page = (int)Tools::getValue('p');
}
}
You need to create the controller with base functions :
./controllers/admin/AdminFooController.php
class AdminFooController extends ModuleAdminController {
public function __construct() {
$this->bootstrap = true;
parent::__construct();
}
public function createTemplate($tpl_name) {
if (file_exists($this->getTemplatePath() . $tpl_name) && $this->viewAccess())
return $this->context->smarty->createTemplate($this- >getTemplatePath() . $tpl_name, $this->context->smarty);
return parent::createTemplate($tpl_name);
}
public function initContent(){
parent::initContent();
$tpl = $this->createTemplate('content.tpl')->fetch();
/* DO STUFF HERE */
$posts = array();
$this->context->smarty->assign('posts', $posts);
}
}
You can use boostrap directly in the template file :
./views/templates/admin/content.tpl
<div class="row">
<div class="col-md-6">
</div>
<div class="col-md-6">
</div>
</div>
If it is an admin module only, then you will have no need to create any views. Because Prestashop provides a nice structure for admin section which is easy to use and we dont need to use any views or .tpl files. For admin section, normally three types of views or .tpl files are required, one for data display in grid, second for form and third for displaying a single record.
Prestashop already created .tpl files for them which you can find in "admin_folder/themes/default/templates". In our controllers for admin, for form and for data grid, we just create arrays and PS handles to view the form and data grid according to the arrays we created.
So if you need a custom form at admin, then create a public function renderForm and create the form array in it, like below:
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Video'),
'image' => '../img/admin/tab-genders.gif'
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Video Title:'),
'name' => 'title',
'lang' => true,
'size' => 70,
'hint' => $this->l('Invalid characters:').' 0-9!<>,;?=+()##"�{}_$%:',
'required' => true
),
array(
'type' => 'textarea',
'label' => $this->l('Video Code'),
'name' => 'video_code',
'rows' => 5,
'cols' => 70,
'desc' => $this->l('Place the embed code for the video')
),
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
return parent::renderForm();
} /* End of render member */
For other fields, checkout other prestashop admin controllers and you will see that how easily we can create forms in PS using that simple definitions in the arrays and we dont need to create .tpl files.
For front end, we can use the new modules MVC structure, where our module folder have sub folders for controllers (controllers/front, controllers/admin) , views and models .
Hope this will help you.
Thank you
You need to use the helper form, here is the documentation for it, it is really easy to use ;) .
http://doc.prestashop.com/display/PS15/HelperForm
You also can find more information about how and where to use helper form, look for the function getContent() and displayForm().
http://doc.prestashop.com/display/PS15/Creating+a+PrestaShop+module
unfortunately any document not exist to point directly to solve this question but hear i have some URLs really useful and you should combine theme and get your realize:
http://presthemes.com/prestashop-news/modules-classes-and-controller-override-by-julien-breux-4.html
http://doc.prestashop.com/display/PS15/Diving+into+PrestaShop+Core+development
http://doc.prestashop.com/display/PS15/New+Developers+Features+In+PrestaShop+1.5
http://blog.belvg.com/how-to-implement-a-controller.html
best regards
extending the answer from #altafhussain create a folder views/templates/admin in your module and place your customview.tpl
Than append the free text block as below.
$this->fields_form = array(
'legend' => array(
'title' => $this->l('Legend')
),
'input' => array(
array(
'type' => 'free',
'label' => 'Whatever label text',
'desc' => $this->display(__FILE__,'views/templates/admin/customview.tpl'),
'name' => 'FREE_TEXT',
'required' => false
)
),
'submit' => array(
'title' => $this->l('Save'),
'class' => 'button'
)
);
return parent::renderForm();
}
I'm looking for a tutorial on authentication with Zend 2 and Doctrine 2.
In particular the creation of the controller and adapter.
The official documentation is too global not help me enough.
thank you
EDIT:
i use "Doctrine Entity" (namespace User\Entity;)
The Entity is register in module.config.php file :
'doctrine' => array(
'driver' => array(
__NAMESPACE__ . '_driver' => array(
'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
'cache' => 'array',
'paths' => array(__DIR__ . '/../src/' . __NAMESPACE__ . '/Entity')
),
'orm_default' => array(
'drivers' => array(
__NAMESPACE__ . '\Entity' => __NAMESPACE__ . '_driver'
)
)
),
)
But now, how can i point my identityClass key to my adapter ?
Controller :
use Zend\Mvc\Controller\AbstractActionController,
Zend\View\Model\ViewModel,
Zend\Authentication\AuthenticationService,
Doctrine\ORM\EntityManager,
DoctrineModule\Authentication\Adapter\ObjectRepository as DoctrineAdapter,
User\Entity\User,
User\Form\UserForm;
class UserController extends AbstractActionController
{
protected $em;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function getEntityManager()
{
if (null === $this->em)
$this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
return $this->em;
}
public function getRepository()
{
if (null === $this->em)
$this->em = $this->getEntityManager()->getRepository('User\Entity\User');
return $this->em;
}
public function loginAction()
{
....
????????????
$adapter = new DoctrineAdapter();
$adapter->setIdentityValue($username);
$adapter->setCredentialValue($password);
$auth = new AuthenticationService();
$result=$auth->authenticate($adapter);
????????????
}
}
I've got this error : Call to a member function getRepository() on a non-object in ...doctrine\doctrine-module\src\DoctrineModule\Options\AuthenticationAdapter.php on line 132
line 123 : return $this->objectManager->getRepository($this->identityClass);
There are lots of ways to do it, but DoctrineModule for zf2 ships with a doctrine based authentication adapter (DoctrineModule\Authentication\Adapter\ObjectRepository). There is also a factory to create the adapter (DoctrineModule\Service\AuthenticationAdapterFactory). DoctrineMongoODMModule has it's module.config.php set up to use these services. (Note that the factory and adapter will work with ORM, but I'm not sure if the config keys have been added to DoctrineORMModule yet - perhaps someone who reads this would like create a PR for that?) These are the relevant config keys:
'authenticationadapter' => array(
'odm_default' => array(
'objectManager' => 'doctrine.documentmanager.odm_default',
'identityClass' => 'Application\Model\User',
'identityProperty' => 'username',
'credentialProperty' => 'password',
'credentialCallable' => 'Application\Model\User::hashPassword'
),
),
The identityClass is the doctrine document that represents your authenticated user. The identityProperty is the normally the username. getUsername will be called by the adapter to access this. credentialProperty is normally the password. getPassword will be called by the adapter to access this. credentialCallable is optional. It should be a callable (method, static method, closure) that will hash the credentialProperty - you don't need to do this, but it's normally a good idea. The adapter will expect the callable to have the following form: function hashPassword($identity, $plaintext).
To get the authentication adapter use:
$serviceLocator->get('doctrine.authenticationadapter.odm_default');
Note that all this only gives you an authetication adapter, it doesn't actually do the authentication. Authentication is done something like this:
$adapter = $serviceLocator->get('doctrine.authenticationadapter.odm_default');
$adapter->setIdentityValue($username);
$adapter->setCredentialValue($password);
$authService = new Zend\Authentication\AuthenticationService
$result = $authService->authenticate($adapter);
This will store the whole doctrine document of the authenticated user in the session object. If you want to store only the document ID in the session object, and retrieve the rest of the authetnicated user document form the DB each request, then take a look at DoctrineModule\Authentication\Storage\ObjectRepository. This provides a new StorageInterface for the Zend\Authentication\AuthenticationService.
I have a method in my Users Controller called view, which should display a specified (by URL) user:
public function view($username = null) {
$this->User->username = $username;
if (!$this->User->exists()) {
throw new NotFoundException('Няма такъв потребител!');
}
if (!$username) {
$this->Session->setFlash('Няма такъв потребител!');
$this->redirect(array('action' => 'index'));
}
$this->set('user', $this->User->read());
}
And in the route config:
Router::connect('/:username', array('controller' => 'users', 'action'=> 'view'), array('username' => '^([a-z0-9])+$'));
But when I try: www.example.com/Username it returns a fatal error: Missing controller.
I tried also this:
Router::connect('/users/:username', array('controller' => 'users', 'action'=> 'view'), array('pass' => array('username'), 'username' => '^([a-z0-9])+$'));
Unfortunately for this sort of setup using /:username is too simple, it will pretty much override every single other route. To do this effectively ( + the proper CakePHP way) you need to setup a custom route, here is mine which pretty much achieves the same thing. Just replace "product" with "user" for most cases, read through it though, to make sure you understand what's going on..
Look at my routes config as well if you still can't work it out.
If you want to route /user/dunhamzz to a profile you would set it up like this:
Router::connect('/user/:username',
array('controller' => 'users', 'action' => 'view'),
array('pass' => array('username')
);
Then your view action simply gets the username as the first argument:
public function view($username) {
}