Laravel error handling, get_class vs instanceof - laravel-5.4

In the following code in app/Exceptions/Handler.php, the first one doesn't work but the second one does.
dd(get_class($exception)); outputs "Illuminate\Database\Eloquent\ModelNotFoundException".
The first one is similar to the doc. How can I make it work using instanceof?
public function render($request, Exception $exception)
{
//dd(get_class($exception));
// this does not work.
if ($exception instanceof Illuminate\Database\Eloquent\ModelNotFoundException
) {
return response()->json(['error'=>['message'=>'Resouce not found']], 404);
}
// This one works.
if(get_class($exception) == "Illuminate\Database\Eloquent\ModelNotFoundException") {
return response()->json(['error'=>['message'=>'Resouce not found']], 404);
}
return parent::render($request, $exception);
}

To use instanceof you must use the full class name, and if your class has a namespace then you should use the fully qualified class name of the class.
And there is an other way to use instanceof using a short name (alias) for a given class thanks to use statement, in your case you can use it like so :
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException; // on top of course :)
if ($exception instanceof ModelNotFoundException) {
return response()->json(['error'=>['message'=>'Resouce not found']], 404);
}

Sometimes an $exception is rethrown, so try to use
$exception->getPrevious() instanceof XXX
or
get_class($exception->getPrevious()) == 'XXX'

Related

Spring WebFlux; unit testing exception thrown in Mono.map()

