Get multi data from one entity with one method - symfony

How I can get multiple data from entity data row
public function findByUser1Id($userId)
{
$connections = $this->_em
->getRepository('AppBundle:ConnectionsList')
->findBy(array('user1Id' => $userId));
foreach($connections as $con)
{
$user = $this->_em
->getRepository('AppBundle\Entity\User')
->findOneBy(array('id' => $con->getUser2Id()));
var_dump($user->getFirstname());
var_dump($user->getLastname());
var_dump($user->getEmail());
var_dump($user->getId());
die;
}
}
I need some way to get data in one row in example:
$user->get(array('firstname', 'lastname', 'email' ...))

I found solution, but can't get all data in one row
code is here:
public function findByUser1Id($userId)
{
$connections = $this->_em
->getRepository('AppBundle:ConnectionsList')
->findBy(array('user1Id' => $userId));
foreach($connections as $con)
{
$user = $this->_em
->getRepository('AppBundle\Entity\User')
->findOneBy(array('id' => $con->getUser2Id()));
array_push($user, array(
'id' => $data->getId(),
'email'=>$data->getEmail(),
'firstname'=>$data->getFirstname(),
'lastname'=>$data->getLastname()
));
}
return $data
}

Related

Symfony 5 - Display id and slug in category url and find it by id when slug is updated

