BindingResolutionException while creating services to access database - laravel

We are trying to implement architecture suggested in following article in order to make our application extensible
http://dfg.gd/blog/decoupling-your-code-in-laravel-using-repositiories-and-services
The article divides the models into following
Entities - normal Eloquent classes
Repositories - these use Entities to get data
Services - Contain Business logic
To try out the architecture we are trying to access a small table
We have created following classes
app/models/entities/Reminder.php //normal Eloquent model
app/models/repositories/reminder/ReminderInterface.php
app/models/repositories/reminder/ReminderRepository.php
app/models/repositories/reminder/ReminderRepositoryServiceProvider.php
app/models/services/reminder/ReminderFacade.php
app/models/services/reminder/ReminderService.php
app/models/services/reminder/ReminderServiceServiceProvider.php
We are struck at following error
Illuminate \ Container \ BindingResolutionException
Target [Repositories\Reminder\ReminderInterface] is not instantiable.
Can someone please guide what may be going wrong?
Our code is exactly the same as in the article. I tried to be brief in this description as posting code of all 7 classes is not sensible. Please let me know if you need any details.

Option 1
You might be missing a binding:
App::bind('Repositories\Reminder\ReminderInterface', 'Repositories\Reminder\ReminderRepository');
If you don't tell Laravel which implementation of your Interface you need it to Instantiate it will try to instantiate ReminderInterface, which is not instantiable, as the error says.
Option 2
If you are binding it in your service provider, you have to make sure your service provider is being executed, by adding it to app/config/app.php?

Related

AsyncCrudAppService Breaks Swagger When Providing TCreateInput and TUpdateInput

I recently downloaded a Single Page Web Application (Angular) from https://aspnetboilerplate.com/Templates using 3.x target version.
I just simply added a few entities and then started to follow the steps on this page https://aspnetboilerplate.com/Pages/Documents/Application-Services
Things do work well for me to Get, List, Update, and Delete entities when my app service class is just inheriting AsyncCrudAppService<Entities.PhoneBook, PhoneBookDto, long, GetAllPhoneBooksInput>, however when it is inheriting AsyncCrudAppService<Entities.PhoneBook, PhoneBookDto, long, GetAllPhoneBooksInput, CreatePhoneBookInput, and UpdatePhoneBookInput> the swagger definition will no longer load.
GitHub Repo: https://github.com/woodman231/MyPhoneBooks
(which currently does not work and will not load Swagger page).
I can get the swagger page to load by removing CreatePhoneBookInput and UpdatePhoneBookInput from
https://github.com/woodman231/MyPhoneBooks/blob/main/aspnet-core/src/MyPhoneBooks.Application/SimpleCrudAppServices/ISimplePhoneBookCrudAppService.cs#L9
and
https://github.com/woodman231/MyPhoneBooks/blob/main/aspnet-core/src/MyPhoneBooks.Application/SimpleCrudAppServices/SimplePhoneBookCrudAppService.cs#L14
However, again I am still unable to create entities using this default implementation. Any ideas?
I have cloned your repo and run it and I figured out the error, first as I tell you in comments I verified the text log, and it said the next:
System.InvalidOperationException: Can't use schemaId "$CreatePhoneBookInput" for type "$MyPhoneBooks.SimpleCrudAppServices.Dtos.CreatePhoneBookInput". The same schemaId is already used for type "$MyPhoneBooks.PhoneBooks.Dtos.CreatePhoneBookInput"
What happenig is that you have these two classes UpdatePhoneBookInput, CreatePhoneBookInput repeated in SanokeCrudAppServices\Dtos and PhoneBooks\Dtos
You have the classes in both folders with same exact name, and thats the problem, if you change the name in whatever place the swagger definition will load without errors, I have do it like this and everything works fine!
Change the name in one of the places, and all will be working fine
Personally I don't like to use a different Dto for Create and Update for me is easier to user just one Dto for all.
Ok I figured it out. I had also made a DIY AppService and some of the DTO Class Names associated with the DIY App Service clashed with the DTO Class Names associated with the Automated Service. It was acceptable in .NET since they were in different name spaces but once the swagger definition was configured I assume that there was multiple instances of the same DTO Defition. I checked the AbpLogs table but they didn't give me much details as to the specifics of the internal server error while loading the definition. It sure would have been useful to know that.

How to mock User model within composer package development tests?

