get several values ​separated by , and save line by line in the database - laravel-nova

I have an input, and I want to extract several numbers separated by , and store each number on each new line in the database.
model - CouponDocument
<?php
namespace App\Models;
use App\Http\Controllers\CouponDocumentController;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class CouponDocument extends Model
{
use HasFactory, SoftDeletes;
protected $table = "coupons_document";
protected $fillable = [
"id",
"cpf",
"coupon_id"
];
protected $hidden = [
'deleted_at',
'created_at',
'updated_at'
];
public function coupon()
{
return $this->belongsTo(Coupon::class, 'coupon_id', 'id')->withTrashed();
}
}
Controller
class CouponDocumentController extends Controller
{
static public function store($request)
{
$data = [];
foreach ($request->input('cpf') as $cpf) {
$data[] = [
'cpf' => trim($cpf),
'coupon_id' => 61
];
}
foreach ($data as $item) {
$couponDocument = new CouponDocument();
$couponDocument->fill($item);
$couponDocument->save();
}
}
}
Resources
class CouponsDocument extends Resource
{
use SearchesRelations;
public static $displayInNavigation = false;
public static $model = \App\Models\CouponDocument::class;
public static $title = 'id';
public static $search = [
'id',
'cpf',
'coupon_id'
];
public static function label()
{
return __('modules.couponDocument.button');
}
public static function singularLabel()
{
return __('modules.couponDocument.button');
}
public function fields(Request $request)
{
return [
Text::make(__('fields.couponDocument.name'), "cpf")
->sortable(),
];
}
where the resource is called
HasMany::make
__("fields.couponDocument.name"),
"documentRelationship",
CouponsDocument::class
I tried to do it with the standard functions of nova, but it ended up not working, I would like to know if there is any other solution

Related

Laravel FormRequest fetch parameter from url

In my update method, I am using FormRequest to validate the input fields. I also need to pass and additional parameter for unique validation rule.
I am trying to fetch the $subscriber variable from the url.
SubscriberController.php
class SubscriberController extends Controller
{
public function update(UpdateSubscriberRequest $request, $subscriber)
{
...
}
}
UpdateSubscriberRequest.php
class UpdateSubscriberRequest extends FormRequest
{
private $data = [];
private $subscriber = null;
public function __construct()
{
$this->data = request()->all();
$this->subscriber = request()->route('subscriber');
}
public function rules()
{
return [
...
'email' => [
'required',
...
"unique:subscribers,email,{$this->subscriber},token,company_id,"
. session()->get('COMPANY_ID')
],
'mobile' => [
'required',
...
"unique:subscribers,mobile,{$this->subscriber},token,company_id,"
. session()->get('COMPANY_ID')
],
...
];
}
}
Although the code is working fine. But, is this the right way to do this..?

How to include EntityManager in ZendFramework 2 AbstractValidator

I have a custom validator, extending Zend AbstractValidator. The thing is, i want to include Doctrine EntityManager, but i keep failing! I tried to make a Factory for my Validator, but it doesn't seem to work. Help!! What am I doing wrong?
Validator:
$this->objectRepository stays empty, while i expect content.
namespace Rentals\Validator;
use Rentals\Response;
use Zend\Validator\AbstractValidator;
use Zend\Stdlib\ArrayUtils;
class ExistentialQuantification extends AbstractValidator
{
const NO_ENTITY_ID = 'noEntityId';
const ENTITY_NOT_FOUND = 'entityNotFound';
const INVALID_ID = 'invalidId';
protected $messageTemplates = [
self::NO_ENTITY_ID => 'The input does not contain an entity id.',
self::ENTITY_NOT_FOUND => 'The entity could not be found.',
self::INVALID_ID => 'The input does not contain an entity id.',
];
protected $objectRepository;
public function __construct(array $options)
{
$this->objectRepository = $options['object_repository'];
parent::__construct($options);
}
public function isValid($value)
{
if ($value === null) {
return true;
}
if (! isset($value->id)) {
$this->error(self::NO_ENTITY_ID);
return false;
}
$entityClass = $this->getOption('entity_class');
$controller = new Controller();
$entity = (new FactoryInterface)(EntityManager::class)->find($entityClass, $entity->id);
if (! $entity instanceof $entityClass) {
$this->error(self::ENTITY_NOT_FOUND);
return false;
}
if (! $entity->getId()) {
$this->error(self::NO_ENTITY_ID);
return false;
}
return true;
}
}
Factory:
namespace Rentals\Validator;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Stdlib\ArrayUtils;
class ExistentialQuantificationFactory implements FactoryInterface, MutableCreationOptionsInterface
{
protected $options = [];
public function setCreationOptions(array $options)
{
$this->options = $options;
}
public function createService(ServiceLocatorInterface $serviceLocator)
{
if (! isset($this->options['object_manager'])) {
$this->options['object_manager'] = 'doctrine.entitymanager.orm_default';
}
$objectManager = $serviceLocator->get($this->options['object_manager']);
$objectRepository = $objectManager->getRepository($this->options['entity_class']);
return new ExistentialQuantification(ArrayUtils::merge(
$this->options, [
'objectManager' => $objectManager,
'objectRepository' => $objectRepository
]
));
}
}
Module config:
<?php
return [
'service_manager' => [
'factories' => [
'Rentals\\Validator\\ExistentialQuantification' => 'Rentals\\Validator\\ExistentialQuantificationFactory'
]
]
];
?>
What if you change your config entry like the following example?
return [
'validators' => [
'factories' => [
ExistentialQuantification::class => ExistentialQuantificationFactory::class,
],
],
];
This change will result in further changes for your factory, because the service locator for the entity manager differs from the one you injected.
namespace Application\Validator\Factory;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsInterface;
use Zend\ServiceManager\MutableCreationOptionsTrait;
use Zend\ServiceManager\ServiceLocatorInterface;
class ExistentialQuantificationFactory implements FactoryInterface, MutableCreationOptionsInterface
{
use MutableCreatinOptionsTrait;
public function createService(ServiceLocatorInterface $serviceLocator)
{
$parentLocator = $serviceLocator->getServiceLocator();
if (! isset($this->creationOptions['object_manager'])) {
$this->creationOptions['object_manager'] = 'doctrine.entitymanager.orm_default';
}
$objectManager = $parentLocator->get($this->creationOptions['object_manager']);
$objectRepository = $objectManager->getRepository($this->creationOptions['entity_class']);
return new ExistentialQuantification(ArrayUtils::merge(
$this->options, [
'objectManager' => $objectManager,
'objectRepository' => $objectRepository
]
));
}
}
What I 've done here? First I implemented the MutableCreationOptionsTrait class. This trait implements the needed functions for working with creation options. But this is just a little hint for avoiding unnecessary work.
Because of setting the validator class as validator in the config, we have to use the parent service locator for getting the entity manager. The inherited service locator just provides access to validators.
Now you can try to access your validator in your controller like in the following examaple.
$validator = $this->getServiceLocator()
->get('ValidatorManager')
->get(ExistentialQuantification::class, [
'entity_class' => YourEntityClass::class,
]);
\Zend\Debug\Debug::dump($validator, __METHOD__);
The validator manager should return your validator so that you can test it.

zf2 - Nested Aggregate Hydrators

Is it possible to nest aggregate hydrators? If i have the following classes:
class Appointment{
public date;
public startTime;
public endTime;
public User; //* #var User */
}
class User{
public Location; //* #var Location*/
}
...being populated with the following AggregateHydrator (created from a factory):
class AppointmentModelHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$serviceManager = $serviceLocator->getServiceLocator();
$arrayHydrator = new ArraySerializable();
$arrayHydrator->addStrategy('date', new DateTimeStrategy())
->addStrategy('endTime', new TimeStrategy())
->addStrategy('startTime', new TimeStrategy());
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($arrayHydrator);
$aggregateHydrator->add($serviceLocator->get('Hydrator\User'));
return $aggregateHydrator;
}
}
With the UserHydratorFactory looking like:
class UserHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$sm = $serviceLocator->getServiceLocator();
$userHydrator = new UserHydrator($sm->get('User\Mapper'));
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($userHydrator );
$aggregateHydrator->add($sm->get('HydratorManager')->get('Hydrator\User\Location'));
return $aggregateHydrator;
}
}
This is throwing an expection as the model is being returned as null, but if i comment out adding the Location hydrator to the User hydrator, it works fine (albeit without location data loaded). So i was wondering if aggregate hydrators are able to be nested?
It is not built-in, but doable.
namespace Hydrator;
use Zend\Stdlib\Hydrator\HydratorInterface;
class NestedHydrator implements HydratorInterface
{
protected $inner_hydrator;
private $empty;
public function __construct ($inner_hydrator, $empty)
{
$this->inner_hydrator = $inner_hydrator;
$this->empty = $empty;
}
public function extract ($object)
{
return [
$this->getPath() => $this->inner_hydrator->extract ($object->{$this->getPath()})
];
}
public function hydrate (array $data, $object)
{
$object->{$this->getPath()} = $this->inner_hydrator->hydrate ($data [$this->getPath()], $this->empty);
return $object;
}
protected function getPath ()
{
return get_class ($this->empty);
}
}
And then:
$u = new User();
$u->Location = "4 Clinton Rd.";
$a = new Appointment();
$a->date = "yesterday";
$a->startTime = "7:00";
$a->endTime = "8:00";
$a->User = $u;
$h = new AggregateHydrator();
$h->add (new ObjectProperty());
$nested = new \Hydrator\NestedHydrator(new ObjectProperty(), new User());
$h->add ($nested);
$data = $h->extract ($a);
$b = $h->hydrate ($data, new Appointment());
$this->assertEquals ($a, $b);

