I have the following code:
class Module {
public function onBootstrap(MvcEvent $e){
$application = $e->getApplication();
$em = $application->getEventManager();
$em->attach(\Zend\Mvc\MvcEvent::EVENT_DISPATCH, array($this,'setupNav'),10000);
}
public function setupNav($e)
{
$serviceLocator = $e->getApplication()->getServiceManager();
$router = $serviceLocator->get('router');
$page = \Zend\Navigation\Page\AbstractPage::factory(array(
'label' => 'Login',
'route' => 'login',
'resource' => 'auth.auth.login'
));
$page->setRouter($router);
$page->set('type','user');
$serviceLocator->get('navigation')->addPage($page);
}
}
The problem is that these pages i create dynamically dont ever get marked as status active when the route matches (and adds an active class). It works fine for the ones loaded with the navigation container (the config navigation) but for some reason when i dynamically add Mvc Pages the status does not become active for these navigation elements
Related
I created new resources with this code:
class WebserviceRequest extends WebserviceRequestCore {
public static function getResources(){
$resources = parent::getResources();
// if you do not have class for your table
$resources['test'] = array('description' => 'Manage My API', 'specific_management' => true);
$resources['categoryecommerce'] = array('description' => 'o jacie marcin', 'class' => 'CategoryEcommerce');
$mp_resource = Hook::exec('addMobikulResources', array('resources' => $resources), null, true, false);
if (is_array($mp_resource) && count($mp_resource)) {
foreach ($mp_resource as $new_resources) {
if (is_array($new_resources) && count($new_resources)) {
$resources = array_merge($resources, $new_resources);
}
}
}
ksort($resources);
return $resources;
}
}
And new class:
class CategoryEcommerceCore extends ObjectModelCore {
public $category_id;
public $category_core_id;
public static $definition = array(
'table' => "category_ecommerce",
'primary' => 'category_id',
'fields' => array(
'category_core_id' => array('type' => self::TYPE_INT),
)
);
protected $webserviceParameters = array();
}
Webservice is override properly. My class WebserviceRequest is copying to
/override/classes/webservice/WebserviceRequest
but class isn't copying to /override/classes/ when i installing my module.
How to add new resourcess with own logic ? I want to add categories within relation to my table.
Regards
Martin
As soon as there is literally nothing regarding the API except Webkul tutorial... I tried to implement the "Webkul's" tutorial, but also failed. However seems that it's better to use hooks instead of overrides. I used my "reverse engineering skills" to determine the way to create that API, so-o-o-o, BEHOLD! :D
Let's assume you have a custom PrestaShop 1.7 module. Your file is mymodule.php and here are several steps.
This is an install method wich allows you to register the hook within database (you can uninstall and reinstall the module for this method to be executed):
public function install() {
parent::install();
$this->registerHook('addWebserviceResources');
return true;
}
Add the hook listener:
public function hookAddWebserviceResources($resources) {
$added_resources['test'] = [
'description' => 'Test',
'specific_management' => true,
];
return $added_resources;
}
That specific_management option shows you are going to use WebsiteSpecificManagement file instead of database model file.
Create WebsiteSpecificManagement file, called WebsiteSpecificManagementTest (Test - is CamelCased name of your endpoint). You can take the skeleton for this file from /classes/webservice/WebserviceSpecificManagementSearch.php. Remove everything except:
setObjectOutput
setWsObject
getWsObject
getObjectOutput
setUrlSegment
getUrlSegment
getContent (should return $this->output; and nothing more)
manage - you should rewrite it to return/process the data you want.
Add
include_once(_PS_MODULE_DIR_.'YOURMODULENAME/classes/WebserviceSpecificManagementTest.php');
to your module file (haven't figured out how to include automatically).
Go to /Backoffice/index.php?controller=AdminWebservice and setup the new "Auth" key for your application, selecting the test endpoint from the permissions list. Remember the key.
Visit /api/test?ws_key=YOUR_KEY_GENERATED_ON_STEP_4 and see the XML response.
Add &output_format=JSON to your URL to see the response in JSON.
You have to use something like $this->output = json_encode(['blah' => 'world']) within manage method at WebsiteSpecificManagementTest.
I have a site in zend framework . Now I am making site in multiple language. For it I need to modify the url.
For example if sitename is www.example.com then i want to make it like
www.example.com/ch
www.example.com/fr
There can be some work around it that you can ask me to create a folder name ch and put a copy of code inside it. But for it I have to manage multiple folder when updating files on server.
What is the best or correct way to do it ?
My routs code is
public function _initRouter() {
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$routes = array(
'page' => new Zend_Controller_Router_Route('page/:slug', array('controller' => 'staticpage', 'action' => 'page', 'slug' => ''))
);
$router->addRoutes($routes);
}
Thanks
You have to add the language as parameter in your route(s). Here is an example: http://devzone.zend.com/1765/chaining-language-with-default-route/
You need a function to get a user choice of a language and a default language used if a user just starts with example.com.
You may want to get the current browser and Language Header from the users HTTP request.
Take a look at Zend_Locale and Zend_Translate.
You can use something like $locale = new Zend_Locale('browser'); to detect the users browser language.
Then look if Zend_Translate or your translation engine has the language available and set it to a cookie or session to store the date.
If the user then navigate to some language change site like example.com/?language=en you may want to set the locale based on the user choice and recheck if available in your translations.
If not, get back to original default language and present an error page or something like that.
If you want to get your Zend_Router urls to be language dependent, which might be a bad choice because of copy paste, backlinks or forum posts of your links, you need to add something before each route.
In my Applications i use something like the following in my main bootstrap.php file. I've cut some parts of to keep it simple.
protected function _initTranslate() {
$session = new Zend_Session_Namespace("globals");
// Get current registry
$registry = Zend_Registry::getInstance();
/**
* Set application wide source string language
* i.e. $this->translate('Hallo ich bin ein deutscher String!');
*/
if(!$session->current_language) {
try {
$locale = new Zend_Locale('browser'); //detect browser language
}
catch (Zend_Locale_Exception $e) {
//FIXME: get from db or application.ini
$locale = new Zend_Locale('en_GB'); //use the default language
}
}
else {
$locale = new Zend_Locale($session->current_language);
}
$translate = new Zend_Translate(
array(
'adapter' => 'array',
'content' => realpath(APPLICATION_PATH . '/../data/i18n/'),
'locale' => $locale,
'scan' => Zend_Translate::LOCALE_DIRECTORY,
'reload' => false,
'disableNotices' => true, //dont get exception if language is not available
'logUntranslated' => false //log untranslated values
)
);
if(!$translate->isAvailable($locale->getLanguage())) {
$locale = new Zend_Locale('en_GB'); //default
}
$translate->setLocale($locale);
$session->current_language = $locale->getLanguage();
//Set validation messages
Zend_Validate_Abstract::setDefaultTranslator($translate);
//Max lenght of Zend_Form Error Messages (truncated with ... ending)
Zend_Validate::setMessageLength(100);
//Zend_Form Validation messages get translated into the user language
Zend_Form::setDefaultTranslator($translate);
/**
* Both of these registry keys are magical and makes do automagical things.
*/
$registry->set('Zend_Locale', $locale);
$registry->set('Zend_Translate', $translate);
return $translate;
}
This is for the default translation setup of each visitor.
To set a user language depending on some HTTP parameters, I decided to create a Plugin, which will run on each request, see if the global language parameter is set (key=_language) and try setting the new language.
I then redirect the user to the new route, depending on his choice.
So, if the user click on the link for english language (example.com/de/test/123?_language=en) he will get redirected to example.com/en/test/123.
class Application_Plugin_Translate extends Core_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$frontController = Zend_Controller_Front::getInstance();
// Get the registry object (global vars)
$registry = Zend_Registry::getInstance();
// Get our translate object from registry (set in bootstrap)
$translate = $registry->get('Zend_Translate');
// Get our locale object from registry (set in bootstrap)
$locale = $registry->get('Zend_Locale');
// Create Session block and save the current_language
$session = new Zend_Session_Namespace('globals');
//get the current language param from request object ($_REQUEST)
$language = $request->getParam('_language',$session->current_language);
// see if a language file is available for translate (scan auto)
if($translate->isAvailable($language)) {
//update global locale
$locale = $registry->get('Zend_Locale');
$locale->setLocale($language);
$registry->set('Zend_Locale', $locale);
//update global translate
$translate = $registry->get('Zend_Translate');
$translate->setLocale($locale);
$registry->set('Zend_Translate', $translate);
//language changed
if($language!=$session->current_language) {
//update session
$session->current_language = $language;
$redirector = new Zend_Controller_Action_Helper_Redirector;
$redirector->gotoRouteAndExit(array());
}
}
else {
$request->setParam('_language', '');
unset($session->current_language);
$redirector = new Zend_Controller_Action_Helper_Redirector;
$redirector->gotoRouteAndExit(array());
}
}
}
And finally, to prepare your router with the new language routes, you need to setup a base language route and chain your other language depending routes.
public function _initRouter() {
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$languageRoute = new Zend_Controller_Router_Route(
':language',
array(
'language' => "de"
),
array('language' => '[a-z]{2}')
);
$defaultRoute = new Zend_Controller_Router_Route(
':#controller/:#action/*',
array(
'module' => 'default',
'controller' => 'index',
'action' => 'index'
)
);
$router->addRoute(
'default',
$defaultRoute
);
$languageDefaultRoute = $languageRoute->chain($defaultRoute);
$router->addRoute(
'language',
$languageDefaultRoute
);
}
Good luck with your project, hope it will help you and others!
i have implementing the project in yii. i done my project but i want to change instead of id to name. ie url management. i did uncomment in config.php then i added the following code. those follows:
my table name is recipe:
public function loadModel($id)
{
$model=Recipe::model()->findByPk($id);
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
public function loadModel2($name)
{
$model=Recipe::model()->find('t.name=:name', array(':name' => $name));
if($model===null)
throw new CHttpException(404,'The requested page does not exist.');
return $model;
}
except this i added top of the sitecontroller use Recipe. but it shows error is
The use statement with non-compound name 'Recipe' has no effect
please suggest me suitable answer
I personally use in my projects something like /product-name/p/1 and this is SEO friendly. To get your links to look like that you have to first change your url rules
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'urlSuffix' => '/',
'rules' => array(
'<title:.*?>/p/<id:\d+>'=>'product/view',
),
),
Then use this to create your URLs.
Yii::app()->createUrl('product/view',array('id'=>$model->id, 'title'=>$model->name))
Now it works both ways, the create url will always create urls like /product-name/p/1 and further more you can show the product the normal way
/**
* Displays a particular model.
* #param integer $id the ID of the model to be displayed
*/
public function actionView($id)
{
$model = $this->loadModel($id);
$this->render('view',array(
'model'=>$model,
));
}
I am experiencing some difficulty setting up the functionality for an admin to edit an items values. I have created the editAction() function in the AdminItemController class. This is contained within a module called catalog. My routing is configured as the following:
resources.router.routes.admin-catalog-edit.route = "/admin/catalog/item/edit/:id"
resources.router.routes.admin-catalog-edit.defaults.module = "catalog"
resources.router.routes.admin-catalog-edit.defaults.controller = "admin.item"
resources.router.routes.admin-catalog-edit.defaults.action = "edit"
I have created a custom Zend_Form class and within this class I set the action and method for the form:
class My_Form_ItemAdd extends Zend_Form
{
public function init()
{
$this->setAction('/admin/catalog/item/edit')
->setMethod('post');
...
Within my controller action I have instantiated the form and pass it to the view to be rendered. I also test if it's a POST (if so validate and save to database), otherwise, test for GET (if so, extract ID and populate()):
class Catalog_AdminItemController extends Zend_Controller_Action
{
...
public function editAction()
{
$form = new My_Form_ItemEdit();
$this->view->form = $form;
...
The form loads just fine in the browser when I supply an ID at the end for GET request... however, when I submit the form an exception is thrown with the following request parameters:
array (
'controller' => 'admin',
'action' => 'catalog',
'item' => 'edit',
'module' => 'default',
...
I have no idea why the it would be doing this... is there something I'm not seeing??? Any advice would be much appreciated!
The problem lies in your route. The default behavior for /admin/catalog/item/edit/:id is to process it like /controller/action/:param/:param/:param which puts both item and edit as parameters instead of your intended purpose. Try adding something like this to your bootstrap:
protected function _initRoutes()
{
// Get front controller
$front = Zend_Controller_Front::getInstance();
// Get router
$router = $front->getRouter();
// Add route
$router->addRoute(
'admin_item_edit',
new Zend_Controller_Router_Route('admin/catalog/item/edit/:id',
array('controller' => 'item',
'action' => 'edit'))
);
}
This allows you to define the specific controller and action from the route.
I have a questiom regarding the Zend Framework 2:
I have
library/System and library/Zend. the system is my custom library, which I want to configure de aplication (routes, modules, etc., and redirect user to correct module, controller and/or action).
I don't want to do this inside each application/modules/ModuleName/Module.php file. So, my library/System can do everything related to application configuration.
As said in the comments above: register to the bootstrap-event and add new routes there:
<?php
namespace Application;
use Zend\Module\Manager,
Zend\EventManager\StaticEventManager;
class Module
{
public function init(Manager $moduleManager)
{
$events = StaticEventManager::getInstance();
$events->attach('bootstrap', 'bootstrap', array($this, 'initCustom'), 100);
}
public function initCustom($e)
{
$app = $e->getParam('application');
$r = \Zend\Mvc\Router\Http\Segment::factory(array(
'route' => '/test',
'defaults' => array(
'controller' => 'test'
)
)
);
$app->getRouter()->addRoute('test',$r);
}
}
$app = $e->getParam('application'); does return an instance of Zend\Mvc\Application. Have a look there to see which additional parts you can get there. The bootstrap event is fired before the actual dispatching does happen.
Note that the ZendFramework 1 routes are not always compatible to the ZendFramework 2 ones.
Update to comments
public function initCustom($e)
{
$app = $e->getParam('application');
// Init a new router object and add your own routes only
$app->setRouter($newRouter);
}
Update to new question
<?php
namespace Application;
use Zend\Module\Manager,
Zend\EventManager\StaticEventManager;
class Module
{
public function init(Manager $moduleManager)
{
$events = StaticEventManager::getInstance();
$events->attach('bootstrap', 'bootstrap', array($this, 'initCustom'), 100);
}
public function initCustom($e)
{
$zendApplication = $e->getParam('application');
$customApplication = new System\Application();
$customApplication->initRoutes($zendApplication->getRouter());
// ... other init stuff of your custom application
}
}
This only happens in one zf2 module (named Application which can be the only one as well). This doesn't fit your needs? You could:
extend a custom module autoloader
extend Zend\Mvc\Application for your own logic
make your code zf2-compatible