I made a form in which I have titlte, image, pdf, content and category and all are working fine, but I want to add submenu in my form and also want to make this dynamic so can show all sub-menu on my website.
You must have to intruduce a key parent_id with categories table.
And in category model do create the relation like this.
class Category extends Model
{
public $fillable = ['title','parent_id'];
/**
* Get the index name for the model.
*
* #return string
*/
public function childs() {
return $this->hasMany('App\Category','parent_id','id') ;
}
}
Here you can find the complete example..https://itsolutionstuff.com/post/laravel-5-category-treeview-hierarchical-structure-example-with-demoexample.html
Hopefully this could help you.
I am using the extension News System, "news", and while changing the templates, I've noticed that while I can use things like {newsItem.datetime} or {newsItem.uid}, I cant use this with the custom fields i have created when extending the table tx_news_domain_model_news, like {newsItem.mycustomfield}
Edit: I have been pointed to this url and I've followed the instructions, but it's not working. This is my code
News.php
<?php
class Tx_WedoExtendnews_Domain_Model_News extends Tx_News_Domain_Model_News {
/**
* #var string
*/
protected $txWedoextendnewsLocation;
public function getTxWedoextendnewsLocation() {
return "this";
return $this->txWedoextendnewsLocation;
}
public function getWedoextendnewsLocation() {
return "that";
return $this->txWedoextendnewsLocation;
}
}
?>
Since I wasn't getting anything, I changed the returning values to string literals, to see if the problem was in the class and method names, or the property. Im still not getting anything. I think the underscored might be playing tricks on my code.
My extension key is wedo_extendnews and the new field is tx_wedoextendnews_location. Any ideas where the error lies?
Yes. To be able to access an object in fluid, you need the according setters in your model and maybe (not sure right now) an entry in the TCA.
If you want to access {newsItem.mycustomfield} you need an according setter in the model, like public function getMycustomfield() (note the get in get<Myfuncname>, it is mandatory).
I need to validate some fields based on values other fields have, within the same model. Since a custom validator only has access to the value it is validating, I can't check other validations there. From inspecting AbstractValidator, I couldn't find a possibility to reach that object the current value is validated.
Is there a solution to validate/add errors in a controller, set errors and render the actual view by keeping the original routine instead of introducing and assigning new objects to the view? Basically I could create a custom $errors var, fill it with errors after having done custom validations and the display it along with the original form errors. But I don't like that workaround approach.
When you add a new model validator, you have access to the other fields of that model
File: test_extension/Classes/Domain/Validator/TestModelValidator.php:
class Tx_TestExtension_Domain_Validator_TestModelValidator extends Tx_Extbase_Validation_Validator_AbstractValidator {
/**
* #param Tx_TestExtension_Domain_Model_TestModel $testModel
* #return boolean
*/
public function isValid($testModel) {
/** #var $testModel Tx_TestExtension_Domain_Model_TestModel */
//Access all properties from $testModel
$field1 = $testModel->getMyField1();
$field2 = $testModel->getMyField2();
}
}
You can also add errors to speific fields, but this code is from TYPO3 4.5, don't know if its still valid:
$error = t3lib_div::makeInstance('Tx_Extbase_Validation_Error', 'The entered value is allready in use.', 1329936079);
$this->errors['field2'] = t3lib_div::makeInstance('Tx_Extbase_Validation_PropertyError', 'field2');
$this->errors['field2']->addErrors(array($error));
I've built a new content element type, and when you look in the backend, inside the box you can see the name of the module only. I'd like to change what information is show inside.
I could use the "header" field, but is there any way to use another field(s)?
Two answers
First answer
The field that's displayed there is the same field that's displayed in the list module. It is set in the table's TCA using ['ctrl']['label'] in the extension's ext_tables.php
$TCA['tx_myext_mytable'] = array(
'ctrl' => array(
'title' => 'My Table'
'label' => 'name_of_the_field_to_display_as_header'
// end snip
Second answer
If that is not enough for you, you can use a hook to display arbitrary HTML in the preview. The hook is called $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'].
The hook will be called with a function with this signature:
public function preProcess(
tx_cms_layout &$parentObject, // parent object
&$drawItem, // i have no idea what this is
&$headerContent, /* the content of the header
(the grey bar in the screenshot i think) */
&$itemContent, /* the content of the preview
(the white area in your screenshot */
array &$row // the content element's record
)
So all you have to do in that function is set the itemContent and, if you want, headerContent to whatever you want displayed.
Gotchas:
The output is inside of a span, so no block elements allowed in the
html. Any styling has to be done inline in the style attribute.
The function will be called on every content element, so you have to
check the row's CType and (if applicable) list_type fields so
that you only manipulate your own content elements.
An example can be found in the "fed" extension. I hope this helps.
Just a little update to adhominem answear #2 which is correct.
Today in TYPO3 6.2 and above your hook class has to inherit the interface TYPO3\CMS\Backend\View\PageLayoutViewDrawItemHookInterface
It´s looks like belove
<?php
namespace TYPO3\CMS\Backend\View;
/**
* Interface for classes which hook into PageLayoutView and do additional
* tt_content_drawItem processing.
*
* #author Oliver Hader <oliver#typo3.org>
*/
interface PageLayoutViewDrawItemHookInterface {
/**
* Preprocesses the preview rendering of a content element.
*
* #param \TYPO3\CMS\Backend\View\PageLayoutView $parentObject Calling parent object
* #param boolean $drawItem Whether to draw the item using the default functionalities
* #param string $headerContent Header content
* #param string $itemContent Item content
* #param array $row Record row of tt_content
* #return void
*/
public function preProcess(\TYPO3\CMS\Backend\View\PageLayoutView &$parentObject, &$drawItem, &$headerContent, &$itemContent, array &$row);
}
&$drawItem is boolean and send as reference and by changing it to $drawItem = false; will stop the default rendering of the preview.
I have just started with Zend Framework, so I have lots of questions about the structure.
I hope I can explain it properly, it's rather difficult.
Ok, I have done the Quickstart Tutorial and decided to use a similar structure for my first project.
So I have a Datamapper, a Model and the Database Table File.
I have created a Form where I can enter a some Information(Item) and upload Images with it.
I have 2 Datamapper (Item and Image) as well as 2 Models for them. I have an Item Controller, that one jumps into the ItemMapper. In the Datamapper I have a save Method. Please see below:
public function save(Application_Model_Item $item)
{
$data = array(
'item_title' => $item->getItemTitle(),
'item_description' => $item->getItemDescription(),
);
$this->getDbTable()->insert($data);
// Add Image Information ($imageData is Session Data)
$table = new Application_Model_DbTable_Image();
foreach ($imageData as $fileData)
{
$image = new Application_Model_Image($fileData);
$data = array(
'image_newname' => $image->getNewImageName(),
'image_thumbname' => $image->getImageThumbName(),
);
$table->insert($data);
}
Now the question I have.
I have Getter and Setter in my Model. Should everything what is in the Item Database Table be in 1 Model? Means everything about the Image should go to the Image Model since it is in a different Database Table?
Is it correct that I save the Information about the Image in the Item Mapper? Shoudl I not have a save() Method in the ImageMapper and save it in there? If so, how do I jump from the Item Mapper to the Image Mapper? Or would I first finish everything about the Item, return the ID to the Controller and than call the ImageMapper from the Controller?
I read something about "Fat Model Thin Controller". I had this all the time in my had, but I noticed that my Controller got pretty fat with just putting the Form together. I have about 5 Dropdown Fields which are depending Dropdowns. When I saw that I duplicating Code I decided to add this in a separate Function. So f.e. I have a Dropdown for counties. I wrote a Function which is also in my Controller so it looks like this:
public function getCounties ()
{
// List of Counties does not exist in Cache, read from DB
if(!$CountyList = $this->getFromCache('counties')){
$geolocationMapper = new Application_Model_GeolocationMapper();
$CountyDropdown = $geolocationMapper->createCountyDropdown();
// Save DB Result in Cache
$this->addToCache ('counties',$CountyDropdown);
return $CountyDropdown;
}
else{
// Return Country List from Cache
return $this->getFromCache('counties');
}
}
In my Add Function I use
// Assign Geo Info to Form
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList);
The Edit Function than
$CountyList = $this->getCounties();
$form->getElement('county')->setMultiOptions($CountyList)->setValue($activeCounty)
all the Functions like getCounties () stay in the Controller or should it be moved to the GeolocationMapper? And if so, how would that be called up?
Should the Form be created in some Function so I would only call up something like createForm() ? I really have a lot of duplication (Add and Edit Function) and than Stuff comes from Database or Form was not Valid and it comes from Cache with a setValue. It just adds up when using dependable Dropdowns.
I know this are lots of questions, but I have the feeling it gets very messy, as a learner you are happy when it works, but I would also like to structure it in a proper way. I hope it all makes sense.
Maybe some of you have a few Tipps I could use. Thanks a lot for your help in advance.
There are quite a few questions here and most of the answers will be down largely to personal preference. With that caveat out of the way:
Should everything what is in the Item Database Table be in 1 Model?
I would say yes, although in general, try and think about it from the perspective of the models rather than the database structure. So all of the 'item' data goes in the Item model - the fact that this is all stored in one database table is irrelevant, since the mapper handles the translation from one to the other.
Is it correct that I save the Information about the Image in the Item Mapper?
It's not clear where $imageData comes from in your example, but I'd say the Item mapper should call the Image mapper if there is image data to save, e.g.:
public function save(Application_Model_Item $item)
{
$data = array(
'item_title' => $item->getItemTitle(),
'item_description' => $item->getItemDescription(),
);
$this->getDbTable()->insert($data);
// save image data if present
if (isset($item->image)) {
$imageMapper = new Yourapp_Mapper_Image();
$imageMapper->save($item->image);
}
return true;
}
[Should] all the Functions like getCounties () stay in the Controller or should it be moved to the GeolocationMapper? And if so, how would that be called up?
I don't see any reason for these functions to be in the controller. Depending on how comfortable you are with the Zend_Form component, one approach might be to write a custom Yourapp_Form_Element_Counties class that extends Zend_Form_Element_Select. You then move your logic from the getCounties function into the this class, so the form element itself is responsible for populating the options it presents. E.g.:
class Yourapp_Form_Element_Counties extends Zend_Form_Element_Select
{
public function getMultiOptions()
{
// load counties here and return an array in the format key -> value
}
}
Another approach, if you have a lot of location-related form elements, might be to create a GeoLocation Service class, which has a function for counties, cities etc. that returns the options.
Should the Form be created in some Function so I would only call up something like createForm()
It's not clear how much form stuff you are doing in the controller already apart from populating select options, so it's hard to answer this one. Here are the principles I generally follow when using Zend_Form:
Each form has its own class, extending Zend_Form (or Zend_Dojo_Form), which exists in application/forms and is named Myapp_Form_*
Each form class sets up its elements in the init() method (which is called automatically by Zend_Form's constructor for exactly this purpose).
If I find I need slight variations to the same form in different actions (e.g. in an add and edit action), I create an abstract base class for the form (e.g. Myapp_Form_Post_Base) which defines the elements, and then action-specific classes which extend it: Myapp_Form_Post_Add, Myapp_Form_Post_Edit and so on. These classes make any changes they need to the base form in their own init() method.
My actions then look something like this:
public function editAction()
{
$form = new Myapp_Form_Post_Edit();
if ($this->_request->isPost()) {
if ($form->isValid($this->_request->getPost()) {
// save data, set flash messge and redirect
}
}
$this->view->form = $form;
}
My only other piece of advice is to try and follow the approach which seems most logical to you. You might find it difficult to find definitive 'best practices' for a lot of this stuff since there are many different ways to do it all.
I have tried to follow your ideas as much as possible, so all the calls for the Counties, Towns and Postcodes are in the GeolocationMapper and the saving of the Image Data is in the ImageMapper.
You asked of how I create my Form right now, here an example from my init() of the Form for the Counties etc...
// Create Dropdown for Counties
$county = new Zend_Form_Element_Select('county');
$county->setLabel('Select a County')
->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description',
array('tag' => 'p', 'class'=>'description')),
'Label',
array('HtmlTag',
array('tag'=>'li','class'=>'county'))
))
->setRequired(false);
// Create Dropdown for Town
$town = new Zend_Form_Element_Select('town');
$town->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
'Label',
array('HtmlTag',array('tag'=>'li','class'=>'town'))
));
// Create Dropdown for Postcode
$postcode = new Zend_Form_Element_Select('postcode');
$postcode->setRegisterInArrayValidator(false)
->setDecorators(array(
'ViewHelper',
'Errors',
array('Description', array('tag' => 'p', 'class' => 'description')),
'Label',
array('HtmlTag',array('tag'=>'li','class'=>'postcode'))
))
->setRegisterInArrayValidator(false);
In my Controller I than get the Elements and fill them:
$geolocationMapper = new Application_Model_GeolocationMapper();
$CountyOptions = $geolocationMapper->createCountyDropdown();
$form->getElement('county')->setMultiOptions($CountyOptions);
In my GeolocationMapper I have the Methods to build my Array of Counties:
/** ===========================================================================
* Get Counties
* #param
* #return Object? of Counties
* ========================================================================= */
public function getCountyList()
{
$table = $this->getDbTable();
$select = $table->select()->distinct()
->from(array('p' => 'geolocation'),'county')
->order('county');
$resultSet = $this->getDbTable()->fetchAll($select);
$entries = array();
foreach ($resultSet as $row)
{
$entry = new Application_Model_Geolocation();
$entry->setId($row->county)
->setCounty($row->county);
$entries[] = $entry;
}
return $entries;
}
/** ===========================================================================
* Create Array which will be used for Dropdown
* #param
* #return Array of Counties
* ========================================================================= */
public function createCountyDropdown()
{
// List of Counties does not exist in Cache, read from DB
if(!$CountyList = $this->getFromCache('counties'))
{
$CountyList = $this->getCountyList();
$Counties[''] = "Please choose";
foreach($CountyList as $value)
{
$Counties[str_replace(' ','_',$value->getCounty())] = $value->getCounty();
}
$CountyDropdown = $Counties;
// Save DB Result in Cache
$this->addToCache ('counties',$CountyDropdown);
return $CountyDropdown;
}else{
return $this->getFromCache('counties');
}
}
The Counties I read in my GeolocationMapper. The Towns and Postcodes get read when you choose a County, which than calls via Ajax the Geolocation Mapper and than createTownDropdown($county) and when a Town is choosen the same procedure but an Ajax call for loadPostcodes() and there createPostcodeDropdown($town).
Does this all sounds correct or any suggestions how I could improve this?
I am sorry but I would really like to add another question since I can't find an answer anywhere... I also have an Image Upload which works via Ajax and jQuery. When you choose an Image to upload, the Image gets straight displayed. For this I create dynamically an input Element with an image src. I have not found ny other way to add Images otherwise to Zend Form. Is there a possibility to add an Image to display the image as a normal ? It would be just a lot easier to have a img, since I would like to use jQuery Drag and Drop. Thanks so much for your help so far !!!