i would like to access to the protected propertie parcelNumber
TNTExpress\Model\Expedition Object
(
[parcelResponses:protected] => Doctrine\Common\Collections\ArrayCollection Object
(
[elements:Doctrine\Common\Collections\ArrayCollection:private] => Array
(
[0] => TNTExpress\Model\ParcelResponse Object
(
[sequenceNumber:protected] => 1
[parcelNumber:protected] => 9112758000000006
[trackingURL:protected] => http://www.tnt.fr/public/suivi_colis/recherche/visubontransport.do?bonTransport=9112345000000006
[stickerNumber:protected] =>
)
)
)
what should i do ?
You have two basic options:
Because its protected you can extend the class, and add new getter (if library is possible to extend)
Or you can use reflection to get your info - http://php.net/manual/en/reflectionproperty.getvalue.php
With reflection it will be something like this:
$reflectionClass = new ReflectionClass(YourClass::class);
$reflectionProperty = $reflectionClass->getProperty('parcelResponses');
$reflectionProperty->setAccessible(true); // change it to public
var_dump($reflectionProperty->getValue($yourInstance)); // You get you value
Related
question is very simple, is there a quick way to translate a preloaded list in db. For example list of towns/countries?
class SeedTownTable extends Seeder
public function run()
{
$town_list = array(
'Акко',
'Арад',
'Ариэль',
'Афула',
'Ашдод',
'Ашкелон',
'Бат-Ям',
'Бейт-Шеан',
'Бейт-Шемеш',
'Бейтар-Илит',
'Беэр-Шева',
'Бней-Брак',
'Герцлия',
'Гиват-Шмуэль',
'Кирьят-Малахи',
'Кирьят-Моцкин',
'Кирьят-Оно',
'Кирьят-Тивон',
'Кирьят-Хаим',
'Кирьят-Шмона',
'Кирьят-Ям',
'Кфар-Саба',
'Лод',
'Маале-Адумим',
'Маалот-Таршиха',
'Метула',
'Мигдаль-ха-Эмек',
'Модиин',
'Ход-ха-Шарон',
'Холон',
'Цфат',
'Эйлат',
'Эльад',
'Явне',
'Яффо'
);
foreach ( $town_list as $town ){
Town::create([
'name' => $town
]);
}
}
I made towns model with records without any backend controller.
And I want to translate this list.
thanks.
Add the translation to your data array and use setAttributeTranslated to add the translated version.
As mentioned in the Docs
// Gets a single translated attribute for a language
$user->getAttributeTranslated('name', 'fr');
// Sets a single translated attribute for a language
$user->setAttributeTranslated('name', 'Jean-Claude', 'fr');
Try
$town_list = array(
[
'name' => 'Town Name Default Lang',
'name-es' => 'Town Name in Spanish',
]
...
)
foreach ( $town_list as $town ){
$t = new TownModel();
$t->name = $town['name'];
$t->setAttributeTranslated('name', $town['name-es'], 'es');
$t->save();
}
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. :)
I have a method that validate an Object calling an external service:
public void Validate(IValidator<MyType> validator)
{
IMapper<MyType> mapper = new MyTypeMapper();
foreach (var element in this.Elements)
{
ValidationResult result = validator.Validate(myTypeInstance, mapper, new ValidationConfiguration());
if (result.IsValid)
// do something
else
// do something else
}
}
Now in my unit test I have a collection of elements. And I want that if an element have a given id number the Validate method should return another stub with validation messages:
// arrange
var myAggregate aggregate = ElementsNonValidated.Stub();
var mockedValidator = new Mock<IValidator<MyType>>();
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
new Mapper(),
new ValidationConfiguration()
)).Returns<ValidationResult>(x => x = new ValidationResult());
// act
myAggregate.Valida(mockedValidator.Object);
The problem is: When unit test starts and go forth till the real method validate still return result=null. Why? What's wrong with my mock?
The problem is here:
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
new Mapper(),
new ValidationConfiguration()
)).Returns<ValidationResult>(x => x = new ValidationResult());
You setup Validate to expect specific Mapper and ValidationResult instances, which of course do not match the instances used in your system under test. If you don't care what instance should be used for a parameter, use It.IsAny<>:
mockedValidator.Setup(a => a.Validate(
It.Is<Mytype>(x => x.Id == Guid.Parse("3F2504E0-4F89-11D3-9A0C-0305E82C3301")),
It.IsAny<Mapper>(),
It.IsAny<ValidationConfiguration>()
)).Returns<ValidationResult>(x => x = new ValidationResult());
This will return a new ValidationResult for any and every invocation to Validate where the object's Id is equal to that particular GUID.
The reason for the TargetParameterCountException is in your Returns statement, and is answered here.
Pretty straight forward question:
I have page--front.tpl and page.tpl template pages in use in a drupal 7 site. However, I'd like to use page-front.tpl on one other page. Is this possible or do I need to create another .tpl page to do this.
The site I'm working on is split into two sections, it's essentially two seperate websites that you can flip between whether your a consumer or business owner. So I want to use the front.tpl template for the home page of each site.
Cheers.
You can add theme_preprocess_page function to your theme's template.php file and then add your template name in templates suggestions list.
function mytheme_preprocess_page(&$vars) {
// you can perform different if statements
// if () {...
$template = 'page__front'; // you should replace dash sign with underscore
$vars['theme_hook_suggestions'][] = $template;
// }
}
EDIT
If you want to specify template name by path alias, you could write code like this:
function phptemplate_preprocess_page(&$variables) {
if (module_exists('path')) {
$alias = drupal_get_path_alias($_GET['q']);
if ($alias != $_GET['q']) {
$template = 'page_';
foreach (explode('/', $alias) as $part) {
$template.= "_{$part}";
$variables['theme_hook_suggestions'][] = $template;
}
}
}
}
Without this function you would have the following node template suggestions by default:
array(
[0] => page__node
[1] => page__node__%
[2] => page__node__1
)
And this function would apply to your node the following new template suggestions.
Example node with node/1 path and page/about alias:
array(
[0] => page__node
[1] => page__node__%
[2] => page__node__1
[3] => page__page
[4] => page__page_about
)
So after that you can use page--page-about.tpl.php for your page.
If you want to apply page--front.tpl.php to your let's say node/15, then in this function you can add if statement.
function phptemplate_preprocess_page(&$variables) {
if (module_exists('path')) {
$alias = drupal_get_path_alias($_GET['q']);
if ($alias != $_GET['q']) {
$template = 'page_';
foreach (explode('/', $alias) as $part) {
$template.= "_{$part}";
$variables['theme_hook_suggestions'][] = $template;
}
}
}
if ($_GET['q'] == 'node/15') {
$variables['theme_hook_suggestions'][] = 'page__front';
}
}
This would give you the following template suggestions:
array(
[0] => page__node
[1] => page__node__%
[2] => page__node__1
[3] => page__page
[4] => page__page_about
[5] => page__front
)
The highest index - the highest template priority.
I would like to return an array of string in my web services
I've tryed :
<?php
require_once('nusoap/nusoap.php');
$server = new soap_server();
$server->configureWSDL('NewsService', 'urn:NewsService');
$server->register('GetAllNews',
array(),
array('return' => 'xsd:string[]'),
'urn:NewsService',
'urn:NewsService#GetAllNews',
'rpc',
'literal',
''
);
// Define the method as a PHP function
function GetAllNews()
{
$stack = array("orange", "banana");
array_push($stack, "apple", "raspberry");
return $stack;
}
but it doesn't work. What is the correct syntax for that ?
Thanks in advance for any help
You first need to define a new type that describes an array of strings like so:
$server->wsdl->addComplexType(
'ArrayOfString',
'complexType',
'array',
'sequence',
'',
array(
'itemName' => array(
'name' => 'itemName',
'type' => 'xsd:string',
'minOccurs' => '0',
'maxOccurs' => 'unbounded'
)
)
);
Then you can use tns:ArrayOfString as the return type.
This site describes a nice way to return complex datatypes and receive it with C#: http://sanity-free.org/125/php_webservices_and_csharp_dotnet_soap_clients.html
When returning array of arrays, you might need a different configuration from Oliver. For example phfunc2php uses this technique in the nusoapcode.class.php file (https://github.com/sylnsr/pgfunc2php/blob/master/nusoapcode.class.php). The code it generates looks like so:
$server->wsdl->addComplexType(
'ArrayOfArrays','complexType','array','',
'SOAP-ENC:Array',
array(),
array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'xsd:string[]')));
and then the functions simply needs to return "tnsArrayOfArrays:
$server->register(
'sel_signon_id_by_uuid',
array('user_uuid' => 'xsd:string'),
array('return'=>'tns:ArrayOfArrays'),
The project mentioned above can compile working code for you, should you want to see this.