Multiple methods for action in API Platform - api-platform.com

I'm writing a custom action and I need to make it available for both GET (collection) and POST methods.
My annotation looks like this.
/**
* #Route(
* name="api_entity_custom",
* path="/entity/custom",
* defaults={
* "_api_resource_class"=Entity::class,
* "_api_collection_operation_name"="EntityCustom"
* }
* )
* #Method("GET")
*/
That works for GET, but when I add POST then I only see GET in docs (swagger)
#Method({"GET", "POST"})
If I change the order then I see POST but not GET
#Method({"POST", "GET"})
Is it possible to do this? How?
EDIT:
I'm using a structure like this
//Path/To/Entity/Action/EntityCustomAction.php
class EntityCustomAction
{
/**
* #Route(
* name="api_entity_custom",
* path="/entity/custom",
* defaults={
* "_api_resource_class"=Entity::class,
* "_api_collection_operation_name"="EntityCustom"
* }
* )
* #Method("GET")
*/
public function __invoke($data)
{
...
which is enabled in routing
entity:
resource: '#EntityBundle/Action/'
type: 'annotation'

You can do it in following way:
Action 1:
/**
* #Route("/data/save", name="data_save")
* #Method({"GET"})
* #Template()
*/
public function dataSaveViewAction()
{
// code here...
}
Action 2:
/**
* #Route("/data/save", name="data_save")
* #Method({"POST"})
*/
public function dataSaveAction(Request $request)
{
// code here ...
}

The problem here is that you are using the same name for both actions. However, the name of a route must be unique. If not, API-Platform won't display it. You should do something like this :
Action 1:
/**
* #Route("/data/save", name="data_save_get") // Choose a unique name
* #Method({"GET"})
* #Template()
*/
public function dataSaveViewAction()
{
// code here...
}
Action 2:
/**
* #Route("/data/save", name="data_save_post") // same here
* #Method({"POST"})
*/
public function dataSaveAction(Request $request)
{
// code here ...
}

Related

Doctrine Event Listener for adding/removing Many to Many relations

I make heavy use of Entity Listeners for logging purposes, generally works really well and keeps all the code out of the controllers/services.
One thing I haven't been able to achieve is logging of items added to a ManyToMany relation. In this instance I want to log when a size is added/removed from a product
/**
* #ORM\Entity
* #ORM\EntityListeners({"EventListener\ProductListener"})
* #ORM\Table(name="products")
*/
class Product
{
// ...
/**
* #var ArrayCollection
*
* #ORM\ManyToMany(targetEntity="Size")
* #ORM\JoinTable(name="productSizes",
* joinColumns={#ORM\JoinColumn(name="productId", referencedColumnName="productId")},
* inverseJoinColumns={#ORM\JoinColumn(name="sizeId", referencedColumnName="sizeId")}
* )
*/
protected $sizes;
/**
* #param Size $size
* #return Product
*/
public function addSize(Size $size)
{
$this->sizes[] = $size;
return $this;
}
/**
* #param Size $size
*/
public function removeSize(Size $size)
{
$this->sizes->removeElement($size);
}
/**
* #return ArrayCollection
*/
public function getSizes()
{
return $this->sizes;
}
// ...
}
Then inside the entity listener
class ProductListener
{
// ...
/**
* #ORM\PostPersist
*/
public function postPersistHandler(Product $product, LifecycleEventArgs $args)
{
$this->getLogger()->info("Created product {$product->getSku()}", [
'productId' => $product->getId()
]);
}
/**
* #ORM\PostUpdate
*/
public function postUpdateHandler(Product $product, LifecycleEventArgs $args)
{
$context = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($product);
$context['productId'] = $product->getId();
$this->getLogger()->info("Updated product", $context);
}
// ...
}
So how can I get the colours added/removed from the unit of work? I'm assuming this is available somewhere but I can't find it.
In your ProductListener
$product->getSizes() returns instance of Doctrine\ORMPersistentCollection. Then you can call 2 methods:
- getDeleteDiff - returns removed items
- getInsertDiff - returns added items

Laravel 4.2 - ReflectionException (-1)

I am getting following error:
ReflectionException (-1)
Class PhotosController does not exist
This is my route:
Route::resource('photos', ' PhotosController');
When I change to Route::get('photos', 'PhotosController#index'); it is working fine, but using resource it is falling? What is going on?
PhotosController:
<?php
class PhotosController extends \BaseController {
/**
* Display a listing of the resource.
* GET /photos
*
* #return Response
*/
public function index()
{
return Photo::all();
}
/**
* Show the form for creating a new resource.
* GET /photos/create
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
* POST /photos
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
* GET /photos/{id}
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
* GET /photos/{id}/edit
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
* PUT /photos/{id}
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
* DELETE /photos/{id}
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
If composer dump-autoload doesn't fix it, then it is probably a typo in the class name or routes file, or incorrectly using subdirectories/namespaces on your controllers.

Having trouble understanding links in laravel 4

I have a problem with link_to_action in laravel 4
In laravel 3 i would show a link like
{{ HTML::link_to_action('user/create', 'Create User') }}
But since I've switched to laravel 4 I'm creating my controllers like this UserController but when I try to use the HTML
{{ HTML::linkAction('user/create', 'Create User') }}
It gives me and error that action doesn't exist even though there's a method named create.
Any help would be greatly appreciated.
And here's my controller
<?php
class UserController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
// L3
{{ HTML::link_to_action('user#create', 'Create User') }}
// L4
{{ HTML::linkAction('UserController#create', 'Create User') }}
edit:
// I think you missed that entry in your routes.php
Route::resource('user', 'UserController');

Symfony2+Doctrine - Validating one-to-many collection of entities

I have a form to create a new entity. That entity has a collection of other entities that are also entered in that form.
I want to use the validation options of the entity in the collection to validate those entities but it does not work. The validation rules of the "main" entity (Person) are checked, but the validation rules of the entities in the addressList collection (Address) are not checked. When I input invalid information in the fields, the submitted form is successfully validated.
In this example, the annotation for street is not used on validation.
class Person
{
...
/**
* #ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
*/
protected $addressList;
....
}
class Address
{
...
/**
* #ORM\ManyToOne(targetEntity="Person", inversedBy="addressList")
* #ORM\JoinColumn(name="person_id", referencedColumnName="id", onDelete="CASCADE")
*/
protected $owner;
/**
* #ORM\Column(type="string", length=75)
* #Assert\MinLength(
* limit=3,
* message="Street must have atleast {{ limit }} characters."
* )
*/
protected $street;
...
}
How can I get the form to validate the supplied Address entities?
I had the same problem but was solved with:
/**
* #ORM\OneToMany(
* targetEntity="Entity",
* mappedBy="mappedEntity",
* cascade={"persist" , "remove"}
* )
* #Assert\Valid
*/
I use this:
use Symfony\Component\Validator\ExecutionContextInterface;
class Person
{
...
/**
* #ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
*/
protected $addressList;
....
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context)
{
if (!$this->getAddressList()->count()) {
$context->addViolationAt(
'addressList',
'You must add at least one address',
array(),
null
);
}
}
}
http://symfony.com/doc/current/reference/constraints/Callback.html
Just add annotation assert like following
/**
* #Assert\Count(
* min = "1",
* minMessage = "You must specify at least one"
* )
* #Assert\Valid
*
*/
protected $name_of_collection_property;
You could also use the "Valid" constraint with the "All" constraint :
/**
* #ORM\OneToMany(targetEntity="Address", mappedBy="owner", cascade={"persist", "detach"})
* #Assert\All({
* #Assert\Valid
* })
*/
protected $addressList;

Zend check if view exist - class does not work

I have found this class:
https://github.com/lloydwatkin/Demos/blob/master/zendframework/renderifexists/RenderIfExists.php
The code looks like this:
<?php
/**
* View helper to render a view file if it exists
*
* #author Lloyd Watkin
* #since 12/12/2010
* #package Pro
* #subpackage View
*/
/**
* View helper to render a view file if it exists
*
* #author Lloyd Watkin
* #since 12/12/2010
* #package Pro
* #subpackage View
*/
class Pro_View_Helper_RenderIfExists
extends Zend_View_Helper_Abstract
{
/**
* Errors
*
* #var string
*/
const INVALID_FILE = 'Invalid file parameter';
/**
* Holds file name for processing
*
* #var string
*/
protected $_file;
/**
* Takes a products options array and converts to a formatted string
*
* #param string $file
* #return string
*/
public function renderIfExists($file)
{
if (!is_string($file) || empty($file)) {
throw new Zend_View_Exception(self::INVALID_FILE);
}
$this->_file = $file;
if (false === $this->_fileExists()) {
return '';
}
return $this->view->render($file);
}
/**
* Check to see if a view script exists
*
* #return boolean
*/
protected function _fileExists()
{
$paths = $this->view->getScriptPaths();
foreach ($paths as $path) {
if (file_exists($path . $this->_file)) {
return true;
}
}
return false;
}
}
I want to check if a view exists; If it does: Show it.
I have placed the file in my /library/. When I call $this->renderIfExists('info-box.phtml'); from the controller I get this error:
Message: Method "renderIfExists" does not exist and was not trapped in __call()
How can I fix this?
Thanks in advance!
to call a view helper from the controller, you should use:
$this->view->renderIfExists()
bit late to this, but the code you've got above is something I wrote. Have you registered the helper path, if w would the framework know where to load the file?

Resources