Zend3 InputFilter not validating Form - zend-framework

I've found another post (ZF2 InputFilter not validating fieldset) for my issue, but it doesn't helped.
I have a Category Entity and i want to validate the length of the title.
So my Model (without the existing getter and setter)
class Category
{
/**
* #var int
*/
private $id;
/**
* #var string
*/
private $name;
}
My Form for the Category:
class CategoryForm extends Form
{
public function init()
{
$this->setHydrator(new ClassMethods(false));
$this->setObject(new Category());
$this->setInputFilter(new CategoryFilter());
$this->add([
'name' => 'id',
'type' => 'hidden'
]);
$this->add([
'name' => 'name',
'type' => 'text'
]);
$this->add([
'name' => 'submit',
'type' => 'submit'
]);
}
}
And the Filter which currently not working.
class CategoryFilter extends InputFilter
{
public function init()
{
$this->add([
'name' => 'name',
'required' => true,
'filters' => [
['name' => StringTrim::class]
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'min' => 5
]
]
]
]);
}
}
And if someone needed my addAction in the Controller:
public function addAction()
{
$request = $this->getRequest();
if ($request->isPost()) {
$this->form->setData($request->getPost());
if ($this->form->isValid()) {
$this->mapper->save($this->form->getData());
$this->redirect()->toRoute('categories');
}
}
return [
'form' => $this->form
];
}
In every example which i found, it should be working. But my form is never validated nor filtered (with the trim).
Did i forget something? Why it doesn't work?

So i've changed a little bit.
The Category Form goes to:
class CategoryForm extends Form
{
public function init()
{
$this->add(array(
'type' => CategoryFieldSet::class,
'options' => array(
'use_as_base_fieldset' => true,
),
));
$this->add([
'name' => 'submit',
'type' => 'submit'
]);
}
}
I changed also the Filter
class CategoryFilter extends InputFilter
{
public function __construct()
{
$this->add([
'name' => 'name',
'required' => true,
'filters' => [
['name' => StringTrim::class]
],
'validators' => [
[
'name' => StringLength::class,
'options' => [
'min' => 5
]
]
]
]);
}
}
And after this i defined the FieldSet with the validators:
class CategoryFieldSet extends Fieldset implements InputFilterProviderInterface
{
/**
*
*/
public function init()
{
$this->setHydrator(new ClassMethods(false));
$this->setObject(new Category());
$this->add([
'name' => 'id',
'type' => 'hidden'
]);
$this->add([
'name' => 'name',
'type' => 'text',
]);
}
/**
* Should return an array specification compatible with
* {#link Zend\InputFilter\Factory::createInputFilter()}.
*
* #return array
*/
public function getInputFilterSpecification()
{
$filter = new CategoryFilter();
return $filter->getInputs();
}
}
After changing this i get the expected error message like:
The input is less than 5 characters long

Related

Laravel 8 Multi user Authentication JWT

I have to models 'User' and 'Admin'. 'User' is the default model in Laravel. I want to authenticate these models separately.
class Admin extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email',
'name',
'contact',
'password'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* #return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
In auth.php,
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt',
'provider' => 'users',
'hash' => false,
],
'admins' => [
'driver' => 'jwt',
'provider' => 'admins',
],
'admin-api' => [
'driver' => 'jwt',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],
In AdminController.php,
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth:admins');
}
public function register(Request $request){
$creds = [
'email' => $request->input('email'),
'name' => $request->input('name'),
'password' => bcrypt($request->input('password')),
'contact' => $request->input('contact'),
];
try {
$admin = Admin::create($creds);
} catch (\Throwable $th) {
return response(
[
'message' => $th,
'success' => false
],
);
}
event(new Registered($admin));
$token = JWTAuth::fromUser($admin);
return response(
[
'user' => $admin,
'message' => 'register success',
'token' => $token,
'success' => true
],
201
);
}
public function login(Request $request){
$creds = [
'email' => $request->input('email'),
'password' => $request->input('password')
];
if(!Auth()->attempt($creds)){
return response([
'message' => 'login faild!',
'success' => false
]);
}
$admin = Auth()->user();
$token = JWTAuth::fromUser($admin);
return response(
[
'user' => $admin,
'token' => $token,
'success' => true
],
201
);
}
can you help me?
I do not know how to use register and login function correctly. Can you explain what is happening in those functions. How to use a middleware correctly?

Can't get a way to read the property "title" in class "App\Entity\Travel" triggered by $form->createView()

