trying to make a form collection Warning: Invalid argument supplied for foreach() - forms

I am making a form collection with the fos user register form. I overrided my register form and added the profile collection, its persisting the data in the database but whenever I load the page it shows this error more then 10 times.
Warning: Invalid argument supplied for foreach() in C:\xampp\htdocs\symfony-bootstrap\vendor\symfony\symfony\src\Symfony\Component\Validator\Mapping\Loader\AnnotationLoader.php on line 65
if i complete the form and send it, it does persist, but the view is a mess showing this error 10 times and i havent seen anyone with this error.
this is my registerformtype.
namespace sava\UserBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class RegistroType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('perfil','sava_userbundle_tblperfil');
}
public function getParent()
{
return 'fos_user_registration';
}
public function getName()
{
return 'sava_user_registration';
}
}
this is how my webpage looks http://prntscr.com/5zess0.
validator code
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien#symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Validator\Mapping\Loader;
use Doctrine\Common\Annotations\Reader;
use Symfony\Component\Validator\Exception\MappingException;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\GroupSequence;
use Symfony\Component\Validator\Constraints\GroupSequenceProvider;
use Symfony\Component\Validator\Constraint;
class AnnotationLoader implements LoaderInterface
{
protected $reader;
public function __construct(Reader $reader)
{
$this->reader = $reader;
}
/**
* {#inheritdoc}
*/
public function loadClassMetadata(ClassMetadata $metadata)
{
$reflClass = $metadata->getReflectionClass();
$className = $reflClass->name;
$loaded = false;
foreach ($this->reader->getClassAnnotations($reflClass) as $constraint) {
if ($constraint instanceof GroupSequence) {
$metadata->setGroupSequence($constraint->groups);
} elseif ($constraint instanceof GroupSequenceProvider) {
$metadata->setGroupSequenceProvider(true);
} elseif ($constraint instanceof Constraint) {
$metadata->addConstraint($constraint);
}
$loaded = true;
}
foreach ($reflClass->getProperties() as $property) {
if ($property->getDeclaringClass()->name == $className) {
foreach ($this->reader->getPropertyAnnotations($property) as $constraint) {
if ($constraint instanceof Constraint) {
$metadata->addPropertyConstraint($property->name, $constraint);
}
$loaded = true;
}
}
}
foreach ($reflClass->getMethods() as $method) {
if ($method->getDeclaringClass()->name == $className) {
foreach ($this->reader->getMethodAnnotations($method) as $constraint) {
if ($constraint instanceof Constraint) {
if (preg_match('/^(get|is)(.+)$/i', $method->name, $matches)) {
$metadata->addGetterConstraint(lcfirst($matches[2]), $constraint);
} else {
throw new MappingException(sprintf('The constraint on "%s::%s" cannot be added. Constraints can only be added on methods beginning with "get" or "is".', $className, $method->name));
}
}
$loaded = true;
}
}
}
return $loaded;
}
}

if line 65 == foreach ($this->reader->getMethodAnnotations($method) as $constraint) ...
chceck $this->reader->getMethodAnnotations($method)
example
print_r('===><pre>');
print_r($this->reader->getMethodAnnotations($method));
print_r('</pre>');
I think, $this->reader->getMethodAnnotations($method) is not array

In symfony 5
run composer require doctrine/annotations it will fix the issue

Related

ContentEntityForm buildForm method parent out of memory

