Extract info from html with Guzzle - symfony

I'm trying to extract Vehicle ID with this code:
$client = new Client();
$request = $client->get('http://www.truck1.eu/_TEN_auto_1522980_Truck_Chassis_MAN_TGA_18_320_BL_Platou_9_80m_lang_manuelles_Getriebe_Euro_4_Motor.html', ['allow_redirects' => false]);
$html = $request->getBody(true);
$crawler = new Crawler();
$crawler->addContent($html);
print $crawler->filterXPath('//*[#id="content"]/div/div[2]/table/tbody/tr[2]/td')->text();
But for some reason i can't get this working. I'm using Guzzle and DomCrawler from Symfony.

Try this XPath to grab the td next to the th containing the 'Vehicle ID' label (and to avoid some unnecessary ancestral dependencies):
//td[preceding-sibling::th = 'Vehicle ID']

Related

web scrape using simple html DOM parser

How to extract specific details like name and price of a product from Amazon platform using simple html DOM parser. for example: (product-image, name and price).
$httpClient = new \GuzzleHttp\Client();
$response = $httpClient->get('https://www.floridaleagueofcities.com/research-resources/municipal-directory/');
$htmlString = (string) $response->getBody();
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML($htmlString);
$xpath = new DOMXPath($doc);
$titles = $xpath->evaluate('//div[#class="accordion-body"]//ul//li/a');

Symfony - findAll() returns ok if render, empty if response

I created a custom Bundle in my Symfony 2.7 website.
One of the entity works perfectly :
Entity class is Version.php
Custom repository is VersionRepository
The MainController.php of my bundle is :
$repository = $this->getDoctrine()->getManager()->getRepository('MyBundle:Version');
$versions = $repository->findAll();
return $this->render('IpadUpdaterBundle:Version:index.html.twig', array(
'versions' => $versions
));
Output in Twig is perfect :
My first version row
My second version row
BUT ... if I want to change the ouput and render a JSON response with the same datas, I make this change in the controller :
$repository = $this->getDoctrine()->getManager()->getRepository('MyBundle:Version');
$versions = $repository->findAll();
$versions = json_encode($versions);
$rep_finale = new Response($versions);
$rep_finale->headers->set('Content-Type', 'application/json');
return $rep_finale;
or :
$repository = $this->getDoctrine()->getManager()->getRepository('MyBundle:Version');
$versions = $repository->findAll();
return new JsonResponse($versions);
.. and the ouput becomes an empty array with 2 children :
[{},{}]
!I can not understand what's wrong and what changes I would implement to solve this issue. I already use "use Symfony\Component\HttpFoundation\Response" and "use Symfony\Component\HttpFoundation\JsonResponse" in the header of my controller.php.
Thanks for your help !
json_encode and JSONResponse don't do well with complex entities, especially with links to other complex entities. Mostly, those are for encoding strings or arrays as JSON.
If you only need some of the information from your entities you can make an array and pass that.
$repository = $this->getDoctrine()->getManager()->getRepository('MyBundle:Version');
$versionInformation = $repository->getIdNameOfVersionsAsArray();
$versionInformation = array_column($versionInformation, 'id', 'name');
return new JSONResponse($versionInformation);
You'll have to implement the getIdNameOfVersionsAsArray function in your repository to just return an array of values.
If you need every field of your version entity it may be easier to use a serializer. JMSSerializer Bundle is the most popular and well-supported.
$serializer = $this->container->get('serializer');
$versionJSON = $serializer->serialize($versions, 'json');
return new Response($versionJSON);
And you'll have to implement annotations in your entities to tell the serializer what to do. See the link above for that.

Symfony test get form errors

If I have a functional test like:
public function testCreate()
{
$client = $this->makeClient();
$crawler = $client->request('POST', "/post/new");
$form = $crawler->selectButton("Create Post")->form();
$values = $form->getPhpValues();
$values['post']['title'] = 'test';
$values['post']['content'] = null; // Should fail because it isn't a string.
$crawler = $client->request($form->getMethod(), $form->getUri(), $values,
$form->getPhpFiles());
assertEquals() // What goes here?
}
How do I use the crawler to get the form errors and compare them?
I see two possible solutions for you:
Use the crawler to check for the actually rendered form errors in your rendered HTML code.
Make use of the profiler and access the form data collector: http://symfony.com/doc/current/testing/profiling.html

why Update and insert in same method is not working in symfony?

