Comments (24)
Hi, parrker! I have just written an example of migrations. Let me know if something is unclear.
from closuretable.
Hi franzose, the migrations were really helpful! Thanks!
Now I have a different problem (probably because I'm not too experienced with both Laravel and the idea of closure tables). How should I go about saving nodes in the tree? I create a new element like this:
$category = new ProductsCategory;
$category->published = 1;
$category->save();
Is this the right way? I can see that data is stored in both my tables successfully, but the ProductsCategory::fulltree()
method now throws an error:
Unhandled Exception
Message:
array_merge() [function.array-merge]: Argument #1 is not an array
Location:
X:\home\ifg.dev\bundles\closuretable\closuretable.php on line 207
I have a feeling I am doing it wrong.
from closuretable.
Hi, parrker) First of all, please, show me what data containts your products' categories table and tree paths one now. Then, if possible, SQL logs. I'm not able to test them at the time.
from closuretable.
These are my migrations for creating tables:
Schema::create('products_categories', function($table) {
$table->increments('id');
$table->integer('parent_id')->unsigned()->nullable();
$table->boolean('published');
$table->integer('created_by');
$table->integer('updated_by');
$table->timestamps();
});
// and another one
Schema::create('products_categories_treepath', function($table) {
$table->increments('tpid');
$table->integer('ancestor')->unsigned();
$table->integer('descendant')->unsigned();
$table->integer('level')->unsigned();
$table->index('level');
});
As you see, I don't have any real data yet, I'll use a separate table for lang data.
And the code I was trying to run is this:
$category1 = new ProductsCategory;
$category1->published = 1;
$category1->save();
$category2 = new ProductsCategory;
$category2->published = 1;
$category2->save();
$category1 = new ProductsCategory;
$category1->published = 1;
ProductsCategory::find(1)->append_child($subcategory);
// this works fine
$categories = ProductsCategory::roots();
// this throws an error
$categories = ProductsCategory::fulltree();
from closuretable.
Please, look at the closuretable.php file now around 197 and 207 lines. I changed the code slightly. Now it tries to convert a given object to array. As I know DB::query method returns either stdClass or array according to the configuration you set. And it returns stdClass by default. So, there was no conversion from stdClass to array that led to wrong argument type error.
Please, try updated code and let me know either about your or about some new errors. Thank you very much.
from closuretable.
I have tried the updated version, and the fulltree() method works fine now. Thanks!
But now I noticed that there is an error when I try to insert a child into an existing node. I tried the following:
// These records was created the same way as in the code in my previous comment.
$subcategory = ProductsCategory::find(3);
$top_level_category = ProductsCategory::find(1);
// First
$top_level_category->descendants()->insert($subcategory);
// Second
$top_level_category->append_child($subcategory);
// Third
$subcategory->move_to($top_level_category);
For the first and second way I get the following error:
Unhandled Exception
Message:
Cannot access static:: when no class scope is active
Location:
X:\home\ifg.dev\bundles\closuretable\closuretable.php on line 147
For the third I get this:
Unhandled Exception
Message:
Cannot use object of type stdClass as array
Location:
X:\home\ifg.dev\bundles\closuretable\treepath.php on line 162
Sorry to keep bothering you about this, but I want to make my trees work via closure tables so much!
from closuretable.
Hi, parrker. I apologize for the delay. I have tested ClosureTable for the issues you mentioned and fixed the latter one in treepath.php.
What is the version of PHP you are using? I cannot reproduce class scope error on 5.4.11...
from closuretable.
I really feel ashamed in front of those almost 120 people who have downloaded the bundle full of bugs :( Thanks for your help, parrker ;)
from closuretable.
Parrker, trouble with class scope may happen due to the fact that there are static calls from the closure. I mean 'descendants' and 'ancestors' methods. There are joins which use closure to define additional join rules. See 133-134 and 147-148 line in closuretable.php.
from closuretable.
Please, try to change 'static::' calls to 'ClosureTable::' in joins' closures of those methods ('ancestors' and 'descendants') and let me know about the results.
from closuretable.
Hi franzose! For a moment I thought you forgot about me and this bundle :)
After updating the Treepath class, the third way of assigning child to a node (using the move_to()
method) indeed started working. And the issue with class scope indeed goes away if you change static::
calls to ClosureTable::
calls in descendants()
method of the ClosureTable class. Should I keep it like that?
P.S. I am using PHP 5.3.17 at the moment. I know that we will have PHP 5.3 on my live web server for some time, so I cannot upgrade :(
from closuretable.
Now I encountered another issue: because we changed the static::
calls to ClosureTable::
, my $table
and $treepath
properties surely are not correct when I try to grab something $category->descendants
. I have to override these methods in my ProductsCategory
class, changing the ClosureTable
to ProductsCategory
(obviously).
I spent some time researching, and this is the solution that I used in the end:
public function descendants()
{
$class = get_called_class();
return $this->has_many(get_class($this), static::$parent_key)
->join(static::$treepath, function($join) use ($class){
$join->on($class::$treepath.'.descendant', '=', $class::$table.'.'.$class::$key);
$join->on($class::$treepath.'.ancestor', '<>', $class::$table.'.'.$class::$key);
})->select(array(static::$table.'.*'));
}
The issue was with the closure's scope. Apparently, in PHP 5.4 you don't have to add use ($class)
, you could simply use $this
(and probably static
too, that's why you did not get this error).
from closuretable.
Hey, it seems that I have found an answer. It's quirky now, but we can define join rules first and then pass them to the closure. So, instead of
public function ancestors()
{
return $this->has_many(get_class($this), static::$parent_key)
->join(static::$treepath, function($join){
$join->on(static::$treepath.'.ancestor', '=', static::$table.'.'.static::$key);
$join->on(static::$treepath.'.descendant', '<>', static::$table.'.'.static::$key);
})->select(array(static::$table.'.*'));
}
public function descendants()
{
return $this->has_many(get_class($this), static::$parent_key)
->join(static::$treepath, function($join){
$join->on(static::$treepath.'.descendant', '=', static::$table.'.'.static::$key);
$join->on(static::$treepath.'.ancestor', '<>', static::$table.'.'.static::$key);
})->select(array(static::$table.'.*'));
}
we will have this:
public function ancestors()
{
$ancestor = static::$treepath.'.ancestor';
$descendant = static::$treepath.'.descendant';
$key = static::$table.'.'.static::$key;
return $this->has_many(get_class($this), static::$parent_key)
->join(static::$treepath, function($join) use($ancestor, $descendant, $key) {
$join->on($ancestor, '=', $key);
$join->on($descendant, '<>', $key);
})->select(array(static::$table.'.*'));
}
public function descendants()
{
$ancestor = static::$treepath.'.ancestor';
$descendant = static::$treepath.'.descendant';
$key = static::$table.'.'.static::$key;
return $this->has_many(get_class($this), static::$parent_key)
->join(static::$treepath, function($join) use($ancestor, $descendant, $key) {
$join->on($descendant, '=', $key);
$join->on(static::$ancestor, '<>', $key);
})->select(array(static::$table.'.*'));
}
It's a bit quirky, but we now prepare values first.
from closuretable.
Oh, I edited my comment without refreshing the page :) My solution is similar, I just pass the class name to closure instead of variables. Yours looks neater, I think.
from closuretable.
From the beginning the purpose was to create a plug-and-play thing. Try my version, if it works appropriately, I will submit changes :)
from closuretable.
Wait, in the ancestors method you still have one static call:
$join->on($descendant, '=', $key);
$join->on(static::$ancestor, '', $key);
from closuretable.
Ooops, it's a mistake. Now it should be just $ancestor
.
from closuretable.
One more thing, some of your joins lost the "not equals" operator:
$join->on($descendant, '', $key);
from closuretable.
May be parser ate them...
from closuretable.
I have updated closuretable.php with this quick fix. Try it. Later I'll solve this issue in more suitable way.
from closuretable.
I have another one.
I cannot grab the node's ancestors for some reason. ProductsCategory::find(8)->ancestors
just returns an empty array, even though in the database i can see three paths for the descendant with ID 8: http://i.imgur.com/85WTYtC.png
The descendants are returned correctly.
from closuretable.
Sorry, parrker, but from 8 till 31 of May I will be unable to maintain the project (and fix all the bugs) due to the trip with my music band... Thank you for forking it ;)
from closuretable.
I am not too sure if I get the fork to work, but it's worth a shot.
Good luck on the tour!
from closuretable.
Hi, parrker. I'm able to work again. See and try my fixes! Now 'ancestors' returns what it should, 'descendants' returns all descendants (not only immediate children). And I added 'children' method to get those immediate fucking children :)))
After all that fixin' I had a thought that it was all quite simple to fix and I don't know now why I missed all that before. Now I will think about your suggestion about 'fulltree' method. I suppose it's not that difficult to implement...
from closuretable.
Related Issues (20)
- Compatibility with later Laravel versions (5.7, 5.8 and 6.x) HOT 5
- make command does not work with Laravel 6.2 HOT 3
- Collection::makeTree() hits database for each child HOT 4
- Upgrade guide to v6 HOT 2
- Examples from readme are not works HOT 2
- Child with multiple parents not possible (child will be moved) HOT 1
- Hardcoded table column names in the ClosureTable model
- Error: array_key_exists() expects parameter 2 to be array, int given HOT 1
- How get Tree from 0 level ? HOT 5
- Problem with createFromArray method HOT 2
- erro in delete member
- createFromArray
- ancestorsWithSelf() queries database for each ancestor
- Readme example doesnt work in 6.1.1 HOT 2
- Multiple parents HOT 1
- Deprecated interfaces in Entity and ClosureTable
- What should I do when my data volume is very large, more than 100 million? HOT 2
- reorderSiblings method doesn't update softdeleted node's position
- Seeking a method to not update updated_at
- Drive: data de modificação sendo alterada
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from closuretable.