ZF2 TableGateway join

I am in the process of trying to learn OO/Zend Framework over standard PHP.. I want to scream and write a mysql query instead of using the TableGateway method.
I have been following tutorials and have successfully printed out a table and some fields, although with the way I have gone about doing this, I am totally lost in how I should make this a join with another table and print out some fields there.
For example.
Table Fields
customer Idx, Company
contact Idx, First_Name
This is my customersController where I assume the work is carried out
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\DB\TableGateway\TableGateway;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array('customer' => $this->getCustomersTable()->select()));
//return new ViewModel(array('customers' => $this->fetchJoin()->select()));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$this->customersTable = new TableGateway (
'customer', //table name
$this->getServiceLocator()->get('Zend\DB\Adapter\Adapter')
);
}
return $this->customersTable;
}
}
Am I on the right track here?
If you need to make joins read about Zend\Db\Sql and Zend\Db\Select
which you can read about here
http://framework.zend.com/manual/2.0/en/modules/zend.db.sql.html
An example would be:
In your model(that extends the TableGateway or the AbstractTableGateway)
in Some function you can have something like(this is from a project) :
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('event_related_events')
->columns(array())
->join('event_invitees', 'event_invitees.event_id =
event_related_events.related_event_id')
->where(array('event_related_events.event_id' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
Then you can loop over the results and do what you need to.
Taking a look at more powerful ORM like Doctrine or Propel may also help, but may be an overkill for a small/hobby project.
EDIT: Answer for what was asked in comments
For Using expression(if, case etc) directly you can use something like :
$sql->select()
->from('table')
->columns(array(
'sorter' => new Expression('(IF ( table.`something` >= 'otherthing', 1, 0))'),
'some_count' => new Expression('(count(*))'),
)
)
Explaining the last line in SQL terms, it would be:
count(*) AS some_count
So this is my controller, basically from the Album example but now it will display customers from the customer table.
<?php
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Customers\Model\Customers;
use Customers\Form\CustomersForm;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array(
'customer' => $this->getCustomersTable()->fetchAll(),
));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$sm = $this->getServiceLocator();
$this->customersTable = $sm->get('Customers\Model\CustomersTable');
}
return $this->customersTable;
}
}
?>
The indexAction calls the getCustomersTable method which goes to the model (CustomersTable) and executes the "query" there.
<?php
namespace Customers\Model;
use Zend\Db\TableGateway\TableGateway;
class CustomersTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function getCustomers($id)
{
}
public function saveCustomers(customers $customers)
{
}
public function deleteCustomers($id)
{
}
}
?>
So from your example, I should be trying to implement this into the fetchAll in the model?
Thanks for the help.
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('customer')
->columns(array())
->join('contact', 'contact.Idx = customer.Idx')
->where(array('contact.Idx' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);

Symfony form collection read-only for first entry

How can I set the read-only option only for the first item in the collection when rendering a form?
My simple models:
class Main
{
public $others;
}
class Other
{
public $field1;
public $field2;
}
Simple Form Type for my models:
class MainType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('others', 'collection', array(
'type' => new OtherType(),
'allow_delete' => true,
'allow_add' => true,
'by_reference' => false,
))
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\MyBundle\Entity\Main',
));
}
public function getName()
{
return 'maintype';
}
}
class OtherType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('field1')
->add('field2')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'App\MyBundle\Entity\Other',
));
}
public function getName()
{
return 'othertype';
}
}
And simple action method my controller
//...
public function indexAction($id)
{
$main = new Main();
$other1 = new Other();
$other1->field1 = 'a';
$other1->field2 = 'b';
$main->others[] = $other;
$other2 = new Other();
$other2->field1 = 'c';
$other2->field1 = 'd';
$main->others[] = $other;
$form = $this->createForm(new MainType(), $main);
//...isValid, persist, flush...
}
//...
I can make a condition when manually render the form, but I want to know if possible at the form code to enter such a restriction.
Currently it is not possible to have the rows of a collection have different options. I invite you to create a feature request on the issue tracker if you feel that this would be a valuable addition.

Resources