Sylius, search products by slug not working - symfony

i'm trying to filter products by slug, using:
$this->get('sylius.repository.product')->findOneBy(array('slug' => $slug));
I've tried using findBy and findOneBySlug, but it always says that Product does not have a "slug" property:
Unrecognized field: slug
or
Entity 'Sylius\Component\Core\Model\Product' has no field 'slug'. You can therefore not call 'findOneBySlug' on the entities' repository
but the documentation on their website says it should be working:
http://docs.sylius.org/en/latest/components_and_bundles/bundles/SyliusProductBundle/product.html
$product = $repository->findOneBy(array('slug' => 'my-super-product')); // Get one product by defined criteria.

I think that doesn't work, because the slug is available on the translations of the product. There are some default methods in the repository available that might be helpful to you, e.g.: findOneByChannelAndSlug or findByName.
Alternatively, you can construct it yourself when extending the product repository:
/**
* #param string $name
* #param string $locale
* #return array
*/
public function findBySlug(string $slug, string $locale): ?ProductInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
->andWhere('translation.slug = :slug')
->setParameter('slug', $slug)
->setParameter('locale', $locale)
->getQuery()
->getOneOrNullResult()
;
}

Related

Symfony3: Default parameter gets first entry even when defaulted to null

I am trying to create an action in my controller that handles a null value for category if it's not passed in.
I've tried annotating 2 routes (one without /{category}) but in every case, when I do not supply a category in the URL, Symfony retrieves the 1st category it can find.
#Route("/accounts/{id}/categories/{category}", defaults={"category" = null})
The action definition looks like this:
public function categoryAction(Request $request, Account $account, Category $category)
I have also tried $category = null in the action, but that does not make a difference.
How can I make this action have a $category with a value of null if the category is not defined in the url?
Update:
To be clear, here is the full annotation and function definition with comments on my xdebug results:
/**
* #Route("/accounts/{id}/categories")
* #Route("/accounts/{id}/categories/{category}, defaults={"category" = null}")
*/
public function categoryAction(Request $request, Account $account, Category $category = null)
{
// When I set a breakpoint here, $category is populated with
// the first category result in the database.
// This is when visiting: http://localhost:8000/accounts/1/categories
You can define multiple routes for same actions, maybe try something like :
/**
* #Route("/accounts/{id}/categories")
* #Route("/accounts/{id}/categories/{category}")
* #Template()
*/
public function categoryAction(Request $request, Account $account, Category $category)
{
And if you try to access /accounts/{id}/categories, $category will be null
I believe this is the change you should make:
/**
* #Route("/accounts/{id}/categories", defaults={"category" = null}")
* #Route("/accounts/{id}/categories/{category})
*/
public function categoryAction(Request $request, Account $account, Category $category)
{
...
Can you try it and let us know? I haven't tested it, but I think it's right.

How to correctly create Custom Post Type with custom fields through WP REST API V2

How do I correctly create a custom post type record through the wp rest api v2 with custom fields? Unable to create custom fields or update them.
I have installed the superlist and superlist-child theme in a self hosted wordpress installation.
This theme uses Custom Taxonomies for categories, locations, Custom Post Types called businesses and custom fields in post meta for the Custom Post Type
I am trying to import data to site using rest api v2 and have successfully created the custom categories and locations.
I used the REST API Enabler plugin to register the custom endpoints and the custom fields.
Using the businesses endpoint http://mysite/wp-json/wp/v2/businesses I can upload a new business through the api but the record created ignores all the meta keys
eg Given the following body
body = {
title: company_name,
listing_address: [address],
listing_map_location_latitude: [c.lat],
listing_map_location_longitude: [c.lon],
content: c.description,
email: c.email,
facebook: [c.facebook],
image_url: c.image_url,
locations: [c.city.server_id],
listing_categories: c.categories.pluck(:server_id),
listing_street_view: ["on"]
status:"publish"
}
request = HTTParty.post(POSTS_END_POINT, body: body, headers: headers)
Correctly attaches the business to the correct location and custom categories (listing_categories) previously created through the REST api however none of the custom fields (wp_postmeta table) are populated e.g. listing_locations lon and lat fields and listing_address
I can query the record uploaded through the rest api and I get a response like this
$ rake upload:test
Result: {"id"=>1749, "date"=>"2016-02-20T05:06:01", "date_gmt"=>nil, "guid"=>{"rendered"=>"http://highstreetbeacons.com/?post_type=business&p=1749"}, "modified"=>"2016-02-20T05:06:01", "modified_gmt"=>nil, "slug"=>"", "type"=>"business", "link"=>"http://highstreetbeacons.com/?post_type=business&p=1749", "title"=>{"rendered"=>"Birmingham Museum and Art Gallery, Chamberlain Square, Birmingham, B3 3DH"}, "content"=>{"rendered"=>"<p>A description</p>\n"}, "author"=>1, "featured_media"=>0, "comment_status"=>"open", "ping_status"=>"closed", "listing_categories"=>[3779, 4095, 4061], "locations"=>[330], "_links"=>{"self"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/businesses/1749"}], "collection"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/businesses"}], "about"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/types/business"}], "author"=>[{"embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/users/1"}], "replies"=>[{"embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/comments?post=1749"}], "https://api.w.org/attachment"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/media?parent=1749"}], "https://api.w.org/term"=>[{"taxonomy"=>"listing_categories", "embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/listing_categories?post=1749"}, {"taxonomy"=>"locations", "embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/locations?post=1749"}]}}
This totally ignores the meta keys.
If in the admin area I manually hit the update button for the generated business I can then re-query through the api and get all the correct fields returned but an POST request to update (Surely should be a PUT) the record still won't set any of the custom fields
e.g.
rake upload:test
Result: {"id"=>1745, "date"=>"2016-02-20T04:53:17", "date_gmt"=>nil, "guid"=>{"rendered"=>"http://highstreetbeacons.com/?post_type=business&p=1745"}, "modified"=>"2016-02-20T04:53:17", "modified_gmt"=>"2016-02-20T04:53:17", "slug"=>"", "type"=>"business", "link"=>"http://highstreetbeacons.com/?post_type=business&p=1745", "title"=>{"rendered"=>"Birmingham Museum and Art Gallery, Chamberlain Square, Birmingham, B3 3DH"}, "content"=>{"rendered"=>"<p>A description</p>\n"}, "author"=>1, "featured_media"=>0, "comment_status"=>"open", "ping_status"=>"closed", "listing_categories"=>[3779, 4095, 4061], "locations"=>[330], "listing_featured_image"=>[""], "listing_banner"=>["banner_featured_image"], "listing_opening_hours"=>["a:7:{i:0;a:4:{s:11:\"listing_day\";s:6:\"MONDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:1;a:4:{s:11:\"listing_day\";s:7:\"TUESDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:2;a:4:{s:11:\"listing_day\";s:9:\"WEDNESDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:3;a:4:{s:11:\"listing_day\";s:8:\"THURSDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:4;a:4:{s:11:\"listing_day\";s:6:\"FRIDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:5;a:4:{s:11:\"listing_day\";s:8:\"SATURDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}i:6;a:4:{s:11:\"listing_day\";s:6:\"SUNDAY\";s:17:\"listing_time_from\";s:0:\"\";s:15:\"listing_time_to\";s:0:\"\";s:14:\"listing_custom\";s:0:\"\";}}"], "listing_map_location"=>["a:2:{s:8:\"latitude\";s:0:\"\";s:9:\"longitude\";s:0:\"\";}"], "listing_street_view_location_latitude"=>["37.812405"], "listing_street_view_location_longitude"=>["-122.47607800000003"], "listing_street_view_location_heading"=>["-18"], "listing_street_view_location"=>["a:5:{s:8:\"latitude\";s:9:\"37.812405\";s:9:\"longitude\";s:19:\"-122.47607800000003\";s:4:\"zoom\";s:1:\"1\";s:7:\"heading\";s:3:\"-18\";s:5:\"pitch\";s:2:\"25\";}"], "listing_locations"=>["a:1:{i:0;s:10:\"birmingham\";}"], "listing_listing_category"=>["a:3:{i:0;s:7:\"museums\";i:1;s:10:\"coffee-tea\";i:2;s:13:\"art-galleries\";}"], "_links"=>{"self"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/businesses/1745"}], "collection"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/businesses"}], "about"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/types/business"}], "author"=>[{"embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/users/1"}], "replies"=>[{"embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/comments?post=1745"}], "https://api.w.org/attachment"=>[{"href"=>"http://highstreetbeacons.com/wp-json/wp/v2/media?parent=1745"}], "https://api.w.org/term"=>[{"taxonomy"=>"listing_categories", "embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/listing_categories?post=1745"}, {"taxonomy"=>"locations", "embeddable"=>true, "href"=>"http://highstreetbeacons.com/wp-json/wp/v2/locations?post=1745"}]}}
I have just created a plugin to register the custom fields rather than relying on REST API Enabler plugin with just one field to see if I can get that to work
<?php
/**
* Plugin Name: Jamesc Register API Fields
* Plugin URI: http://danielpataki.com
* Description: This plugin exposes business meta data mfields to REST API.
* Version: 1.0.0
* Author: Smiler
*/
/**
* Use arbitrary functions to add a field
*/
add_action( 'rest_api_init', 'register_something_random' );
function slug_register_something_random() {
register_rest_field( 'business',
'listing_address',
array(
'get_callback' => 'get_meta_field',
'update_callback' => 'update_meta_field',
'schema' => null,
)
);
}
/**
* Handler for getting custom field data.
*
* #since 0.1.0
*
* #param array $object The object from the response
* #param string $field_name Name of field
* #param WP_REST_Request $request Current request
*
* #return mixed
*/
function get_meta_field( $object, $field_name, $request ) {
return get_post_meta( $object[ 'id' ], $field_name );
}
/**
* Handler for updating custom field data.
*
* #since 0.1.0
*
* #param mixed $value The value of the field
* #param object $object The object from the response
* #param string $field_name Name of field
*
* #return bool|int
*/
function update_meta_field( $value, $object, $field_name ) {
if ( ! $value || ! is_string( $value ) ) {
return;
}
return update_post_meta( $object->ID, $field_name, strip_tags( $value ) );
}
But this has no effect.
I am now totally stuck having tried everything I can think of.
There was a glaringly obvious problem with my wordpress plugin where the add action function name did not match the actual function name
register_something_random and slug_register_something_random()
add_action( 'rest_api_init', 'register_something_random' );
function slug_register_something_random() {
Should be
add_action( 'rest_api_init', 'register_something_random' );
function register_something_random() {
Made this change and all is now ok

Key "catTitle" for array with keys "0" does not exist in EagleShopBundle:global:product.html.twig

I'm trying to join two tables and print a value in twig template but I'm having this issue.
This is my Controller action.
/**
* #Route("products/display/{id}")
* #Template()
*/
public function displayAction($id) {
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p', 'pc.catTitle')
->from('EagleShopBundle:Products', 'p')
->leftJoin('EagleShopBundle:ProductCategory', 'pc', \Doctrine\ORM\Query\Expr\Join::WITH, 'pc.id = p.category')
->where($qb->expr()->eq('p.id', '?5'))
->setParameter(5, $id);
$product = $qb->getQuery()->getResult();
return $this->render("EagleShopBundle:global:product.html.twig", array(
'product' => $product,
'image_path' => '/bundles/eagleshop/images/'
));
}
This is my twig file line related to the issue,
<small class="pr_type">{{product.catTitle}}</small>
But instead of printing 'catTitle' I'm having this issue,
Key "catTitle" for array with keys "0" does not exist in
EagleShopBundle:global:product.html.twig
It is simple: getResult() returns an array of objects, even if there is only one. If you are expecting that this query would return only one object use getOneOrNullResult(). But after that and before you are displaying results you need to check if smth is returned (for example: product instanceof Products) or null is returned.

Key "productTitle" for array with keys "0, catTitle" does not exist in EagleShopBundle:global:product.html.twig

I'm trying to join two tables and print a value in twig template but I'm having this issue.
This is my Controller action.
/**
* #Route("products/display/{id}")
* #Template()
*/
public function displayAction($id) {
$em = $this->container->get('doctrine.orm.entity_manager');
$qb = $em->createQueryBuilder();
$qb->select('p, pc.catTitle')
->from('EagleShopBundle:Products', 'p')
->leftJoin('EagleShopBundle:ProductCategory', 'pc', \Doctrine\ORM\Query\Expr\Join::WITH, 'pc.id = p.category')
->where($qb->expr()->eq('p.id', '?5'))
->setParameter(5, $id);
$product = $qb->getQuery()->getOneOrNullResult();
return $this->render("EagleShopBundle:global:product.html.twig", array(
'product' => $product,
'image_path' => '/bundles/eagleshop/images/'
));
}
This is my twig file line related to the issue,
<h1>{{product.productTitle}}</h1>
I guess issue is related to this line
$qb->select('p, pc.catTitle')
This is the error I get,
Key "productTitle" for array with keys "0, catTitle" does not exist in
EagleShopBundle:global:product.html.twig
You could try next query:
$qb->select('p, partial pc.{id, catTitle}')
// if you need full productCategory object then write just 'p, pc'
->from('EagleShopBundle:Products', 'p')
->leftJoin('p.category', 'pc')
//productCategory is the field
//in product entity which has relation to product category entity,
//paste your field (not column!) name here
//if it is not productCategory
->where('p.id = :productId')
->setParameter('productId', $id);
P.S.
It is better to move queries to entity repositories :)
P.P.S.
Doctrine partial objects
UPD
Fixed query - with right field name

Unable to deal with MySQL column of type "SET" in Sonata Admin

I have a column in MySQL table defined as follows:
`fuel_type` set('gasoline','diesel','LPG','CNG','ethanol','bio-diesel','hydrogen') DEFAULT NULL,
I generated entities usingn doctrine's database introspection feature. The generated code in the entity in question is this:
/**
* #var simplearray
*
* #ORM\Column(name="fuel_type", type="simplearray", nullable=true)
*/
private $fuelType;
/**
* Set fuelType
*
* #param \simplearray $fuelType
* #return NomEngine
*/
public function setFuelType(\simplearray $fuelType)
{
$this->fuelType = $fuelType;
return $this;
}
/**
* Get fuelType
*
* #return \simplearray
*/
public function getFuelType()
{
return $this->fuelType;
}
In my sonata admin class the configureFormsFields method is thefined this way:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('fuel_type', 'choice', array(
'choices' => array(
'gasoline' => 'Gasoline',
'diesel' => 'Diesel',
'LPG' => 'LPG',
'CNG' => 'CNG',
'ethanol' => 'Ethanol',
'bio-diesel' => 'Bio Diesel',
'hydrogen' => 'Hydrogen'
),
'multiple' => true,
'required' => false
));
;
}
The problem is that after I try to save record in the database I get this exception:
Unknown column type "simplearray" requested. Any Doctrine type that you use has to be registered with \Doctrine\DBAL\Types\Type::addType(). You can get a list of all the known types with \Doctrine\DBAL\Types\Type::getTypesMap(). If this error occurs during database introspection then you might have forgot to register all database types for a Doctrine Type. Use AbstractPlatform#registerDoctrineTypeMapping() or have your custom types implement Type#getMappedDatabaseTypes(). If the type name is empty you might have a problem with the cache or forgot some mapping information.
500 Internal Server Error - DBALException
I tried a couple of things to resolve this issue:
I noticed, that the generated type is 'simplearray', but in doctrine this type is 'simple_array'. I thought there was a typo.
Without success I tried to map simplearray to simple_array in config.yml :
doctrine:
dbal:
mapping_types:
simplearray: simple_array
After that I tried to change simplearray to simple_array in the entity. I got this error:
Catchable Fatal Error: Argument 1 passed to Acme\AdminBundle\Entity\Engine::setFuelType() must be an instance of simple_array, array given,
I thought that the admin class was passing array, and the entity was expecting simple_array, so I changed simple_array to array in the entity.
Now the error was this:
Could not convert database value "" to Doctrine Type array 500 Internal Server Error - ConversionException
Any insights about dealing with set columns in Sonata Admin will be greatly appreciated!
Your entity setter & getter are wrong too and should deals with a PHP array as Doctrine is converting it, I think you must change them to:
/**
* Set fuelType
*
* #param array $fuelType
*
* #return NomEngine
*/
public function setFuelType(array $fuelType)
{
$this->fuelType = $fuelType;
return $this;
}
/**
* Get fuelType
*
* #return array
*/
public function getFuelType()
{
return $this->fuelType;
}
It seems that Doctrine doesn't handle well the set syntax in MySQL. I see 2 ways you could solve your issue:
Change your MySQL schema to put in a json array or a varchar instead of your set. Probably the fastest way.
You might not have the luxury to change your schema. In that case, define a custom Doctrine type to suit your needs as described there: http://docs.doctrine-project.org/en/2.0.x/cookbook/mysql-enums.html#solution-2-defining-a-type ; you'll need then to register it to Symfony as explained there: http://symfony.com/doc/current/cookbook/doctrine/dbal.html#registering-custom-mapping-types
Hope it helps!

Resources