I am using symfony3 with window 7:
This method should work for both action update and add.But its behavior only insertion. while i am setting $id also.
/**
* #Route("entity/entity/{id}", name="entity_entity",defaults={"id" = 0})
*/
public function entityAction(Request $request,$id){
$action = false;
$arr_XYZ_data = array();
$arr_XYZ_prepare_data = array();
$form_title = 'Add New XYZ';
$obj_XYZ = new XYZ();
$form = $this->createForm(XYZType::class, $obj_XYZ);
if($id!=0){
$obj_repo = $this->getDoctrine()->getRepository('AppBundle:XYZ');
$arr_XYZ_data = $obj_repo->find($id);
if($arr_XYZ_data){
$action = true;
$form_title = 'Update XYZ';
$arr_XYZ_data = $obj_repo->findXYZById($id);
$arr_XYZ_prepare_data = $this->_prepareData($arr_XYZ_data);
}
}
$form->handleRequest($request);
if (($form->isSubmitted())) {
$obj_XYZ->setXYZId($id);
$str_hiddenfield_result = $form->get('extraformfield')->getData();
$arr_hiddenfield_result = explode('&',$str_hiddenfield_result);
$obj_XYZ->setDef($obj_XYZ->getDef()->getDefId());
$obj_XYZ->setAbc($arr_hiddenfield_result[3]);
$obj_XYZ->setAuthor(1); //ldap session value
$em = $this->getDoctrine()->getManager();
$em->persist($obj_XYZ);
$em->flush();
$this->addFlash('success', 'Your record has been added successfully!');
return $this->redirectToRoute('XYZ_index', array(), 301);
}
}
anyone can suggest me how can i achieve this ?
Some remarks:
Are you calling the right URL (with $id != 0)?
Check if the form that is submitted is valid before doing anything.
Why are you calling setId() on the entity? Doctrine will set the ID of a new and persisted entity.
Finally, you are using a 301 redirect, which is a Permanent Redirect. This means that the browser will redirect any request to entity/entity/{id} to whichever URL is generated by XYZ_index.
I would recommend the following things:
Use isValid instead of isSubmitted for the form (it might not be valid but you are persisting its data!).
Use the built-in Forms, which you can load with an entity (so that you do not have to process data fields yourself).
Return a $this -> redirectToRoute('...', array(...)) instead of a 301.
After a lot of R&D i got the solution:
use:
$em->merge($obj_XYZ) instead of $em->persist($obj_XYZ);
before
$em->flush();

Symfony2 Functional test: Passing form data directly

I am using phpunit to run functional tests but I am having a problem with a few of the forms. The problem is that phpunit is not aware of JS, and I have a form with a dynamically populated select box that needs jQuery.
So I need to pass the form data directly. The 'book' gives the following example:
// Directly submit a form (but using the Crawler is easier!)
$client->request('POST', '/submit', array('name' => 'Fabien'));
When I used this example the controller didn't receive any of the form data. Intially I saw that passing the array key 'name' wasn't correct in my situation as I needed the form name which was 'timesheet' in my code. So I tried something like:
$client->request('POST', '/timesheet/create', array('timesheet[project]' => '100'));
But this still didn't work. In the controller I tried to understand what was happening and what if anything was being received:
$postData = $request->request->get('timesheet');
$project = $postData['project'];
This didn't work and $project remained empty. However if I used the following code I got the value:
$project = $request->request->get('timesheet[project]');
But clearly that's not what I want. Atleast though I can see that there is some POST data. My last attempt was to try the following in the test method:
$this->crawler = $this->client->request('POST', '/timesheet/create/', array('timesheet' => array(project => '100'));
So I am trying to pass a 'timesheet' array as the first element of the request parameter array. But with this I get the error:
Symfony\Component\Form\Exception\UnexpectedTypeException: Expected argument of type "array", "string" given (uncaught exception) at /mnt/hgfs/pmt/src/vendor/symfony/src/Symfony/Component/Form/Form.php line 489
I would be very happy if someone can expand on what's in the 'book' about how I am supposed to get this working.
Form bind in controller:
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
$postData = $request->request->get('timesheet');
$project = $postData['project'];
$timesheetmanager = $this->get('wlp_pmt.timesheet_db_access');
$timesheetmanager->editTimesheet($timesheet);
return $this->redirect($this->generateUrl('timesheet_list'));
}
}
If you are wanting to know how to inject arrays of POST data using the test client...
In your test method, do something like
$crawler = $client->request('POST', '/foo', array(
'animal_sounds' => array(
'cow' => 'moo',
'duck' => 'quack'
)
); // This would encode to '/foo?animal_sounds%5Bcow%5D=moo&animal_sounds%5Bduck%5D=quack'
$this->assertTrue( ... );
In the controller, you would access your params like this:
$data = $request->request->get('animal_sounds');
$cowNoise = $data['cow'];
$duckNoise = $data['duck'];
Or you could just use the forms API if the test method was injecting valid form data...
do you have a $request parameter in your action?
that was the reason why my request->get() was empty:
//WRONG
public function projectAction()
{
$request = Request::createFromGlobals();
$project = $request->request->get('timesheet[project]');
//$project will be empty
}
//CORRECT
public function projectAction(Request $request)
{
$project = $request->request->get('timesheet[project]');
//$project is not empty
}
see
How do I create a functional test which includes a POST to a page with parameters?
Try to use $form->bind($clientData) instead of $form->bindRequest($request).

Resources