My category url contains both id and slug like https://myapp.com/category/56-category-name (id field = 56 and slug field = category-name in the DB), when updating category name the slug field in DB is updated but the id still the same.
I would like to display my category whatever the slug provided that the id is correct and of course display the correct url. In this case SEO still correct i think.
Here my show method :
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id): Response
{
$category = $categoryRepository->find($id);
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
It works if the given id exists in DB, othewise i got an error Call to a member function getSlug() on null. I can throw a NotFoundException, but i think this method use many times queries.
So please help me doing these properly with more flexibility and performance.
In case I would like to display the category in the post url as well like https://myapp.com/56-category-name/23-post-title how to go about it ??
Thanks in advance
Use findOneBy() and check if the result is null
/**
* #Route("/category/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
* #Route("/{id}-{slug}/{idArticle}-{postSlug}", name="article_show", requirements={"idArticle"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug, $id, $idArticle = false, $postSlug = false ): Response
{
$category = $categoryRepository->findOneBy(['id'=>$id]);
if(is_null($category)){
throw new NotFoundHttpException(); //404, nothing found
}else{
//Category found.
if($idArticle){ // https://myapp.com/56-category-name/23-post-title
//Article route, put your logic here
}else{ //https://myapp.com/category/56-category-name
// Category route, logic here
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
}
}
here is what i found good for my app :
in my CategoryController.php i create, the show method :
/**
* #Route("/{id}-{slug}", name="category_show", requirements={"id"="\d+"})
*/
public function show(CategoryRepository $categoryRepository, $slug = null, $id): Response
{
$category = $categoryRepository->find($id);
if (!$category) {
throw new NotFoundHttpException();
}
if($category->getSlug() !== $slug) {
return $this->redirectToRoute('category_show', [
'id' => $id,
'slug' => $category->getSlug()
]);
}
return $this->render('category/show.html.twig', [
'category' => $category
]);
}
in my index template to display the category_show link :
show
in my ArticleController.php i create, the show method :
/**
* #Route("/{category}/{id}-{slug}", name="article_show", requirements={"id"="\d+"})
*/
public function show(ArticleRepository $articleRepository, $slug = null, $id, $category = null): Response
{
$article = $articleRepository->find($id);
if (!$article) {
throw new NotFoundHttpException();
}
$cat = $article->getCategory()->getId() . '-' . $article->getCategory()->getSlug();
if($article->getSlug() !== $slug || $cat !== $category) {
return $this->redirectToRoute('article_show', [
'id' => $id,
'slug' => $article->getSlug(),
'category' => $cat
]);
}
return $this->render('article/show.html.twig', [
'article' => $article,
]);
}
in my index template to display the article_show link :
show
For me that solves my problem. But still, if we can improve the process, I'm a buyer.
Thanks

How to fix the output?

I need of you for helping to resolve my problem.
I use Symfony 4 for display some charts with the bundle google charts
Thanks you a lot
This is my function controller
/**
* #Route("/admin/test", name="statsTest")
*/
public function statsTest(){
$results = $this->getDoctrine()->getRepository(IssueNubitalk::class)
->CountIssueByPartenaire('Canal');
dump($results);
// $results = [];
foreach ($results as $key => $val) {
// dump($results);
$results[] = [
'campaign' => $val->getCampaign(),
'total' => $val->getTotal(),
];
}
dump($results);
$data = json_decode(json_encode($results), true);
$pieChart = new PieChart();
$pieChart->getData()->setArrayToDataTable($data);
$pieChart->getOptions()->setHeight(250);
$pieChart->getOptions()->setWidth(400);
$pieChart->getOptions()->getTitleTextStyle()->setBold(true);
$pieChart->getOptions()->getTitleTextStyle()->setColor('#009900');
$pieChart->getOptions()->getTitleTextStyle()->setItalic(true);
$pieChart->getOptions()->getTitleTextStyle()->setFontName('Arial');
$pieChart->getOptions()->getTitleTextStyle()->setFontSize(20);
return $this->render('backend/test.html.twig', [
'piechart' => $pieChart,
]);
}
this is my repository
public function CountIssueByPartenaire($partenaire){
return $this->createQueryBuilder('i')
->select('i.campaign')
->addSelect('COUNT(DISTINCT i.sessionId) as total')
->where('i.campaign LIKE :campaign')
->setParameter('campaign', $partenaire.'_%')
->groupBy('i.campaign')
->getQuery()
->getResult();
}
this is the output
Call to a member function getCampaign() on array

How do you mock a function call that called multple times with changing parameters in PHPSpec?

I'm trying to create a test in PHPSpec for an function that calls a function on another object with differing parameters. So far, my attempts have caused several different errors so I'll outline what I have so far.
The most recent error:
- it should find all realm data
method call:
- fetch(LeagueOfData\Adapters\Request\RealmRequest:000000001212f67d000000001262e5c6 Object (
'apiDefaults' => Array &0 (
'region' => 'euw'
)
'format' => null
'data' => null
'query' => null
'where' => Array &0
))
on Double\AdapterInterface\P51 was not expected, expected calls were:
fetch(exact(Double\RequestInterface\P50:000000001212f607000000001262e5c6 Object (
'objectProphecy' => Prophecy\Prophecy\ObjectProphecy Object (*Prophecy*)
The PHPSpec file:
class JsonRealmsSpec extends ObjectBehavior
{
function let(AdapterInterface $adapter, LoggerInterface $logger, RequestInterface $request)
{
// fetch called with multiple request objects but we're not interested in the exact data it returns yet.
$adapter->fetch($request)->willReturn(['test data']);
$this->beConstructedWith($adapter, $logger);
}
function it_should_find_all_realm_data()
{
$this->findAll()->shouldReturnArrayOfRealms();
}
function getMatchers()
{
return [
'returnArrayOfRealms' => function($realms) {
foreach ($realms as $realms) {
if (!$realm instanceof Realm) {
return false;
}
}
return true;
}
];
}
}
And the actual function being tested:
class JsonRealms implements RealmService
{
const REGIONS = ['euw', 'eune', 'na'];
private $source;
private $log;
private $realms;
public function __construct(AdapterInterface $adapter, LoggerInterface $log)
{
$this->source = $adapter;
$this->log = $log;
}
public function findAll() : array
{
$this->realms = [];
foreach (self::REGIONS as $region) {
$request = new RealmRequest(['region' => $region]);
$response = $this->source->fetch($request);
$this->realms[] = new Realm($realm['cdn'], $realm['v'], $region);
}
return $this->realms;
}
}
I'm sure I'm probably missing something really obvious but for the life of me I cannot see it right now.
So it turns out I was missing something obvious, I was trying to solve it with a single mock call, as opposed to one for each case:
function let(AdapterInterface $adapter, LoggerInterface $logger) {
$request = new RealmRequest(['region' => 'euw']);
$adapter->fetch($request)->willReturn([
'cdn' => 'http://test.url/euw',
'v' => '7.4.3'
]);
$request = new RealmRequest(['region' => 'eune']);
$adapter->fetch($request)->willReturn([
'cdn' => 'http://test.url/eune',
'v' => '7.4.3'
]);
$request = new RealmRequest(['region' => 'na']);
$adapter->fetch($request)->willReturn([
'cdn' => 'http://test.url/na',
'v' => '7.4.3'
]);
}
This appropriately sets up the mock adapter so that we can test the service is correctly creating the Realm objects.

Drupal Views Filter Handler

I wrote a custom views handler, that mark message private to 0 or 1 or 2; any is value of hers label [MARK_READ,ARK_NEW,...] :
function mydevel_views_data() {
$data['mydevel']['table']['group'] = t('mydevel');
$data['mydevel']['table']['join'] = array(
// Exist in all views.
'#global' => array(),
);
$data['mydevel']['mydevel_isnewmessage'] = array(
'title' => t('is new message field'),
'help' => t('is new message field.'),
'field' => array(
'handler' => 'mydevel_handler_field_isnewmessage',
'click sortable' => TRUE,
),
'filter' => array(
'handler' => 'mydevel_handler_filter_isnewmessage',
),
);
and wrote a filed handler that work properly; message_mark function is wrote on mydevel module file and work currectly; if the message is new that filed label row by "now":
class mydevel_handler_field_isnewmessage extends views_handler_field_numeric {
var $field_alias = 'mydevel_field_isnewmessage';
function query() {
}
function option_definition() {
$options = parent::option_definition();
//dsm($this);
return $options;
}
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
}
function get_value($values, $field = NULL) {
return intval(message_mark($values->mid, $values->message_timestamp));
}
function render($values) {
$value = $this->get_value($values);
$value_theme = theme('mark', array('type' => $value));
return $value_theme;
}
}
Now, i want to write a views filter handler that filter on that filed on numeric mode [0 or 1 or 2] or on check list mode [all, read, new, updated]. but I don't want to overwite query function on filter handler and want to use from value that returned by this common handler filed (mydevel_handler_filter_isnewmessage) that added to views filed. can wrote this idea by extend the standard views handler? what i do my dears? I wrote this but not work: this is return error
class mydevel_handler_filter_isnewmessage extends views_handler_filter_numeric {
var $always_multiple = TRUE;
function option_definition() {
$options = parent::option_definition();
return $options;
}
function operators() {
$operators = parent::operators();
return $operators;
}
function query() {
}
}
tank you a lot.

symfony2 chained selectors

I have three entities: Country, State and City with the following relationships:
When creating a City, I want two selectors, one for the Country and one for the State where the city belongs. These two selectors need to be chained so changing the Country will "filter" the States shown in the other selector.
I found a tutorial showing how to do this using Form Events but their example it's not quite my case. My entity City it's not directly related to the Country entity (they are indirectly related through State) so, when setting the country field in the City form (inside the class CityType), I'm forced to declare that field as 'property_path'=>false as you can see in the code below:
class CityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('country', 'entity', array(
'class'=>'TestBundle:Country',
'property'=>'name',
'property_path'=>false //Country is not directly related to City
));
$builder->add('name');
$factory = $builder->getFormFactory();
$refreshStates = function ($form, $country) use ($factory)
{
$form->add($factory->createNamed('entity', 'state', null, array(
'class' => 'Test\TestBundle\Entity\State',
'property' => 'name',
'query_builder' => function (EntityRepository $repository) use ($country)
{
$qb = $repository->createQueryBuilder('state')
->innerJoin('state.country', 'country');
if($country instanceof Country) {
$qb->where('state.country = :country')
->setParameter('country', $country);
} elseif(is_numeric($country)) {
$qb->where('country.id = :country')
->setParameter('country', $country);
} else {
$qb->where('country.name = :country')
->setParameter('country', "Venezuela");;
}
return $qb;
}
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if($data == null)
return;
if($data instanceof City){
if($data->getId()) { //An existing City
$refreshStates($form, $data->getState()->getCountry());
}else{ //A new City
$refreshStates($form, null);
}
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshStates)
{
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('country', $data)) {
$refreshStates($form, $data['country']);
}
});
}
public function getName()
{
return 'city';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Test\TestBundle\Entity\City');
}
}
The problem is that when I try to edit an existing City, the related Country is not selected by default in the form. If I remove the line 'property_path'=>false I get (not surprisingly) the error message:
Neither property "country" nor method "getCountry()" nor method "isCountry()" exists in class "Test\TestBundle\Entity\City"
Any ideas?
OK, I finally figured out how to do it properly:
namespace Test\TestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\Event\DataEvent;
use Test\TestBundle\Entity\Country;
use Test\TestBundle\Entity\State;
use Test\TestBundle\Entity\City;
class CityType extends AbstractType
{
public function buildForm(FormBuilder $builder, array $options)
{
$builder->add('name');
$factory = $builder->getFormFactory();
$refreshStates = function ($form, $country) use ($factory) {
$form->add($factory->createNamed('entity','state', null, array(
'class' => 'Test\TestBundle\Entity\State',
'property' => 'name',
'empty_value' => '-- Select a state --',
'query_builder' => function (EntityRepository $repository) use ($country) {
$qb = $repository->createQueryBuilder('state')
->innerJoin('state.country', 'country');
if ($country instanceof Country) {
$qb->where('state.country = :country')
->setParameter('country', $country);
} elseif (is_numeric($country)) {
$qb->where('country.id = :country')
->setParameter('country', $country);
} else {
$qb->where('country.name = :country')
->setParameter('country', null);
}
return $qb;
})
));
};
$setCountry = function ($form, $country) use ($factory) {
$form->add($factory->createNamed('entity', 'country', null, array(
'class' => 'TestBundle:Country',
'property' => 'name',
'property_path' => false,
'empty_value' => '-- Select a country --',
'data' => $country,
)));
};
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (DataEvent $event) use ($refreshStates, $setCountry) {
$form = $event->getForm();
$data = $event->getData();
if ($data == null) {
return;
}
if ($data instanceof City) {
$country = ($data->getId()) ? $data->getState()->getCountry() : null ;
$refreshStates($form, $country);
$setCountry($form, $country);
}
});
$builder->addEventListener(FormEvents::PRE_BIND, function (DataEvent $event) use ($refreshStates) {
$form = $event->getForm();
$data = $event->getData();
if(array_key_exists('country', $data)) {
$refreshStates($form, $data['country']);
}
});
}
public function getName()
{
return 'city';
}
public function getDefaultOptions(array $options)
{
return array('data_class' => 'Test\TestBundle\Entity\City');
}
}
The jQuery AJAX selector
$(document).ready(function () {
$('#city_country').change(function(){
$('#city_state option:gt(0)').remove();
if($(this).val()){
$.ajax({
type: "GET",
data: "country_id=" + $(this).val(),
url: Routing.generate('state_list'),
success: function(data){
$('#city_state').append(data);
}
});
}
});
});
I hope this will be helpful to somebody else facing the same situation.
Since your link to this approach is down i decided to complement your excelent answer so anyone can use it:
In order to execute the following javascript command:
url: Routing.generate('state_list'),
You need to install FOSJsRoutingBundle that can be found in here.
ATENTION: in the read me section of the bundle there are instalation instructions but there is something missing. If you use the deps with this:
[FOSJsRoutingBundle]
git=git://github.com/FriendsOfSymfony/FOSJsRoutingBundle.git
target=/bundles/FOS/JsRoutingBundle
You must run the php bin/vendors update before the next steps.
I'm still trying to find out what route is needed in the routing.yml for this solution to work. As soon as i discover i will edit this answer.
You will need a dedicated FieldType for the chained selectbox. And also an xhr controller that can return child options based on passed parameter. Ofcourse property_path should be set to false.

Resources