I have the following issue with my form class that extends the ContentEntityForm class.
When calling the parent buildForm which is needed my system runs out of memory.
/**
* {#inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
// Here is already runs of memory. $form is never initiated.
/* #var $entity \Drupal\sg_configuration_rule\Entity\ConfigurationRule */
$entity = $this->entity;
$form_state->set('old_cron_value', $entity->get('cron_settings')->first()->value);
$type = FALSE;
if (!$entity->isNew()) {
$type = $entity->getPluginInstance()->getPluginId();
}
if ($entity->isNew()) {
$type = \Drupal::request()->query->get('type');
if (!$type) {
return new RedirectResponse(Url::fromRoute('configuration_rule.add_form_step1')->toString());
}
}
if ($type) {
try {
/** #var \Drupal\sg_base_api\Plugin\BaseApiPluginInterface $enabled_api */
$enabled_api = $this->baseApiPluginManager->createInstance($type);
}
catch (PluginException $exception) {
LoggerService::error($exception->getMessage());
return new RedirectResponse(Url::fromRoute('configuration_rule.add_form_step1')->toString());
}
$enabled_api->configRuleForm($form, $entity);
$form['plugin_type']['widget'][0]['value']['#value'] = $type;
$form['plugin_type']['widget'][0]['value']['#access'] = FALSE;
$form['plugin_type']['widget'][0]['value']['#disabled'] = TRUE;
$form['server_node']['widget']['#options'] = $this->getServerNodesByType($enabled_api->entityType());
}
$form['user_id']['#access'] = FALSE;
return $form;
}
When i check the parent function i noticed that the line:
$form = $this->form($form, $form_state); is causing this in the class EntityForm(Core method).
/**
* {#inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// During the initial form build, add this form object to the form state and
// allow for initial preparation before form building and processing.
if (!$form_state->has('entity_form_initialized')) {
$this->init($form_state);
}
// Ensure that edit forms have the correct cacheability metadata so they can
// be cached.
if (!$this->entity->isNew()) {
\Drupal::service('renderer')->addCacheableDependency($form, $this->entity);
}
// Retrieve the form array using the possibly updated entity in form state.
// This is causing my memory timeout.
$form = $this->form($form, $form_state);
// Retrieve and add the form actions array.
$actions = $this->actionsElement($form, $form_state);
if (!empty($actions)) {
$form['actions'] = $actions;
}
return $form;
}
If i comment that line out it is working fine but this is needed to save my values in config. Also this is core and should work.
Anyone else have this problem and knows the solutions to this?
Thanks.
This is solved, the error was that too much results where loaded in a select field.

how to config container with request variable

In the first place I had to configure parameters using the class "ParametersCompilerPass" to get data from database.Here si my class :
class ParametersCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$em = $container->get('doctrine.orm.default_entity_manager');
$boutique = $em->getRepository('AcmeBundle:Boutique')->findOneByNom($container->getParameter('boutique.config'));
if(null !== $boutique){
$container->setParameter('url_site', $boutique->getUrl());
$container->setParameter('idboutique', $boutique->getId());
}else{
$container->setParameter('url_site', null);
$container->setParameter('idboutique', 0);
}
}
}
and when i set a parameter from request, it dont work, i tried in adding this code :
$request = $container->get('request_stack')->getCurrentRequest();
if($request->getMethod() == 'POST'){
if (null !== $choixbout = $request->get('choixbout')){
// $this->container->setParameter('idboutique',$choixbout);
}
}
the service request_stack return null.
I do not know how to configure a parameter from a POST variable.
Hope you can help me.
thanks
Is it solid requirement to have the parameter set?
It could be handy to create a service which has a request dependency that can act as a boutique parameter holder.
For example
# app/config/services.yml
app.boutique:
class: AppBundle\Boutique\Boutique
arguments: ['#request_stack']
app.boutique_info_dependant1:
class: AppBundle\Boutique\BoutiqueDependant1
arguments: ['#app.boutique']
app.boutique_info_dependant2:
class: AppBundle\Boutique\BoutiqueDependant2
arguments: ['#app.boutique']
This would be a parameter handler.
# AppBundle/Boutique/Boutique.php
class Boutique
{
/** #var RequestStack */
private $requestStack;
/**
* BoutiqueListener constructor.
* #param ContainerInterface $container
*/
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
public function getBoutique()
{
$request = $this->requestStack->getCurrentRequest();
/// here you can add an extra check if the request is master etc.
if ($request->getMethod() == Request::METHOD_POST) {
if (null !== $choixbout = $request->get('choixbout')) {
return $choixbout;
}
}
return null;
}
}
Then using the handler
class BoutiqueDependant1
{
public function __construct(Boutique $boutique)
{
$this->myBoutique = $boutique->getBoutique();
}
}
This does not look like the best solution but could work...
Other option would be to rethink the application architecture to handle boutique information somehow differently.

Symfony2: Delete entity through post request (improvements required)