I started creating a laravel 5.8 based modular API framework for our company which should be extended using composer packages.
Now I stumbled over the problem to test each package by itself (each package has it's own GIT project of course) if the package needs to have access to the User model given in the base framework (App/Models/User).
There will be various packages naturally depending on the User model such as specific auth modules.
Unfortunately testing also gets more complex because we are using GraphQL (Lighthouse).
So how should this be done? I tried mocking App/Models/User with a User model contained in the tests folder of my package, but this did not work as expected:
$this->userMock = \Mockery::mock('CompanyName\\PackageName\\Tests\\User');
$this->app->instance('App\\Models\\User', $this->userMock);
When, after that, posting a GraphQL request the resolver method throws a Class App\Models\User does not exist error.
I am quiet new to testing with phpunit so maybe I am just missing something here?
Edit:
I just found out that the error message above is displayed because the User model is also referenced within the GraphQL schema file.
So I there is any solution out there it has to somehow "emulate" the not existing User model class for the whole request lifecycle I guess...
Ok I finally solved my problem which was more conceptual wise I guess. As the user model is pretty strongly tied to the (core) package I want to test, I have now moved the model into the package itself and removed it from the base project.
This has the advantage that the "end user developer" doesn't even see and has to cope with the user model which is handles by the package anyway.
Now I can test the package independently and only have to put a line of documentation into the README to tell, that a user has to change the auth.providers.users.modelvalue to let laravel use the appropriate model (e.g. CompanyName\\PackageName\\Models).
If there will be other packages extending the user model, they will have to depend on the core package (which they should either way) and can extend the model class and tell the user to update auth.providers.users.model again. This way it is also quiet transparent to see which user model is used currently.
For the GraphQL / Lighthouse part I have added the following code to the boot method of the package's service provider to make lighthouse know about new models within the package automatically:
$lighthouseModels = config('lighthouse.namespaces.models');
array_push($lighthouseModels, 'CompanyName\\PackageName\\Models');
config([
'lighthouse.namespaces.models' => $lighthouseModels
]);
This can be repeated for every package adding models as well so lighthouse knows about all of them.

how to properly handle OData complex type relationships

Trying to build a WebAPI 2 / OData v4 service around a typical default Northwind database, using Entity Framework 6.1
My WebApiConfig is unhappy about "complex type relationships":
An exception of type 'System.InvalidOperationException'
occurred in System.Web.OData.dll
but was not handled in user code
Additional information: The complex type 'ODataProductService.Models.Order_Detail'
refers to the entity type 'ODataProductService.Models.Product'
through the property 'Product'.
Obviously, in any given database, these relationships are very likely to occur.
What is the proper way of hanlding this?
Here is how I gat this resolved:
1) added the following statements to my WebApiConfig.cs:
I have made a GitHub repo with a working solution in it:
builder.EntitySet<Customer>("Customers");
builder.EntitySet<Product>("Products");
builder.EntitySet<Order>("Orders").EntityType.HasKey(o => o.OrderID);
builder.EntitySet<Order_Detail>("Order Details").EntityType.HasKey(od => od.OrderID);
builder.EntitySet<CustomerDemographic>("CustomerDemographics").EntityType.HasKey(cd => cd.CustomerTypeID);
I have also made a repo with a working solution:
https://github.com/eugene-goldberg/ODataProductService/
The Readme file pretty much describes what to pay attention to.
You could also use the containment feature of OData V4. Using containment, you can avoid defining an entity set for Order_Detail.

How do I register an IBindingTypeConverter in ReactiveUI

I'm attempting to use the "new" binding code for ReactiveUI and when I do wire my view model property to my control I get the following error:
Additional information: Can't two-way convert between <type1> and <type2>. To fix this, register a IBindingTypeConverter
So... how do I register an IBindingTypeConverter ? I'm struggling to find an comprehensible example.
n.b. the code that's throwing the error is not relevant to this question, it may in itself be wrong but that is an entirely different issue
The way to do it is via Splat's service locator:
Locator.CurrentMutable.RegisterConstant(
new MyCoolTypeConverter(), typeof(IBindingTypeConverter));
Update: If you're using RxUI 5.x, it's "RxApp.CurrentMutable"

using doctrine with codeigniter

I am planning to use doctrine to write a module of my app which is built with codeigniter.
I have a very basic question :
lets say I have a table called "user", with doctrine generate-models from db, 3 classes are generated BaseUser.php, User.php and UserTable.php. Now as I saw in the examples they use User class straigtaway. Should I be doing this ? I need additional business functionality for the user objects. So should I create a codeigniter model user_model and then use User class inside it (aggregation) or somehow extend user class ( i dont know how this will be done as user_model extends model)
Am little confused on this one and cannot locate any appropriate literature for the same.
Any help would be appreciated.
thanks in advance,
For anyone who is interested - I’ve posted up a project starter on my blog - a dev ready incorporation of the following technologies:
ExtJS : client side JS library,
CodeIgniter : presentation + domain tier,
Doctrine : ORM data layer framework
Some features of this project starter are:
- CodeIgniter Models have been replaced with Doctrine Records
- Doctrine is loaded into CI as a plugin
- RoR type before and after filters….
- Doctrine transactions automatically wrapped around every action at execution time (ATOMIC db updates)
Basic Role based security (I think Redux may be in there as well?)
Simply extract, hook up the database.php config file and viola…. You can start coding your layouts, views and models. Probably a few things to iron out - but enjoy!
Hope it helps
GET IT AT: http://thecodeabode.blogspot.com
Check out this info on Doctrine_Table class.
To your 3 generated files:
BaseXXX.php:
Holds the definition of your models so that Doctrine is able to handle the operations on the database. This class tells the ORM what colums are available, their types, advaned functions (like Timestampable,...) and more. You should not put your own data into this file since it will be over-written when re-creating the models from the database.
XXX.php:
Your actual model. This won't be re-created with each new generation process and this is were you keep most of your code. You can overwrite functions of the BaseXXX.php if you have to.
XXXTable.php:
Check my link from the top, This gives you access to the table itself. Personally, I do not use it that often since I put most of the code into XXX.php.
Of course you can create new classes and use them inside your XXX.php file. In order to actually do something with the data (save, read,...) you need classes that are connected (exteneded) from Doctrine's classes.
edit: also check this on a more infos with extending from the Doctrine_Table class

Resources