ZF2 - how to check if a route with child exists - zend-framework

Given this route:
'country' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/1country',
'defaults' => array(
'controller' => 'Index',
'action' => 'country',
'country_id' => '5',
),
),
'may_terminate' => true,
'child_routes' => array(
'city' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/1city',
'defaults' => array(
'controller' => 'Index',
'action' => 'city',
'city_id' => '4',
),
),
),
),
),
if I do:
$this->getServiceLocator()->get('Router')->hasRoute('country'); //true
$this->getServiceLocator()->get('Router')->hasRoute('country/city'); //false
While both should be true.. Any ideas?

Try this:
// explode if child..
$route = 'home/default';
$names = explode('/', $route, 2);
// use
/* #var Router $router */
$router = $container->get('Router');
if (!$router->hasRoute($names[0])) {
// ...
}

Related

routing after authentication doesn't work properly

I probably have an understanding issue how the routing works. I tried a bit with zend-authentication, you can see the controllercode below.
If the authentication is valide I want a routing to another controller index action. Should be quite simple, but the routing doesn't work I stay at the loginform. I added an echo just to see where I am after authentication and the authentication is valide. Here is the code:
$form = new LoginForm();
//return ['form' => $form];
$form->get('submit')->setValue('Login');
//echo "hier";
//$this->layout()->setTemplate('layout/login-layout');
$request = $this->getRequest();
if (! $request->isPost()) {
return ['form' => $form];
}
else {
$username=$request->getPost('accessname');
$password=$request->getPost('passwort');
//echo $password;
$adapter = $this->authService->getAdapter();
$adapter->setIdentity($request->getPost('accessname'));
$adapter->setCredential($request->getPost('passwort'));
$result = $this->authService->authenticate();
if ($result->isValid()){
echo "valide";
//return $this->redirect()->toRoute('import');
return $this->redirect()->toRoute('import', ['action' => 'index']);
}
else{
return ['form' => $form, 'messages' => $result->getMessages()];
}
}
as you can see I tried several possibilities. The other controller is placed in the same module.
Here additional the index action of the destinationcontroller.
I'm not finished there, because of the false routing I toggled everything else, so it just shows the echotext when I land there.
public function indexAction()
{
echo "importcontroller";
// $result = $this->authService->has
// $auth=Zend_Auth::getInstance();
// $adapter = $this->authService->getAdapter();
// if(!$this->authService->hasIdentity())
// {
// return $this->redirect()->toRoute('./index/index');
// }
// else {
// return new ViewModel([
// 'projects' => $this->projectTable->fetchAll(),
// ]);
// }
}
EDIT1: Add module.confg.php
'router' => [
'routes' => [
'import' => [
'type' => Segment::class,
'options' => [
'route' => '/import[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ImportController::class,
'action' => 'index',
],
],
],
'project' => [
'type' => Segment::class,
'options' => [
'route' => '/project[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ProjectController::class,
'action' => 'index',
],
],
],
'unit' => [
'type' => Segment::class,
'options' => [
'route' => '/unit[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UnitController::class,
'action' => 'index',
],
],
],
'index' => [
'type' => Segment::class,
'options' => [
'route' => '/index[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'user' => [
'type' => Segment::class,
'options' => [
'route' => '/user[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UserController::class,
'action' => 'index',
],
],
],
'followup' => [
'type' => Segment::class,
'options' => [
'route' => '/followup[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\FollowupController::class,
'action' => 'index',
],
],
],
Can you show contents of module.config.php with routing configuration?
Maybe your routing was wrong and redirect to the same page where you are before correct authentication?
P.s. I think, You should always filternig data from form and get it by $form->getDate() function. Of course before you should apply appropriate filters.
this concept is described in zend framework tutorial:
https://docs.zendframework.com/tutorials/getting-started/forms-and-actions/

edit action similar to tutorial doesn't work