I have some code that returns Mono<List<UserObject>>. The first thing I want to do is check the List is not empty, and if it is, throw a NoUsersFoundException. My code looks like this:
IUserDao.java
Mono<List<UserAccount>> getUserProfiles(final Set<UserQueryFilter> filters,
final Set<String> attributes);
GetUserAccount.java
public Mono<UserAccount> doGetUserAccount() {
return userDao.getUserProfiles(filters, attributes)
.map(list -> {
if (CollectionUtils.isEmpty(list)) {
throw new NoUsersFoundException();
}
return list;
})
.map(this::removePermissions)
.map(this::removeDuplicates);
}
I want to write a unit test that will test that the NoUsersFoundException is thrown when userDao.getUserProfiles(filters, attributes) returns an empty list. When I use Mockito#when with a .thenReturn(), the test will, as expected, return immediately once userDao.getUserProfiles(...) is called without continuing the flow into the .map() where the list is checked and exception thrown.
#Mock
private IUserDao userDao;
private UserPolicies userPolicies;
#BeforeEach
public void init() {
userPolicies = new UserPolicies(Set.of("XYZ", USER_AFF, "123"),
Set.of(TestUserConstants.ID, TestUserConstants.SUBSCRIPTION_LEVEL));
}
#Test
void shouldThrowExceptionIfNoUsersFound() {
final Set<UserFilter> filters = new UserFilterBuilder().withId(ID)
.withSubscription(PREMIUM)
.build();
when(userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
.thenReturn(Mono.just(Collections.emptyList()));
testClass = new GetUserAccount(userDao,
userPolicies,
filters,
userPolicies.getUserAttributeIds());
assertThatThrownBy(() -> testClass.doGetUserAccount()).isInstanceOf(NoUsersFoundException.class);
}
I have tried .thenAnswer() but it essentially does the same thing as the method called is not a void:
userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
.thenAnswer((Answer<Mono<List>>) invocationOnMock -> Mono.just(Collections.emptyList()));
I can't see how using reactor.test.StepVerifier would work for this case.
i dont really understand what you are asking for, but we commonly dont "throw" exceptions in reactor. We return a Mono#error downstream, and different operators will react accordingly as the error travels downstream.
public Mono<List<Foobar> fooBar(filters, attributes) {
return daoObject.getUserProfiles(filters, attributes)
.map(list -> {
if (CollectionUtils.isEmpty(list)) {
// Return a mono#error
return Mono.error( ... );
}
return list;
})
}
And then test using the step verifier. With either expectNext or expectError.
// Happy case
StepVerifier.create(
fooBar(filters, attributes))
.expectNext( ... )
.verify();
// Sad case
StepVerifier.create(
fooBar(filters, attributes))
.expectError( ... )
.verify();

Yii2: Convert hasMany() relation into hasOne()

I need to be able to convert a hasMany() relation, which queries and return an array into a hasOne() relation which returns object|null.
Use case:
public function getItems() : \yii\db\ActiveQuery {
return $this->hasMany(Item::class, ['parent_id' => 'id']);
}
I want to create a relation which returns one specific Item object (or null if it does not exist).
I would like to do something like this:
public function getPrimaryItem() : \yii\db\ActiveQuery {
return $this->getItems()->andWhere(["primary"=>true])->toHasOne();
}
Please do not tell me to call ->one() on the original query, because that is not going to solve the problem. I need to be able to:
call $model->primaryItem and receive either Item or null
call $model->getPrimaryItem() and receive the relation's ActiveQuery
You can toggle it by multiple property of \yii\db\ActiveQuery
public function getPrimaryItem() : \yii\db\ActiveQuery {
$query = $this->getItems();
$query->multiple = false;
//Your logics
$query->andWhere(["primary"=>true])
return $query;
}

Yii2: Model column alias

I have some silly column names in my database, is there an easy way to alias a column name so it's always used for example:
public function columnAlias(){
return ['id'=>'ID', 'foo'=>'Bar'];
}
$model->id === $model->ID
$model->foo === $model->Bar
If it's only for accessing the attributes on the model you can write a get function.
So adding:
public function getId() {
return $this->ID;
}
public function getFoo() {
return $this->Bar;
}
will enable you to access ID and Bar like
$model->id;
$model->foo;
This works because of Yii2's use of the magic method __get: https://github.com/yiisoft/yii2/blob/master/framework/base/Component.php#L134

Simple LINQ to SQL extension method

How would I write a simple LINQ to SQL extension method called "IsActive" which would contain a few basic criteria checks of a few different fields, so that I could reuse this "IsActive" logic all over the place without duplicating the logic.
For example, I would like to be able to do something like this:
return db.Listings.Where(x => x.IsActive())
And IsActive would be something like:
public bool IsActive(Listing SomeListing)
{
if(SomeListing.Approved==true && SomeListing.Deleted==false)
return true;
else
return false;
}
Otherwise, I am going to have to duplicate the same old where criteria in a million different queries right throughout my system.
Note: method must render in SQL..
Good question, there is a clear need to be able to define a re-useable filtering expression to avoid redundantly specifying logic in disparate queries.
This method will generate a filter you can pass to the Where method.
public Expression<Func<Listing, bool>> GetActiveFilter()
{
return someListing => someListing.Approved && !someListing.Deleted;
}
Then later, call it by:
Expression<Func<Filter, bool>> filter = GetActiveFilter()
return db.Listings.Where(filter);
Since an Expression<Func<T, bool>> is used, there will be no problem translating to sql.
Here's an extra way to do this:
public static IQueryable<Filter> FilterToActive(this IQueryable<Filter> source)
{
var filter = GetActiveFilter()
return source.Where(filter);
}
Then later,
return db.Listings.FilterToActive();
You can use a partial class to achieve this.
In a new file place the following:
namespace Namespace.Of.Your.Linq.Classes
{
public partial class Listing
{
public bool IsActive()
{
if(this.Approved==true && this.Deleted==false)
return true;
else
return false;
}
}
}
Since the Listing object (x in your lambda) is just an object, and Linq to SQL defines the generated classes as partial, you can add functionality (properties, methods, etc) to the generated classes using partial classes.
I don't believe the above will be rendered into the SQL query. If you want to do all the logic in the SQL Query, I would recommend making a method that calls the where method and just calling that when necessary.
EDIT
Example:
public static class DataManager
{
public static IEnumerable<Listing> GetActiveListings()
{
using (MyLinqToSqlDataContext ctx = new MyLinqToSqlDataContext())
{
return ctx.Listings.Where(x => x.Approved && !x.Deleted);
}
}
}
Now, whenever you want to get all the Active Listings, just call DataManager.GetActiveListings()
public static class ExtensionMethods
{
public static bool IsActive( this Listing SomeListing)
{
if(SomeListing.Approved==true && SomeListing.Deleted==false)
return true;
else
return false;
}
}
Late to the party here, but yet another way to do it that I use is:
public static IQueryable<Listing> GetActiveListings(IQueryable<Listing> listings)
{
return listings.Where(x => x.Approved && !x.Deleted);
}
and then
var activeListings = GetActiveListings(ctx.Listings);

Best practice for interface with a getter function that could return multiple types

I have several data manipulation widgets that all implement a custom IPropertyEditor interface. I would like to include a GetValue getter, but the return types could be String, Boolean or int, off the top of my head. In AS3, all of that inherits from Object, so I could have GetValue return an object, but I don't feel great about that approach. At the risk of asking a subjective question, does anyone have any recommendations on how to approach this?
In ActionScript I'm pretty sure you can set a variable return type by defining a function in the following way:
public function getValue():* {
return "Any of these would be fine.";
return true;
return 1;
return new Sprite();
}
Hope that helps.
In practice, there is an actual getter/setter model in ActionScript. For your case, you could use it like this:
private var _value:*;
public function get value() : * {
return _value;
}
public function set value(val:*) : void {
if (typeof val == "int" || typeof val == "boolean" || typeof val == "string") {
_value = val;
}
}
This limits the user to setting (per your requirements) the value of this "value" property to data types int, Boolean, or String.