I am getting the following error on my symfony page. Using a CRUD system when I try to edit one item, I fall onto the following error:
Can't get a way to read the property "title" in class
"App\Entity\Travel".
My "Travel" entity has no such "title" property as it is not expected. The only place a "title" property is defined is in the TravelTranslation entity, which is in a ManyToOne relationship with travel.
After I have commented all references to the form in my twig templates all I find is that the error is triggered by $form->createView() in my controller.
/**
* #Route("/{id}/edit", name="travel_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Travel $travel): Response
{
$entityManager = $this->getDoctrine()->getManager();
$langs = $entityManager->getRepository(Lang::class)->findAll();
$media = $entityManager->getRepository(Media::class)->findAll();
$form = $this->createForm(TravelType::class, $travel);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute('travel_index');
}
return $this->render('crud/travel/edit.html.twig', [
'langs' => $langs,
'travel' => $travel,
'media' => $media,
'form' => $form->createView()
]);
}
But then my TravelType form contains the following code:
class TravelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('main_title')
->add('category', EntityType::class,[
'class' => Category::class,
'choice_label' => 'name',
'query_builder' => function(EntityRepository $er) {
return $er->createQueryBuilder('c')
->andWhere('c.type = :type')
->setParameter('type', 'country')
->orderBy('c.name', 'ASC');
},
])
->add('price_driver', MoneyType::class,[
'divisor' => 100,
])
->add('price_codriver', MoneyType::class,[
'divisor' => 100,
])
/* ->add('country') */
->add('km')
->add('media', EntityType::class, [
'class' => Media::class,
'choice_label' => 'name',
'multiple' => true
])
->add('status')
->add('duration')
->add('level')
->add('travelTranslations', CollectionType::class, [
'entry_type' => TravelTranslationType::class,
'entry_options' => [
'label' => false
],
'by_reference' => false,
// this allows the creation of new forms and the prototype too
'allow_add' => true,
// self explanatory, this one allows the form to be removed
'allow_delete' => true
])
->add('dates', CollectionType::class, [
'entry_type' => DatesType::class,
'entry_options' => [
'label' => false
],
'by_reference' => false,
// this allows the creation of new forms and the prototype too
'allow_add' => true,
// self explanatory, this one allows the form to be removed
'allow_delete' => true
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Travel::class,
'allow_extra_fields' => true
]);
}
}
I managed to fix the error by getting into the DatesType::class (a custom entity type form not DateType) and fixing it as it was the one getting with the trouble of referring to the wrong property "title" in a collection type
By changing
->add('travel', EntityType::class, [
'class' => Travel::class,
'choice_label' => 'title'
] )
By:
->add('travel', EntityType::class, [
'class' => Travel::class,
'choice_label' => 'main_title'
] )
Where main_title is the real property.

ZF3 - Set field in fieldset required depnding on form

I have a fieldset with a field called "company" which is not required by default. Now there is a form which adds this fieldset and now "company" should be required. Is there a way to do this in e. g. the form factory? Or can I rewrite the input filters of the fieldset in my inputfilter class binded to the form?
Thanks for any response!
Fieldset
class MyFieldset extends Fieldset implements InputFilterProviderInterface {
public function init() {
$this->add([
'name' => 'company',
'options' => [
'label' => 'Firma'
],
'attributes' => [
'id' => 'address-company'
]
]);
}
public function getInputFilterSpecification() {
return [
'company' => [
'required' => false,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
['name' => 'ToNull']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 128
]
]
]
],
];
}
}
Form
class MyForm extends Form {
public function init() {
$this->add([
'type' => MyFieldset::class,
'name' => 'test',
'options' => [
'use_as_base_fieldset' => true
]
]);
}
}
Form Factory
class MyFormFactory implements FactoryInterface {
public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
$hydratorManager = $container->get('HydratorManager');
$inputFilterManager = $container->get('InputFilterManager');
$form = new MyForm();
$form->setHydrator($hydratorManager->get(DoctrineObject::class));
$form->setInputFilter($inputFilterManager->get(MyInputFilter::class));
$form->bind(new Entity());
return $form;
}
}
The only way I can think of doing it is.
In your fieldset use:
private $companyRequired = FALSE;
public function setCompanyRequired($companyRequired)
{
$this->companyRequired = (bool) $companyRequired;
}
public function getInputFilterSpecification()
{
return [
'company' => [
'required' => $this->companyRequired,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
['name' => 'ToNull']
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 128
]
]
]
],
];
}
in the form where the company is required place this in your init() method after adding the fieldset:
$this->get('test')->setCompanyRequired(TRUE);
As the getInputFilterSpecification() method is not read until you validate your form this should work.
I have previously answered a similar question relating to over loading the default input filter options of a nested fieldset.
You can do the same inside the form using the Zend\InputFilter\InputFilterProviderInterface
class MyForm extends Form implements InputFilterProviderInterface
{
public function init()
{
//..
}
public function getInputFilterSpecification()
{
return [
'test' => [
'type' => 'Zend\\InputFilter\\InputFilter',
'company' => [
'required' => true,
],
],
];
}
}
Or alternately, you can achieve the same by manually configuring the fieldset's input filter inside MyFormFactory;
class MyFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
//.. same code
$form->getInputFilter() // fetch the input filter you just attached.
->get('test') // the name of the neseted fieldset (another input filter)
->get('company') // the name of the input
->setRequired(true); // set required to true :)
return $form;
}
}

