I am new to java 8 and I have this question
private Supplier<MissingAttribute> getExceptionSupplier(final String message) {
return () -> new MissingAttribute(message);
}
A team member of mine said taking in message object makes it no longer a supplier but a function but another team member said this is still a supplier (a get function). The message in the function is predefined
I am confused as to what is right.
public class MissingAttribute extends Exception {
public MissingAttribute(String message, Exception cause) {
super(message + " : " + cause.getMessage(), cause);
}
public MissingAttribute(String message) {
super(message);
}
.
.
.
I did research online, but I am still not sure of the answer. Any insights on this are appreciated!!
Your method returns technically a Supplier, i.e. an Object that receives no parameters and that returns something.
But in the idea, it looks like a Function because you provide a parameter to the method and the supplier it creates is dependent of this parameter.
Nevertheless it is still a Supplier because once it is created you will always have the same behaviour at each call. Note that it's perfectly standard for a Supplier to take an external constant into account.
In conclusion, following the use of this supplier in the calling code, it could be refactored as a Function or it makes sense to keep this method that creates a Supplier with a parameter.
Your function getExceptionSupplier returns a Supplier taking a String as it's argument. Supplier here is not taking any object as it's input. You function here taking a String instead. You are confusing with ordinary function & Function<T,U> Functional Interface which takes type T as input & produces type U as output.
Related
I saw this in a code, but I can't figure it out, and I didn't find it in documentation (Most probably I don't know how to search)
so it's like that in a model:
public function functionName(int $parameter): ClassName{...}
What does the Class after the parameter list stands for?
public function functionName(int $parameter): ClassName{...}
In this case ClassName is written to specify the return type of function.
functionName returns object instance of ClassName
you can read more about return types here: https://wiki.php.net/rfc/return_types
this is the return type declarations. PHP7 introduces this syntex.
It indicates the types of value that the function will return.
you can use int float and it's not limited to array you can use your own class
public function functionName(int $parameter): ClassName{...}
it's not just readability, if the function returns anything elase then it will throw an error
I have model House with relation hasMany HousePhotos.
I try get link to main photo from table house_photos.
class House extends Model
{
public function photos(){
return $this->hasMany('app\HousePhoto');
}
public function get_main_photo(){
return $this->photos()->where('main', true);
}
}
Controller:
$house=House::find(1);
In View i use
{{$house->main_photo()->link}}
and got error.
When i use
{{$house->main_photo()}}
i got object. How to get string value of link to photo?
First of all you need to understand the difference between the Builder object and the Collection object.
As it is now, function get_main_photo returns a Builder object (actually a Relation object, which contains a Builder).
On these objects you can call function get() to finish the query and get the results. In this case you will get a Collection object, which you will be able to iterate.
Alternatively, in this case you seem to only have one 'main photo' per house, so instead you can call first():
public function get_main_photo(){
return $this->photos()->where('main', true)->first();
}
This will return the single associated model, on which you will be able to access ->link (if the model was found).
Remember at any point while debugging you can call the convenient dd function (which dumps the object passed as parameter and terminates the applicacion) to see what type of object you are dealing with, and all its attributes.
class Batch extends Eloquent {
public function coupons() {
return $this->hasMany('Coupon');
}
}
class Coupon extends Eloquent {
public function batch() {
return $this->belongsTo('Batch');
}
public function price() {
$batch = $this->batch;
return $batch->price;
}
}
$coupon->price gives me this error:-
LogicException Relationship method must return an object of type
Illuminate\Database\Eloquent\Relations\Relation
However, $coupon->batch->price works just fine.
What am I missing?
Your issue here is that you define a non-relationship method price() but you call it as if it was a relationship method (i.e. you call it as a property and not as a method).
The code you should be using to get the Coupon's price is:
$coupon->price();
The reason the relationship thing works (i.e. $coupon->batch over $coupon->batch()) is that Laravel has some special logic in - basically it catches you trying to access a property (->batch in this case) and checked to see if there's a corresponding method (->batch()). If there is one, it calls it and expects it to return a relationship, and then it calls ->first() of ->get() on that relationship depending on whether it's a single-result or a multiple-result relationship.
So what's happening in your code here is that you call $coupon->price and Laravel, behind the scenes, decides that being as there's a ->price() method it must be a relationship. It calls the method, checks that it returns one of the Laravel relationship types, and when it doesn't, throws that LogicException.
The general rules of thumb is this:
If you want an actual property (i.e. anything defined on the table) or the results of a relationship query, use property access
If you want anything else (i.e. behaviour you're defined using a method) you must call the method directly
Also, sometimes there is a good reason to call a relationship as the method rather than the property - calling the method returns something you can add query builder constraints on to, whereas calling the property gets you all the results. So say Coupons can be enabled or disabled (for example), the following holds:
$batch->coupons gets you all coupons that the batch has
$batch->coupons()->whereEnabled(1)->get() gets you all enabled coupons for a given batch
$batch->coupons()->orderBy('order')->get() gets you all the coupons that the batch has, ordered by a field called order
$coupon->batch gets you the given coupon's batch
Hopefully that explains the difference between Eloquent's use of methods versus properties for relationships, and why all augmented behaviour (like price on coupon in your example, but not price on batch, which is inherent behaviour) must be called as a method.
Take a moment to realize what objects you actually have here.
When you call $this->batch; you're no longer chaining the relationship queries - you've actually retrieved the information from the database already. In order to define that query you'd have to do it one of several ways including:
Coupon::with('batch.price')->get();
You could of course do it with relationships but it's late and I'm not sure where exactly Price belongs in the scheme of this since I don't see a method for it associated with batch. Presumably you could do:
public function price()
{
return $this->batch->price;
}
if Price is a derivative of Batch.
In my edmx model are 2 related tables: Challenge and ChallengeNote (has FK back to ChallengeID)
I can do this in breeze all day long
var qry = dataservice.getQuery("Challenges");
However, this fails every time:
var qry = dataservice.getQuery("Challenges").expand("ChallengeNotes");
The searchFailed is called and is the only error information in the console.
return dataservice.execute(qry.inlineCount(true))
.then(seachSucceeded)
.fail(searchFailed);
Does Breeze support relational data like this?
Does one need to write some custom code to support?
What am I missing?
Here's related answered question, but I was already following (unless I missed something) the answer's solution (and why I have the 2 context.Configuration settings in my ContextProvider).
breezejs-error-when-loading-an-entity-with-related-data
Here's another similar question that's been unanswered breeze-expand-query-fails-with-object-object-has-no-method-getproperty
Here's my provider code (want to use the BeforeSaveEntity override further on in the project):
public class ModelProvider : EFContextProvider<ModelEntities>
{
public ModelProvider()
: base()
{
this.Context.Configuration.LazyLoadingEnabled = false;
this.Context.Configuration.ProxyCreationEnabled = false;
}
}
Here's my controller code:
[BreezeController]
public class DataController : ApiController
{
readonly ModelProvider _contextProvider = new ModelProvider();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[Queryable(AllowedQueryOptions = AllowedQueryOptions.All)]
[HttpGet]
public IQueryable<Challenge> Challenges()
{
return _contextProvider.Context.Challenges.Include(x => x.ChallengeNotes);
}
[HttpPost]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
[HttpGet]
public IQueryable<ChallengeNote> ChallengeNotes()
{
return _contextProvider.Context.ChallengeNotes;
}
}
When I browse to the URL, it's including the related entity:
http://localhost:53644/breeze/data/Challenges?$filter=Active%20eq%20true&$top=10&$expand=ChallengeNotes&$inlinecount=allpages
Here is the data coming from the Controller
At this point all things, imo, are pointing to Breeze configuration on either the Server or Client.
TIA
Breeze absolutely does support this, but you do need to make sure that your Entity Framework model is set up correctly. Take a look at the DocCode sample in the Breeze zip for a number of examples of using both expand (client side) or EF include (server side) clauses.
One guess about your problem is that you are using the Breeze camelCasing naming convention and therefore your "expand" clause should be
var qry = dataservice.getQuery("Challenges").expand("challengeNotes");
i.e. "challengeNotes" (note the casing) is the name of the client side property that corresponds to a server side property of "ChallengeNotes". To clarify, "expand" clauses take the names of client side "properties" as parameters and property names are what are transformed as a result of the Breeze.NamingConvention.
In contrast, a query resource name i.e. "Challenges" in your example is the name of the server side resource ( as a result of marking your "Challenges" method with the [HttpGet] annotation. This name is NOT affected by the NamingConvention.
Side notes: Your example has both an expand and an Include clause. Either of these is sufficient all by itself. You do not need both. In general you can either include an "expand" clause in your client side query OR have an Entity Framework "Include" clause on the server. The advantage of the first is that you can control the expand on the client, the advantage of the second is that you can insure that every query for a specified resource always fetches some related entities.
Hope this helps!
For years I have been using #ModelAttribute to create and initialize my command object like so:
#RequestMapping()
public String someHandler(#ModelAttribute("formBean") FormBean formBean) {
// Do something
}
#ModelAttribute("formBean")
public FormBean createFormBean() {
FormBean formBean = new FormBean();
// Do some sort of initialization
return formBean;
}
In this example, I have a handler in a Controller that needs a FormBean, and a "create" method that gives it one if one isn't already in the Model (or session, if using #SessionAttributes). So, when my someHandler() method is ran, the FormBean is already there and populated because my createFormBean() had already ran.
However, my colleague is claiming that, although this works just fine, that I am misusing the #ModelAttribute for a purpose it wasn't intended for, namely in the creation of the Command object. In his interpretation from the JavaDoc, you should only use #ModelAttribute to create static data, like items used to populate a dropdown list or such.
I know this works for creating and initializing my Command object quite well, but am I using this for a purpose it was not originally intended for? Am I breaking some cardinal rule here?
#ModelAttribute("formBean")
public FormBean createFormBean() {
FormBean formBean = new FormBean();
// Do some sort of initialization
return formBean;
}
This can be useful if you need to initialize model attribute before binding form values from view. For example, you can query object from database (to get available it in current session).
In other cases I prefer to use this method:
#RequestMapping
public String someHandler(final Model model) {
FormBean formBean = new FormBean();
// Do some sort of initialization
model.addAttribute("formBean", formBean);
}
I think it more clear to understand. But I don't think that you "breaking some cardinal rule here".