How to find an element by attribute using QueryPath - attr

I need to find all tables with width=230
So far I have:
foreach($qp->top('table')->get() as $table) {
$width = $table->attr('width');
}
But I get a "Call to undefined method DOMElement::attr()" error.

Try something like
$table->find('[width="230"]');

It seems, $table is a DOMElement, so probably you can do
$width = $table->getAttribute('width);

Related

Cache eloquent model with all of it's relations then convert it back to model with relations?

I am trying to optimize a project that is working pretty slow using caching. I'm facing a problem that I don't quite understand how to cache full eloquent models with their relationships and later on covert them back to a model with all relations intact. Here's a fragment of my code
if (Cache::has($website->id.'_main_page')) {
$properties = (array) json_decode(Cache::get($website->id.'_main_page'));
$page = Page::hydrate($properties);
}else{
$expiresAt = now()->addMinutes(60);
$page = Page::with(['sections', 'pageSections.sectionObjects'])->where('website_id', $website->id)->where('main', 1)->first();
Cache::put($website->id.'_main_page', $page->toJson(), $expiresAt);
}
Problem is, hydrate seems to be casting this data as a collection when in fact it's suppose to be a single model. And thus later on I am unable to access any of it's properties without getting errors that they don't exists. $properties variable looks perfect and I would use that but I need laravel to understand it as a Page model instead of stdClass, I also need all of the relationships to be cast into their appropriate models. Is this even possible? Any help is much appreciated
Is there any reason you can't use the cache like this
$page = Cache::remember($website->id.'_main_page', 60 * 60, function () use ($website) {
return Page::with(['sections', 'pageSections.sectionObjects'])
->where('website_id', $website->id)
->where('main', 1)
->first();
});
Conditional
$query = Page::query();
$key = $website->id.'_main_page';
if (true) {
$query = $query->where('condition', true);
$key = $key . '_condition_true';
}
$query::with(['sections', 'pageSections.sectionObjects'])
->where('main', 1)
$page = Cache::remember($key, 60 * 60, function () use ($query) {
return $query->first();
});

Laravel sortBy() not working to sort a collection

I want to sort a collection by name column. Using sortBy() method is not working.
$collection = \App\Http\Resources\MyResource::collection($test);
return $collection->sortBy('name');
For me only worked example exactly as in the docs
$statisticCollection = collect($statistics);
$sorted = $statisticCollection->sortByDesc('date');
return $sorted->values()->all();
So the problem was that I did not save the sorted result to a variable before returning it.
I found that I had to use values() after sorting, as suggested in the documentation.
The thing you want to do is:
$collection = \App\Http\Resources\MyResource::collection($test);
return $collection->sortBy('name')->all();
Check how it is done in the docs.
The default sortBy for Laravel is defined as ascending:
public function sortBy($callback, $options = SORT_REGULAR, $descending = false)
If you were looking to sort descending use sortByDesc:
public function sortByDesc($callback, $options = SORT_REGULAR)
{
return $this->sortBy($callback, $options, true);
}
Where the first parameter $callback can be a string or a callable, so your code could look something like this with items sorted descending:
$collection = \App\Http\Resources\MyResource::collection($test);
return $collection->sortByDesc('name')->all();
If the Laravel default sorting doesn't work for your purpose, try to do this:
$collection = \App\Http\Resources\MyResource::collection->sortBy(function ($element, $key) {
return yourFunctionForSorting($element['name']);
});
Replace obviously "yourFunctionForSorting", with your sorting criteria.

Laravel Eloquent: get model id from inside getAttribute function?

I have a model like the following:
User extends Authenticatable
{
protected $appends = array('role');
public function getRoleAttribute()
{
$role = DB::table('acl_user_has_roles')->where('user_id', $this->id)
->value('role');
return $role;
}
}
When I try to reference this foo attribute like the following:
$user = User::find(1);
unset($user->id); // This line causes the problem.
echo $user->role;
I always get "null" instead of expected "Owner".
What did I miss here?
I am running this in laravel 5.5.43.
In the following post, getKey() function was mentioned, that didn't work.
The problem is actually caused by something else, as described in the following medium post.
Just in case anyone else runs into the same issue. The problem is caused by another line in the code. I unset $user->id before echo.
The issue is described in detail in the following medium post:
Be Careful to Use Laravel Eloquent’s Accessors, Mutators And Events

Laravel 5 Eager Loading with parameters

I'm working on a project with a bit of a complex model that has joins in its relations and also requires a parameter. It all works pretty well, except for when I need to eager load the relationship, as I couldn't figure out if there is a way to pass a parameter/variable to it.
The Controller
$template = Template::find($request->input('id'));
$this->output = $template->zones()->with('widgets_with_selected')->get();
The Model
public function widgets_with_selected($banner_id)
{
return $this->belongsToMany('App\Models\Widget', 'zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
This is returning a Missing argument error as the variable is not being passed.
I have resolved the issue by moving the logic to the controller, but I want to know if there is a way to keep the relationship in the model and just call it with a parameter.
Looking at the laravel code I dont think this is possible as you'd like to do it. You simply cant pass parameters to a with() call.
A possible workaround is to have an attribute on your model for $banner_id.
$template = Template::find($request->input('id'));
$template->banner_id = 1;
$this->output = $template->zones()->with('widgets_with_selected')->get();
Then change your relationship
public function widgets_with_selected()
{
return $this>belongsToMany('App\Models\Widget','zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($this->banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
You could perhaps alter it a bit by passing the banner_id through a method. Sortof like this in your model:
public function setBanner($id) {
$this->banner_id = $id;
return $this;
}
Then you can do:
$template->setBanner($banner_id)->zones()->with('widgets_with_selected')->get();
Not sure if this works, and it's not really a clean solution but a hack.

Laravel 4 - Method [where] does not exist

I am trying to get row from the table with "->find(X)" or "->where" but i get error in return. i guess i am missing something but i can't tell what.
<?php
class SnippetsController extends BaseController {
public $restful = true;
public function index($id)
{
$snippet = SnippetsController::where('id', '=', 11)->get();
i tried it with find but noting helps.
$snippet = SnippetsController::find(11);
with "->get" and without. but noting works. i do have the "11" id in the table itself and the error seems to have noting to do with it.
maybe i need to extend the class to Eloquent? if so, how do i keep the BaseController on top of it?
Thanks!
error:
BadMethodCallException Method [find] does not exist.
You must have a Model called Snippet, right? So this is how you use it:
$snippet = Snippet::find(11);
Your SnippetsController is not tied to a database (Eloquent ORM), so you must create (if you don't have already) a model:
class Snippet extends Eloquent {
}
Just edit the code $snippet = SnippetsController::where('id', '=', 11)->get(); with $snippet = Snippets::where('id', '=', 11)->get();. May be your model name is Snippets it may solve your problem.

Resources