Typo3 extbase validating custom or manual objects - validation

I have created extbase extension, there for some reason I need to create object manually in create action.
My create action looks like this,
/**
* action create
*
* #return void
*/
public function createAction() {
$newObj = new \TYPO3\Myext\Domain\Model\Modelname();
$newObj->setMyval('value');
$this->myrepository->add($newObj);
}
Here the problem is its not validating for require field, captcha etc even if I mention #validate NotEmpty in model.
So how to make the validation of manually created object ?
It should throw error to form like out-of-the-box features.
Thank you.

Out of the box validation is only triggered on constructing model objects from GET/POST parameters according to your controller actions signature.

It should look something like this:
/**
* action create
* #param \TYPO3\Myext\Domain\Model\Modelname $newObject
* #return void
*/
public function createAction(\TYPO3\Myext\Domain\Model\Modelname $newObject) {
$this->myrepository->add($newObj);
}
Take a look at the extension_builder, create a model and let the new/create action be generated for you. That will give you a good example on the create action as well as on the new action where the form is being rendered.

Related

Laravel form request duplicate query

I want to fetch a record and perform validation with that.
So I see two option using validation in the controller and using form request
I prefer using form request
So according to a document I can fetch a record in Form request and use it.
But the problem is I need that record in the controller too, So if I going this way I load one record twice.
I'm solving my problem with property in the form request
for example
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$this->post = Post::find($this->input('id'));
return [
... // my rules base on $this->post
];
}
and then in the controller, I can access the post value
public function store(PostPublishCreate $request)
{
$request->post;
....
1.But I'm confused in this way, Is there a problem in my way? Is there a better solution to do it in laravel?
2.In this example I don't use dependency injection, So how I can approach this with dependency injection?
public function store(PostPublishCreate $request,Post $post)
{
// how to prevent to my record provided twice
// PostPublishCreate load post because of the rules
// Post loaded again with DI
....
I try to use the Rule class for my custom validation, But I'm not sure how to pass the record to Rule without reloading it
Form Request is not loading the record. It just validates the parameters present in the $request object. In the second example, $post is automatically retrieved by DI where then you can manipulate your record as you wish.

Using adapter pattern when consuming 3rd party APIs and creating a domain in Laravel

In my Laravel REST API project I mainly consume 3rd party APIs. For that, I have a 'Services' folder grouped by APIs (Accommodation, Planning, Discount etc) to send correct parameters to APIs and get the raw data.
I feel that I need to use adapter pattern here, because this 3rd party outputs need to be formatted.
Let me try to give an example.
I have an EventDao interface (Data access object) and one or multiple concrete EventDao classes like EventbriteDao.
I also have an adapter for each concrete DAO. e.g: EvenbriteAdapter
I will have some business logic somewhere so I need to have an Event entity class. To pass the adapter's data to the entity, I need an EventDTO class (data transfer object)
Finally I can call the eventDao (via interface thanks to Laravel's service providers)
I pass its raw output to the adapter, then adapter's output to the entity. Then I can call one of methods of the entity class. (After that I need to convert it to a proper json data, but it is the easy part.)
I don't get where to put other CRUD logic like updateEvent, deleteEvent, getAll etc. Should I call them directly in controller or create repositories (the repository pattern)? I am confused about it.
Would it be a good approach or over-engineering? Because I have 5-6 classes/interfaces other than controller.
Another problem is calling EventbriteAdapter directly in the controller. Should I have an interface for it? In this case I will need to bind both service and adapter interfaces to its implementations in AppServiceProvider.
My another concern is having collections for entity chunks. If I call getAll() method I can loop through the data and create an array of objects, but I am not comfortable with it. Laravel's collections would be useful, but I want to separate application layer from domain. What would be a good solution for it?
Here example codes for some of the files I mentioned are:
interface EventAdapter
{
public function getId();
public function getName();
public function getStartDate();
public function getLocationName();
}
class EventbriteAdapter implements EventInterface
{
private $raw;
public function __construct(array $raw)
{
$this->raw = $raw;
}
public function getName()
{
return $this->raw['name'];
}
public function getStartDate()
{
return $this->raw['start'];
}
public function getLocation()
{
return $this->raw['venue']['name'].' '.$this->raw['venue']['address'];
}
}
// Fetch event from Eventbrite (or other third-party)
$result = fetchEventFromEventbrite();
// Wrap event in adapter
$adapter = new EventbriteAdapter($result);
I don't get where to put other CRUD logic like updateEvent,
deleteEvent, getAll etc. Should I call them directly in controller or
create repositories (the repository pattern)? I am confused about it.
You can use the Gateway pattern to encapsulate all logic of interaction with 3rd party API. The gateway can contain methods to get data and save data. For example:
interface EventGatewayInterface
{
/**
* Get an event by id
*
* #param mixed $id unique identifier of an event
* #return Event the event
*/
public function getById($id);
/**
* Get all events
*
* #return Event[] list of events
*/
public function getAll();
/**
* Add an event
*
* #param Event $event the event which will be added
*/
public function add(Event $event);
/**
* Update an event
*
* #param Event $event the event which will be updated
*/
public function update(Event $event);
/**
* Delete an event
*
* #param Event $event the event which will be removed
*/
public function delete();
}
Would it be a good approach or over-engineering? Because I have 5-6
classes/interfaces other than controller.
In fact, you use the Adapter pattern to translate one representation (raw representation) to another (object representation). But the Adapter pattern is used to translate one program interface into a compatible program interface. To convert representations used the Mapper pattern. You can implement simple mapper for example:
class RawEventMapper
{
/**
* Map raw data to an event object
*
* #param array $data raw data
* #return Event the event object
*/
public function map(array $data)
{
$event = new Event();
$event->name = $data['name'];
$event->startDate = $data['start'];
$event->location = $data['venue']['name'].' '.$data['venue']['address'];
return $event;
}
}
and use it in Gateway to convert raw data to an object.
class ConcreteEventGateway implement EventGatewayInterface
{
/** #var RawEventMapper data mapper */
protected $mapper;
/**
* Constructor
*
* #param RawEventMapper $mapper data mapper
*/
public function __construct(RawEventMapper $mapper)
{
$this->mapper = $mapper;
}
/** #inheritdoc */
public function getById($id)
{
// get raw data from 3rd party API
return $this->mapper->map($raw);
}
}
Laravel's collections would be useful, but I want to separate
application layer from domain. What would be a good solution for it?
If you aim to create a domain layer independent on the framework you shouldn't use Laravel collection.

Laravel Nova - Save multiple rows to database on create

I'm converting a Laravel app that was using Backpack across to Laravel Nova.
One of my models Images allows the user to add multiple images with a base set of information from the initial form. The form in this instance asks how many images are in the series via a dropdown and then has a number of relevant fields that will be used for all of the new images being added. When saving, in the controller, I'm using the following eloquent feature to run a number of tasks and insert the required number of rows:
public function store(StoreRequest $request){
//Get some info
//Make some tweaks
//Use for loop to save multiple records
for ($k = 0; $k < $addim; $k++){
//Do some stuff
parent::storeCrud(${"request"});
}
}
This works perfectly and inserts however many records are required.
In Laravel Nova, I can't see a way to use this same approach. Using an event listener in the model doesn't seem like the right way to save multiple records and I can't find any reference to a controller function I can use to achieve this.
I would really appreciate some thoughts and guidance on the best way to complete this part.
If someone has stumbled upon this type of problem.
You can use Laravel Observers.
In order to restrict the event to be fired only when resource is created and only using nova you can declare Observer in NovaServiceProvider.php as follows
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
parent::boot();
Nova::serving(function () {
Image::observe(ImageObserver::class);
});
}
Above code will only be triggered when your image object is modified using nova system only.
For ref Observer code will look like following
<?php
namespace App\Observers;
use App\Models\Document;
class ImageObserver
{
/**
* Handle the Image "created" event.
*
* #param \App\Models\Image $image
* #return void
*/
public function created(Image $image)
{
//logic to create multiple records
}
}
You can use the saving event in an observable
https://laravel.com/docs/5.8/eloquent#events

How to add an Action to Account Controller in Shopware

How to add a custom action to an existing Controller in Shopware?
Examples (url structure):
/account/bonus
/account/custom
/account/...
Usually it's easier and cleaner to create a new controller for that purpose, but in some cases it's necessary.
You should not replace the "account" controller.
You can define you own action for existing controller with following:
public static function getSubscribedEvents()
{
return [
'Enlight_Controller_Action_Frontend_Account_MyBonus' => 'onAccountMyBonus',
];
}
and then
public function onAccountMyBonus(\Enlight_Event_EventArgs $args)
{
$args->setProcessed(true);
.....
your code here
}
Spoiler: Replace the controller
There is no cleaner way than to replace the whole controller and extend it's functionality, so it's nearly as clean as Shopware's hooks.
Guide
Add a new Subscriber to your Plugin
class AccountSubscriber implements SubscriberInterface
{
/**
* #return array
*/
public static function getSubscribedEvents()
{
return array(
'Enlight_Controller_Dispatcher_ControllerPath_Frontend_Account' => 'getAccountController'
);
}
/**
* #return string
*/
public function getAccountController()
{
return $this->getPath() . '/Controllers/Frontend/AccountExtended.php';
}
/**
* #return string
*/
public function getPath()
{
$plugin = Shopware()->Container()->get('kernel')->getPlugins()['AcmeYourPlugin'];
return $plugin->getPath();
}
}
Downsides
Unfortunately some controller have private methods which impact the logic. Like the Account Controller. So it's not always possible to simply extend the controller.
In the end, try to add a new controller with a new route.
It's easier, and cleaner.
There is a cleaner way than replacing the whole Controller.
It is also not recommended to replace a whole controller due to the lack of update compatibility.
In the worst case something like that could kill the whole website.
A while ago I created a thread in the shopware forum (german) discussing the exact same issue. I wanted to extend an existing finishAction() in the checkout Controller.
public function onPostDispatchCheckout(\Enlight_Controller_ActionEventArgs $args)
{
/** #var \Enlight_Controller_Action $controller */
$controller = $args->getSubject();
/** #var \Enlight_Controller_Request_Request $request */
$request = $controller->Request();
if ($request->getActionName() !== 'finish') {
return;
}
// do your stuff here
}
So even though it is not the exact same issue you have, the procedure is quite the same.
First off you subscribe to the controller (in my case the PostDispatchCheckout Controller) afterwards you edit the controller in your Bootstrap.php
To make sure, that it just alters a specific action you have to use the if-construction so your code gets just triggered on the wished action [in my case the finishAction()].
I hope this helps. What wonders me though is why you have to add a new action to an already existing controller. I can think of no situation where something like that is more practicable than creating a complete new custom controller.
Kind regards,
Max

typo3 extbase validate for multiple records

I have written one extbase plugin, that creates the FE users from front end form.
The create action is something like this
/**
* action create
*
* #param \TYPO3\Usermanagement\Domain\Model\Users $newUsers
* #return void
*/
public function createAction(\TYPO3\Usermanagement\Domain\Model\Users $newUsers) {
$this->usersRepository->add($newUsers);
}
Here I want to validate for same username or email already exists or not.
How can I do this ?
Any suggestions ?
Thank you.
You don't need to bind a $newUser as an action's param, instead you can just read some fields using $this->request->hasArgument('something') and $this->request->getArgument('something') to validate properties yourself, and create new user object manually like.
public function createAction() {
$newUsers = new \TYPO3\Usermanagement\Domain\Model\Users();
// do something with $newUsers object...
$this->usersRepository->add($newUsers);
}
It will not throw an exception in case when there's no valid user object in the request, so it will allow you to handle form's error as you want/need.
It will also allow you to use some preprocessing before saving ie hashing/salting passwords.

Resources