I'm trying to do like so:
Stream<dynamic> searchEpic(
Stream<PerformSearchAction> actions,
EpicStore<AppState> store,
) {
return actions.asyncMap((action) => fetchPost()
.then((results) => SearchResultsAction(results['title']))
.catchError((error) => SearchErrorAction(error.message)));
}
However I get the follow error message:
type 'SearchErrorAction' is not a subtype of type "FutureOr SearchResultsAction "
I just needed to define that the type I wanted to work through the pipe as dynamic, like so:
Stream<dynamic> searchEpic(
Stream<PerformSearchAction> actions,
EpicStore<AppState> store,
) {
return actions.asyncMap<dynamic>((action) => fetchPost()
.then<dynamic>((results) => SearchResultsAction(results['title']))
.catchError((error) => SearchErrorAction(error.message)));
}
Related
I'm currently getting this error when trying to load an edit form for my Profile entity.
The form's view data is expected to be an instance of class AppBundle\Entity\Profile, but is a(n) array. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) array to an instance of AppBundle\Entity\Profile.
I was Wondering if anyone knows how to fit this. I'm using a Profile controller and the User and Profile have a OneToOne relationship with each other.
Here is my code for the Profile controller that loads that form
/**
* #Route("/profile/edit", name="profile_edit")
*/
public function editAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$profileRepository = $em->getRepository(Profile::class);
$user = $this->getUser();
$profile = $profileRepository->getProfileByUserId($user->getId());
$form = $this->createForm(ProfileType::class, $profile);
$form->handlerequest($request);
if( $form_.isSubmitted() && $form->isValid()) {
$firstname = $form->get('firstname')->getData();
$lastname = $form->get('lastname')->getData();
$description = $form->get('description')->getData();
$profile->setFirstname($firstname);
$profile->setLastName($lastname);
$profile->setDescription($description);
$em->persist($profile);
$em->flush();
$this->addFlash('flash-profileeditted', 'You\'ve successfully updated your profile.');
$this->redirectToRoute('profile_page');
}
return $this->render('profile/edit.html.twig', ['form' => createForm(), 'profile' => $profile]);
}
And here is my ProfileType::class
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname', TextType::class, [ 'label' => 'Firstname', 'attr' => ['class' => 'form-control']])
->add('lastname', TextType::class, ['label' => 'Lastname', 'attr' => ['class' => 'form-control']])
->add('description', TextareaType::class, ['label' => 'In Your Own Words', 'attr' => ['class' => 'form-control']])
->add('user')
->add('submit', SubmitType::class, ['label' => 'Edit Profile', 'attr' => ['class' => 'btn btn-info']]);
}
/**
* {#inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Profile'
));
}
/**
* {#inheritdoc}
*/
public function getBlockPrefix()
{
return 'appbundle_profile';
}
Not Sure what else to include here, hopefully everything is ok and the solution can be found within this code.
I should also point out that I am using FOSUserBundle.
Thanks in advance,
Ok. I finally found out what was happening. I was using the Profile Repository to find a user by their id, but that was returning an array. So what I had to do is use this code:
$profile = $profileRepository->findOneByUser($user->getId());
This actually returns the Object as an AppBundle\Entity\Profile object which can then be used to populate the form.
This is my first question, so I would also appreciate hints on how to ask properly.
So, In my Laravel app, I have a database table with users. For start, I wanted to have a model factory for it. So I took a standard code from laravel doc page:
$factory->define(App\User::class, function (Faker\Generator $faker) {
return [
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
And I changed it to:
$factory->define(App\User::class,
function(Faker\Generator $faker) {
return [
'name' => $faker->name(),
'email' => $faker->safeEmail(),
'password' => bcrypt(str_random(10)),
'phone_number' => $faker->phoneNumber(),
'remember_token' => str_random(10),
'account_type' => 0,
];
});
So far, everything works. But I wanted it to be more sophisticated, and I decided to use more specific kind of Faker class, to generate Italian data. I changed it to:
$factory->define(App\User::class,
function(Faker\Generator $faker,
Faker\Provider\it_IT\PhoneNumber $fakerITPN,
Faker\Provider\it_IT\Person $fakerITPER,
Faker\Provider\it_IT\Internet $fakerITInt) {
return [
'name' => $fakerITPER->name(),
'email' => $fakerITInt->safeEmail(),
'password' => bcrypt(str_random(10)),
'phone_number' => $fakerITPN->phoneNumber(),
'remember_token' => str_random(10),
'account_type' => 0,
];
});
In seeder class I wrote:
factory(App\User::class)->create();
And then, after I used Artisan, command:
artisan migrate:refresh --seed -vvv
I get following error (just the head, for clearance):
[ErrorException]
Argument 2 passed to Illuminate\Database\Eloquent\Factory::{closure}() must be an instance of Faker\Provider\it_IT\PhoneNumber, array given
Exception trace:
() at /home/vagrant/php/housing/database/factories/ModelFactory.php:19
Illuminate\Foundation\Bootstrap\HandleExceptions->handleError() at /home/vagrant/php/housing/database/factories/ModelFactory.php:19
Illuminate\Database\Eloquent\Factory::{closure}() at n/a:n/a
call_user_func() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:130
Illuminate\Database\Eloquent\FactoryBuilder->Illuminate\Database\Eloquent\{closure}() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:2308
Illuminate\Database\Eloquent\Model::unguarded() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:133
Illuminate\Database\Eloquent\FactoryBuilder->makeInstance() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:105
Illuminate\Database\Eloquent\FactoryBuilder->make() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:83
Illuminate\Database\Eloquent\FactoryBuilder->create() at /home/vagrant/php/housing/database/seeds/UsersTableSeeder.php:24
UsersTableSeeder->run() at /home/vagrant/php/housing/vendor/laravel/framework/src/Illuminate/Database/Seeder.php:42
Clearly, there is something wrong with dependency injection, but I don't know what. I know, that in this case I could just manually create instances of classes I need, but I want to know, how to do it properly. Can anyone help?
If you take a look at the documention of faker # https://github.com/fzaninotto/Faker#localization, you'll see that you can simply assign the proper localization as a parameter to create.
In your case, just use:
Faker\Factory::create('it_IT');
You don't need to add more parameters in the anonymous function when you define the factory.
Edit:
Just to add on the issue on dependency injection. If you trace the source code, it does not do any dependency injection underneath.
$factory->define(...)
Only sets an array of definitions
public function define($class, callable $attributes, $name = 'default')
{
$this->definitions[$class][$name] = $attributes;
}
Calling
Faker\Factory::create();
or
factory(App\User::class)->create();
$factory->of($class)
calls "of" method that instantiate FactoryBuilder
(see lines 169-172 of Illuminate\Database\Eloquent\Factory.php)
public function of($class, $name = 'default')
{
return new FactoryBuilder($class, $name, $this->definitions, $this->faker);
}
after that, it chains "create" method of FactoryBuilder that calls "make" method which also calls "makeInstance"
protected function makeInstance(array $attributes = [])
{
return Model::unguarded(function () use ($attributes) {
if (! isset($this->definitions[$this->class][$this->name])) {
throw new InvalidArgumentException("Unable to locate factory with name [{$this->name}].");
}
$definition = call_user_func($this->definitions[$this->class][$this->name], $this->faker, $attributes);
return new $this->class(array_merge($definition, $attributes));
});
}
Notice "call_user_func" inside "makeInstance", that is the one responsible for calling the anonymous function created as the 2nd argument to define (inside ModelFactory.php). It specifically pass only 2 arguments to the callable function, these are:
...$this->faker, $attributes);
Only 1 faker is passed on the first argument and an array of attributes on the 2nd argument (this is the one you saw on your ErrorException earlier)
That means you can only define your factory in this way:
$factory->define(App\User::class,
function (Faker\Generator $faker, $attributes=array()) {
return [
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
If you really need other classes, you can initialize it outside of "define" and use it in the function like this:
$sampleInstance = app(App\Sample::class);
$factory->define(App\User::class,
function (Faker\Generator $faker, $attributes=array()) use($sampleInstance){
//...do something here
//...or process the $attributes received
//...or call a method like
$sampleData = $sampleInstance->doSomething();
return [
'someField' => $sampleData,
'name' => $faker->name,
'email' => $faker->email,
'password' => bcrypt(str_random(10)),
'remember_token' => str_random(10),
];
});
You can put this setting in register() of AppServiceProvider:
$this->app->singleton(\Faker\Generator::class, function () {
return \Faker\Factory::create('it_IT');
});
What I am actually doing is, fetching a list of companies from the database and passing that to the form SELECT element.
So I created a Model file, which returns an array
//=== return an array of $ID => $name of companies to use in dropdown in reports form
public function getTotalResult($table, $type, $id) {
$this->table = $table;
$select = new Select();
$spec = new Where();
$spec->equalTo('status', 1);
if ($type == 'name') {
$spec->equalTo('id', $id);
}
$select->from($this->table);
$select->where($spec);
$resultSet = $this->selectWith($select);
//$resultSet->buffer();
return $resultSet;
}
public function resultList($table){
$results = $this->getTotalResult($table, '', '');
foreach ($results as $result) {
$this->id[] = $result->id;
$this->name[] = $result->name;
}
$result = array_combine($this->id, $this->name);
return $result;
}
Then I tested this in my Controller, which returned exactly what I wanted:
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use SpangelLogin\Model\Register; // <-- Add this import
use SpangelLogin\Model\companyList; // <-- Add this import
class RegisterController extends AbstractActionController
{
protected $registerTable;
protected $companyList;
public function getcompanyList()
{
if (!$this->companyList) {
$sm = $this->getServiceLocator();
$this->companyList = $sm->get('SpangelLogin\Model\companyList');
}
return $this->companyList;
}
public function indexAction()
{
//== get list of companies
$company_table = 'rs_company';
$sector_table = 'rs_sector';
$companiesList = $this->getcompanyList()->getName($company_table, 2);
}
}
So now I want this companiesList array passed in my form's Select Element. How can I achieve that. Here is my form in which I am using select.
use Zend\Form\Form;
use Zend\Form\Element;
class SectorReportForm extends Form
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('sectorreport');
$companiesArray = $this->companiesList();
$sectorsArray = $this->sectorsList();
$this->setAttribute('method', 'post');
$this->setAttribute('enctype','multipart/form-data');
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'company',
'attributes' => array(
'id' => 'company',
'multiple' => true,
'options' => $companiesArray,
),
'options' => array(
'label' => 'Company',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Upload',
'id' => 'submitbutton',
'class' => 'button violet right'
),
));
}
}
From a Design-Perspective, the best approach would be to handle this via Dependency-Injection. That sneaky little buzzword that confuses people so much, but actually is nothing more but to forward data between objects :P
General Dependency-Injection for Forms can be seen looking at the following answer, as well as my Blog article
How to get data from different model for select?
Zend\Form\Element\Select and Database-Values
If you do not want to go this approach, you can handle this at the Controller level, too.
$form = new My\Form();
$select = $form->get('selectCountries');
$model = new My\Countries();
$listData = $model->getCountriesAsArray();
$select->setValueOptions($listData);
I still advise you to go the different approach ;) Keeps the controllers more clean, too, which is always a good thing. Separation of concern!
When supplying savon with:
hash = {
"Objects" => { //stuff here },
:attributes! => { "Objects" => {"xsi:type" => "Something"}}
}
I get:
<Objects>...</Objects>
When supplying savon with anything else i get the expected result:
hash = {
"foo" => { //stuff here },
:attributes! => { "foo" => {"xsi:type" => "Something"}}
}
I get:
<foo xsi:type="Something"></foo>
I must use the string "Objects" as the key. I am coding to a 3rd party SOAP web service. I cannot use a symbol because the first letter would become a lower cap.
thanks,
You have to change :attributes! to :#xsi:type=>"Something" within the hash where you want the attribute
Like:
"foo"=>{:#xsi:type=>'something', //stuff here}
I'd like to be able to use a BodyParser on an authenticated request and I'm having trouble figuring out how to do that if my Authentication is set up like the ZenTasks example.
My authentication method,
def IsAuthenticated(f: => String => Request[AnyContent] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
def HasRole(role: List[String])
(f: => String => Request[AnyContent] => Result) = IsAuthenticated {
user => request => if (role.contains(getRole(user))) {
f(user)(request) // This function returns the result.
} else {
Results.Forbidden
}
}
My controller method,
def controller = HasRole(List("admin")) { user => _ => {
Action(parse.temporaryFile){ implicit request =>
request.body.moveTo(new File("/tmp/filepath"))
Redirect(routes.home)
}
}
This is the error I'm seeing,
[error] found : play.api.mvc.Action[play.api.libs.Files.TemporaryFile]
[error] required: play.api.mvc.Result
[error] Action(parse.temporaryFile){ implicit request =>
[error] ^
Here is a related question: parse.json of authenticated play request
This person found a workaround, and I believe there is one for the temporary file example as well, but I'd like to know how (or why) what I'm doing is not working.
I believe I've figured this out, mainly because I left some details out of the original question that I did not realize were important.
The problem was that I was wrapping an Action { Action { } } because the IsAuthenticated method already had a call to the Action function inside it. What I ended up doing was overloading the IsAuthenticated function with a method that took BodyParser as a parameter. Because I am using the TemporaryFile method, which is not a subclass of AnyContent, I also had to change the request type.
Now, this is what my Secured trait looks like:
def IsAuthenticated(f: => String => Request[Any] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
}
def IsAuthenticated(b: BodyParser[Any] = parse.anyContent)
(f: => String => Request[Any] => Result) = {
Security.Authenticated(username, onUnauthorized) { user =>
Action(b)(request => f(user)(request))
}
}
def HasRole(role: List[String])(b: BodyParser[Any] = parse.anyContent)
(f: => String => Request[Any] => Result) = IsAuthenticated(b) {
user => request => getRole(user) match {
case Some(r) if role.contains(r) => f(user)(request)
case _ => Results.Forbidden
}
}
And this is what my controller looks like:
def controller = HasRole(List("admin"))(parse.temporaryFile) { user => request =>
request.body match {
case b:TemporaryFile => b.moveTo(new File("/tmp/file"))
case _ => Status(404)
}
}
Hope this helps someone else!