I followed the ZF3 tutorial and I'm quite satisfied, but I'm something missing with the edit action in my controller. the add action works fine while the edit action doesn't. Probably I don't see it by myself, so I post it here, asking for help, even if it is really basic.
My model is nearly the same as in the tutorial, here a part of it:
public function exchangeArray(array $data)
{
$this->ProjectID= !empty($data['ProjectID']) ? $data['ProjectID'] : null;
$this->CI_Number= !empty($data['CI_Number']) ? $data['CI_Number'] : null;
$this->Description= !empty($data['Description']) ? $data['Description'] : null;
$this->Projectname= !empty($data['Projectname']) ? $data['Projectname'] : null;
$this->Shortcut= !empty($data['Shortcut']) ? $data['Shortcut'] : null;
$this->Component_Class= !empty($data['Component_Class']) ? $data['Component_Class'] : null;
}
public function getArrayCopy()
{
// echo var_dump(get_object_vars($this)
// );
//return get_object_vars($this);
return [
'ProjectID' => $this->ProjectID,
'CI_Number' => $this->CI_Number,
'Description' => $this->Description,
'Projectname' => $this->Projectname,
'Shortcut' => $this->Shortcut,
'Component_Class' => $this->Component_Class,
];
}
and here also my controlleraction:
public function editAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
echo $id;
if (0 === $id) {
return $this->redirect()->toRoute('project', ['action' => 'add']);
}
else {
try {
$project = $this->projectTable->getProject($id);
} catch (\Exception $e) {
return $this->redirect()->toRoute('project', ['action' => 'index']);
}
$form = new ProjectForm();
$form->bind($project);
//$form->bind($project->current());
$form->get('submit')->setAttribute('value', 'save changes');
$request = $this->getRequest();
$viewData = ['ProjectID' => $id, 'form' => $form];
if (! $request->isPost()) {
return $viewData;
}
$form->setInputFilter($project->getInputFilter());
$form->setData($request->getPost());
if (! $form->isValid()) {
echo "nicht valide";
return $viewData;
}
else{
echo $project;
$this->projectTable->saveProject($project);
}
}
// Redirect to album list
// return $this->redirect()->toRoute('project', ['action' => 'index']);
}
here for completion reasons my view edit.phtml:
<?php
$title = 'projects';
$this->headTitle($title);
?>
<h1><?= $this->escapeHtml($title) ?></h1>
<?php
// This provides a default CSS class and placeholder text for the artist element:
$ProjectID= $form->get('ProjectID');
$ProjectID->setAttribute('class', 'form-control');
$ProjectID->setAttribute('placeholder', 'ProjectID');
$Projectname= $form->get('Projectname');
$Projectname->setAttribute('class', 'form-control');
$Projectname->setAttribute('placeholder', 'Projectname');
$CI_Number= $form->get('CI_Number');
$CI_Number->setAttribute('class', 'form-control');
$CI_Number->setAttribute('placeholder', 'CI_number');
$Shortcut= $form->get('Shortcut');
$Shortcut->setAttribute('class', 'form-control');
$Shortcut->setAttribute('placeholder', 'Shortcut');
$Description= $form->get('Description');
$Description->setAttribute('class', 'form-control');
$Description->setAttribute('placeholder', 'Description');
$Component_Class= $form->get('Component_Class');
$Component_Class->setAttribute('class', 'form-control');
$Component_Class->setAttribute('placeholder', 'Component_Class');
// This provides CSS classes for the submit button:
$submit = $form->get('submit');
$submit->setAttribute('class', 'btn btn-primary');
//$form->setAttribute('action', $this->url('project', ['action' => 'edit',])); //,'id'=> $id
$form->setAttribute('action', $this->url('project', [
'action' => 'edit',
'ProjectID' => $id,
]));
$form->prepare();
echo $this->form()->openTag($form);
?>
<?php // Wrap the elements in divs marked as form groups, and render the
// label, element, and errors separately within ?>
<div class="form-group">
<?= $this->formElement($ProjectID) ?>
<?= $this->formElementErrors()->render($ProjectID, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($CI_Number) ?>
<?= $this->formElement($CI_Number) ?>
<?= $this->formElementErrors()->render($CI_Number, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($Description) ?>
<?= $this->formElement($Description) ?>
<?= $this->formElementErrors()->render($Description, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($Projectname) ?>
<?= $this->formElement($Projectname) ?>
<?= $this->formElementErrors()->render($Projectname, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($Shortcut) ?>
<?= $this->formElement($Shortcut) ?>
<?= $this->formElementErrors()->render($Shortcut, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($Component_Class) ?>
<?= $this->formElement($Component_Class) ?>
<?= $this->formElementErrors()->render($Component_Class, ['class' => 'help-block']) ?>
</div>
<?php
echo $this->formSubmit($submit);
//echo $this->form->get('DCLID');
echo $this->formHidden($form->get('ProjectID'));
echo $this->form()->closeTag();
It will show the recordset properly, but won't save the changes to the database and afterwards redirects to my add action. I hope somebody sees what I'm missing, even it might be a stupid error.
EDIT1: Here is my routing link from index.phtml
Edit
EDIT2: Screenshot to show the routing parameter
EDIT3: describing test issues
here again my controller edit action, to follow up:
public function editAction()
{
$id = (int) $this->params()->fromRoute('id', 0);
echo "variable id: ". $id;
if (0 === $id) {
//return $this->redirect()->toRoute('project', ['action' => 'index']);
echo "id = 0";
}
else {
try {
$project = $this->projectTable->getProject($id);
} catch (\Exception $e) {
return $this->redirect()->toRoute('project', ['action' => 'index']);
}
$form = new ProjectForm();
$form->bind($project);
//$form->bind($project->current());
$form->get('submit')->setAttribute('value', 'save changes');
var_dump(get_object_vars($project));
$request = $this->getRequest();
$viewData = ['ProjectID' => $id, 'form' => $form];
if (!$request->isPost()) {
return $viewData;
}
else {
$form->setInputFilter($project->getInputFilter());
$form->setData($request->getPost());
if (!$form->isValid()) {
echo "nicht valide";
return $viewData;
}
else{
echo "valide";
echo $project;
$this->projectTable->saveProject($project);
}
}
}
// Redirect to album list
// return $this->redirect()->toRoute('project', ['action' => 'index']);
}
I get the output of the vardump, so the project to edit will be delivered correctly. If I send the form with the recordchanges the controller won't catch it, the controller action sees id=0 then, so the method saveProject will be never called. In my understanding it might has to do with the formvalid something, because after sending the data I come never further than if (0 === $id).
EDIT 4: After some actual tests I think it must be a routing issue. If I give the route manually via browser, I won't get the target page at all. If I dump the value, it is always NULL. So I think it could be a bracket to much/to less issue in my module.config.php I show it here because I couldn't finde the problem, I countedt the braskets several times and I won't get it. So any help is appreciated, it must be a very simple topic:
<?php
namespace Import;
use Zend\Router\Http\Segment;
use Zend\Router\Http\Literal;
use Zend\ServiceManager\Factory\InvokableFactory;
//use Zend\ServiceManager\Factory\InvokableFactory;
return [
/* 'controllers' => [
'factories' => [
Controller\ImportController::class => InvokableFactory::class,
],
], */
// hier die Einstellungen für die Routen
'router' => [
'routes' => [
'index' => [
'type' => Segment::class,
'options' => [
'route' => '/import[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'import' => [
'type' => Segment::class,
'options' => [
'route' => '/import[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ImportController::class,
'action' => 'index',
],
],
],
'importdcl' => [
'type' => Segment::class,
'options' => [
'route' => '/importdcl[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ImportdclController::class,
'action' => 'index',
],
],
],
'project' => [
'type' => Segment::class,
'options' => [
'route' => '/project[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ProjectController::class,
'action' => 'index',
],
],
],
'unit' => [
'type' => Segment::class,
'options' => [
'route' => '/unit[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UnitController::class,
'action' => 'index',
],
],
],
'index' => [
'type' => Segment::class,
'options' => [
'route' => '/index[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'user' => [
'type' => Segment::class,
'options' => [
'route' => '/user[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\UserController::class,
'action' => 'index',
],
],
],
'followup' => [
'type' => Segment::class,
'options' => [
'route' => '/followup[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\FollowupController::class,
'action' => 'index',
],
],
],
],
],
'view_manager' => [
'template_path_stack' => [
'import' => __DIR__ . '/../view',
],
],
/* ... */
'navigation' => [
'default' => [
[
'label' => 'Dashboard',
'route' => 'home',
],
[
'label' => 'Project',
'route' => 'project',
'pages' => [
[
'label' => 'Add',
'route' => 'project',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'project',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'project',
'action' => 'delete',
],
],
],
[
'label' => 'Unit',
'route' => 'unit',
'pages' => [
[
'label' => 'Add',
'route' => 'unit',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'unit',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'unit',
'action' => 'delete',
],
],
],
[
'label' => 'Importlog',
'route' => 'importdcl',
'action' => 'index',
'pages' => [
[
'label' => 'Add',
'route' => 'unit',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'unit',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'unit',
'action' => 'delete',
],
],
],
[
'label' => 'Follow up',
'route' => 'followup',
'action' => 'index',
'pages' => [
[
'label' => 'Add',
'route' => 'unit',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'unit',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'unit',
'action' => 'delete',
],
],
],
[
'label' => 'User',
'route' => 'user',
'pages' => [
[
'label' => 'Add',
'route' => 'unit',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'unit',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'unit',
'action' => 'delete',
],
],
],
[
'label' => 'Logout',
'route' => 'user',
'action' => 'logout',
'pages' => [
[
'label' => 'Add',
'route' => 'unit',
'action' => 'add',
],
[
'label' => 'Edit',
'route' => 'unit',
'action' => 'edit',
],
[
'label' => 'Delete',
'route' => 'unit',
'action' => 'delete',
],
],
],
],
],
/* ... */
];
I'm testing in the usercontroller at the moment, but I have had the same problem in others routes, so I think the error might be in this file.
Based on your code, seem the problem is on $id. It mean the value is 0, that's why it is redirected to project/add.
$id = (int) $this->params()->fromRoute('id', 0);
echo $id;
if (0 === $id) {
return $this->redirect()->toRoute('project', ['action' => 'add']);
}
In your view script, the form action is set to project/edit/ProjectID/$id
$form->setAttribute('action', $this->url('project', [
'action' => 'edit',
'ProjectID' => $id,
]));
That's why your controller cannot retrieve $this->params()->fromRoute('id', 0), because the form send ProjectID param instead of id.
So, the solution please adjust your form (using id) or your controller (using ProjectID).
I at last solved it. My suggestion was right, it was a problem with the module.config.php, I have set an endbracket at the wrong place.
After writing it in parts new, tsting and complete the file, it now works.

Extbase: configure controller and action in realURL for detail

I'm going nuts with realURL and extbase.
Is there a simple solution for a list/detail extension to display URLs that are at least orderly, maybe in the form of
/show/detail/title-of-the-item
"show" and "detail" being action and controller, e.g.
I've been trying to remove controller and action, for example as suggested in RealURL: Remove Controller and Action from URL - but there's always something not working. Crazy.
It's not even removing the cHash.
My realurl_conf at the moment is:
<?php
$TYPO3_CONF_VARS['EXTCONF'] ['realurl'] ['_DEFAULT'] = getRealURL('1');
function getRealURL($root)
{
return array(
'init' => array(
'appendMissingSlash' => 'ifNotFile',
'enableUrlDecodeCache' => 1,
'enableCHashCache' => 1,
'enableUrlEncodeCache' => 1,
'respectSimulateStaticURLs' => 0,
'postVarSet_failureMode'=>'redirect_goodUpperDir',
),
'redirects_regex' => array (
),
'preVars' => array(
array(
'GETvar' => 'L',
'valueMap' => array(
'de' => '0',
'fr' => '1',
),
'valueDefault' => 'de',
'noMatch' => 'bypass',
),
array(
'GETvar' => 'no_cache',
'valueMap' => array(
'no_cache' => 1,
),
'noMatch' => 'bypass',
),
),
'pagePath' => array(
'type' => 'user',
'userFunc' => 'EXT:realurl/class.tx_realurl_advanced.php:&tx_realurl_advanced->main',
'spaceCharacter' => '-',
'languageGetVar' => 'L',
'expireDays' => 7,
'rootpage_id' => 1,
),
'postVarSets' => array(
'_DEFAULT' => array(
'wb' => array(
array(
'GETvar' => 'tx_weiterbildung_pi1[item]' ,
'lookUpTable' => array(
'table' => 'tx_weiterbildung_domain_model_item',
'id_field' => 'uid',
'alias_field' => 'kurs_titel',
'addWhereClause' => ' AND NOT deleted',
'useUniqueCache' => 1,
'useUniqueCache_conf' => array(
'strtolower' => 1,
'spaceCharacter' => '-',
),
),
),
),
),
),
'fileName' => array(
'defaultToHTMLsuffixOnPrev'=>0,
'index' => array(
'rss.xml' => array(
'keyValues' => array(
'type' => 100,
),
),
'rss091.xml' => array(
'keyValues' => array(
'type' => 101,
),
),
'rdf.xml' => array(
'keyValues' => array(
'type' => 102,
),
),
'atom.xml' => array(
'keyValues' => array(
'type' => 103,
),
),
),
),
);
}
/**********************************
REALURL end
***********************************/
?>
Not quite simple, but at least working...
In EVERY of my ext I DO NOT use f:link.action VH, instead f:link.page so you can genearte links like
?id=123&tx_yourext_foo=bar
Without controller and action params, of course as you can see most probably you'll need to modify your FE plugins, to read these params with GeneralUtility::_GP('tx_yourext_foo'), especially if this plugin uses more than on mode (action) depending on params

TYPO3 object storage is empty

i wanna ad a relation from one model to a nother.
/**
* #var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
* #inject
*/
protected $objectManager;
/**
* action create
*
* #param \ReRe\Rere\Domain\Model\Modul $newModul
* #return void
*/
public function createAction(\ReRe\Rere\Domain\Model\Modul $newModul) {
$this->addFlashMessage('The object was created. Please be aware that this action is publicly accessible unless you implement an access check. See Wiki', '', \TYPO3\CMS\Core\Messaging\AbstractMessage::ERROR);
$this->modulRepository->add($newModul);
// Erzeugt ein Leeres Fach
$fachHelper = new \ReRe\Rere\Domain\Model\Fach();
$fach = $this->objectManager->create('\ReRe\Rere\Domain\Model\Fach');
// Fach Werte setzen
$fach->setFachname($this->request->getArgument('fachname'));
$fach->setFachnr($this->request->getArgument('fachnummer'));
$fach->setPruefer($this->request->getArgument('pruefer'));
$fach->setNotenschema($this->request->getArgument('notenschema'));
// Fach einem Modul zuordnen
$fach->setModulnr($newModul->getModulnr());
//$request = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance("\ReRe\Rere\Domain\Model\Fach");
//\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($newModul);
// Fach speichern
$this->fachRepository->add($fach);
$newModul->addFach($fach);
$this->redirect('list');
}
in database in modul the relationcounter will increased ...
DB looks like this:
but if I want to render the view like this:
<f:for each="{moduls}" as="modul">
{modul.modulname}
<f:for each="{modul.fach}" as="fach">
{fach.fachname}
no fach objects were printed ..
if I do <f:debug> of modul i got this:
Here The TCA-Configs:
Modul:
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
$GLOBALS['TCA']['tx_rere_domain_model_modul'] = array(
'ctrl' => $GLOBALS['TCA']['tx_rere_domain_model_modul']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, modulnr, modulname, gueltigkeitszeitraum, fach',
),
'types' => array(
'1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, hidden;;1, modulnr, modulname, gueltigkeitszeitraum, fach, --div--;LLL:EXT:cms/locallang_ttc.xlf:tabs.access, starttime, endtime'),
),
'palettes' => array(
'1' => array('showitem' => ''),
),
'columns' => array(
'sys_language_uid' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
'config' => array(
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
),
),
),
'l10n_parent' => array(
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),
),
'foreign_table' => 'tx_rere_domain_model_modul',
'foreign_table_where' => 'AND tx_rere_domain_model_modul.pid=###CURRENT_PID### AND tx_rere_domain_model_modul.sys_language_uid IN (-1,0)',
),
),
'l10n_diffsource' => array(
'config' => array(
'type' => 'passthrough',
),
),
't3ver_label' => array(
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
'config' => array(
'type' => 'input',
'size' => 30,
'max' => 255,
)
),
'hidden' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.hidden',
'config' => array(
'type' => 'check',
),
),
'starttime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.starttime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'endtime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.endtime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'modulnr' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_modul.modulnr',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim'
),
),
'modulname' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_modul.modulname',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim,required'
),
),
'gueltigkeitszeitraum' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_modul.gueltigkeitszeitraum',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim'
),
),
'fach' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_modul.fach',
'config' => array(
'type' => 'inline',
'foreign_table' => 'tx_rere_domain_model_fach',
'foreign_field' => 'modulnr',
'maxitems' => 9999,
'appearance' => array(
'collapseAll' => 0,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showAllLocalizationLink' => 1
),
),
),
),
);
And TCA Fach
<?php
if (!defined ('TYPO3_MODE')) {
die ('Access denied.');
}
$GLOBALS['TCA']['tx_rere_domain_model_fach'] = array(
'ctrl' => $GLOBALS['TCA']['tx_rere_domain_model_fach']['ctrl'],
'interface' => array(
'showRecordFieldList' => 'sys_language_uid, l10n_parent, l10n_diffsource, hidden, fachnr, fachname, pruefer, notenschema, modulnr, matrikelnr',
),
'types' => array(
'1' => array('showitem' => 'sys_language_uid;;;;1-1-1, l10n_parent, l10n_diffsource, hidden;;1, fachnr, fachname, pruefer, notenschema, modulnr, matrikelnr, --div--;LLL:EXT:cms/locallang_ttc.xlf:tabs.access, starttime, endtime'),
),
'palettes' => array(
'1' => array('showitem' => ''),
),
'columns' => array(
'sys_language_uid' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.language',
'config' => array(
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xlf:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xlf:LGL.default_value', 0)
),
),
),
'l10n_parent' => array(
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.l18n_parent',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),
),
'foreign_table' => 'tx_rere_domain_model_fach',
'foreign_table_where' => 'AND tx_rere_domain_model_fach.pid=###CURRENT_PID### AND tx_rere_domain_model_fach.sys_language_uid IN (-1,0)',
),
),
'l10n_diffsource' => array(
'config' => array(
'type' => 'passthrough',
),
),
't3ver_label' => array(
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.versionLabel',
'config' => array(
'type' => 'input',
'size' => 30,
'max' => 255,
)
),
'hidden' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.hidden',
'config' => array(
'type' => 'check',
),
),
'starttime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.starttime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'endtime' => array(
'exclude' => 1,
'l10n_mode' => 'mergeIfNotBlank',
'label' => 'LLL:EXT:lang/locallang_general.xlf:LGL.endtime',
'config' => array(
'type' => 'input',
'size' => 13,
'max' => 20,
'eval' => 'datetime',
'checkbox' => 0,
'default' => 0,
'range' => array(
'lower' => mktime(0, 0, 0, date('m'), date('d'), date('Y'))
),
),
),
'fachnr' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.fachnr',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim'
),
),
'fachname' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.fachname',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim,required'
),
),
'pruefer' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.pruefer',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim'
),
),
'notenschema' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.notenschema',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim,required'
),
),
'modulnr' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.modulnr',
'config' => array(
'type' => 'input',
'size' => 30,
'eval' => 'trim,required'
),
),
'matrikelnr' => array(
'exclude' => 1,
'label' => 'LLL:EXT:rere/Resources/Private/Language/locallang_db.xlf:tx_rere_domain_model_fach.matrikelnr',
'config' => array(
'type' => 'select',
'foreign_table' => 'tx_rere_domain_model_pruefling',
'MM' => 'tx_rere_fach_pruefling_mm',
'size' => 10,
'autoSizeMax' => 30,
'maxitems' => 9999,
'multiple' => 0,
'wizards' => array(
'_PADDING' => 1,
'_VERTICAL' => 1,
'edit' => array(
'type' => 'popup',
'title' => 'Edit',
'script' => 'wizard_edit.php',
'icon' => 'edit2.gif',
'popup_onlyOpenIfSelected' => 1,
'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
),
'add' => Array(
'type' => 'script',
'title' => 'Create new',
'icon' => 'add.gif',
'params' => array(
'table' => 'tx_rere_domain_model_pruefling',
'pid' => '###CURRENT_PID###',
'setValue' => 'prepend'
),
'script' => 'wizard_add.php',
),
),
),
),
'modul' => array(
'config' => array(
'type' => 'passthrough',
),
),
'note' => array(
'config' => array(
'type' => 'passthrough',
),
),
),
);
The model class looks ok and all annotations seem to be correct.
Could you please post your TCA configuration for both Modul and Fach (the relation entry for both should be enough).
Quick question, are you able to see the relations between the two objects in the backend and if so, can you see it from both sides?
Go to the BE and check with the list tool if you can see related "Fach" objects in a "Modul" object and vise versa.
Maybe the TCA relation is no set up correctly and you can only access the relation from one side.
From which side have you created the relations (Modul->Fach or Fach->Modul)?
Of course it should be working either way.
UPDATE 1
Does the column "modulnr" in your table "tx_rere_domain_model_fach" contain the correct Modul-UIDs?
-> To speed the process up, could you send me a download link to your extension? I would then install it on a test system and we will quickly find out what is wrong.
UPDATE 2
I found what is going wrong in your extension. After creating a new Modul and Fach the class \ReRe\Rere\Controller\ModulController handles the form data. In line 116
$fach->setModulnr($newModul->getModulnr());
the value for the reference, which should be the UID of the Modul is set to the Modulnr. As the reference to the foreign table is configured to be the UID, the UID of the Modul needs to be set here. Change the line to the following and it works:
$fach->setModulnr($newModul->getUid());
You will have to change this in every controller action that creates a new Fach-Modul relation. So this is only an example of what you need to do.
Sidenote
As an additional tip, you might want to take a look into the best practises on how to handle form data in Extbase.
Calls like this
$fach->setFachnr($this->request->getArgument('fachnummer'));
will work but open up a world of pain when it comes to injections, as there is no validation etc.
A very easy and quick way to set up basic validation and also make your code much more readable is to use annotations and parameters in your controller action. So instead of getting the arguments yourself, let the framework to the work for you:
/**
* action create
*
* #param \ReRe\Rere\Domain\Model\Modul $newModul
* #param string $fachname
* #param int $fachnummer
*/
public function createAction(\ReRe\Rere\Domain\Model\Modul $newModul, $fachname, $fachnummer) {
...
If you want to make a parameter optional, just give it a value in the method call:
public function createAction(\ReRe\Rere\Domain\Model\Modul $newModul, $fachname = "foo", $fachnummer="bar") {
...
As I said, this is just a tip, you might want to consider :)
Please check if the ObjectStorage is related to the correct class in your model. Sometimes the extensionbuilder does set up the ObjectStorage but messes up the annotation.
Check if the annotation for "fach" in your ReRe\Rere\Domain\Model\Modul class contains the referenced class. It should look like this:
#var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\ReRe\Rere\Domain\Model\Fach>
If assume your looks just like this, which is wrong and leads to an empty ObjectStorage in the FE:
#var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<>
See how the class the ObjectStorage contains is missing.

zf2 form collection don't show element description

When the collection element is rendered , description element does not appear.
ZF2 seems to ignore the description option in the form collection.
Form
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'value',
'options' => array(
'label' => 'Please choose value',
'count' => 1,
'should_create_template' => true,
'target_element' => new ValueFieldset($objectManager)
)
));
Form Fieldset: ValueFieldset
$this->add(array(
'name' => 'name',
'type' => 'Zend\Form\Element\Text',
'options' => array(
'label' => 'Values',
'label_attributes' => array(
'class' => 'form-label'
),
'description' => 'X',
'multiple' => true,
),
)
);
View
echo $this->formCollection($values);