Search

Hi,

I have a pretty complicated searching issue in my website and I must create a custom datasource to handle this. I know that EntryManager class and database structure are a bit messy to play with so what is the recommended way instead of them? Will SymQL do fine?

I have a pretty complicated searching issue

Will SymQL do fine?

If it’s complicated then using heavy abstraction tools may not be enough; they are generally used for more basic querying SymQL mostly achieves the same querying results as using a standard Data Source, so if your requirements are significantly more complex than a standard Data Source then you’ll likely be looking at more complex code.

What exactly are you trying to achieve?

It’s not SO complicated, in fact it is pretty easy. By being complicated I meant being too complicated for datasource filtering (unless I don’t know some trick).

There is a section with “title” text field, category (selectbox link) and subsection manager with “elements” (let’s say that “elements” have only one text field as well). Search engine should search either by title or by any of those elements titles from SSM. In addition, there is one filtering parameter thanks to which user can select a category (if this parameter is set to “all” then there is no filtering). And results always should be paginated.

I will take a closer look at SymQL… generally I asked my question because I wanted to know if there are any other wrappers to EntryManager class. I have a feeling that I saw something different from SymQL once :)

EDIT:

Okayyy: “SymQL continues what DatabaseManipulator started, and is intended as a full replacement”. So once upon a time, there was a DatabaseManipulator. But as I understand, it is deprecated now and I should use SymQL instead.

There was DatabaseManipulator (deprecated) which SymQL is mostly just a tidier rewrite with a more friendly API. They’re similar in concept. SymQL also has a fork named SymQuery by Rowan Lewis which is more his own personal experiment for his own projects than something stable and production-worthy.

You might also want to try Search Index. It’s still kind of in development (it hasn’t reached version 1.0 yet) but it would allow you to use a native Symphony Data Source for your searching:

  • install the extension
  • configure your indexes (i.e. choose the fields of which you will search as plain text)
  • add the Search Index field to your section (it’s invisible, but allows you to filter in a DS)
  • in your DS filter your category as required, and also by keywords on the Search Index extension

Okay, now I understand SymQL. However, there’s a little thing which makes me curious:

There is a way to convert results to an array by SymQL::RETURN_ARRAY, which I really like. My question is if there is a way to convert a processed array to XML. I know it could be written quite easily with a little bit of recursion, but still, maybe there is a built-in-already-done function? Nick? :)

there is a way to convert a processed array to XML

No need, if you don’t specify a return type then the default of RETURN_XML is used. This is an XMLElement (Symphony’s own representation of XML) which you can return from your Data Source and it’ll be handled correctly. Alternatively if you need the XMLElement as raw XML you can call the generate() method on the object which will return its built XML as a string, which you can then convert to an XML object using DomDocument or simplexml.

For a list of return types see the list under “Run the query” in the README:

https://github.com/nickdunn/symql/blob/master/README.markdown

No need, if you don’t specify a return type then the default of RETURN_XML is used.

I know, I know, I’ve read the whole README carefully :) I meant something else:

  1. I get data by SymQL::run
  2. I PROCESS THEM, namely, remove many of entries, because that’s how my search engine is gonna work. I know it is far from being time-effective but there will be no more than 100 entries queried at once in the website so it doesn’t matter.
  3. After processing, I want them to be converted into XML.

I thought that RETURN XML returns a pure string with XML content and this would be sooo hard to process! That’s why I used RETURN ARRAY which is easy to play with. But the array is supposed to change after some operations and after that, I would like it to be converted to XML. And I ask if there is a function, which does the trick :)

Or maybe, XMLElement is easy to process (I mean, traversing the XML-tree like an associative array and removing nodes when neccessary)?

I hope this is clear now.

PS In my custom datasource the $param_pool seems to be empty, although I pass parameters to the page, how to read them? ;(

I see what you mean. If you’re running one of the latest versions of Symphony there’s a array_to_xml() function in the General class which should do you what need :-)

$parent = new XMLElement('entries');
General::array_to_xml($parent, $array_from_symql);

Yeaaaah, that works fine, huge thanks! :)

Not fully :( Nodes are fine, but arguments don’t work.

RETURN ARRAY returns an associative array. When a key starts with an underscore like

_id

then it means that it is an argument of it’s parent. Unfortunately, arraytoxml treats it as a node.

How about traversing and modyfing XMLElement? Is it possible?

Damn, documentation of classes like XMLElement, EntryManager and other core stuff would be a great thing! :)

How about traversing and modyfing XMLElement? Is it possible?

Certainly. Just take a look at class.xmlelement.php and you’ll see all of the public method of that class. You can iterate over getChildren() and update attributes and values.

But you might find it easier to convert the XML string into a simplexml object and manipulate it that way, if that’s your bag.

I hear that class API documentation is coming in Symphony 2.2 :-)

Haha, a funny thing is that XMLElement library is better at handling attributes but worse in traversing. What I mean is that there is no possibility to pick nodes with given node names, or to delete nodes. I’ve dealt with it by adding some code to XMLElement class:

        public function getChildrenByName($name) {
        $ret = array();
        foreach($this->_children as $child)
        {
            if($child->getName() == $name)
            {
                $ret[] = $child;
            }
        }
        return $ret;
    }

    public function getChildByName($name) {
        foreach($this->_children as $child)
        {
            if($child->getName() == $name)
            {
                return $child;
            }
        }
        return NULL;
    }

    public function deleteChild($key)
    {
        unset($this->_children[$key]);
    }

I know that it would be neater to do it by inheritance but in my project there is just no need :)

Summary:

Everything should be done by a complex SQL query which would be very hard because of complicated database structure and quite unpleasant EntryManager. I think that in an awful lot of cases, processing data in a datasource is enough.

Arrays are very easy to process but there are problems with converting them to XML. You must write your own converter because General::arraytoxml function doesn’t process attributes well.

You can traverse and modify XMLElement tree but it lacks some user-friendly methods which are naturally built-in in associative arrays. My methods from above solve this issue. I wonder if there is any possibility to add something like them to the Symphony core.

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details