Laravel Queries / Controller Edits - sql

So I am pretty new to Laravel, and I have spent the whole day fishing through various documentations but I am stuck on the way queries work within the actual application. Right now, I am trying to get some data in my database to display, and I looked at the query builder so that's where I am right now. I am also using a CRUD based admin panel for entry in the database. And since it is CRUD based, it has created the model and the controller already, so I am wondering if I need to edit any of those files to get this to work. Here is what the public function index() has right now (Using Laraadmin):
$module = Module::get('Events');
if(Module::hasAccess($module->id)) {
return View('la.events.index', [
'show_actions' => $this->show_action,
'listing_cols' => $this->listing_cols,
'module' => $module
]);
} else {
return redirect(config('laraadmin.adminRoute')."/");
}`
Obviously, I am trying to display some data from this Events table into my blade view. From what I was reading, I understood (or I thought) that it would be something similar to this:
foreach ($module as $module) {
echo $module->id;
}
But, I keep getting an error that whatever variable I pass in the loop is undefined, although I thought it was in the controller. Right now my model is just returning the view as well. Any help with this is greatly appreciated, or even just an explanation of the relationships with queries in Laravel. Thanks!

A few things to check when this happens:
Change module to a known array. This tests if your data array is set up correctly:
'module' => [ '1', '2', '3' ], // previously $module
Within the blade, now write a simple loop, such as:
#foreach ($module as $m)
{{ $m }}
#endforeach
If this version does work, then you know you have something up with your $module variable.
If the above still doesn't work, try to simplify your view request (temporarily):
view('foo', ['a' => 555]);
Then in foo.blade.php, simply have:
hello {{ a }}
EDIT
If all this seems to be correct, then the data being fetched is probably wrong (so its not a view issue). Try $module = Module::all();

It seems like you are returning a view that doesn't exist. If what you have now was correct, it would be looking for resources/views/la/events/index.blade.php Try replacing that return view line with this:
return view('events', [ ... rest of your variables ]);
And just a side note, on your foreach statement, it's probably best to use two separate variable names... so something like:
foreach ($module as $element) { ...

Related

Is there a way to bind a variable number of queries?

I'm coding an app for managing shift work. The idea is pretty simple: the team is shared between groups. In those groups are specific shifts. I want to get something like that:
Group 1
- shift11
- shift12
- shift13
Group 2
- shift21
- shift22
- shift23
I already made a couple of tests, but nothing is really working as I would like it to: everything reactive, and dynamic.
I'm using vue.js, firestore (and vuefire between them).
I created a collection "shiftGroup" with documents (with auto IDs) having fields "name" and "order" (to rearrange the display order) and another collection "shift" with documents (still auto IDs) having fields "name", "order" (again to rearrange the display order, inside the group) and "group" (the ID of the corresponding shiftGroup.)
I had also tried with firestore.References of shifts in groups, that's when I was the closest to my goal, but then I was stuck when trying to sort shifts inside groups.
Anyway, with vuefire, I can easily bind shiftGroup like this:
{
data () {
return {
shiftGroup: [], // to initialize
}
},
firestore () {
return {
shiftGroup: db.collection('shiftGroup').orderBy('order'),
}
},
}
Then display the groups like this:
<ul>
<li v-for="(group, idx) in shiftGroup" :key="idx">{{group.name}}</li>
</ul>
So now time to add the shifts...
I thought I could get a reactive array of shifts for each of the groups, like that:
{
db.collection('shift').where('group', '==', group.id).orderBy('order').onSnapshot((querySnapshot) => {
this.shiftCollections[group.id] = [];
querySnapshot.forEach((doc) => {
this.shiftCollections[group.id].push(doc.data());
});
});
}
then I'd call the proper list like this:
<ul>
<li v-for="(group, idx) in shiftGroup" :key="idx">
{{group.name}}
<ul>
<li v-for="(shift, idx2) in shiftCollections[group.id]" :key="idx1+idx2">{{shift.name}}</li>
</ul>
</li>
</ul>
This is very bad code, and actually, the more I think about it, the more I think that it's just impossible to achieve.
Of course I thought of using programmatic binding like explained in the official doc:
this.$bind('documents', documents.where('creator', '==', this.id)).then(
But the first argument has to be a string whereas I need to work with dynamic data.
If anyone could suggest me a way to obtain what I described.
Thank you all very much
So I realize this is an old question, but it was in important use case for an app I am working on as well. That is, I would like to have an object with an arbitrary number of keys, each of which is bound to a Firestore document.
The solution I came up with is based off looking at the walkGet code in shared.ts. Basically, you use . notation when calling $bind. Each dot will reference a nested property. For example, binding to docs.123 will bind to docs['123']. So something along the lines of the following should work
export default {
name: "component",
data: function () {
return {
docs: {},
indices: [],
}
},
watch: {
indices: function (value) {
value.forEach(idx => this.$bind(`docs.${idx}`, db.doc(idx)))
}
}
}
In this example, the docs object has keys bound to Firestore documents and the reactivity works.
One issue that I'm trying to work through is whether you can also watch indices to get updates if any of the documents changes. Right now, I've observed that changes to the Firestore documents won't trigger a call to any watchers of indices. I presume this is related to Vue's reactivity, but I'm not sure.

Running a forEach loop in Mongoose, in reverse

I'm currently trying to make a faux blog style page. All the relevant information is in MongoDB and I'm extracting it using a forEach loop.
`<% blogs.forEach(function(blog){ %>
<img src="<%= blog.image %>" >
<%=blog.title%>
<span><%= blog.created.toDateString() %></span>
<p><%- blog.body.substring(0, 100) %>...</p>
<% }) %>`
The database contains these objects when you create/edit a post. When you run a forEach it will start at the beginning of the database and then work forwards. I'm trying to figure out how to make it go in reverse as a typical blog site will push older posts down the page when new content is posted (as of now it's displaying the first post first, second one second, etc.)
I thought about creating a for loop and constraining the length of it by using the .count() mongoose command but I can't seem to figure out how I can relate it the various objects in the database. Basically I'm trying to convert this forEach to use a variable (like [i]).
Use the Mongoose . It is a MongoDB object modeling tool designed to work in an asynchronous environment. Mongoose makes it very easy to work with MongoDB. You can try these (some of these may not work properly) , hopefully it will help you.
model_name.find({}).sort('-date').exec(function(err, docs) { ... });
model_name.find({}).sort({date: -1}).exec(function(err, docs) { ... });
model_name.find({}).sort({date: 'desc'}).exec(function(err, docs) { ... });
model_name.find({}).sort({date: 'descending'}).exec(function(err, docs) { ... });
model_name.find({}).sort([['date', -1]]).exec(function(err, docs) { ... });
model_name.find({}, null, {sort: '-date'}, function(err, docs) { ... });
model_name.find({}, null, {sort: {date: -1}}, function(err, docs) { ... });

Laravel 5.3 Route model binding with multiple parameters

Is it possible to have route model binding using multiple parameters? For example
Web Routes:
Route::get('{color}/{slug}','Products#page');
So url www.mysite.com/blue/shoe will be binded to shoe Model, which has color blue.
First of all, it would feel more natural to have a route like the following:
Route::get('{product}/{color}', 'Products#page');
and to resolve product by route binding, and just use the color parameter in the controller method directly, to fetch a list of blue shoes for example.
But let's assume that for some reason it's a requirement. I'd make your route a bit more explicit, to start with:
Route::get('{color}/{product}', 'Products#page');
Then, in the boot method of RouteServiceProvider.php, I would add something like this:
Route::bind('product', function ($slug, $route) {
$color = $route->parameter('color');
return Product::where([
'slug' => $slug,
'color' => $color,
])->first() ?? abort(404);
});
first here is important, because when resolving route models like that you effectively want to return a single model.
That's why I think it doesn't make much sense, since what you want is probably a list of products of a specific color, not just a single one.
Anyways, I ended up on this question while looking for a way to achieve what I demonstrated above, so hopefully it will help someone else.
Do not forget to declare the parameter types:
Route::delete('safedetail/{safeId}/{slug}', [
'as' => 'safedetail.delete',
'uses' => 'SafeDetailController#destroy',
])->where([
'safeId' => '[0-9]+',
'slug' => '[a-z]+',
]);
Try changing your controller to this:
class Pages extends Controller{
public function single($lang, App\Page $page){
dd($page);
}
}
You must add the Page Model.

How to use store.filter / store.find with Ember-Data to implement infinite scrolling?

This was originally posted on discuss.emberjs.com. See:
http://discuss.emberjs.com/t/what-is-the-proper-use-of-store-filter-store-find-for-infinite-scrolling/3798/2
but that site seems to get worse and worse as far as quality of content these days so I'm hoping StackOverflow can rescue me.
Intent: Build a page in ember with ember-data implementing infinite scrolling.
Background Knowledge: Based on the emberjs.com api docs on ember-data, specifically the store.filter and store.find methods ( see: http://emberjs.com/api/data/classes/DS.Store.html#method_filter ) I should be able to set the model hook of a route to the promise of a store filter operation. The response of the promise should be a filtered record array which is a an array of items from the store filtered by a filter function which is suppose to be constantly updated whenever new items are pushed into the store. By combining this with the store.find method which will push items into the store, the filteredRecordArray should automatically update with the new items thus updating the model and resulting in new items showing on the page.
For instance, assume we have a Questions Route, Controller and a model of type Question.
App.QuestionsRoute = Ember.Route.extend({
model: function (urlParams) {
return this.get('store').filter('question', function (q) {
return true;
});
}
});
Then we have a controller with some method that will call store.find, this could be triggered by some event/action whether it be detecting scroll events or the user explicitly clicking to load more, regardless this method would be called to load more questions.
Example:
App.QuestionsController = Ember.ArrayController.extend({
...
loadMore: function (offset) {
return this.get('store').find('question', { skip: currentOffset});
}
...
});
And the template to render the items:
...
{{#each question in controller}}
{{question.title}}
{{/each}}
...
Notice, that with this method we do NOT have to add a function to the store.find promise which explicitly calls this.get('model').pushObjects(questions); In fact, trying to do that once you have already returned a filter record array to the model does not work. Either we manage the content of the model manually, or we let ember-data do the work and I would very much like to let Ember-data do the work.
This is is a very clean API; however, it does not seem to work they way I've written it. Based on the documentation I cannot see anything wrong.
Using the Ember-Inspector tool from chrome I can see that the new questions from the second find call are loaded into the store under the 'question' type but the page does not refresh until I change routes and come back. It seems like the is simply a problem with observers, which made me think that this would be a bug in Ember-Data, but I didn't want to jump to conclusions like that until I asked to see if I'm using Ember-Data as intended.
If someone doesn't know exactly what is wrong but knows how to use store.push/pushMany to recreate this scenario in a jsbin that would also help too. I'm just not familiar with how to use the lower level methods on the store.
Help is much appreciated.
I just made this pattern work for myself, but in the "traditional" way, i.e. without using store.filter().
I managed the "loadMore" part in the router itself :
actions: {
loadMore: function () {
var model = this.controller.get('model'), route = this;
if (!this.get('loading')) {
this.set('loading', true);
this.store.find('question', {offset: model.get('length')}).then(function (records) {
model.addObjects(records);
route.set('loading', false);
});
}
}
}
Since you already tried the traditional way (from what I see in your post on discuss), it seems that the key part is to use addObjects() instead of pushObjects() as you did.
For the records, here is the relevant part of my view to trigger the loadMore action:
didInsertElement: function() {
var controller = this.get('controller');
$(window).on('scroll', function() {
if ($(window).scrollTop() > $(document).height() - ($(window).height()*2)) {
controller.send('loadMore');
}
});
},
willDestroyElement: function() {
$(window).off('scroll');
}
I am now looking to move the loading property to the controller so that I get a nice loader for the user.

How does one add a 'plain text node' to a zend form?

I'm trying to add a plain text node in a zend form - the purpose is to only dispay some static text.
The problem is - im not aware of any such way to do it.
I have used 'description' but that HAS to be attached to a form element.
Is there any way to simply display some text as part of a form? Zend considers everything as a form element so I cannot just print it out.
Eg:
The following will test your ability on so and so.
.
.
.
etc...
Any thoughts?
Zend has a form note view helper (Zend_View_Helper_FormNote), which you can use to add text.
Just create a new form element (/application/forms/Element/Note.php):
class Application_Form_Element_Note extends Zend_Form_Element_Xhtml
{
public $helper = 'formNote';
}
In your form:
$note = new Application_Form_Element_Note(
'test',
array('value' => 'This is a <b>test</b>')
);
$this->addElement($note);
Adding a hidden element with non-escaped description does the thing.
$form->addElement('hidden', 'plaintext', array(
'description' => 'Hello world! Check it out',
'ignore' => true,
'decorators' => array(
array('Description', array('escape'=>false, 'tag'=>'')),
),
));
Works perfectly. It is still attached to an element, which is, however, not rendered this way.
Code taken from: http://paveldubinin.com/2011/04/7-quick-tips-on-zend-form/
There might be a better way, but I created a paragraph by using a custom form element and view helper. Seems like alot of code for something so simple. Please let me know if you've found a more simplistic way to do it.
//From your form, add the MyParagraph element
$this->addElement(new Zend_Form_Element_MyParagraph('myParagraph'));
class Zend_Form_Element_MyParagraph extends Zend_Form_Element
{
public $helper = 'myParagraph';
public function init()
{
$view = $this->getView();
}
}
class Zend_View_Helper_MyParagraph extends Zend_View_Helper_FormElement {
public function init() {
}
public function myParagraph() {
$html = '<p>hello world</p>';
return $html;
}
}
A little late but thought I'd throw it in anyway for the benefit of the community.
Aine has hit the nail on the head. FormNote is what you need if you want to use text in Zend_Form. However, you can use it without needing to extend Zend_Form_Element_Xhtml. See example below:
$text = new Zend_Form_Element_Text('myformnote');
$text->setValue("Text goes here")
->helper = 'formNote';
Note that you can use both text and html with the formNote helper.
This functionality is built into Zend via Zend_Form_Element_Note.
$note = new Zend_Form_Element_Note('forgot_password');
$note->setValue('Forgot Password?');
I faced the same problem and decided is better not to use Zend_Form at all, but to use directly view helpers (like Ruby on Rails does) and validate on the model.
This one-liner works for me:
$objectForm->addElement(new Zend_Form_Element_Note('note', array('value' => 'Hello World')));