I'm trying to build a query string as following:
Next Page
I want to add an array to query string. For example, array('find_loc'=>'New+York', 'find_name'=>'starbucks')
I expect to get url that looks like http://example.com/1/?find_loc=New+York&find_name=starbucks
What's the best way to do this? I found a similar question that suggested appending the string to the url. Is there a helper for query string?
Simple answer to your question is no.
Here is the class description:
/**
* Helper for making easy links and getting urls that depend on the routes and router
*
* #package Zend_View
* #subpackage Helper
* #copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
* #license http://framework.zend.com/license/new-bsd New BSD License
*/
Helper for making easy links and getting urls that depend on the routes and router
I think the description is clear in it's purpose. Use it for making URLs that depend on the routes and router. So, just append your query strings as recommend in the link you posted in your question.
The following should work for you:
Next Page
The ZF-Router will map the values to the Request object.
In your controller you can access these params with the Response-Object:
$loc = $this->getRequest()->getParam('find_loc');
$name = $this->getRequest()->getParam('find_name);
You can make custom helper:
class My_View_Helper_UrlHttpQuery extends Zend_View_Helper_Abstract
{
public function urlHttpQuery($query)
{
$urlHelper = $this->view->getHelper('url');
$params = func_get_args();
array_shift($params);//removing first argument
$url = call_user_func_array(($urlHelper, 'url'), $params);
if(!is_string($query)) { //allow raw query string
$query = array($query);
$query = http_build_query($query);
}
if(!empty($query) {
$url .= '?' . ltrim('?', $query);
}
return $url;
}
}
After you register this helper with view, you can use it like this Next Page
Working code
/**
* Class Wp_View_Helper_UrlHttpQuery
*/
class Wp_View_Helper_UrlHttpQuery extends Zend_View_Helper_Abstract
{
public function urlHttpQuery($query = array())
{
$urlHelper = $this->view->getHelper('url');
$params = func_get_args();
//removing first argument
array_shift($params);
$url = call_user_func_array(array($urlHelper, 'url'), $params);
if (is_array($query) || is_object($query)) {
$query = http_build_query($query);
}
if (!empty($query)) {
$url .= '?' . ltrim($query, '?');
}
return $url;
}
}
since the upstream code doesn't work
Related
I need to add a custom validator to the datepicker field. By default, this field comes without any validators.
I've already made the validator settings visible in the TCA of tx_powermail_domain_model_field and added my custom validator as usual.
Now I need the attributes data-parsley-customXXX and data-parsley-error-message added to the HTML input field which is usually done via the the viewhelper in ValidationDataAttributeViewHelper.php:
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/ValidationDataAttributeViewHelper.php#L342
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/ValidationDataAttributeViewHelper.php#L348
This is the code I need to extend:
https://github.com/einpraegsam/powermail/blob/develop/Classes/ViewHelpers/Validation/DatepickerDataAttributeViewHelper.php#L32
I found a solution for my problem. As suggested in the comment it's possible to extend the Viewhelper:
ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects'][\In2code\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper::class] = [
'className' => \Vendor\MyExt\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper::class
];
myext/Classes/Powermail/ViewHelpers/Validation/DatepickerDataAttributeViewHelper.php
<?php
declare(strict_types=1);
namespace Vendor\MyExt\Powermail\ViewHelpers\Validation;
use In2code\Powermail\Domain\Model\Field;
use In2code\Powermail\Utility\LocalizationUtility;
class DatepickerDataAttributeViewHelper extends \In2code\Powermail\ViewHelpers\Validation\DatepickerDataAttributeViewHelper
{
/**
* Returns Data Attribute Array Datepicker settings (FE + BE)
*
* #return array for data attributes
*/
public function render(): array
{
/** #var Field $field */
$field = $this->arguments['field'];
$additionalAttributes = $this->arguments['additionalAttributes'];
$value = $this->arguments['value'];
$additionalAttributes['data-datepicker-force'] =
$this->settings['misc']['datepicker']['forceJavaScriptDatePicker'];
$additionalAttributes['data-datepicker-settings'] = $this->getDatepickerSettings($field);
$additionalAttributes['data-datepicker-months'] = $this->getMonthNames();
$additionalAttributes['data-datepicker-days'] = $this->getDayNames();
$additionalAttributes['data-datepicker-format'] = $this->getFormat($field);
if ($value) {
$additionalAttributes['data-date-value'] = $value;
}
if ($field->getValidation() && $this->isClientValidationEnabled()) {
$value = 1;
if ($field->getValidationConfiguration()) {
$value = $field->getValidationConfiguration();
}
$additionalAttributes['data-parsley-custom' . $field->getValidation()] = $value;
$additionalAttributes['data-parsley-error-message'] =
LocalizationUtility::translate('validationerror_validation.' . $field->getValidation());
}
$this->addMandatoryAttributes($additionalAttributes, $field);
return $additionalAttributes;
}
}
I am trying to send a modification through Json to my project in Symfony 5, but I only get error responses, as if there is no Url, I have not inserted any API key or any header, I have searched for a guide but I cannot find it:
UserController.php
<?php
namespace App\Controller;
use App\Entity\User;
use App\Repository\UserRepository;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class UserController
{
private $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
/**
* #Route("/user/", name="add_user", methods={"POST"})
* #param Request $request
* #return JsonResponse
*/
public function add(Request $request): JsonResponse
{
$data = json_decode($request->getContent(), true);
$firstName = $data['firstName'];
$lastName = $data['lastName'];
$email = $data['email'];
$phoneNumber = $data['phoneNumber'];
if (empty($firstName) || empty($lastName) || empty($email) || empty($phoneNumber)) {
throw new NotFoundHttpException('Expecting mandatory parameters!');
}
$this->userRepository->saveUser($firstName, $lastName, $email, $phoneNumber);
return new JsonResponse(['status' => 'User created!'], Response::HTTP_CREATED);
}
UserRepository.php:
public function saveUser($firstName, $lastName, $email, $phoneNumber)
{
$newUser = new User();
$newUser
->setFirstName($firstName)
->setLastName($lastName)
->setEmail($email)
->setPhoneNumber($phoneNumber);
$this->manager->persist($newUser);
$this->manager->flush();
}
As for the GET, I have done it correctly and I get an answer with the data.
Your path looks wrong. On the controller action you define the route as:
/**
* #Route("/user/", name="add_user", methods={"POST"})
* #param Request $request
* #return JsonResponse
*/
The add_user is just the internal route name. The url in postman should probably be:
https://127.0.0.1:8000/user/
Additionally, since you did not get any response, so not even a 404 not found, I assume you do not have a web server running right now. If you use the Symfony CLI-tool you can call the command: symfony serve in your project directory to get the web server running. Closing the terminal window or restarting your computer will stop the web server.
I need to get all registed routes to work with into a controller.
In slim 3 it was possible to get the router with
$router = $container->get('router');
$routes = $router->getRoutes();
With $app it is easy $routes = $app->getRouteCollector()->getRoutes();
Any ideas?
If you use PHP-DI you could add a container definition and inject the object via constructor injection.
Example:
<?php
// config/container.php
use Slim\App;
use Slim\Factory\AppFactory;
use Slim\Interfaces\RouteCollectorInterface;
// ...
return [
App::class => function (ContainerInterface $container) {
AppFactory::setContainer($container);
return AppFactory::create();
},
RouteCollectorInterface::class => function (ContainerInterface $container) {
return $container->get(App::class)->getRouteCollector();
},
// ...
];
The action class:
<?php
namespace App\Action\Home;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Response;
use Slim\Http\ServerRequest;
use Slim\Interfaces\RouteCollectorInterface;
final class HomeAction
{
/**
* #var RouteCollectorInterface
*/
private $routeCollector;
public function __construct(RouteCollectorInterface $routeCollector)
{
$this->routeCollector = $routeCollector;
}
public function __invoke(ServerRequest $request, Response $response): ResponseInterface
{
$routes = $this->routeCollector->getRoutes();
// ...
}
}
This will display basic information about all routes in your app in SlimPHP 4:
$app->get('/tests/get-routes/', function ($request, $response, $args) use ($app) {
$routes = $app->getRouteCollector()->getRoutes();
foreach ($routes as $route) {
echo $route->getIdentifier() . " → ";
echo ($route->getName() ?? "(unnamed)") . " → ";
echo $route->getPattern();
echo "<br><br>";
}
return $response;
});
From there, one can use something like this to get the URL for a given route:
$routeParser = \Slim\Routing\RouteContext::fromRequest($request)->getRouteParser();
$path = $routeParser->urlFor($nameofroute, $data, $queryParams);
With the following caveats:
this will only work for named routes;
this will only work if the required route parameters are provided -- and there's no method to check whether a route takes mandatory or optional route parameters.
there's no method to get the URL for an unnamed route.
I am trying to read the username of a front end user whose uid is known. I tried this in my controller's showAction method:
$objectManger = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
// get repository
$repository = $objectManger->get('Tx_Extbase_Domain_Repository_FrontendUserRepository ');
$newObject = $repository->findByUid($coupon->getCreator()); //this is the uid of whoever was loggin in
print_r($newObject);
echo $newObject->getUsername(); die;
but when that code runs I get:
Oops, an error occured!
"Tx_Extbase_Domain_Repository_FrontendUserRepository " is not a valid cache entry identifier.
It turns out that $repository is empty, so how do I get fe_user data?
I am using typo3 v4.5 with extbase.
Thanks
Update to show complete answer.
This is the code (it goes in my CouponController) that worked (plus the typoscript mentioned):
/**
* #var Tx_Extbase_Domain_Repository_FrontendUserRepository
*/
protected $userRepository;
/**
* Inject the user repository
* #param Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository
* #return void */
public function injectFrontendUserRepository(Tx_Extbase_Domain_Repository_FrontendUserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function showAction(Tx_Coupons_Domain_Model_Coupon $coupon) {
$userRepository = $this->objectManager->get("Tx_Extbase_Domain_Repository_FrontendUserRepository");
$newObject = $userRepository->findByUid($coupon->getCreator());
$this->view->assign('coupon', $coupon);
$this->view->assign('creatorname', $newObject->getUsername() );
}
If you are using extbase yourself you dont have to call makeInstance for your objectManager, it's already there ($this->objectManager).
anyway, you should inject this repository (see my answer here: TYPO3 - Call another repository)
Clear the Cache after the Injection.
You maybe have to disable the recordtype extbase sets for its FrontendUser:
config.tx_extbase.persistence.classes.Tx_Extbase_Domain_Model_FrontendUser.mapping.recordType >
Set the source storage pid where the repository fetches the data from:
/** #var Tx_Extbase_Domain_Repository_FrontendUserRepository $repos */
$repos = $this->objectManager->get("Tx_Extbase_Domain_Repository_FrontendUserRepository");
$querySettings = $repos->createQuery()->getQuerySettings();
$querySettings->setStoragePageIds(array(123, 567));
$repos->setDefaultQuerySettings($querySettings);
$user = $repos->findByUid(56); // Queries for user 56 in storages 123 and 567
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.