ZF3 unable to populate select field from db

Can anyone explain me the easiest way to populate select field in form from db?
ChartsForm.php
<pre>
<?php
namespace Charts\Form;
use Zend\Form\Form;
use Charts\Model\PostRepositoryInterface;
class ChartsForm extends Form
{
private $postRepository;
public function __construct(PostRepositoryInterface $postRepository)
{
$this->postRepository = $postRepository;
// We will ignore the name provided to the constructor
parent::__construct('album');
$this->add([
'name' => 'id',
'type' => 'hidden',
]);
$this->add([
'name' => 'title',
'type' => 'text',
'options' => [
'label' => 'Title',
],
]);
$this->add(array(
'type' => 'Radio',
'name' => 'select',
'options' => array(
'label' => 'select type',
'value_options' => array(
'1' => 'Index',
'2' => 'Security',
),
),
'attributes' => array(
'value' => '1'
)
));
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'gender',
'options' => array(
'value_options' => $this->postRepository->findAllPosts(),
),
'attributes' => array(
'value' => '1'
)
));
$this->add([
'name' => 'submit',
'type' => 'submit',
'attributes' => [
'value' => 'Go',
'id' => 'submitbutton',
],
]);
}
}
</pre>
module.config.php
<pre>
<?php
namespace Charts;
use Zend\ServiceManager\Factory\InvokableFactory;
use Zend\Db\Adapter\AdapterAbstractServiceFactory;
return [
'controllers' => [
'factories' => [
Model\ChartSqlRepository::class => Factory\ChartSqlRepositoryFactory::class,
],
],
'service_manager' => [
'aliases' => [
Model\PostRepositoryInterface::class => Model\PostRepository::class,
],
'factories' => [
Model\PostRepository::class => InvokableFactory::class,
],
],
'view_manager' => [
'template_path_stack' => [
'charts' => __DIR__ . '/../view',
],
],
'router' => [
'routes' => [
'charts' => [
'type' => 'segment',
'options' => [
'route' => '/charts[/:action[/:id]]',
'constraints' => [
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
],
'defaults' => [
'controller' => Controller\ChartsController::class,
'action' => 'index',
],
],
],
],
],
// 'service_manager' => [
// 'factories' => [
// 'Zend\Db\Adapter\Adapter' => AdapterAbstractServiceFactory::class,
// ],
// ],
];
</pre>
module.php
<pre>
<?php
namespace Charts;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;
class Module implements ConfigProviderInterface
{
public function getConfig()
{
return include __DIR__ . '/../config/module.config.php';
}
public function getServiceConfig()
{
return [
'factories' => [
Model\BKPagesTable::class => function($container) {
$tableGateway = $container->get(Model\BKPagesTableGateway::class);
return new Model\BKPagesTable($tableGateway);
},
Model\BKPagesTableGateway::class => function ($container) {
$dbAdapter = $container->get(AdapterInterface::class);
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\BKPages());
return new TableGateway('bkpages', $dbAdapter, null, $resultSetPrototype);
},
Model\BuyOrdersTable::class => function($container) {
$tableGateway = $container->get(Model\BuyOrdersTableGateway::class);
return new Model\BuyOrdersTable($tableGateway);
},
Model\BuyOrdersTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\BuyOrders());
return new TableGateway('BuyOrders', $dbAdapter2, null, $resultSetPrototype);
},
//Stocklist Table
Model\StockListTable::class => function($container) {
$tableGateway = $container->get(Model\StockListTableGateway::class);
return new Model\StockListTable($tableGateway);
},
Model\StockListTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\StockList());
return new TableGateway('StockList', $dbAdapter2, null, $resultSetPrototype);
},
//Fulldayquot Table
Model\FulldayquotTable::class => function($container) {
$tableGateway = $container->get(Model\FulldayquotTableGateway::class);
return new Model\FulldayquotTable($tableGateway);
},
Model\FulldayquotTableGateway::class => function($container) {
$dbAdapter2 = $container->get('api2web');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Model\Fulldayquot());
return new TableGateway('fulldayquot', $dbAdapter2, null, $resultSetPrototype);
},
],
];
}
public function getControllerConfig()
{
return [
'factories' => [
Controller\ChartsController::class => function($container) {
return new Controller\ChartsController(
$container->get(Model\BKPagesTable::class)
);
},
],
];
}
}
</pre>
ChartSqlRepositoryFactory.php
<pre>
<?php
namespace Charts\Factory;
use Charts\Model\ChartSqlRepository;
use Zend\Db\Adapter\AdapterInterface;
use Blog\Model\PostRepositoryInterface;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class ChartSqlRepositoryFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new ChartSqlRepository(
$container->get($container->get(PostRepositoryInterface::class)
);
}
}
</pre>
ChartSqlRepository.php
<pre>
<?php
namespace Charts\Model;
use InvalidArgumentException;
use RuntimeException;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\Adapter\Driver\ResultInterface;
use Zend\Db\ResultSet\ResultSet;
class ChartSqlRepository implements PostRepositoryInterface
{
private $db;
private $repository;
public function __construct( ChartSqlRepository $repository)
{
$this->repository = $repository;
}
public function findAllPosts()
{
$sql = new Sql($this->db);
$select = $sql->select('BKPages');
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute();
var_export($result);
die();
}
public function IndexesOptions()
{
$sql = new Sql($this->db);
$select = $sql->select('BKPages');
$stmt = $sql->prepareStatementForSqlObject($select);
$result = $stmt->execute();
$selectData = array();
foreach ($result as $res) {
$selectData[$res['MenuID']] = $res['MenuID'];
}
return $selectData;
}
public function findPost($id)
{
}
}
</pre>
I am trying to populate select field in ChartsForm.php from db and created a factory, maybe some error in module.config.php it's says.
Catchable fatal error: Argument 1 passed to Charts\Form\ChartsForm::__construct() must be an instance of Charts\Model\PostRepositoryInterface, none given, called in C:\wamp\www\bw\module\Charts\src\Controller\ChartsController.php on line 60 and defined in C:\wamp\www\bw\module\Charts\src\Form\ChartsForm.php on line 24
Help me out please.
Can you be more specific? What type of database?
You have two options: PDO (For all driver) and MySQLy (for MySQL).
Look here for a greater response:
https://stackoverflow.com/a/8255054/6784143
UPDATE:
You can connect your Sql Server with this line code (running good on .php).
resource mssql_connect ([ string $servername [, string $username [, string $password [, bool $new_link = false ]]]] )
You can execute a query with this line code.
mixed sqlsrv_query ( resource $conn , string $sql [, array $params [, array $options ]] )

How to change migration db connection

I have more than one connection setting in config/database.php, I can and have to connect to several database in the same case, this is how I try to do but not work.
<?php
class Migration_Create_loggers_table extends CI_Migration
{
public function __construct()
{
parent::__construct();
$this->load->database('master');
}
public function up()
{
$this->dbforge->add_field([
'id' => [
'type' => 'int',
'unsigned' => true,
'auto_increment' => true
],
'name' => [
'type' => 'varchar',
'constraint' => 50
]
]);
$this->dbforge->add_key('id', true);
$this->dbforge->create_table('members');
}
public function down()
{
$this->dbforge->drop_table('members');
}
}
I haven't tried but I think you are missing parent::__construct(); at your __construct method
So your __construct method should be like this
class Migration_Create_loggers_table extends CI_Migration
{
public function __construct()
{
$this->load->database('master');
parent::__construct();//add this line
}
public function up()
{
$this->dbforge->add_field([
'id' => [
'type' => 'int',
'unsigned' => true,
'auto_increment' => true
],
'name' => [
'type' => 'varchar',
'constraint' => 50
]
]);
$this->dbforge->add_key('id', true);
$this->dbforge->create_table('members');
}
public function down()
{
$this->dbforge->drop_table('members');
}
}