I need some improvements about my actual way to delete entities:
public function deleteAction($path)
{
$form = $this->createFormBuilder(array('path' => $path))
->add('path')
->setReadOnly(true)
->getForm();
if ($this->getRequest()->getMethod() === 'POST') {
$form->bindRequest($this->getRequest());
if ($form->isValid()) {
$image = $this->getImageManager()->findImageByPath($path);
$this->getImageManager()->deleteImage($image);
return $this->redirect($this->generateUrl('AcmeImageBundle_Image_index'));
}
}
return $this->render('AcmeImageBundle:Image:delete.html.twig', array(
'form' => $form->createView(),
));
}
Two improvements I already found while writting:
CreateFormBuilder in extra method in controller
Hidden field and overgive extra image-entity to get rendered
Are there other thing I could make better?
Regards
(my answer is too long for the comment so i add it here)
First you have to create a Type file (generally in YourApp\YourBundle\Form\yourHandler.php), some basique code to put inside if you don't know:
<?php
namespace ***\****Bundle\Form;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;
use ***\****Bundle\Entity\your_entity;
class *****Handler
{
protected $form;
protected $request;
protected $em;
public function __construct(Form $form, Request $request, EntityManager $em)
{
$this->form = $form;
$this->request = $request;
$this->em = $em;
}
public function process()
{
if( $this->request->getMethod() == 'POST' )
{
$this->form->bindRequest($this->request);
if( $this->form->isValid() )
{
$this->onSuccess($this->form->getData());
return true;
}
}
return false;
}
public function onSuccess(your_entity $object)
{
// Make your stuff here (remove,....)
}
}
And in your controller i just call it this way:
if (!empty($_POST))
{
$formHandler = new *****Handler($my_form, $this->get('request'), $this->getDoctrine()->getEntityManager());
$formHandler->process();
}
Hope i'm clear enough

ZF using placeholders inside plugins

I'm trying to implement a plugin that handles responses to the user on success or failure in a persistance transaction. When the response is false I use a _forward to the action that performed the form's submit and get my placeholder message shown but when the response is true I use a _redirect to the browse with the new record shown.
My problem is that when I use _redirect the browser doesn't show the placeholder message. I'll show the code here:
/**
* Plugin
*/
class Application_Plugin_PostMessage extends Zend_Controller_Plugin_Abstract
{
public function postDispatch(Zend_Controller_Request_Abstract $request)
{
$message = $request->getParam('message');
$error = $request->getParam('error');
if (null !== $message || null !== $error) {
$layout = Zend_Layout::getMvcInstance();
$view = $layout->getView();
$placeHolder = $view->placeholder('message');
$placeHolder->setPostfix('</div>');
if (null !== $error) {
$placeHolder->setPrefix('<div class="errorMessage">')
->append($error);
}
elseif (null !== $message) {
$placeHolder->setPrefix('<div class="infoMessage">')
->append($message);
}
}
}
}
/**
* Controller
*/
class My_FooController extends Zend_Controller_Action
{
public function init()
{
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_PostMessage());
}
...
public function browseAction()
{
...
// No message is shown here on redirect
...
}
public function newAction()
{
...
// This code shows the placeholder on _forward call
...
}
public function insertAction()
{
if(true) {
return $this->_redirect('/my/foo/browse?message='
. urlencode("success message"));
}
else {
return $this->_forward('new', null, null, array(
'error' => 'error messsage'
));
}
}
}
I can't use _forward on success because I don't want the use of [F5] key repeats the insert action
Thanks in advance
This is what Flash Messenger is for:
http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelper.flashmessenger.basicusage
It stores messages in your session removing the need for passing messages as you are.

