Scenario:
An alert belongs to 1 user and 1 location, both referenced, respectively, by foreign keys in the alert table - user_id and location_id. The user_id will be the same for each request, but the location_id most definitely differs.
I want to display all alerts relating to that one user, I have successfully achieved this but without the use of eager loading.
my getIndex function so far:
public function getIndex()
{
$alert = User::with('alerts.location')
->where('id', '=', Auth::user()->id)->first();
$this->layout->content = View::make('agents.index',
array('alert' => $alert));
}
Printing the MYSQL query seems logically correct however, I am struggling to show the 'locations' part of the query.
My foreach loop is:
#foreach($alert->locations as $alert)
<td>{{ $alert->location->address_1}}</td>
#endforeach
However, it returns the error:
Invalid argument supplied for foreach()
Thank you for your help.
By accessing the data using this forloop, I was able to resolve the problem #foreach($alert->alerts as $alert).
Related
I have a really weird one.
I have a master - detail relationship, lets call it Order and OrderItem. On the front page I have a list of Orders and alongside each row I have an "Edit" link which takes me to an edit page.I need to show the Order details at the top and I edit the Order Item details at the bottom.
However the "Id" hidden field for the "Order Item" form is showing the "Order" Id Value. What is even more weird is that DisplayFor shows the correct value and HiddenFor and EditorFor Show the "Order" Id Value.
I am using a View Model to contain the Master and Detail entities for the Razor view which I populate in the controller.
Assume Order# = 16 and OrderItem# = 7
So :
#model vmOrder // ViewModel that contains myOrder and MyOrderItems.
#Html.EditorFor(m=>m.myOrderItems.First().Id) // Produce 16
#Html.HiddenFor(m=>m.myOrderItems.First().Id) // Produce 16
#Html.DisplayFor(m=>m.myOrderItems.First().Id) // Produce 7 which is correct.
I did intend to just return the first record hence "First()" for other reasons. It seems MVC is getting muddled...
Any thoughts. Seems most bizarre to me?
Many thanks,
Sam
What is myOrderItems? If it contains the results of a deferred LINQ query, each time you call First it will re-evaluate the query. Depending on how you have your query written, this could cause the value to change.
If myOrderItems is IEnumerable, make sure you are calling ToList or ToArray to force the query to run.
Second, don't call First multiple times. Try something like this.
#model vmOrder // ViewModel that contains myOrder and MyOrderItems.
#var first = Model.myOrderItems.First()
#Html.EditorFor(m => first.Id)
#Html.HiddenFor(m => first.Id)
#Html.DisplayFor(m => first.Id)
I have added Model error from controller using
if( model property not selected)
{
ModelState.AddModelError("SelectionRequired","Please select atleast one value");
}
This error I am adding at many places in that same method but ultimately I want to show to user only one such message out of the ModelState errors collection.
For that purpose before returning to view I have to remove all similar messages except one.
How can i remove this messages using "SelectionRequired" i.e. key and not using "Please select atleast one value".This "SelectionRequired" is not a model property name is just a key we want to use.
I checked ModelState.Keys collection at runtime I don't see the "SelectionRequired" at all in those collection and also not even in ModelState.Values collection. Then where does this key *"SelectionRequired" goes ? and how to select errors based on it ?
is there any better way to do this ?
This might work:
var error = ModelState["SelectionRequired"].Errors.First();
ModelState["SelectionRequired"].Errors.Clear();
ModelState["SelectionRequired"].Errors.Add(error);
I want to do a simple join using zf2 selecting fields from the first and second table, but I get an error ('Statement could not be executed') when I try to put an array of fields into the columns method.
public function fetchAll()
{
$resultSet = $this->tableGateway->select(function (Select $select) {
$select->columns();// ->with params gives an 'Statement could not be executed'
$select->join(array('t2' => 'categories'), 'table1.idCategory = t2.id');
$select->order('dateTime DESC')->limit(100);
});
...
}
You will need to make sure the dateTime/id fields are in the column list you provide.
If you dump out the exception ($e->getTraceAsString()) you will get some more information about what is causing your error.
Either comment this statement Or add atleast one valid 'column' name in array (table column/field name).
$select->columns(array('column_one', 'column_two', 'column_N'));
A blank $select->columns(); statement generates sql query something like SELECT FROM table_name which results in error.
When you comment this statement, it generates sql query like SELECT * FROM table_name
and if you pass column names, asterisk replaced by them.
I was following this tutorial http://www.asp.net/mvc/tutorials/mvc-music-store
when I stumbled on this piece of code.
public ActionResult AddToCart(int id)
{
// Retrieve the album from the database
var addedAlbum = storeDB.Albums
.Single(album => album.AlbumId == id);
// Add it to the shopping cart
var cart = ShoppingCart.GetCart(this.HttpContext);
cart.AddToCart(addedAlbum);
// Go back to the main store page for more shopping
return RedirectToAction("Index");
}
I don't understand two things:
1)
var addedAlbum = storeDB.Albums
.Single(album => album.AlbumId == id);
What is this code doing? I don't know what the operator => does. Also I guess .Single is some function for the database?
2)
This function is having a call to itself? I don't see how it adds the album to the cart this way. Wouldn't this cause a function to go into an infinite loop?
It seems there are a lot of core C# that you aren't quite familiar with yet.
the => operator is the lambda operator, which is a succinct way of writing an inline function.
The Single function is an extension method which in this case is makes a call to the database. This method makes use of a neat feature known as expression trees to convert the strongly typed C# comparison into the corresponding SQL code. How it works is a pretty advanced topic, so for now just consider it "magic".
The AddToCart method of the cart object is different from the AddToCart controller action method the code is currently in. I don't have a link for that, since that's fairly basic object-oriented programming.
I would assume that cart.AddToCart will actually update the database.
Also read up on LINQ for a better understanding. This is most likely either Linq To Sql or LINQ to Entities using the Entity Framework.
The Action is being passed the ID of a album which can then be retrieved from the database with storeDB.Albums.Single() call. (the lambda is saying "find the entry in the database where the value in the AlbumId column matches the ID passed to the controller.") Think of .Single as the LINQ facsimile of:
SELECT TOP(1) *
FROM Albums
WHERE Albums.AlbumId = <id>
It's then grabbing the user's shopping cart and adding that fetched album object to the cart.
Then you're redirected to the index where it can list all entries in the cart.
I'm attempting to create a Product Engine for Apostrophe. I'm having trouble extending the Page Settings form, at the moment I want to add a simple textarea to add a synopsis to the page - eventually I want to add Product settings but I need to get the basics working first.
I've created a form and a settings partial, it's displaying fine and saving the data (with the help of a little hack - might not be correct). The trouble I'm having is when you edit a page the data is not being pulled back in to the form. To be honest I probably doing something fundamentally wrong but I lack experience in Symfony.
My table schema
ccProduct:
tableName: cc_product
actAs:
Timestampable: ~
columns:
page_id:
type: integer
notnull: true
synopsis:
type: text
relations:
Page:
class: aPage
local: page_id
foreign: id
type: one
onDelete: CASCADE
My form ccProductEngineForm.class.php
class ccProductEngineForm extends ccProductForm
{
public function __construct($object = null, $options = array(), $CSRFSecret = null)
{
// when editing the page the values are not show, this is an attempt to get it to work - it still doesn't :(
$page_id = sfContext::getInstance()->getRequest()->getParameter('id');
sfContext::getInstance()->getRequest()->setParameter('page_id', $page_id);
$ccProduct = Doctrine::getTable('ccProduct')->findOneByPageId($page_id);
if ($ccProduct) {
sfContext::getInstance()->getRequest()->setParameter('id', $ccProduct->getId());
}
// aPageForm object is passed in
parent::__construct(null, $options, $CSRFSecret); // construct normally
//$this->mergeForm(new aPageForm($object, $options, $CSRFSecret)); // merge the aPageForm - Nope, ignore it!?
}
public function setup() {
parent::setup();
$this->useFields(array('synopsis'));
$this->widgetSchema->setNameFormat('enginesettings[%s]');
$this->widgetSchema->setFormFormatterName('aPageSettings');
}
protected function doSave($con = null)
{
// page_id is missing! possible bug? BaseaActions.class.php ~ 520
$this->values['page_id'] = sfContext::getInstance()->getRequest()->getParameter('enginesettings[pageid]');
parent::doSave($con);
}
}
Thanks in advance for any help
EDIT:
Thanks for your answer Tom, I'll try to add a little more detail.
I was aware that a page object is passed into the Engine, but I wasn't exactly sure what do to with it - see my confused line of code:
//$this->mergeForm(new aPageForm($object, $options, $CSRFSecret)); // merge the aPageForm - Nope, ignore it!?
To clarify my 'product' is a page that uses the ccProduct engine. I now want to add extra information to that page. Does that make sense? In your words..
Are you trying to actually create a unique product that has its sole "home" on a product engine page? That's what subclassing ccProductForm would do
Yes :)
EDIT 2:
Following Tom's first suggestion (Apostrophe CMS: Engine Creation) I was able to extend the aPage table with my extra fields and the Engine is now saving these.
However, the standard aPageTable::getPagesInfo function isn't returning the fields I saved. I assume I'll have to select these separately?
EDIT 3:
aPageTable::retrieveBySlug() will do the job :)
REVISITED
I decided to revisit this and try Tom's second approach..
The other approach (if for whatever reason you don't want extra columns in aPage) is to keep your ccProduct table and fetch the relevant one
I managed to get this working, my ccProductEngine form constructor now looks like this..
class ccProductEngineForm extends ccProductForm
{
public function __construct($aPage = null, $options = array(), $CSRFSecret = null)
{
$page_id = $aPage->getId();
if ($page_id) {
$product = Doctrine_Core::getTable('ccProduct')->findOneByPage_id($page_id);
if ($product) {
$ccProduct = $product;
} else {
$ccProduct = new ccProduct();
}
}
parent::__construct($ccProduct, $options, $CSRFSecret);
}
I hope this helps someone :)
The main thing to remember is that your engine settings form receives a page object as the first parameter to the constructor, and you need to associate whatever your data is with that page object. Usually the engine settings form is a subclass of aPageForm, but it does not have to be. All that is required is that you associate your product object(s) with the page object in some way. Depending on your goals you probably want a refClass that creates a one-to-many relationship between product engine pages and products, and a form for manipulating those relationships.
From your code it is difficult for me to guess what you really want to do. Are you trying to actually create a unique product that has its sole "home" on a product engine page? That's what subclassing ccProductForm would do. Or do you just want to select an existing product from the product table and associate it with each engine page? Or do you want to select one or more products and associate them with the engine page?
Stuffing things into the request object is definitely not the way to go (:
Please clarify and I can help you further.
Tom Boutell, Apostrophe senior developer
There are two approaches you could follow here.
One is to just extend the schema of aPage in your project level config/doctrine/schema.yml file:
aPage:
columns:
synopsis:
type: text
Now every aPage object has a synopsis column, which will be null by default, and your engine settings form can just manipulate that one column. Your engine form subclasses aPageForm. You don't need a constructor at all (the default one will suit you), and your configure() method is just:
$this->useFields(array('synopsis'));
Boom, you have a textarea for the synopsis that appears when the page type is set to this engine. You don't need a ccProduct table at all.
The other approach (if for whatever reason you don't want extra columns in aPage) is to keep your ccProduct table and fetch the relevant one. Your engine form class then does not subclass aPageForm, and your constructor has to use the page passed to it to fetch the related ccProduct object (using a Doctrine relation) or create a new one if there is none yet. This is not difficult, but so far it looks like you can keep it even simpler by just adding a column to aPage.