Basically what i'm trying to do is to pass some data from "parent" controller to the controller of its children module, for example:
header controller
$this->children = array(
'module/newslettersubscribe'
);
newslettersubscribe controller
public function index() {
// Use here data from the header controller
}
Is that even possible to do?
Here the approach is incorrect. You should edit only the slider controller and check whether there is a path variable available in the GET (query string), e.g.:
if (!empty($this->request->get['path'])) { /* ... */ }
If it is you can now extract the categories from it's value (which is e.g. 1_12_36):
if (!empty($this->request->get['path'])) {
$category_ids = explode('_', (string)$this->request->get['path']);
}
Now knowing the category IDs (or the category path) you can display the appropriate images only using whatever code you made up.
Related
I am working on Xcart-5 website customization. And I created my own module and doing work on that. I just created some Global Attributes (" As a Plain text ") field and assign these attributes to some product. Now I want to access these fields value in programming in the product details page for assigning some other value programatically at run time.
How can I achieve this task. Kindly provide me the solution .
In your module you should decorate the \XLite\Model\Attribute class and extend the getAttributeValue() method there.
For instance, if I use a module with developer ID Tony and module ID AttributesDemo, then I would need to create the XCartDirectory/classes/XLite/Module/Tony/AttributesDemo/Model/Attribute.php file with the following content:
<?php
// vim: set ts=4 sw=4 sts=4 et:
namespace XLite\Module\Tony\AttributesDemo\Model;
/**
* Attribute
* #MappedSuperClass
*/
abstract class Attribute extends \XLite\Model\AttributeAbstract implements \XLite\Base\IDecorator
{
public function getAttributeValue(\XLite\Model\Product $product, $asString = false)
{
$result = parent::getAttributeValue($product, $asString);
if (!$asString) {
foreach ($result as $obj) {
if ($obj->asString() == 'Mac') {
$obj->getAttributeOption()->setName('Windows');
}
}
}
return $result;
}
}
Such implementation will change Mac values to Windows ones in all attributes.
I want to save both layout and view template CONTENT in the database. Each view template will be associated to a layout_id. When a controller action loads, it will fetch the appropriate layout and view from database.
I've done fair amount of researching, looks like this hasn't been discussed before, at least not with ZF2. Not only I want different themes for the site, I also want version control on the design, user can work on a version of template, save it and when done publish the site. I've been looking into custom view strategy and renderer and could not find out how to piece everything together.
Please advice how to proceed with this problem. If there are any tutorials out there please let me know.
First, you have to decide your database structure. I would prefer a table where for each controller/action, depending on the version of the design, you have a file for the layout view, and another for the action view. I think it is a flexible way, since you can have for instance the same layout for all the controllers, but a a different view for the content of every action, or you can have a different layout for an specific controller.
It could be something like this.
CREATE TABLE `templates` (
`version` INT(5) NOT NULL,
`controller` VARCHAR(30) NOT NULL,
`action` VARCHAR(30) NOT NULL,
`layout_view` VARCHAR(30) DEFAULT NULL,
`action_view` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`version`,`module`,`controller`,`action`)
)
remember that the template names has to be 'MODULE/CONTROLLER/ACTION' that is the format that the function ViewModel::setTemplate is expecting. So if in your Module Foo, you have the folder view, with a hierachy like this Foo/view/foo/controllerName/actionName.phtml in your database you should store: foo/controllerName/actionName
Then you have to set, somewhere in the config files, the current design version that has to be used. This version could be a different one in your local machine, and in the production server. For that, you leverage the /config/autoload/local.php that allows you to have different configuration in the different enviroments, just telling your git, subversion, or ftp, to ignore this file, so you can have a different one in every enviroment. Check this docs. It will be enough if you put something like this:
/config/autoload/local.php
return array(
'designVersion' => 1,
);
Then when the application loads, you have to check the current version of the design, and set the correct templates to be used. I would do it after the dispatch event, so the way would be to add a listener in the app bootstrarp. For that, in your main module (i.e. "App" or "Application" module), in the Module.php you overwrite the onBootstrap function, load the event manager, and add a callback to the MvcEvent::EVENT_DISPATCH event.
There, you can have access to the serviceManager, so you can retrieve your database adapter, also, you can know the current requested controller and action, the current viewmodel object, and from it, the action viewmodel. So you already have everything you need. So you can go like this:
public function onBootstrap(MvcEvent $e) {
//get the service manager
$sm = $e->getApplication ()->getServiceManager ();
//get your db adapter
$db=$sm->get("whatever is the service name of your database adapter, entity manager, or whatever you are using");
//get the config
$config = $sm->get ( 'config' );
$version = $config ['designVersion'];
//get the event manager, and attach a callback to the MvcEvent::EVENT_DISPATCH
$em = $e->getApplication ()->getEventManager ();
$em->attach ( MvcEvent::EVENT_DISPATCH, function ($e) use($sm) {
//you get the routeMath, so you can know the controller and action
$routeMatch = $e->getRouteMatch ();
$action=$routeMatch->getParam ( 'action' );
$controller=$routeMatch->getParam ( 'controller' );
//now, with $action, $controller, and $version
//you query your db to get the layout and view templates:
$views=$db->whetever..
$layout_template= $views->layout_view;
$action_template= $views->action_view;
//you get the current viewModel, it hasnt been rendered yet, so we can set the templates
$viewModel = $e->getViewModel ();
if (is_null ( $viewModel ))
return;
$viewModel->setTemplate ($layout_template);
//and now, we get the action view model, that we know that is set as a children of the layout viewmodel. So we can retrieve it like this:
$children = $viewModel->getCurrent()->getChildren();
$child = $children[0];
//if we are afraid the view could have more children, and you want to make sure that you rerieve the correct one, then you could iterate over $children and look for the child that has the correct captureTo name set. For the action’s view model, this defaults to content:
/*
$children = $viewModel->getCurrent()->getChildren();
$child=null;
foreach($children as $c) {
if ($c->captureTo() == 'content') {
$child=$c;
break;
}
}
*/
//and now, you set the template to the view:
$child->setTemplate ($action_template);
}, - 100 );
}
If I have an image field in a parameter template, what are the steps involved in getting the URL of the image in c#?
#mdresser makes a valid point about what should and should not be a rendering parameter. However, I don't think that Sitecore intentionally made it difficult to use image fields in parameter templates. They simply built the parameter template functionality over the existing key-value pair rendering parameter functionality.
If the name of your image field on the rendering parameters template was BackgroundImage, you could use the following code to get the URL of the selected image:
var imageId = XmlUtil.GetAttribute("mediaid", XmlUtil.LoadXml(this.Parameters["BackgroundImage"]));
MediaItem imageItem = Sitecore.Context.Database.GetItem(imageId);
backgroundImageUrl = MediaManager.GetMediaUrl(imageItem);
If you don't already have a base class for your sublayouts that provides the Parameters property, you will need to also add this:
private NameValueCollection parameters;
public virtual NameValueCollection Parameters
{
get
{
if (this.parameters == null)
{
var parameters = this.Attributes["sc_parameters"];
this.parameters = string.IsNullOrEmpty(parameters)
? new NameValueCollection()
: WebUtil.ParseUrlParameters(parameters);
}
return this.parameters;
}
}
To achieve this you would have to look at how the sitecore image field renders the raw text value into an img tag. However, there is a reason that this doesn't work out of the box with sitecore; parameters templates are designed to define info about how a rendering or sublayout should render. E.g. You could use it to tell a list control to show a certain number of items etc. I'd advise against using rendering parameters for content as this will make content editing very cumbersome. If your aim is to have the content of a particular sublayout defined somewhere other than the page itself, put it into a sub item instead.
You can have a 2 separate functions to retrieve the value of image field in the parameter template that you gave to the sub layout .
First Step : Get the value associated with the parameter of image . Please use below function to retrieve the value .
/// <summary>
/// Returns a specific parameter value
/// Use this for Single-line, multiline text fields, linkfield, Image field etc.
/// </summary>
/// <param name="parameterName"></param>
/// <returns></returns>
public MediaItem GetValueFromRenderingParameter(string parameterName)
{
var item = !string.IsNullOrEmpty(_params[parameterName]) ? _params[parameterName] : string.Empty;
if(item == null)
{
return null ;
}
return Sitecore.Context.Database.GetItem(item);
}
Second step : Create another function where you can use the above mentioned function to retrieve the value of image field and use it appropriately. Here is the code snippet of the same :
Public string RenderImage()
{
Sitecore.Data.Fields.ImageField imageField =GetValueFromRenderingParameter("Image parameter name");
return MediaManager.GetMediaUrl(imageField.MediaItem) ;
}
Hope This Helps .
I need to put a search box within a list of objects as a result of a typical indexSuccess action in Symfony. The goal is simple: filter the list according to a criteria.
I've been reading the Zend Lucene approach in Jobeet tutorial, but it seems like using a sledge-hammer to crack a nut (at least for my requirements).
I'm more interested in the auto-generated admin filter forms but I don't know how to implement it in a frontend.
I could simply pass the search box content to the action and build a custom query, but is there any better way to do this?
EDIT
I forgot to mention that I would like to have a single generic input field instead of an input field for each model attribute.
Thanks!
I'm using this solution, instead of integrating Zend Lucene I manage to use the autogenerated Symonfy's filters. This is the way i'm doing it:
//module/actions.class.php
public function executeIndex(sfWebRequest $request)
{
//set the form filter
$this->searchForm = new EmployeeFormFilter();
//bind it empty to fetch all data
$this->searchForm->bind(array());
//fetch all
$this->employees = $this->searchForm->getQuery()->execute();
...
}
I made a search action which does the search
public function executeSearch(sfWebRequest $request)
{
//create filter
$this->searchForm = new EmployeeFormFilter();
//bind parameter
$fields = $request->getParameter($this->searchForm->getName());
//bind
$this->searchForm->bind($fields);
//set paginator
$this->employees = $this->searchForm->getQuery()->execute();
...
//template
$this->setTemplate("index");
}
It's important that the search form goes to mymodule/search action.
Actually, i'm also using the sfDoctrinePager for paginate setting directly the query that the form generate to get results properly paginated.
If you want to add more fields to the search form check this :)
I finally made a custom form using the default MyModuleForm generated by Symfony
public function executeIndex {
...
// Add a form to filter results
$this->form = new MyModuleForm();
}
but displaying only a custom field:
<div id="search_box">
<input type="text" name="criteria" id="search_box_criteria" value="Search..." />
<?php echo link_to('Search', '#my_module_search?criteria=') ?>
</div>
Then I created a route named #my_module_search linked to the index action:
my_module_search:
url: my_module/search/:criteria
param: { module: my_module, action: index }
requirements: { criteria: .* } # Terms are optional, show all by default
With Javascript (jQuery in this case) I append the text entered to the criteria parameter in the href attribute of the link:
$('#search_box a').click(function(){
$(this).attr('href', $(this).attr('href') + $(this).prev().val());
});
And finally, back to the executeIndex action, I detect if text was entered and add custom filters to the DoctrineQuery object:
public function executeIndex {
...
// Deal with search criteria
if ( $text = $request->getParameter('criteria') ) {
$query = $this->pager->getQuery()
->where("MyTable.name LIKE ?", "%$text%")
->orWhere("MyTable.remarks LIKE ?", "%$text%")
...;
}
$this->pager->setQuery($query);
...
// Add a form to filter results
$this->form = new MyModuleForm();
}
Actually, the code is more complex, because I wrote some partials and some methods in parent classes to reuse code. But this is the best I can came up with.
I've set up a self-referencing entity per the manual here:
http://www.google.com/url?sa=D&q=http://www.doctrine-project.org/docs/orm/2.0/en/reference/association-mapping.html%23one-to-many-self-referencing
My class is Page (instead of Category, like in the docs). In my entity
class I have a toArray() method that I've implemented that will give
me back the values of my member variables. For those fields that are
associations, I've made sure to grab the associated class object then
grab the id. I'm doing this to populate a form. Here is the code from
my toArray() method in my Page entity as well as my PageService
function to grab a Page object and my Page Controller code that calls
toArray() to populate my form.
http://pastie.org/1686419
As I say in the code comments, when the toArray() method is called in
the Page Controller, all values get populated except for parent id.
page_type is also a ManyToOne association and it gets populated no
problem. Explicitly grabbing the parent id from the Page object
outside of the toArray() method (in the Page Controller) does return
the parent id value. (See code.)
As a side note, I'm using __get() and __set() in my Page entity instead of full blown getters/setters.
I think it is because you are getting caught out by proxies. When you have an association in Doctrine 2, the related objects are not returned directly as objects, but as subclasses which do not fill their properties until a method is called (because of lazy loading to save database queries).
Since you are calling the property directly (with $this->parent->id) without invoking any method the object properties are all empty.
This page http://www.doctrine-project.org/docs/orm/2.0/en/tutorials/getting-started-xml-edition.html#a-first-prototype has a warning about this type of thing in the warning box. Although yours isn't a public property, you are accessing as though it were because that object is of the same class and the same problem is occuring.
Not sure of exactly what is causing your described behavior, but you're probably better anyway to have your toArray() method call getters/setters rather than having toArray() operate directly on the class properties. This will give you consistency so that if you implement custom getters for certain properties, you'll always get back the same result from toArray() and the getter.
A rough example:
<?php
/** #Entity */
class MyEntity {
// ....
/** #Column */
protected $foo;
public function setFoo($val)
{
$this->foo = $val;
}
public function getFoo()
{
return 'hello ' . $this->foo;
}
public function toArray()
{
$fields = array('foo');
$values = array();
foreach($fields as $field) {
$method = 'get' . ucfirst($field);
if (is_callable(array($this, $method)) {
$fields[$field] = $this->$method();
} else {
$fields[$field] = $this->$field;
}
}
return $fields;
}
}
Now you get the same result:
<?php
$e = new MyEntity;
$e->setFoo('world');
$e->getFoo(); // returns 'hello world'
$e->toArray(); // returns array('foo' => 'hello world')