I have a collection of Recipes and each one contains Categories. This are my models:
class Recipe extends \Model {
public static $_table = "recipe";
public function categories() {
return $this->has_many_through('Category');
}
}
class Category extends \Model {
public static $_table = "category";
public function categories() {
return $this->has_many_through('Recipe');
}
}
And the table to relate both:
class CategoryRecipe extends \Model {
public static $_table = "category_recipe";
}
Now I need to create a query to get all the Recipes that are under one/more categories. What is the way to achieve this? I want to avoid making things like this:
$results = $app['paris']->getModel('CategoryRecipe')
->where_in("category_id",$selected_categories)
->find_many();
foreach($results as $result) {
$recipe = $app['paris']->getModel('Recipe')
->where('id',$result->recipe_id)
->find_one();
var_dump($receta->name);
}
Create filters? functions inside the models? Is not possible to make it more elegant?
That is pretty much how I would do it, but you can optimise in one way. Add relation functions to your linking/many-to-many table. Then instead of doing that extra query in your foreach loop you simply do:
foreach($results as $result) {
$recipe = $result->recipe()->find_one();
var_dump($recipe)
}
So your CategoryRecipe model might look like:
class CategoryRecipe extends \Model {
public static $_table = "category_recipe";
public function recipe() {
$this->belongs_to('Recipe', 'recipe_id');
}
public function category() {
$this->belongs_to('Category', 'category_id');
}
}
I haven't tested this code, but it should be what you're after I think.
Related
I'm learning ASP.NET Core MVC development. I'm trying to create a search query that returns the book if author name or the book title matches from a dummy database.
This is my BookRepository (data source):
public class BookRepository
{
public List<BookModel> SearchBook(string title, string authorName)
{
return DataSource().Where(x => x.Title.Contains(title) || x.Author.Contains(authorName)).ToList();
}
private List<BookModel> DataSource()
{
return new List<BookModel>
{
new BookModel(){Id=1, Author="Einstein", Title="The Grand Design"},
new BookModel(){Id=2, Author="Author", Title="ASP.Net"},
new BookModel(){Id=3, Author="Author1", Title="Visual Studio"}
};
}
}
My BookController class is:
using Book_Store.Repository;
namespace Book_Store.Controllers
{
public class BookController : Controller
{
private readonly BookRepository bookRepository = null;
public BookController()
{
bookRepository = new BookRepository();
}
public List<BookModel> SearchBook(string bookName, string authorName)
{
return bookRepository.SearchBook(bookName, authorName);
}
}
}
The problem is this query is returning a null array every time. I'm executing the command like this:
Can someone please identify the problem in this rather simple program?
Thanks!
If I want to use a Table from a DataContext, I need to instantiate it:
Table<Customer> customers = db.GetTable<Customer>();
But if it's in a custom DataContext:
public partial class Northwind : DataContext
{
public Table<Customer> Customers;
...
}
I can just use it like this:
Table<Customer> customers = db.Customers;
Where is it instantiated?
Based on the documentation, it is just a property getter that return this.GetTable<TEntity>().
Eg.
public partial class DataClasses1DataContext : System.Data.Linq.DataContext {
public System.Data.Linq.Table<User> Users {
get {
return this.GetTable<User>();
}
}
}
How do you implement interface for external package in Laravel? Say, I want to use Mashape/Unirest API to get analyse of text, but in future I would like to switch to other API provider and do not change to much in code.
interface AnalyzerInterface {
public function analyze(); //or send()?
}
class UnirestAnalyzer implements AnalyzerInterface {
function __constructor(Unirest unirest){
//this->...
}
function analyze($text, $lang) {
Unirest::post(.. getConfig() )
}
//some private methods to process data
}
And where to put that files interfece and UnirestAnalyzer? Make special folder for them, add to composer? Add namespace?
This is how I would go to Interface and Implement something like this:
interface AnalyzerInterface {
public function analyze();
public function setConfig($name, $value);
}
class UnirestAnalyzer implements AnalyzerInterface {
private $unirest;
private $config = [];
public function __construct(Unirest unirest)
{
$this->unirest = $unirest;
}
public function analyze($text, $lang)
{
$this->unirest->post($this->config['var']);
}
public function setConfig($name, $value)
{
$this->config[$name] = $value;
}
//some private methods to process data
}
class Analyser {
private $analizer;
public function __construct(AnalyzerInterface analyzer)
{
$this->analyzer = $analyzer;
$this->analyzer->setConfig('var', Config::get('var'));
}
public function analyze()
{
return $this->analyzer->analyze();
}
}
And you must bind it on Laravel:
App::bind('AnalyzerInterface', 'UnirestAnalyzer');
I have two models with a one-to-many relationship.
class User extends ConfideUser {
public function shouts()
{
return $this->hasMany('Shout');
}
}
class Shout extends Eloquent {
public function users()
{
return $this->belongsTo('User');
}
}
This seem to work fine.
BUT, How do I get this to return the users object nested in the shout objects?
Right now it only returns all my Shouts, but I have no access in the JSON to the belonging user model.
Route::get('api/shout', function() {
return Shout::with('users')->get();
});
This just returns this JSON, with no user object for every shout:
[{"id":"1","user_id":"1","message":"A little test shout!","location":"K","created_at":"2013-05-23 19:51:44","updated_at":"2013-05-23 19:51:44"},{"id":"2","user_id":"1","message":"And here is an other shout that is a little bit longer...","location":"S","created_at":"2013-05-23 19:51:44","updated_at":"2013-05-23 19:51:44"}]
I was having the same trouble using Laravel 5. Just wanted to add that I got it to work by using the Model::with("relationship")->get() method on the model.
I figured it out.
The method needs to be named user() not users() when working with "belongsTo" relationship.
Makes sense.
And seems to work.
If you are using:
protected $visible = ['user'];
Don't forget to add there relationship, to be visible in JSON
u can use protected $with = ['users']; on Class Shout and use protected $with = ['shouts'];.
and Give Full namespace model name
class Shout extends Eloquent {
protected $with = ['users'];
public function users()
{
return $this->belongsTo('App\User');
}
}
and
class User extends ConfideUser {
protected $with = ['shouts'];
public function shouts()
{
return $this->hasMany('App\Shout');
}
}
Receive It
Route::get('api/shout', function() {
return Shout::all()->toJson;
});
I wonder how to add state to the chain of decorators that will be available to the consumer. Given this simplified model:
abstract class AbstractPizza
{
public abstract print(...);
}
class Pizza : AbstractPizza
{
public int Size { get; set; }
public print(...);
}
abstract class AbstractPizzaDecorator
{
public Pizza:AbstractPizza;
public abstract print();
}
class HotPizzaDecorator : AbstractPizzaDecorator
{
public int Hotness { get; set; }
public print(...);
}
class CheesyPizzaDecorator : AbstractPizzaDecorator
{
public string Cheese { get; set; }
public print(...);
}
void Main()
{
BigPizza = new Pizza();
BigPizza.Size = 36;
HotBigPizza = new HotPizzaDecorator();
HotBigPizza.Pizza = BigPizza;
HotBigPizza.Hotness = 3;
HotBigCheesyPizza = new CheesyPizzaDecorator();
HotBigCheesyPizza.Pizza = HotBigPizza;
HotBigCheesyPizza.Cheese = "Blue";
HotBigCheesyPizza.print();
HotBigCheesyPizza.size = 28; // ERRRRRR !
}
Now if they all implement the print method and propagate that though the chain, it's all good. But how does that work for the state? I can't access the size property on the HotBigCheesyPizza.
What's the part that I'm missing? Wrong pattern?
Thanks for helping!
Cheers
The decorator pattern is for adding additional behavior to the decorated class without the client needing to adjust. Thus it is not intended for adding a new interface (e.g. hotness, cheese) to the thing being decorated.
A somewhat bad example of what it might be used for is where you want to change how size is calculated: you could create a MetricSizePizzaDecorator that converts the size to/from English/metric units. The client would not know the pizza has been decorated - it just calls getSize() and does whatever it needs to do with the result (for example, to calculate the price).
I would probably not use the decorator in my example, but the point is: it does not alter the interface. In fact, nearly all design patterns come down to that - adding variability to a design without changing interfaces.
one way of adding state is by using a self referential data structure (a list). but this uses the visitor pattern and does more than you probably want. this code is rewritten from A little Java, a few patterns
// a self referential data structure with different types of nodes
abstract class Pie
{
abstract Object accept(PieVisitor ask);
}
class Bottom extends Pie
{
Object accept(PieVisitor ask) { return ask.forBottom(this); }
public String toString() { return "crust"; }
}
class Topping extends Pie
{
Object topping;
Pie rest;
Topping(Object topping,Pie rest) { this.topping=topping; this.rest=rest; }
Object accept(PieVisitor ask) { return ask.forTopping(this); }
public String toString() { return topping+" "+rest.toString(); }
}
//a class to manage the data structure
interface PieManager
{
int addTopping(Object t);
int removeTopping(Object t);
int substituteTopping(Object n,Object o);
int occursTopping(Object o);
}
class APieManager implements PieManager
{
Pie p=new Bottom();
// note: any object that implements a rational version of equal() will work
public int addTopping(Object t)
{
p=new Topping(t,p);
return occursTopping(t);
}
public int removeTopping(Object t)
{
p=(Pie)p.accept(new RemoveVisitor(t));
return occursTopping(t);
}
public int substituteTopping(Object n,Object o)
{
p=(Pie)p.accept(new SubstituteVisitor(n,o));
return occursTopping(n);
}
public int occursTopping(Object o)
{
return ((Integer)p.accept(new OccursVisitor(o))).intValue();
}
public String toString() { return p.toString(); }
}
//these are the visitors
interface PieVisitor
{
Object forBottom(Bottom that);
Object forTopping(Topping that);
}
class OccursVisitor implements PieVisitor
{
Object a;
OccursVisitor(Object a) { this.a=a; }
public Object forBottom(Bottom that) { return new Integer(0); }
public Object forTopping(Topping that)
{
if(that.topping.equals(a))
return new Integer(((Integer)(that.rest.accept(this))).intValue()+1);
else return that.rest.accept(this);
}
}
class SubstituteVisitor implements PieVisitor
{
Object n,o;
SubstituteVisitor(Object n,Object o) { this.n=n; this.o=o; }
public Object forBottom(Bottom that) { return that; }
public Object forTopping(Topping that)
{
if(o.equals(that.topping))
that.topping=n;
that.rest.accept(this);
return that;
}
}
class RemoveVisitor implements PieVisitor
{
Object o;
RemoveVisitor(Object o) { this.o=o; }
public Object forBottom(Bottom that) { return new Bottom(); }
public Object forTopping(Topping that)
{
if(o.equals(that.topping))
return that.rest.accept(this);
else return new Topping(that.topping,(Pie)that.rest.accept(this));
}
}
public class TestVisitor
{
public static void main(String[] args)
{
// make a PieManager
PieManager pieManager=new APieManager();
// add some toppings
pieManager.addTopping(new Float(1.2));
pieManager.addTopping(new String("cheese"));
pieManager.addTopping(new String("onions"));
pieManager.addTopping(new String("cheese"));
pieManager.addTopping(new String("onions"));
pieManager.addTopping(new String("peperoni"));
System.out.println("pieManager="+pieManager);
// substitute anchovies for onions
int n=pieManager.substituteTopping(new String("anchovies"),new String("onions"));
System.out.println(n+" pieManager="+pieManager);
// remove the 1.2's
n=pieManager.removeTopping(new Float(1.2));
System.out.println(n+" pieManager="+pieManager);
// how many anchovies do we have?
System.out.println(pieManager.occursTopping(new String("anchovies"))+" anchovies");
}
}
I believe your component Pizza and your abstract decorator PizzaDecorator are supposed to share the same interface, that way each instance of the decorator is capable of the same operations as the core component Pizza.