I got the following problem. I started to move all the database logic to the repositories, but when I call the repository from the controller it gives me an error: "Class App\Repositories\TransactionRepository does not exist".
I tried to fix it doing "composer dump-autoload", "composer install", "composer update", "php artisan cache:clear"
I started creating a repository at App/Repositories/TransactionRepository.php
<?php
namespace App\Repositories;
use Finance\Transaction;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class TransactionRepository
{
/**
* #param $date
*/
public function byDate($date)
{
return Transaction::select(DB::raw('*'))
->where('user_id', '=', Auth::user()->id)
->where(DB::raw('DATE(datetime)'), '=', DATE('Y-m-d', strtotime($date)))
->get();
}
}
Then I call it from the proper TransactionController.php
<?php
namespace Finance\Http\Controllers;
use Finance\Category;
use Illuminate\Support\Facades\Cache;
use Session;
use Redirect;
use Finance\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Finance\Http\Requests;
use Illuminate\Support\Facades\Auth;
use App\Repositories\TransactionRepository;
class TransactionController extends Controller
{
protected $TransactionRepo;
/**
* TransactionController constructor.
*/
public function __construct(TransactionRepository $transactionRepository)
{
$this->TransactionRepo = $transactionRepository;
$this->middleware('auth');
}
And here is my composer.json:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"Finance\\": "app/"
}
},
If someone have any idea I'll be so glad.
Im so happy to put an alternative solution that it works for me.
So different from another answers I saw in similar post, I found this:
At composer.json add the classmap : "app/Repositories"
"autoload": {
"classmap": [
"app/Repositories"
]
}
Enjoy it like I do ;)
Related
I try to write, at first glance, it would seem a trivial test for my repository's "update" method:
<?php
declare(strict_types=1);
namespace Paneric\Authorization\ORM\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\ORMException;
use Paneric\Authorization\DTO\FieldDTO;
use Paneric\Authorization\ORM\Entity\Field;
use Doctrine\ORM\EntityRepository;
use Paneric\Authorization\Interfaces\FieldRepositoryInterface;
class FieldRepository extends EntityRepository implements FieldRepositoryInterface
{
const ENTITY_CLASS = Field::class;
public function __construct(EntityManagerInterface $_em)
{
parent::__construct($_em, $_em->getClassMetadata(self::ENTITY_CLASS));
}
...
public function update(int $fieldId, FieldDTO $fieldDTO): void
{
try {
$field = $this->find($fieldId);
$field->transfer($fieldDTO);
$this->_em->flush();
} catch (ORMException $e) {
echo $e->getMessage();
}
}
...
}
with a spec method:
<?php
namespace spec\Paneric\Authorization\ORM\Repository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\QueryBuilder;
use Paneric\Authorization\DTO\FieldDTO;
use Paneric\Authorization\ORM\Entity\Field;
use Paneric\Authorization\ORM\Repository\FieldRepository;
use Doctrine\ORM\AbstractQuery;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class FieldRepositorySpec extends ObjectBehavior
{
public function let(EntityManagerInterface $_em, ClassMetadata $classMetadata)
{
$_em->getClassMetadata(Field::class)->willReturn($classMetadata);
$this->beConstructedWith($_em);
}
...
public function it_updates(Field $field, FieldDTO $fieldDTO, EntityManagerInterface $_em)
{
$fieldId = 1;
$field = $this->find($fieldId);
$field->transfer($fieldDTO)->shouldBeCalled();
$_em->flush()->shouldBeCalled();
$this->update($fieldId, $fieldDTO);
}
...
}
and receive the following error:
Unexpected method call on Double\EntityManagerInterface\EntityManagerInterface\P1:
- find(
null,
1,
null,
null
)
expected calls were:
- getClassMetadata(
exact("Paneric\Authorization\ORM\Entity\Field")
)
- find(
exact("Paneric\Authorization\ORM\Entity\Field"),
exact(1)
)
- flush(
)
Apparently issue is related to the call:
...
$field = $this->find($fieldId);
...
Although the second remark related to getClassMetadata, looks strange, considering the fact that my spec let method:
public function let(EntityManagerInterface $_em, ClassMetadata $classMetadata)
{
$_em->getClassMetadata(Field::class)->willReturn($classMetadata);
$this->beConstructedWith($_em);
}
does its job in case of other spec tests.
Can anyone help me to solve this issue ? Thx in advance.
In my repository's "update" metod, line:
$field = $this->find($fieldId);
has to be replaced by:
$field = $this->_em->find(Field::class, $fieldId);
so the complete spec test looks like:
public function it_updates(Field $field, FieldDTO $fieldDTO, EntityManagerInterface $_em)
{
$fieldId = 1;
$_em->find(Field::class, $fieldId)->willReturn($field);
$field->transfer($fieldDTO)->shouldBeCalled();
$_em->flush()->shouldBeCalled();
$this->update($fieldId, $fieldDTO);
}
I have a very simple API. You can POST a price (value and currency) to the API. The default currency is EUR, so it's ok to omit the currency. The API returns the full price object:
$ curl -d '{"value":12.1}' http://localhost:8000/prices.json
{
"value": 12.1,
"currency": "EUR"
}
So I wanted to implement this using Symfony Forms. I've set up a small data model with some basic validation rules:
namespace AppBundle\Model;
use Symfony\Component\Validator\Constraints as Assert;
class Price
{
/**
* #Assert\NotBlank()
* #Assert\GreaterThanOrEqual(0)
*/
public $value;
/**
* #Assert\NotBlank()
* #Assert\Length(min=3, max=3)
*/
public $currency = 'EUR';
}
And a controller with a form:
namespace AppBundle\Controller;
use AppBundle\Model\Price;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
class PriceController extends Controller
{
/**
* #Route("/prices.json")
*/
public function apiAction(Request $request)
{
$product = new Price();
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->getForm();
$form->submit(json_decode($request->getContent(), true));
if ($form->isValid()) {
return new JsonResponse($product);
}
return new JsonResponse($form->getErrorsAsString());
}
}
This works only if I pass all fields in the request body. I cannot omit the currency. Also setting data or empty_data does not help.
I tried to toggle $clearMissing on the submit() method, but this disables the validation of the model:
$form->submit(json_decode($request->getContent(), true), false);
The best working idea I came up so far is an event listener merging the data:
$form = $this->createFormBuilder($product, [
'csrf_protection' => false,
])
->add('value', 'number')
->add('currency')
->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $e) {
$e->setData(array_merge((array) $e->getForm()->getData(), $e->getData()));
})
->getForm();
This works for my simple example. But is this the best way to go? Or are there other / better alternatives?
Your solution looks good to me! I think adding the event listener like you did is the best way to go.
I suggest using array_replace() instead of array_merge(), since it is dedicated to associative arrays.
Based on this answer: Omnipay how to add new gateway
I try to add a new gateway for omnipay.
My folder structure:
lib/omnipay/newgw/
lib/omnipay/newgw/src/
lib/omnipay/newgw/src/Gateway.php
lib/omnipay/newgw/composer.json
vendor/omnipay/...
...
composer.json
In main composer.json I have:
{
"require": {
...
"omnipay/omnipay": "dev-master"
...
},
"autoload": {
"psr-0": {
"": "lib/",
"Omnipay\\NewGw\\" : "lib/omnipay"
}
}
}
Do composer update.
In gateway.php:
namespace Omnipay\NewGw;
use Omnipay\Common;
use Omnipay\Common\AbstractGateway;
use Omnipay\NewGw\Message\PurchaseRequest;
use Omnipay\NewGw\Message\RefundRequest;
class Gateway extends AbstractGateway{
}
And when I try to run it:
use Omnipay\Omnipay;
class TestController extends ControllerBase{
public function index(){
$gateway = Omnipay::create('NewGw');
}
}
It say's that class not found:
Omnipay\Common\Exception\RuntimeException: Class '\Omnipay\NewGw\Gateway' not found
I don't figure it out why the class isn't loaded.
Please help, Thanks.
I just created a new Gateway myself, I believe your problem is the fact that you are doing something like
"psr-0": {
"": "lib/",
"Omnipay\\NewGw\\" : "lib/omnipay"
}
And it should be
"Omnipay\\NewGw\\" : "lib/omnipay/src"
You are setting the namespace of the new library to lib/omnypay but it should actually be lib/omnypay/src
I'm trying to write some loggin failure info in database from a custom authentication handler.
My problem is to gain access to the database since I don't know where the Doctrine object might be stored
Here's my code for now :
namespace MyApp\FrontBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request as Request;
use Symfony\Component\HttpFoundation\RedirectResponse as RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Security\Http\Authentication as Auth;
use Symfony\Component\Security\Core\Exception\AuthenticationException as AuthException;
class SecurityHandler implements Auth\AuthenticationFailureHandlerInterface
{
public function onAuthenticationFailure(Request $request, AuthException $token)
{
try
{
$lastLoginFailure = new DateTime();
// get database object here
}
catch(\Exception $ex)
{
}
}
}
Any ideas ?
Turn your SecurityHandler into a service and then inject the doctrine entity manager into it.
http://symfony.com/doc/current/book/service_container.html
Start command php app/console container:debug.
Copy doctrine.orm.entity_manager and paste to your hadler constructor arguments like
[...., #doctrine.orm.entity_manager].
In hadler use Doctrine\ORM\EntityManager;
I think you should extends your class "SecurityHandler" with ContainerAware if you want to use service since your Security Handler is not a controller.
class SecurityHandler extend ContainerAware implements Auth\AuthenticationFailureHandlerInterface{
public function onAuthenticationFailure(Request $request, AuthException $token)
{
try
{
$lastLoginFailure = new DateTime();
// get database object here
$doctrine = $this->container->get('doctrine');
$repository = $doctrine->getRepository('*NAME OF REPO*');
}
catch(\Exception $ex)
{
}
}
}
I am using PHP Yii Framework with MongoDB(yiimongodbsuite). I have created a Model which extends from EMongoDocument.
<?php
class MyModel extends EMongoDocument
{
public $attr1;
public $attr2;
// rules, custom validations and other functions....
public function setAttributes($values, $safeOnly=true)
{
if(!is_array($values))
return;
if($this->hasEmbeddedDocuments())
{
$attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
foreach($this->embeddedDocuments() as $fieldName => $className)
if(isset($values[$fieldName]) && isset($attributes[$fieldName]))
{
$this->$fieldName->setAttributes($values[$fieldName], $safeOnly);
unset($values[$fieldName]);
}
}
parent::setAttributes($values, $safeOnly);
}
}
In Controller,
$dataModel = new MyModel();
$dataModel->setAttributes($_POST['MyModel']);
if($dataModel->validate()){
$dataModel->save();
}
the above code is not setting the attribute value.
Please let me know if there is any mistake.
You need to make sure that the 'safe' validation rules is used on each level.
To understand more read this http://www.yiiframework.com/wiki/161/understanding-safe-validation-rules/
Try to determine which valdation errors you have:
if(!$model->validate()) {
die( print_r($model->getErrors()) );
}