Sorry for the rudimentary question.I'm developing PHP small test class that manipulates AWS Elasticsearch Service.
<?php
namespace MyCompany\Aws;
use Elasticsearch\ClientBuilder;
class ElasticsearchApi {
private $client;
function __construct(string $hosts='', string $username='', string $password=''){
... //configure $this->client
}
/**
* Create index
* #param string $index
* #param array $body
* #return bool
*/
public function createIndex(string $index, array $body = []):bool{
$request = array(
'index' => $index,
'body' => $body
);
$ret = $this->client->indices()->create($request);
return $ret['acknowledged'];
}
}
And call createIndex function specifying alias as described at:
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html
<?php
require 'vendor/autoload.php';
use MyCompany\Aws\ElasticsearchApi as ES;
$es = new ES();
$body = array('aliases'=>array(
'actions'=>array(
'add'=>array(
'alias'=>'sample-alias',
'index'=>'test-index'
)
)
));
$ret = $es->createIndex('test-index',$body);
var_dump($ret);
This operation normally ends:
PS D:\My_Documents\Proj\Elasticsearch\index-gen> php es-lib-test.php
bool(true)
PS D:\My_Documents\Proj\Elasticsearch\index-gen>
However the generated index does not seem to have alias.
What is wrong with createIndex parameter? I'm using version 7.8 of Elasticsearch on AWS.
Addendum
Based on the #Val 's suggestion, I changed the code as follows:
$body = array(
'aliases'=>array(
'sample-alias'=>array()
)
);
$ret = $es->createIndex('test-index',$body);
var_dump($ret);
However I got the following exception. Are there any mistakes?
PS D:\My_Documents\Proj\Elasticsearch\index-gen> php es-lib-test.php
PHP Fatal error: Uncaught Elasticsearch\Common\Exceptions\BadRequest400Exception: {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"No alias is specified"}],"type":"illegal_argument_exception","reason":"No alias is specified"},"status":400} in D:\My_Documents\Proj\Elasticsearch\index-gen\vendor\elasticsearch\elasticsearch\src\Elasticsearch\Connections\Connection.php:641
Stack trace:
#0 D:\My_Documents\Proj\Elasticsearch\index-gen\vendor\elasticsearch\elasticsearch\src\Elasticsearch\Connections\Connection.php(328): Elasticsearch\Connections\Connection->process4xxError(Array, Array, Array)
#2 D:\My_Documents\Proj\Elasticsearch\index-gen\vendor\ezimuel\ringphp\src\Future\CompletedFutureValue.php(55): React\Promise\FulfilledPromise->then(Object(Closure), NULL, NULL)
#3 D:\My_Documents\Proj\Elasticsearch\index-gen\vendor\ezimuel\ring in D:\My_Documents\Proj\Elasticsearch\index-gen\vendor\elasticsearch\elasticsearch\src\Elasticsearch\Connections\Connection.php on line 641
Your body should simply look like this:
$body = array('aliases' => array('sample-alias' => array()));
The syntax you're using is for the _aliases endpoint not for the index creation one.
Related
I created a TYPO3 extension which allows to select several images. I activated metadata via the filemetadata extension. When I browse the image files in a fluid template loop, I try to display the metadata. This works {file.properties.uid}
{file.properties.categories}, but for the categories I get a number. Now I would like to have the category selected.
I used this:
https://coding.musikinsnetz.de/typo3/fluid-viewhelpers/access-system-categories-in-content-elements-templates
<f: if condition = "{files}">
<f: for each = "{files}" as = "file">
<f: for each = "{bg2yg: CategoriesOutput (recUid: data.uid)}" as = "category">
<b style = 'color: blue'> <span class = "{category.title}"> CATEGORY: {category.title} </span> </b> <br />
</ f: for>
</ f: for>
</ f: if>
This displays the main category because 'data.uid': {bg2yg: CategoriesOutput (recUid: data.uid)}
However, I want the categories of images, I tested this:
<f: for each = "{bg2yg: CategoriesOutput (recUid: file.properties.uid)}" as = "category">
Without success ! Do you have an idea ?
Best regards,
Bruno
thank you for your respective help. Here I coded this:
<?php
/**
* This file is part of the "hexagonalgallery" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE file that was distributed with this source code.
*/
namespace BG2YG\Hexagonalgallery\ViewHelpers;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
* will return certain system categories (sys_category) data of an element
* either as an array or as a string with certain parameters
*
* EXAMPLES:
*
* EMBEDDING IN TEMPLATE: {namespace my = YourVendor\YourExtension\ViewHelpers}
*
* call an array with all category data to be used in a loop, e.g. for an HTML tag for each files:
* <f:if condition="{file}">
* <f:for each="{my:FileCategoriesOutput(recUid: data.uid)}" as="category">
* <span class="{category.title}">{category.title}</span>
* </f:for>
* </f:if>
*
* call a “data-categories” attribute with the slug field of the categories, comma-separated (default):
* {my:FileCategoriesOutput(recUid: file.properties.uid, tableName: 'sys_file_metadata', fieldString: 'title', htmlAttr: 'data-categories')}
* output: ' data-categories="catx,caty"'
*
* call all categories as CSS classes (space as string separator, prefix 'cat-' for each files)
* {my:FileCategoriesOutput(recUid: file.properties.uid, tableName: 'sys_file_metadata', fieldString: 'title', stringSeparator: ' ', catPrefix: 'cat-')}
* output: 'cat-catx cat-caty'
*/
class FileCategoriesOutputViewHelper extends AbstractViewHelper
{
protected $escapeOutput = false;
public function initializeArguments()
{
$this->registerArgument('recUid', 'integer', 'record UID, e.g. of a content element', true);
$this->registerArgument('tableName', 'string', 'optional: table of records you want the categories returned for (default: tt_content)', false, 'tt_content');
$this->registerArgument('fieldString', 'string', 'optional: name of sys_categories table field – if given, the return value will be a string', false, null);
$this->registerArgument('stringSeparator', 'string', 'optional: separator for string', false, ',');
$this->registerArgument('htmlAttr', 'string', 'optional: wrap in attribute for HTML tag (in case of fieldString given)', false, null);
$this->registerArgument('catPrefix', 'string', 'optional: prefix for each category (e.g. for CSS classes)', false, null);
}
/**
* #return mixed
*/
public function render()
{
$recUid = $this->arguments['recUid'];
$tableName = $this->arguments['tableName'];
$fieldString = $this->arguments['fieldString'];
$stringSeparator = $this->arguments['stringSeparator'];
$htmlAttr = $this->arguments['htmlAttr'];
$catPrefix = $this->arguments['catPrefix'];
define(DEBUG,false);
/*
SELECT uid_local FROM sys_file_reference WHERE uid = 152
*/
if (DEBUG)
echo "<b style='color:blue;'>\$recUid=".$recUid."</b><br />";
/**
* default query for sys_file_reference table
* SQL : SELECT uid_local FROM sys_file_reference WHERE uid = $recUid
*/
$queryBuilder0 = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
$queryBuilder0->select('uid_local');
$queryBuilder0->from('sys_file_reference');
$queryBuilder0->where(
$queryBuilder0->expr()->eq('sys_file_reference.uid', $queryBuilder0->createNamedParameter($recUid, \PDO::PARAM_INT)));
$result_uid = $queryBuilder0->execute();
$uid=$result_uid->fetch();
$uid=$uid['uid_local'];
if (DEBUG)
echo "<b style='color:blue;'>\$uid=".print_r($uid)."</b><br />";
/**
* default query for sys_category table
*/
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_category');
/**
* select the fields that will be returned, use asterisk for all
*/
$queryBuilder->select('sys_category.uid', 'sys_category.title', 'sys_category_record_mm.uid_foreign', 'sys_category_record_mm.tablenames');
$queryBuilder->from('sys_category');
$queryBuilder->join(
'sys_category',
'sys_category_record_mm',
'sys_category_record_mm',
$queryBuilder->expr()->eq('sys_category_record_mm.uid_local', $queryBuilder->quoteIdentifier('sys_category.uid'))
);
$queryBuilder->where(
$queryBuilder->expr()->eq('sys_category_record_mm.uid_foreign', $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)),
$queryBuilder->expr()->like('sys_category_record_mm.tablenames', $queryBuilder->createNamedParameter($tableName))
);
$result = $queryBuilder->execute();
$res = [];
$returnString = '';
$i = 1;
while ($row = $result->fetch()) {
$res[] = $row;
if ($fieldString !== null) {
if (isset($row[$fieldString])) {
$returnString .= ($i === 1) ? '' : $stringSeparator;
$returnString .= ($catPrefix !== null) ? $catPrefix : '';
$returnString .= $row[$fieldString];
}
}
$i++;
}
if (DEBUG) {
echo "\$returnString=" . $returnString . "<br />";
echo "\$res=<b style='color:red;'>" . print_r($res) . "</b><br />";
}
if ($returnString !== '') {
return ($htmlAttr !== null)
? ' ' . $htmlAttr . '="' . $returnString . '"'
: $returnString;
} elseif ($fieldString !== null) {
return '';
} else {
return $res;
}
}
}
And it works. Thank you for indicating to me if this code seems to you written in the rules of art.
Best regards,
Bruno
It looks like categories are not handled in the model, so the fastest thing you can do is to create your own ViewHelper for fetching them as suggested in answer to a similar question, my fast test for TYPO3 9.5
IMPORTANT! for ver.: 10+ check annotation changes at the bottom of this post.
<?php
namespace VENDOR\Toolbox\ViewHelpers;
use TYPO3\CMS\Core\Resource\FileReference;
use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
/**
*
* #package TYPO3
* #subpackage toolbox
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 2 or later
* #author Marcus Biesioroff biesior#gmail.com>
*
* Sample ViewHelper for listing file's categories
*
* Usage:
* {namespace toolbox=VENDOR\Toolbox\ViewHelpers}
* or in ext_tables.php:
* $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['toolbox'] = ['VENDOR\Toolbox\ViewHelpers'];
*
* <toolbox:fileCategories file="{file}" />
* or
* {toolbox:fileCategories(file: file)}
*/
class FileCategoriesViewHelper extends AbstractViewHelper
{
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository
* #inject
*/
protected $categoryRepository;
public function initializeArguments()
{
parent::initializeArguments();
$this->registerArgument('file', 'mixed', 'File');
}
public function render()
{
/** #var FileReference $fileRef */
$fileRef = $this->arguments['file'];
$file = $fileRef->getOriginalFile();
$uid = $file->getUid();
/** #var QueryResult $res */
$res = $this->getCategories($uid);
return $res->toArray();
}
private function getCategories($uid)
{
$query = $this->categoryRepository->createQuery();
$sql = "SELECT sys_category.* FROM sys_category
INNER JOIN sys_category_record_mm ON sys_category_record_mm.uid_local = sys_category.uid AND sys_category_record_mm.fieldname = 'categories' AND sys_category_record_mm.tablenames = 'sys_file_metadata'
INNER JOIN sys_file_metadata ON sys_category_record_mm.uid_foreign = sys_file_metadata.uid
WHERE sys_file_metadata.file = '" . (int)$uid . "'
AND sys_category.deleted = 0
ORDER BY sys_category_record_mm.sorting_foreign ASC";
return $query->statement($sql)->execute();
}
}
So you can use it within your Fluid template like:
<h3>File categories:</h3>
<ul>
<f:for each="{toolbox:fileCategories(file: file)}" as="file_cat">
<li>{file_cat.title}</li>
</f:for>
</ul>
Don't forget to use your own vendor and subpackage key.
Of course, after injecting anything don't forget to flush your caches, sometimes maaaany times.
Important info for ver.: 10.* +
According to this article #inject annotation is depreciated in ver. 9.x and removed in ver." 10.x You should use #TYPO3\CMS\Extbase\Annotation\Inject instead.
So proper injection of the categoryRepository in TYPO3 10.x and newer should look like:
/**
* #var \TYPO3\CMS\Extbase\Domain\Repository\CategoryRepository
* #TYPO3\CMS\Extbase\Annotation\Inject
*/
protected $categoryRepository;
You can also search for deprecated annotations within your ext via Upgrade module > Scan Extension Files
In my repositories, I have methods with too many arguments (for use in where) :
Example :
class ProchaineOperationRepository extends EntityRepository
{
public function getProchaineOperation(
$id = null, // Search by ID
\DateTime $dateMax = null, // Search by DateMax
\DateTime $dateMin = null, // Search by DateMin
$title = null // Search by title
)
In my controllers, I have differents action ... for get with ID, for get with ID and DateMin, for get ID and Title, ...
My method is too illegible because too many arguments ... and it would be difficult to create many methods because they are almost identical ...
What is the best practice ?
You have two main concerns in your question
You have too many arguments in your repository method which will be used in 'where' condition of the eventual query. You want to organize them in a better way
The repository method should be callable from the controller in a meaningful way because of possible complexity of arguments passed
I suggest you to write a Repository method like:
namespace AcmeBundle\Repository;
/**
* ProchaineOperationRepository
*
*/
class ProchaineOperationRepository extends \Doctrine\ORM\EntityRepository
{
public function search($filters, $sortBy = "id", $orderBy = "DESC")
{
$qb = $this->createQueryBuilder("po");
foreach ($filters as $key => $value){
$qb->andWhere("po.$key='$value'");
}
$qb->addOrderBy("po.$sortBy", $orderBy);
return $qb->getQuery()->getArrayResult();
}
}
The $filters variable here is an array which is supposed to hold the filters you are going to use in 'where' condition. $sortBy and $orderBy should also be useful to get the result in properly sequenced way
Now, you can call the repository method from your controller like:
class ProchaineOperationController extends Controller
{
/**
* #Route("/getById/{id}")
*/
public function getByIdAction($id)
{
$filters = ['id' => $id];
$result = $this->getDoctrine()->getRepository("AcmeBundle:ProchaineOperation")->search($filters);
//process $result
}
/**
* #Route("/getByTitle/{title}")
*/
public function getByTitleAction($title)
{
$filters = ['title' => $title];
$sortBy = 'title';
$result = $this->getDoctrine()->getRepository("AcmeBundle:ProchaineOperation")->search($filters, $sortBy);
//process $result
}
/**
* #Route("/getByIdAndDateMin/{id}/{dateMin}")
*/
public function getByIdAndDateMinAction($id, $dateMin)
{
$filters = ['id' => $id, 'dateMin' => $dateMin];
$sortBy = "dateMin";
$orderBy = "ASC";
$result = $this->getDoctrine()->getRepository("AcmeBundle:ProchaineOperation")->search($filters, $sortBy, $orderBy);
//process $result
}
}
Note that you are calling the same repository method for all controller actions with minor changes according to your parameters. Also note that $sortBy and $orderBy are optionally passed.
Hope it helps!
If your objective is only to query with an AND operator between each properties, the best way could be to use the method proposed by doctrine for that : findBy() cf : this part of the doc
for instance :
$results = $this
->getDoctrine()
->getRepository('AppBundle:ProchaineOperation')
->findBy(array('dateMax' => $myDate, 'title' => 'Hello world');
EDIT : after comment
Then use the same way as Doctrine do : Pass only an array with id, dateMax... as keys if these are set. This should be solve the method signature problem which gives you so much trouble. :)
My Select function of my QueryManager:
/**
* Führt eine SELECT - Query durch
*
* #param $select = array( array(column, [...]), table, shortcut )
* $orderby = array(column, sorting-type)
* $where = array( array( column, value, type[or, and] ), [...] )
* $innerjoin = array( table, shortcut, condition )
* $pagination = array( page, limit )
*
* #return array $data
*/
public function select($select,$orderby, $where, $innerjoin, $pagination)
{
$qb = $this->conn->createQueryBuilder()
->select($select[0])
->from($select[1], $select[2])
;
if ($orderby) {
$qb->orderBy($orderby);
}
if ($where) {
foreach($where as $cond) {
$x = 0;
if ( key($cond) == 0 ) {
$qb
->where($cond[0] . ' = ?')
->setParameter($x,$cond[1]);
}
elseif ( $cond[2] == 'and' ) {
$qb
->andWhere($cond[0] . ' = ?')
->setParameter($x,$cond[1]);
}
elseif ( $cond[2] == 'and' ) {
$qb
->orWhere($cond[0] . ' = :' . $x)
->setParameter($x,$cond[1]);
}
$x++;
}
}
if ($innerjoin) {
$qb->join($select[2],$innerjoin);
}
$this->sql = $qb->getSQL();
$this->totalRowCount = count( $qb->execute() ) ;
if ($pagination) {
$max = $pagination[0] * $pagination[1];
$first = $max - $limit;
$qb
->setFirstResult($first)
->setMaxResults($max)
;
}
$stmt = $qb->execute();
return $stmt->fetchAll();
}
I don't know why, but in action, this function produces a select query without inserted values for the parameters:
/**
* Lädt einen User nach dessen Username
*
* #param $username
* #return User $user | null
*/
public function getUser($username)
{
if($data = $this->select(array('*','users','u'), null, array( array('username',$username) ), null,null)) {
return $user = $this->hydrate($data);
}
return null;
}
I didn't get a result, and the query is not setup correctly:
array(0) { }
SELECT * FROM users u WHERE username = ?
In my opinion the Builder doesn't supstitute my parameters with the provided values ...
I got the latest version of Doctrine DBAL (2.4) and this version should support this features!
Thanks for Help and Suggestions :)
I also had this Problem. I have readed here doctrine 2 querybuilder with set parameters not working that:
You cant bind parameters to QueryBuilder, only to Query
But im creating SQL conditions as collected AND & OR experssions in deep nested objects, and the toppest object creates the query object. So i cant create the query object before, i always return expression objects.
So i solved the problem with direct including the variable into the prepared variable's position.
$qb->where($cond[0] . '=' . $cond[1]);
And because i expect strings there i added hard coded quotes. This is not the desired way, but at the moment i dont know how to solve that in an other way with binding parameters to the QueryBuilder object.
$expr = $d_qb->expr()->between($t_c, "'" . $date_from . "'", "'" . $date_from . "'");
Other suggestions?
Following codes results:
$expr = $d_qb->expr()->between($t_c, ':from', ':to');
$d_qb->setParameter('from', 1);
$d_qb->setParameter('to', 1);
or
$expr = $d_qb->expr()->between($t_c, ':from', ':to');
$d_qb->setParameter(':from', 1);
$d_qb->setParameter(':to', 1);
Results:
e0_.created BETWEEN ? AND ?
I programmed a custom field plugin for Virtuemart 2.6.6, which show some parameters on the product page for example "size", and that parameter is a cart variable either.
A huge help was this article:
https://www.spiralscripts.co.uk/Joomla-Tips/custom-plugin-fields-in-virtuemart-2-2.html
And of course stackoverflow forum and factory default VM custom plugins.
Everything is working (the size is displayed in product details view, and in the cart, when you added the product to it) but one thing:
after sending the order the parameter has not displayed in the order details, so I don't know what size of product was bought.
I placed following functions into my plugin, but not solved my problem:
function plgVmOnViewCart($product, $row, &$html)
{
if (empty($product->productCustom->custom_element) or $product->productCustom->custom_element != $this->_name) return '';
if (!$plgParam = $this->GetPluginInCart($product)) return false ;
$html .= '<div class="parameterek_attributes">';
foreach ($plgParam as $attributes) {
foreach ($attributes as $k => $attribute) {
if ($k =='child_id') continue;
if ($k == 'custom_param_default3') $name = 'Veľkosť'; else $name = '';
$html .='<span class="parameterek_attribute"> '.$name.': '.JText::_($attribute).' </span>';
}
}
$html.='</div>';
return true;
}
/**
*
* shopper order display BackEnd
*/
function plgVmDisplayInOrderBE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
if(!empty($productCustom)){
$item->productCustom = $productCustom;
}
$this->plgVmOnViewCart($item, $row,$html);
}
/**
*
* shopper order display FrontEnd
*/
function plgVmDisplayInOrderFE($item, $row,&$html)
{
if (empty($item->productCustom->custom_element) or $item->productCustom->custom_element != $this->_name) return '';
$this->plgVmOnViewCart($item, $row,$html);
}
Into database table called #__virtuemart_order_items were saved values: something like:
{"357":"5"}
but it should be something like:
{"357":"size M"}
I see that the key function is GetPluginInCart($product), and when I printed out the $product->param in that function I've got this output, when I go through checkout process:
Array
(
[0] => Array
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
but after I finish the order and go into order details the $product->param has this value:
Array
(
[357] => 5
)
So I think, before I finish the order I have to somehow handle the
chosen product parameter and transform it into the correct form, but
I don't know how.
On the following site
https://dev.virtuemart.net/projects/virtuemart/wiki/Product_Plugins
I found a function:
plgVmOnViewCartOrder($product, $param,$productCustom, $row)
handel $param before adding it in the order
return $param;
but when I searched for the string "plgVmOnViewCartOrder" in the whole virtuemart installation, it was not found, so it means it is not launched (?)
If anybody could help me or send a fair documentation would be very good. Thank you!
I think, I solved my problem, what was:
in function plgVmOnDisplayProductVariantFE I made a mistake, I didn't use layout renderer, which generates an object $viewData with variable virtuemart_customfield_id.
Then in your plugin's layout, input field name has to be as follows:
<input
class="parameterekInput"
type="radio"
id="plugin_param['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.']['.$c.']"
name="customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][custom_param_default3]"
value="'.$size.'" />
so the name attribute should be always:
customPlugin['.$viewData[0]->virtuemart_customfield_id.']['.$this->_name.'][whatever]
The right usage of plgVmOnDisplayProductVariantFE function is to use expression:
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group )
Here the whole function with the right expresion:
function plgVmOnDisplayProductVariantFE ($field, &$idx, &$group) {
if ($field->custom_element != $this->_name) return '';
$this->getCustomParams($field);
$this->getPluginCustomData($field, $field->virtuemart_product_id);
$group->display .= $this->renderByLayout('default',array($field,&$idx,&$group ) );
return true;
}
Now when I print_r -ing $product->param in function GetPluginInCart($product), I get this:
Array
(
[273] => Array //previously the key was Zero, now it is 273, value of virtuemart_customfield_id
(
[parameterek] => Array
(
[custom_param_default3] => L
)
)
)
...and now I'm glad, that I can move on in my project :)
I have a client input form that has the following two reg expressions that works when creating a client but not when updating a client. The update form is a class that extends the crate form.
// Create text input for mobile
$mobile = new Zend_Form_Element_Text ('mobile');
$mobile->setLabel ('Mobile Number:')
->setDescription('Enter mobile in the format 353XXYYYYYYY')
->setOptions(array('size'=>'14'))
->setRequired(false)
->addValidator('Regex',false,array(
'pattern'=>'/^\d{12}$/',
'messages'=>array(
Zend_Validate_Regex::INVALID => '\'%value%\' Invalid mobile number it does not match the required format 353XXYYYYYYY',
Zend_Validate_Regex::NOT_MATCH =>'\'%value%\'does not match the required format 353XXXXXXXX')
)
)
->addFilter('HtmlEntities')
->addFilter('StringTrim');
// Create text input for landline
$landline = new Zend_Form_Element_Text ('landLine');
$landline->setLabel ('Phone Number:')
->setDescription('Enter phone number in the format +353(0) X YYY YYYZ')
->setOptions(array('size'=>'20'))
->setRequired(false)
->addValidator('StringLength', false, array('min' => 8))
->addValidator('Regex', false, array(
'pattern' => '/^\+353\(0\)\s\d\s\d{3}\s\d{3,4}$/',
'messages' => array(
Zend_Validate_Regex::INVALID =>
'\'%value%\' In valid Phone number does not match required number format +353(0) X YYY YYYZ',
Zend_Validate_Regex::NOT_MATCH =>
'\'%value%\' does not match required number format of +353(0) X YYY YYYZ'
)
))
->addFilter('HtmlEntities')
->addFilter('StringTrim');
When I enter an invalid mobile or land line number when creating a client the reg expression works and prevents the record from being saved.
However when I enter an invalid mobile or land line number when updating a client the reg expression fails and an 404 error occurs.
I think that the issue may be related to the get section of my update action within my controller as shown below but I can't figure out what is causing this as the route I have configured in my ini file retrieves the record as required.
public function updateAction(){
// generate input form
$form = new PetManager_Form_UpdateClient;
$this->view->form=$form;
/* if the requrest was made via post
test if the input is valid
retrieve current record
update values and save to DB */
if($form->isValid($this->getRequest()->getPost())){
$input=$form->getValues();
$client = Doctrine::getTable('PetManager_Model_Clients')
->find($input['clientid']);
$client->fromArray($input);
if($client->email=='')
{$client->email=NULL;}
if($client->mobile=='')
{$client->mobile=NULL;}
if($client->landLine=='')
{$client->landLine=NULL;}
if($client->address3=='')
{$client->address3=NULL;}
$client->save();
$sessionClient = new Zend_Session_Namespace('sessionClient');
$id = $client->clientid;
$fname = $client->firstName;
$lname = $client->lastName;
$sessionClient->clientid=$id;
$sessionClient->clientfName=$fname;
$sessionClient->clientlName=$lname;
$sessionClient->clientfName=$fname;
$this->_helper->getHelper('FlashMessenger')
->addMessage('The record for '.$fname.' '.$lname. ' was successfully updated.');
$this->_redirect('clients/client/success');
}else{
/* if GET request
set filters and validators for GET input
test if input is valid, retrieve requested
record and pree-populate the form */
$filters = array(
'id'=>array('HtmlEntities','StripTags','StringTrim')
);
$validators = array(
'id'=>array('NotEmpty','Int')
);
$input = new Zend_Filter_Input($filters,$validators);
$input->setData($this->getRequest()->getParams());
if($input->isValid()){
$qry = Doctrine_Query::create()
->from('PetManager_Model_Clients c')
->leftJoin('c.PetManager_Model_Counties co')
->where('c.clientid=?',$input->id);
$result = $qry->fetchArray();
if(count($result)==1){
$this->view->form->populate($result[0]);
}else{
throw new Zend_Controller_Action_Exception('Page not found',404);
}
}else{
throw new Zend_Controller_Action_Exception('Invalid Input');
}
}
}
All help greatly appreciated.
Ok I've sorted this I stupidly left out a check in my update action to see if the request was being made by post as this is the action defined in my form.
The corrected code is shown below in case this helps anyone else.
// action to update an individual clients details
public function updateAction()
{
// generate input form
$form = new PetManager_Form_UpdateClient;
$this->view->form=$form;
/* if the requrest was made via post
test if the input is valid
retrieve current record
update values and save to DB */
if ($this->getRequest()->isPost()) {
if($form->isValid($this->getRequest()->getPost())){
$input=$form->getValues();
$client = Doctrine::getTable('PetManager_Model_Clients')
->find($input['clientid']);
$client->fromArray($input);
if($client->email=='')
{$client->email=NULL;}
if($client->mobile=='')
{$client->mobile=NULL;}
if($client->landLine=='')
{$client->landLine=NULL;}
if($client->address3=='')
{$client->address3=NULL;}
$client->save();
$sessionClient = new Zend_Session_Namespace('sessionClient');
$id = $client->clientid;
$fname = $client->firstName;
$lname = $client->lastName;
$sessionClient->clientid=$id;
$sessionClient->clientfName=$fname;
$sessionClient->clientlName=$lname;
$sessionClient->clientfName=$fname;
$this->_helper->getHelper('FlashMessenger')
->addMessage('The record for '.$fname.' '.$lname. ' was successfully updated.');
$this->_redirect('clients/client/success');
}
}else{
/* if GET request
set filters and validators for GET input
test if input is valid, retrieve requested
record and pree-populate the form */
$filters = array(
'id'=>array('HtmlEntities','StripTags','StringTrim')
);
$validators = array(
'id'=>array('NotEmpty','Int')
);
$input = new Zend_Filter_Input($filters,$validators);
$input->setData($this->getRequest()->getParams());
if($input->isValid()){
$qry = Doctrine_Query::create()
->from('PetManager_Model_Clients c')
->leftJoin('c.PetManager_Model_Counties co')
->where('c.clientID=?',$input->id);
$result = $qry->fetchArray();
if(count($result)==1){
$this->view->form->populate($result[0]);
}else{
$t=count($result);
throw new Zend_Controller_Action_Exception('Page not found',404);
}
}else{
throw new Zend_Controller_Action_Exception('Invalid Input');
}
}
}