I'm creating my first drupal website and I've come to a roadblock. I'm creating a multi-author website that authors can list their books on. So far they can list books with a cover image, however I'm stuck when I try and make a list of these books somewhere for users to easily view them.
What I need to do:
Create a menu item that users can click on, "Books"
Direct them to url.com/books
Display a list containing the cover images of the most recently released books, 4 per row. The user can then click on an image to view more details of the book.
I have a custom content type, "book" that has title, blurb, author, and cover fields.
I also want to create a menu on the left side that has a list of authors or genres (similar to what is on Amazon.com). When the user clicks on an author or genre, it narrows the search results down.
What do I need to do this? I'm not familiar enough with Drupal's terminology yet.
Questing is too big, bug any way, you can use following code get list of books.
$result = db_query("
SELECT nid
FROM node
WHERE type = :type limit 4 OFFSET :offset",
array(':type' => 'book',':offset' => $offset))->fetchAll();
And I guess you may need to create a menu on the left, so following code just a simple example.
function books_menu() {
$items = array();
$items['books'] = array(
'title' => t('books'),
'page callback' => 'your_call_back_method',
'access arguments' => array('books'),
'weight' => 0,
);
return $items;
}
function your_call_back_method() {
$pagecontent = ''; // your page layout.
return $pagecontent ;
}
Related
I'm creating a webform to build up a subscription form, on Drupal 7.65
Goal
What I need to do is: to select a role from a list, and automatically to display the associated name of that role, in a text field.
As I said, the name should be displayed into a not modifiable text field just below it.
Suppose valid, the following list (key => value)
Field: Department
business_manager|Business Manager
hr_consultant|Human Resources
training_developer|Training Developer
and from the time going on, the associated names, are respectively
Options can appear into text field hr_business_partner
Steve Abc
Gertrude Def
Sven Hgj Klm
Thus when the trainee selects "Human Resources", the name of "Gertrude Def" should appear into the text field below the select one.
I've attached a mokup to better understand what I do need.
IMPORTANT
I can't put the names into the list as value, because the association can change but old records should keep the previously registered associations
You can use hook_form_alter() and add a new select field with the paired key value list you need to the webform. And then use javascript to update which field value gets shown in the HR Business Partner field on change, which by the way would also need to be added via your hook_form_alter. You could use a taxonomy to maintain a list of Departments/Business partners which would populate your department and business partners.
Write some javascript to dynamically update your original fields not added through the form_alter, on change. I would suggest making two textfields in your webform components which will hold the value from your form alter added fields. So that these values selected by the user gets saved in your form.
function MODULENAME_form_alter(&$form, &$form_state, $form_id) {
if($form_id == "webform_client_form_####"){
$form['#attached']['js'] = array(drupal_get_path('module','MODULENAME') . '/js/webform.js');
$form['hr_dept'] = array(
"#type" => "select",
"#options" => array("business_manager"=>"Business Manager", "hr_consultant"=>"Human Resources"),
);
$partners = taxonomy_get_tree(#); //the VID of the taxonomy
$list = array("0"=>"None"); //first option
foreach($partners as $tid => $partner){
$list[$partner->tid] = $partner->name;
}
$form['hr_partner'] = array(
'#type' => 'select',
'#options' => $list,
);
}
}
In your javascript file, /js/webform.js you can include all your logic to check for which value is selected on the Department field and then display the correct value in the Partners fields. At the same time, updating the original fields you've added as textfields in the webform components UI.
I have two tables: Ingredients and Customers. The relationship between them is that Customers hasMany Ingredients. By default when doing the cakebake using the console, the only way to change them is by assigning an ingredient to the customer in the Ingredients page. However, I want to have in Customers page a checkbox list of Ingredients that can be assigned. Is it possible to do this? If yes, how?
edit:
What I have done until now is that I add this code to my add.ctp:
echo $this->Form->input('Ingredient',
array('label'=>'',
'type'=>'select',
'multiple'=>'checkbox',
'options'=>$ingredients));
However, it gives me "Undefined variable: ingredients" error when I tried to open the add view.
You want and need a HABTM relationship. Different customers can access and use the same ingredients. Look at the docs here yours would be very similar to different Posts using same Tags.
If you are getting this error:
"Undefined variable: ingredients"
It sounds like you haven't declared this variable in your controller, and set it so that the view can use it. Without knowing your code, you would probably need do do something like this (please note I am guessing what your application structure looks like and have not tested this code).
CustomersController.php
// The controller action for your view
public function view() {
// Get the ID and name of all your ingredients
$ingredients = $this->Ingredient->find('all', array(
'fields' => array('id', 'name'),
'order' => 'name',
'recursive' => -1
));
// We will use this array to store all the HTML select options
$ingredientOptions = array();
// Loop through all the ingredients and add them to the select
// options in a format that is suitable for CakePHP to use in
// the view to build your HTML select menu.
foreach ($ingredients as $i) {
$ingredient = $i['Ingredient'];
$ingredientOptions[$ingredient['id']] = $ingredient['name'];
}
// Make the variable available to the view
$this->set('ingredients', $ingredientOptions);
}
I'm writing an application that uses Zend Framework 2 and Doctrine (both the latest stable version).
There is much documenation (mainly tutorials and blog posts) that deal with saving doctrine entities to the database in combination with Zend Form. Unfortunately they only deal with simple entities that do not have one-to-many or many-to-many relationships.
This is one of those examples that i have adopted into my own code.
http://www.jasongrimes.org/2012/01/using-doctrine-2-in-zend-framework-2/
I understand that in the Album Entity of this example, the artist is a string to keep the (already lengthy) tutorial as simple as possible. But in a real world situation this would of course be a one-to-many releationship with an Artist Entity (or even a many-to-many). In the view, a select-box could be displayed where the artist can be selected, listing all the artist-entities that could be found in the database, so the right one can be selected.
Following the example with the album, this is how i've set up an 'edit' Action in my controller:
public function editAction()
{
// determine the id of the album we're editing
$id = $this->params()->fromRoute("id", false);
$request = $this->getRequest();
// load and set up form
$form = new AlbumForm();
$form->prepareElements();
$form->get("submit")->setAttribute("label", "Edit");
// retrieve album from the service layer
$album = $this->getSl()->get("Application\Service\AlbumService")->findOneByAlbumId($id);
$form->setBindOnValidate(false);
$form->bind($album);
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
// bind formvalues to entity and save it
$form->bindValues();
$this->getEm()->flush();
// redirect to album
return $this->redirect()->toRoute("index/album/view", array("id"=>$id));
}
}
$data = array(
"album" => $album,
"form" => $form
);
return new ViewModel($data);
}
How would this example need to be altered if the artist wasn't a string, but an Artist Entity?
And suppose the album also has multiple Track Entities, how would those be processed?
The example would not need to be changed at all, the changes will happen with your entity and your form.
This is a good reference: Doctrine Orm Mapping
So to save yourself a lot of extra work, your OnToMany relationship would use: cascade = persist:
/**
* #ORM\OneToMany(targetEntity="Artist" , mappedBy="album" , cascade={"persist"})
*/
private $artist;
When it comes to persisting the form object, the entity knows it must save the associated entity as well. If you did not include this, then you would have to do it manually using a collection.
To make like easier with your form, you can use Doctrines Object Select like this:
$this->add(
[
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'artist',
'options' => [
'object_manager' => $this->objectManager,
'target_class' => 'Artist\Entity\Artist',
'property' => 'name', //the name field in Artist, can be any field
'label' => 'Artist',
'instructions' => 'Artists connected to this album'
],
'attributes' => [
'class' => '', //Add any classes you want in your form here
'multiple' => true, //You can select more than one artist
'required' => 'required',
]
]
);
So now your form takes care of the collection for you, the controller as per your example does not need to change since the entity will take care of the persisting...
Hope this gets you on track.
In our website on base of Drupal 7 we need to make a gallery of images that would show, at first, the categories of the galleries on the Gallery Page (in our case, "Groups", "Events", "Internships" etc.) and then, all the albums of the specific category (e.g. all the galleries of category "Events"). I solved this according to this Russian tutorial http://sherskova.ru/drupal/galereya-na-drupal-7-svoimi-rukami-views-panels-colorbox, where Colorbox, Views, Ctools and Panels modules are required. At first, I created a vocabulary in Taxonomy with the needed terms (categories of the galleries), then I created a content type "Gallery" with the corresponding fields: "Album" of type "term reference" to the corresponding vocabulary, "Gallery Description" of "long text" and "Gallery Images" of "Image" that would open in Colorbox. Then, I created two views: the first one for the output of gallery cover of each category --> all on one page, and the second one -- for the output of all the galleries of a particular category on one page.
This solution works apart from one problem: we need the gallery page to be presented in English and German languages. The found solution works however only in one language, so the German (original) version of the gallery page is shown both in German and English versions of the site.
For the translation we found the solution with Filter Criteria - Content:language, but it does not work for View of type "Term", which we have, because there is no such filter criteria.
Does anyone know how to translate Views of type "Term"? Or are there other ways to create galleries with the listed functionality that could be translated?
Thanks in advance!
It might just be a quick fix but try this code:
Found on this blog: http://smartwolverine.net/article/drupal-7-taxonomy-language-filter-absent-views#comment-17
It will do the job of a filter: "current language" for the specified view.
<?php function mymodule_views_query_alter(&$view, &$query) {
if ($view->name == 'yourviewmachinename') {
$query->where[] = array(
'conditions' => array(array(
'field' => 'taxonomy_term_data.language',
'value' => array('***CURRENT_LANGUAGE***'),
'operator' => 'in',
)),
'args' => array(),
'type' => 'AND',
); } } ?>
It worked for me.
I am working on a book review application and I am using autoComplete to search for titles in when creating a review. The review model has an associated book_id field and the relationship is setup as the review hasOne book and a book hasMany reviews.
I am trying to pass the Book.id (into the book_id field), but I want to display Book.name for the user to select from. With the default setup (accomplished via CakePHP's tutorial), I can only pass Book.name. Is it possible to display the name and pass the id?
Also, I am passing it via the following code in the create() action of the review controller:
$this->data['Review']['book_id'] = $this->data['Book']['id'];
Is that the proper way to do it in CakePHP? I know in Ruby on Rails, it is automatic, but I can't seem to make it work automagically in CakePHP. Finally, I am not using the generator because it is not available in my shared hosting environment... so if this is the wrong way, what do I need other than associates in my models to make it happen automatically?
Thanks for the help and I promise this is my question for awhile...
UPDATE- I tried the following, but it is not working. Any ideas why?
function autoComplete() {
$this->set('books', $this->Book->find('all', array(
'conditions' => array(
'Book.name LIKE' => $this->data['Book']['name'].'%'
),
'fields' => array('id','name')
)));
$this->layout = 'ajax';
}
The problem is that when I use the code above in the controller, the form submits, but it doesn't save the record... No errors are also thrown, which is weird.
UPDATE2:
I have determine that the reason this isn't working is because the array types are different and you can't change the array type with the autoComplete helper. As a workaround, I tried the follow, but it isn't working. Can anyone offer guidance why?
function create() {
if($this->Review->create($this->data) && $this->Review->validates()) {
$this->data['Review']['user_id'] = $this->Session->read('Auth.User.id');
$this->Book->find('first', array('fields' => array('Book.id'), 'conditions' => array('Book.name' => $this->data['Book']['name'])));
$this->data['Review']['book_id'] = $this->Book->id;
$this->Review->save($this->data);
$this->redirect(array('action' => 'index'));
} else {
$errors = $this->Review->invalidFields();
}
}
FINAL UPDATE:
Ok, I found that the helper only takes the find(all) type or array and that the "id" field wasn't passing because it only applied to the autoComplete's LI list being generated. So, I used the observeField to obtain the information and then do a database lookup and tried to create a hidden field on the fly with the ID, but that didn't work. Finally, the observeField would only take the characters that I put in instead of what I clicked, due to an apparent Scriptaculous limitation. So, I ended up going to a dropdown box solution for now and may eventually look into something else. Thanks for all of the help anyway!
First of all, $this->data will only contain ['Book']['id'] if the field exists in the form (even if it's hidden).
To select something by name and return the id, use the list variant of the find method, viz:
$selectList = $this->Book->find('list', array(
'fields' => array(
'id',
'name'
)));
$this->set('selectList', $selectList);
In the view, you can now use $selectList for the options in the select element:
echo $form->input('Book.id', array('type' => 'hidden'));
echo $form->input('template_id', array(
'options' => $selectList,
'type' => 'select'
));