I am using Symfony 3.3.10
I have the following code
/**
* #Route("/meta/edit/{metaId}", name="edit_price_meta_data")
*/
public function editMetaAction(Request $request,ItemPriceMeta $metaId)
{
$metaDataForm = $this->createForm("ItemBundle\Form\ItemPriceMetaType");
$data = [
'metaData'=>$metaId,
'metaDataForm'=>$metaDataForm->createView(),
];
return $this->render("#Item/Prices/Manage/editMetaData.html.twig",$data);
}
It produces the following error.
Error: Maximum execution time of 60 seconds exceeded
in vendor\doctrine\orm\lib\Doctrine\ORM\UnitOfWork.php (line 2513)
public function createEntity($className, array $data, &$hints = array()){
$class = $this->em->getClassMetadata($className);
//$isReadOnly = isset($hints[Query::HINT_READ_ONLY])
$id = $this->identifierFlattener->flattenIdentifier($class, $data);
$idHash = implode(' ', $id);
if (isset($this->identityMap[$class->rootEntityName][$idHash])) {
$entity = $this->identityMap[$class->rootEntityName][$idHash];
$oid = spl_object_hash($entity);
The actual line highlighted as causing the error is $id = $this->identifierFlattener->flattenIdentifier($class, $data);
Removing 'metaDataForm'=>$metaDataForm->createView(), from my array, removes the error, so it seems to be the rendering of the form that is causing the error.
Increase PHP memory usage in php.ini
Related
I have a plugin in my module that was working in Magento 2.3, but after upgrade to 2.4 i am getting the error
TypeError: Argument 2 passed to
..\Plugin\Controller\Checkout\Sidebar\RemoveItemPlugin::afterExecute()
must be an instance of Magento\Framework\App\Response\Http, instance
of Magento\Framework\Controller\Result\Json\Interceptor given
This is the code :
use Magento\Customer\CustomerData\SectionPoolInterface;
use Magento\Framework\Serialize\Serializer\Json;
class RemoveItemPlugin
{
public function __construct(
SectionPoolInterface $sectionPool,
Json $json
) {
$this->sectionPool = $sectionPool;
$this->json = $json;
}
public function afterExecute(
\Magento\Checkout\Controller\Sidebar\RemoveItem $subject,
\Magento\Framework\App\Response\Http $result
): \Magento\Framework\App\Response\Http {
/* Get Cart Items */
$sectionNames = "cart";
$sectionNames = $sectionNames ? array_unique(\explode(',', $sectionNames)) : null;
$forceNewSectionTimestamp = false;
$response = $this->sectionPool->getSectionsData($sectionNames, (bool)$forceNewSectionTimestamp);
/* Prepare Result */
$content = $this->json->unserialize($result->getContent());
$content['cartSection'] = $response;
$content = $this->json->serialize($content);
$result->setContent($content);
return $result;
}
}
I tried the answer in this question :
https://magento.stackexchange.com/questions/351344/magento-2-4-sidebar-removeitem-afterexecute-must-be-an-instance-of-magento-f
but once I change $result to be type resultInterface, I can no longer use $result->getContent() to return the cart json. Is there a way to do this with resultInterface?
What is right way to send variables to the layout templete for it be approachable in error pages?
I have AppFrontController above all my frontend controllers. It have code (code is near) in onDispatch() method:
$assocArrayOfVars = $this->MyPlugin()->getDbVariablesArray();
foreach($assocArrayOfVars as $name => $value){
$this->layout()->$name = $value;
}
list($catalog, $count_goods) = $this->MyPlugin()->getStandardCatalogDataForLayout();
$this->layout()->catalog = $catalog;
$this->layout()->count_goods = $count_goods;
As the result, I have my local variables in every frontend page. But I have’nt it in an error page. How I can to deside this problem? I very need your advices! Thank you!
Thank you for your advices! Problem is solved. Code of final version Module.php file below. I use listener instead of a “parent controller” by froschdesign advice.
public function onBootstrap(MvcEvent $event)
{
$application = $event->getApplication();
$eventManager = $application->getEventManager();
$eventManager->attach('dispatch', array($this, 'loadConfiguration'), 2);
$eventManager->attach('dispatch.error', array($this, 'loadConfiguration'), 2);
}
public function loadConfiguration(MvcEvent $e)
{
$application = $e->getApplication();
$sm = $application->getServiceManager();
$sharedManager = $application->getEventManager()->getSharedManager();
$router = $sm->get('router');
$request = $sm->get('request');
$zendCart = $sm->get('ControllerPluginManager')->get('ZendCart');
$myPlugin = $sm->get('ControllerPluginManager')->get('MyPlugin');
$viewModel = $e->getViewModel();
$viewModel->setVariable('total', $zendCart->total());
$viewModel->setVariable('total_items', $zendCart->total_items());
$viewModel->setVariable('rusmonth', $rusmonth);
/* Layout variables */
$assocArrayOfVars = $myPlugin->getDbVariablesArray();
foreach ($assocArrayOfVars as $name => $value) {
$viewModel->setVariable($name, $value);
}
list($catalog, $count_goods) = $myPlugin->getStandardCatalogDataForLayout();
$viewModel->setVariable('catalog', $catalog);
$viewModel->setVariable('count_goods', $count_goods);
}
More listener examples here.
Now that I've upgraded to "facebook/php-ads-sdk": "2.8.*" (https://github.com/facebook/facebook-php-ads-sdk), this function of mine doesn't work anymore:
public function addToCustomAudience($entriesArray, $audienceId, $inputType = CustomAudienceTypes::EMAIL) {
$audience = new CustomAudience($audienceId);
$result = $audience->addUsers($entriesArray, $inputType);
return $result;
}
Apparently addUsers is no longer available.
I see a createUser function, but it looks quite different, and there is no documentation online about how to migrate from addUsers to createUser.
What I want to do is simple.
Given an array of email addresses and an ID of an audience, how can I add all of those email addresses to that Facebook Custom Audience?
From what I can see in the code, addUsers is still there, and it's documented on the Developer site.
I just used the latest SDK along with the following code to update an audience:
use FacebookAds\Object\CustomAudience;
use FacebookAds\Object\Values\CustomAudienceTypes;
$emails = array(
'test1#example.com',
'test2#example.com',
'test3#example.com',
);
$audience = new CustomAudience(<CUSTOM_AUDIENCE_ID>);
$audience->addUsers($emails, CustomAudienceTypes::EMAIL);
This seems to work for my purposes.
I copied some code from the facebook-php-ads-sdk as a workaround.
$audience = new CustomAudience($audienceId);
$params = $this->formatParams($entriesArray, $inputType, [], false);
$audience->createUser([], $params, false);
/**
* Copied this from Facebook's https://github.com/facebook/facebook-php-ads-sdk/blob/d51193b19d730ae9274d45540986e1ac311b074d/src/FacebookAds/Object/CustomAudience.php#L363
* Take users and format them correctly for the request
*
* #param array $users
* #param string $type
* #param array $app_ids
* #param bool $is_hashed
* #return array
*/
protected function formatParams(array $users, $type, array $app_ids = array(), $is_hashed = false) {
if ($type == CustomAudienceTypes::EMAIL || $type == CustomAudienceTypes::PHONE) {
$normalizer = new EmailNormalizer();
$hash_normalizer = new HashNormalizer();
foreach ($users as &$user) {
if ($type == CustomAudienceTypes::EMAIL) {
$user = $normalizer->normalize(CustomAudienceTypes::EMAIL, $user);
}
if (!$is_hashed) {
$user = $hash_normalizer->normalize(
CustomAudienceTypes::EMAIL, $user);
}
}
}
$payload = array(
'schema' => $type,
'data' => $users,
);
if ($type === CustomAudienceTypes::ID) {
if (empty($app_ids)) {
throw new \InvalidArgumentException(
"Custom audiences with type " . CustomAudienceTypes::ID . " require"
. "at least one app_id");
}
$payload['app_ids'] = $app_ids;
}
return array('payload' => $payload);
}
I can't seem to get ZF2 to show just one error message for failed form validation messages.
For example, an EmailAddress validator can pass back up to 7 messages and typically shows the following if the user has made a typo:
oli.meffff' is not a valid hostname for the email address
The input appears to be a DNS hostname but cannot match TLD against known list
The input appears to be a local network name but local network names are not allowed
How can I override the error to show something a little more friendly, such as "Please enter a valid email address" instead of specifics like the above?
OK, managed to come up with a solution for this. Instead of using the same string as the error for all validator failures as Sam suggested above, I have overridden the error messages in the InputFilter for the elements and then used a custom form error view helper to show only the first message.
Here is the helper:
<?php
namespace Application\Form\View\Helper;
use Traversable;
use \Zend\Form\ElementInterface;
use \Zend\Form\Exception;
class FormElementSingleErrors extends \Zend\Form\View\Helper\FormElementErrors
{
/**
* Render validation errors for the provided $element
*
* #param ElementInterface $element
* #param array $attributes
* #throws Exception\DomainException
* #return string
*/
public function render(ElementInterface $element, array $attributes = array())
{
$messages = $element->getMessages();
if (empty($messages)) {
return '';
}
if (!is_array($messages) && !$messages instanceof Traversable) {
throw new Exception\DomainException(sprintf(
'%s expects that $element->getMessages() will return an array or Traversable; received "%s"',
__METHOD__,
(is_object($messages) ? get_class($messages) : gettype($messages))
));
}
// We only want a single message
$messages = array(current($messages));
// Prepare attributes for opening tag
$attributes = array_merge($this->attributes, $attributes);
$attributes = $this->createAttributesString($attributes);
if (!empty($attributes)) {
$attributes = ' ' . $attributes;
}
// Flatten message array
$escapeHtml = $this->getEscapeHtmlHelper();
$messagesToPrint = array();
array_walk_recursive($messages, function ($item) use (&$messagesToPrint, $escapeHtml) {
$messagesToPrint[] = $escapeHtml($item);
});
if (empty($messagesToPrint)) {
return '';
}
// Generate markup
$markup = sprintf($this->getMessageOpenFormat(), $attributes);
$markup .= implode($this->getMessageSeparatorString(), $messagesToPrint);
$markup .= $this->getMessageCloseString();
return $markup;
}
}
It's just an extension of FormElementErrors with the render function overridden to include this:
// We only want a single message
$messages = array(current($messages));
I then insert the helper into my application using the solution I posted to my issue here.
I followed Rob Allens ZF 1 Tutorial and wanted to pimp it up with some UnitTesting. But whenever I run the phpunit command, i get the message:
here was 1 failure:
1) IndexControllerTest::testDeleteAction
Failed asserting last controller used <"error"> was "Index"
/path/to/library/Zend/Test/PHPUnit/ControllerTestCase.php:1000
/path/to/tests/application/controllers/IndexControllerTest.php:55
FAILURES!
Tests: 4, Assertions: 9, Failures: 1.
The Action in question is the deleteAction and looks like this:
public function deleteAction() {
if ($this->getRequest()->isPost()) {
$del = $this->getRequest()->getPost('del');
if ($del == 'Yes') {
$id = $this->getRequest()->getPost('id');
$wishes = new Application_Model_DbTable_Wishes();
$wishes->deleteWish($id);
}
$this->_helper->redirector('index');
}
else {
$id = $this->_getParam('id', 0);
$wishes = new Application_Model_DbTable_Wishes();
$this->view->wish = $wishes->getWish($id);
}
}
I tracked the error down to be $wishes>getWish($id); so if i go to that function, that looks like this:
public function getWish($id) {
$id = (int) $id;
$row = $this->fetchRow('id = ' . $id);
if(!$row){
throw new Exception("Could not find row $id");
}
return $row->toArray();
}
it appears the line $row = $this->fetchRow('id = ' . $id); causes the problem. And I can't figure out why. All action work just fine, they do as expected.Any idea how to fix this?
Thanks!
Maybe try using the select() object instead if a plain string:
public function getWish($id) {
$id = (int) $id;
$select = $this->select();
$select->where('id = ?', $id);
$row = $this->fetchRow($select);
if(!$row){
throw new Exception("Could not find row $id");
}
return $row->toArray();
}
This just a wild guess, but who knows. The only thing that looks at all odd is the lack of a placeholder in the query string (?).
FetchRow() does like to work with the select() object, in fact if you pass a string the first thing fetchRow() does is build a select(). So maybe it just doesn't like the string.