Idea discussion: dynamic view script switching in zend MVC implementation [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
This is basically the "Am i doing it right?" question.
I have an idea how i can transparently switch views for default/mobile version/admin areas at run time. And I would like to know what pros and cons you see in this approach.
Main requirements are:
switch entire application with
little to no coding
integrate into zend MVC workflow,
not overwrite it
fallback to default
preserve standard functionality
controllers shouldn't be aware of
changes
Here is my pseudohelper
class Xrks_Controller_Action_Helper_VrExtension extends Zend_Controller_Action_Helper_Abstract
{
public function postDispatch()
{
if(!$this->_shouldRender()) {
return; //just skip
}
try {
$vr = $this->_getViewRenderer();
$backupView = clone $vr->view;
$this->_setBasePaths(); //set base path(s) through ViewRenderer::initView($path)
$oldSpecArray = $this->_setVrPathSpecs(); //set VR view script path specs
$vr->render();
$vr->setNoRender(true); //disable renderer
} catch(Zend_View_Exception $e) { //fallback to default viewscripts if view script file not found
$vr->setView($backupView); //restore view on error
} catch(Exception $e) {
$vr->setView($backupView); //restore view on error
$this->_setVrPathSpecs($oldSpecArray); //restore script path spec
throw $e;
}
$this->_setVrPathSpecs($oldSpecArray);//restore script path spec
}
/**
* Same functionality as ViewRenderer helper _shouldRender method
* #return boolean
*/
protected function _shouldRender();
/**
* #return Zend_Controller_Action_Helper_ViewRenderer
*/
protected function _getViewRenderer();
/**
* Sets viewRenderer path specifications
*
* #param array $spec if NULL uses $this->_viewRendererPathSpecs
* #return array old path spec (0 => pathSpec, 1 => pathNoControllerSpec)
*/
protected function _setVrPathSpecs(array $spec = NULL);
}
How exactly helper should be configured is not important and that part skipped
Here is example how it supposed to work:
$this->_setBasePaths(); sets view base paths to application/views/default/ and application/views/admin/
$this->_setVrPathSpecs(); set path specification to ':module/:controller/:action.:suffix'
so for foo-baz-bar it will search at
1. application/views/admin/scripts/foo/baz/bar.phtml
2. application/views/default/scripts/foo/baz/bar.phtml
if view script not found fall back to default ViewRenderer:
3. application/modules/foo/views/scripts/baz/bar.phtml
Ask questions if I missed something
Upd: After some research i decided to use action helper to autoregister view scriptPaths based on specification for inflector and specified variables. I also modified partial helpers to register scriptPaths if partial from other module requested.
This is crude but working version of action helper:
class Xrks_Controller_Action_Helper_ViewRendererPathstack extends Zend_Controller_Action_Helper_Abstract
{
const PATH_APPEND = 'append';
const PATH_PREPEND = 'prepend';
protected $_enabled = FALSE;
protected $_viewScriptPaths = array();
/**
* By default following vars available: baseDir, area, theme, module
* #var string
*/
protected $_viewScriptPathSpec = ':baseDir/:area/:module';
protected $_defaults = array(
'area' => 'frontend',
'theme' => 'default',
);
protected $_vars = array();
protected $_inflector;
protected $_viewRenderer;
public function __construct($baseDir = NULL)
{
if($baseDir == NULL) {
$baseDir = APPLICATION_PATH . DS . 'views';
}
$this->setDefaultVar('baseDir', $baseDir);
$this->addPath(array());
}
/**
* Enter description here ...
* #return Zend_Controller_Action_Helper_ViewRenderer
*/
protected function _getViewRenderer()
{
if(!$this->_viewRenderer) {
$this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
}
return $this->_viewRenderer;
}
/**
* Should the ViewRenderer render a view script?
*
* #return boolean
*/
protected function _shouldRender()
{
$vR = $this->_getViewRenderer();
return (!$this->getFrontController()->getParam('noViewRenderer')
&& !$vR->getNeverRender()
&& !$vR->getNoRender()
&& (null !== $vR->getActionController())
&& $vR->getRequest()->isDispatched()
&& !$vR->getResponse()->isRedirect()
);
}
public function generatePaths(array $vars = array())
{
$this->_registerVarsWithInflector();
$vars = array_merge($this->_defaults, $this->_vars, $vars);
$inflector = $this->getInflector();
$generatedPaths = array();
foreach($this->_viewScriptPaths as $path) {
$pathVars = array_merge($vars, $path);
$generatedPaths[] = $inflector->filter($pathVars);
}
return array_reverse(array_unique(array_reverse($generatedPaths)));//last occurence more important than first
// array('test', 'test2', 'test') => array('test2', 'test')
// #todo rethink this code piece later. must be better solution
}
protected function _registerVarsWithInflector()
{
$vars = array_merge($this->_defaults, $this->_vars);
$inflector = $this->getInflector();
$unregistered = array_keys(array_diff_key($vars, $inflector->getRules()));
sort($unregistered, SORT_DESC);//more specific first (moduleDir prior to module key)
foreach($unregistered as $var) {
$inflector->addFilterRule($var, array('Word_CamelCaseToDash', 'StringToLower'));
}
}
protected function _viewAddScriptPaths(Zend_View_Abstract $view, $paths)
{
foreach ($paths as $path) {
$view->addScriptPath($path);
}
}
/**
* Get inflector
*
* #return Zend_Filter_Inflector
*/
public function getInflector()
{
if (null === $this->_inflector) {
$this->_inflector = new Zend_Filter_Inflector();
$this->_inflector->setThrowTargetExceptionsOn(true);
//setup default rules
$this->_inflector->addRules(array(
':baseDir' => array(),
))
->setTargetReference($this->_viewScriptPathSpec);
}
return $this->_inflector;
}
/**
*
* #return array
*/
public function getPaths()
{
return $this->_basePaths;
}
public function getEnabled()
{
return $this->_enabled;
}
public function setEnabled($flag = TRUE)
{
$this->_enabled = (bool)$flag;
return $this;
}
/**
*
* #todo add check for $pathVars keys and values validity
* #param array $pathVars associative array
* #param string $placement either append or prepend
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack
*/
public function addPath(array $pathVars, $placement = self::PATH_APPEND)
{
if($placement == self::PATH_PREPEND) {
array_unshift($this->_viewScriptPaths, $pathVars);
} else {
$this->_viewScriptPaths[] = $pathVars;
}
return $this;
}
/**
*
* #param array|Zend_Config $paths
* #param string $placement either append or prepend
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack
* #throws Xrks_Exception
*/
public function addPaths($paths, $placement = self::PATH_APPEND)
{
if($paths instanceof Zend_Config) {
$paths = $paths->toArray();
} elseif (!is_array($paths)) {
throw new Xrks_Exception('$paths should be either array or instance of Zend_Config');
}
if($placement == self::PATH_PREPEND) {
$paths = array_reverse($paths);
}
foreach($paths as $path) {
$this->addPath((array)$path, $placement);
}
return $this;
}
/**
*
* #param array $pathVars associative array
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack
*/
public function setPath(array $pathVars)
{
$this->_basePaths = array();
$this->addPath($pathVars);
return $this;
}
/**
*
* #param array|Zend_Config $paths
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack
* #throws Xrks_Exception
*/
public function setPaths($paths)
{
$this->_basePaths = array();
$this->addPaths($paths);
return $this;
}
/**
*
* #param string $varName
* #return string |NULL
*/
public function getDefaultVar($varName)
{
if(key_exists($varName, $this->_defaults)) {
return $this->_defaults[$varName];
}
return NULL;
}
/**
* #param string $varName
* #param string $value
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack Provides fluent interface
*/
public function setDefaultVar($varName, $value)
{
$this->_defaults[$varName] = (string)$value;
return $this;
}
/**
*
* #param string $name
* #return string |NULL
*/
public function getVar($name, $defaults = false)
{
if(key_exists($name, $this->_vars)) {
return $this->_vars[$name];
}
return $defaults ? $this->getDefaultVar($name) : NULL;
}
/**
* #param string $varName
* #param string $value
* #return Xrks_Controller_Action_Helper_ViewRendererPathstack Provides fluent interface
*/
public function setVar($varName, $value)
{
$this->_vars[$varName] = $value;
return $this;
}
public function unsetVar($name)
{
if(key_exists($name, $this->_vars)) {
unset($this->_vars[$name]);
}
return $this;
}
public function postDispatch()
{
if(!$this->getEnabled() || !$this->_shouldRender()) {
return; //just skip
}
try {
$vr = $this->_getViewRenderer();
$this->setVar('module', $vr->getModule());
$paths = $this->generatePaths();
$this->_viewAddScriptPaths($vr->view, $paths);
if(Zend_Registry::isRegistered('Zend_Log')) {
Zend_Registry::get('Zend_Log')
->log($paths, Zend_Log::DEBUG);
}
} catch(Exception $e) {
if(Zend_Registry::isRegistered('Zend_Log')) {
Zend_Registry::get('Zend_Log')
->log($e, Zend_Log::WARN);
}
throw $e;
}
}
}
The way I usually handle this:
I register a Layout Plugin, extending Zend_Layout_Controller_Plugin_Layout
I use the preDispatch hook to determine what module, controller, action I am in
I switch between layouts and views depending on the context
For me, that's by far the easiest method.
GJ