Reverse detail from Kakelbont MS 1, a fifteenth-century French Psalter. This image is in the public domain. Daniel Paul O'Donnell

Forward to Navigation

Yii Basic Steps

Posted: Apr 06, 2012 16:04;
Last Modified: May 23, 2012 18:05

---

This is just a reminder to myself about setting up a Yii install. There are much more detailed examples on the web.

Build database

Build a database (I use MySql with innodb engine). The innodb engine is important because it allows you to document foreign key associations

Copy yii to top level of webdirectory

If you haven’t already done so, get a copy of the latest version of yii, uncompress it, and install it in a webdirectory immediately below the web root.

In my case, I tend to put it under /var/www/ and call the directory yii.

Use yiic to build initial site

navigate to the root of your web directory. Assuming yii is an immediate child of this directory, use the following to build the initial site of your website, where $site is the directory name you want to use for your site and $path the full path to the current directory:

yii/framework/yiic webapp $site

The response should be: Your application has been created successfully under $path/$site

Prepare for building the scaffolding

change directory to $path/$site/protected/config/

edit main.php:

  1. remove the comments surrounding the section on the gii tool (you’ll want to put these back in production)
  2. make sure you put a password in
  3. (for MySql) remove the comments surrounding the MySql Stanza and modify/supply the required information (usernames, passwords, servers, etc.)
  4. fix the admin email.

Use gii to establish the basic scaffolding

  1. point your webbrowser at the site (e.g. http://localhost/$site/ or http://example.com/$site/)
  2. click on the “home” link in the menubar to get the top URL (it will be something like this: http://$domain/$site/index.php?r=site/index)
  3. in the location bar, replace site/index with gii
  4. enter the database root password

Develop models

Most if not all dbases will have a model in the system.

  1. Select “Model Generator”.
  2. enter * in the “Table name” field to generate models for all tables; otherwise type the table name in the box for a specific table.
  3. click on preview.
  4. if everything is good, click on generate (need to make sure permissions all generation).

Develop CRUD

  1. select “crud generator”
  2. enter Model names for the models for which you want to have specific forms and actions (not all tables will require this: some will be written automatically or through relations)
----  

Adding an attribute for title to a yii widget

Posted: Feb 24, 2012 15:02;
Last Modified: May 23, 2012 18:05

---

The Yii file view.php by default uses the [zii.widgets.CDetailView] to display all examples of a given model. In the standard scaffolding produced by the gii utility, this widget consists of references to attributes of the model without any further information (e.g. attribute names and the like):

<?php $this->widget('zii.widgets.CDetailView', array(
	'data'=>$model,
	'attributes'=>array(
		'editorialInstance_id',
		'journal.shortTitle', // a reference to a relational attribute
		'type',
                'LastNamesFirstName', // a reference to a compound attribute
	),

In this minimalist form, yii will calculate an appropriate label for the attribute on the basis of the attribute name: so, for example, in this case, editorialInstance_id will be appear in the view labelled “Editorial Instance” because Yii understands camelCase naming conventions and knows to strip off _id (it’s that good!).

A problem with this, however, is that we also provide customised label names as part of the attributeLabels() method in our Model controller. Since that method allows arbitrary names, and since CDetailView attempts to calculate labels on the basis of the attribute name, it is highly likely that the labels for different attributes will get out of synch in different places in your site. To give an example: in this particular case, the model for editorialInstance might have defined the label for editorialInstance_id as “ID” rather than “Editorial Instance”: since CDetailView doesn’t check to see what you had on attributeLabels() in the model class, switching from an edit view to an index will mean that the label of the attribute switches.

Ideally what you want to do is keep CDetailView and attributeLabels() in synch automatically. I’m sure there must be a way of doing this. In the meantime, however, here’s how you can set an arbitrary label in the widget (I’ve used it on the first and last):

<?php $this->widget('zii.widgets.CDetailView', array(
	'data'=>$model,
	'attributes'=>array(
                array('value' => 
                      $model->editorialInstance_id, 'label' => 'ID'),
		'journal.shortTitle',
		'type',
		array('value' => $model->person->lastNameFirstNames, 'label' => 'Person'),
	),
----  

Yii Ensuring that key terms are always linked

Posted: Feb 24, 2012 11:02;
Last Modified: May 23, 2012 18:05

---

As we are building our workflow manager, we are discovering that we develop a more intuitive interface if some terms are always hyperlinked and point to a standard presentation of the relational information.

One example of this might be names of people associated with the workflow (editors, authors, copyeditors, production assistants). An intuitive internal navigation method seems to be to have the names of these people always hyperlinked with the hyperlink always pointing to the person’s profile page.

One way of doing this in Yii would be to modify the views associated with each table in the site so that every time a name is called, you get a link. This is contrary to spirit of the MVC model, however, since it means you are using a view to present logic about the underlying model. And it is also prone to error, since it means you a) need to find every possible invocation of the name in all you various views and b) not make an error as you enter the same code over an over again in all these different views.

The better approach is to add this functionality to the underlying datamodel that supplies the information to the entire site in the first place—that is, to the model for the database that is providing the name information and the page you want to link to in the end.

Here’s some code for your model that would allow you produce a linked name anywhere in your yii site (for simplicity’s sake in this example, I am wrapping a single attribute from my database in a hyperlink. This post shows you how to use a similar method to first make compound attributes):

public function getLastNameLink()
    {
    return CHtml::link(CHtml::encode($this->lastName),
    array('person/view', 'id'=>$this->person_id));
    }

Here are some underlying premises behind this code:

  1. There is a table in my database called person
  2. I have written a view for this database (either by hand or using the gii utility to build one automatically): person/view is the URL fragment CHtml::link will use to build the link to the profile page for a given person (note: it is tempting to just use view for the URL because we are already in the person model; you should use the “full” yii-path however because you will be invoking this throughout the site from views associated with all sorts of other models)
  3. The table person has an attribute (column) called person_id.

Once this has been added to my Person model, I can call the code (and add a link to the person profile) in any view by just invoking the method: from now on, the LastNameLink functions as an attribute of the Person model and can be used in exactly the same way actual direct, table-based attributes can be invoked. For example, in a different model’s view:

<?php echo $data->person->LastNameLink; ?>

This code will produce a link to index.php?r=person/view&id=n where n is the id number of a given record in the table. If I hadn’t added the above code to the Person model, the code required to do the equivalent would have been:

<?php echo 
CHtml::link(CHtml::encode($data->person->lastNameFirstNames),
array('person/view', 'id'=>$data->person->person_id)); ?>
----  

Extracting a catalogue of element names from a collection of XML documents using XSLT 2.0

Posted: Sep 15, 2011 17:09;
Last Modified: May 23, 2012 19:05

---

We are trying to build a single stylesheet to work with the documents of two independent journals. In order to get a sense of the work involved, we wanted to create a catalogue of all elements used in the published articles. This means loading as input document directories’ worth of files and then going through extracting and sorting the elements across all the input documents.

Here’s the stylesheet that did it for us. It is probably not maximally optimised, but it currently does what we need. Any suggestions for improvements would be gratefully received.

Some notes:

  1. Our goal was to pre-build some templates for use in a stylesheet, so we formatted the elements names into xsl templates.
  2. Although you need to use this sheet with an input document, the input document is not actually transformed (the files we are extracting the element names from are loaded using the collection() function). So it doesn’t matter what the input document is as long as it is valid XML (we used the stylesheet itself)
<?xml version="1.0"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

<!-- this output is because we are going to construct 
ready-made templates for each element -->
    <xsl:output method="text"/>

<!-- for pretty printing -->
    <xsl:variable name="newline">
        <xsl:text> 
        </xsl:text>
    </xsl:variable>

<!-- Load the files 
in the relevant directories -->
    <xsl:variable name="allFiles"
    select="collection(iri-to-uri('file:///some/path/to/the/directories?select=*.xml;
    recurse=yes'))"/>

<!-- Dump their content into a single big pile -->
    <xsl:variable name="everything">
        <xsl:copy-of select="$allFiles"/>
    </xsl:variable>

<!-- Build a key for all elements using their name -->
    <xsl:key name="elements" match="*" use="name()"/>

<!-- Match the root node of the input document
(since the files we are actually working on have been 
loaded using the using the collection() function, nothing 
is actually going to happen to this element) -->
    <xsl:template match="/">

       <!-- this is information required to turn the output into an 
              XSL stylesheet itself -->
        <xsl:text>&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            version="1.0"></xsl:text>
        <xsl:value-of select="$newline"/>
        <xsl:text>&lt;!--Summary of Elements --&gt;</xsl:text>
        <xsl:value-of select="$newline"/>
        <xsl:value-of select="$newline"/>

       <!-- this invokes the collection of all elements in all the files
       in the directory for further processing -->
        <xsl:for-each select="$everything">

           <!-- This makes sure we are dealing with the first named key -->
            <xsl:for-each 
            select="//*[generate-id(.)=generate-id(key('elements',name())[1])]">

               <!-- sort them -->
                <xsl:sort select="name()"/>

                <xsl:for-each select="key('elements', name())">

                   <!-- this makes sure that only the first instance 
                    of each element name is outputted -->
                    <xsl:if test="position()=1">
                        <xsl:text>&lt;xsl:template match="</xsl:text>
                        <xsl:value-of select="name()"/>
                        <xsl:text>"> </xsl:text>
                        <xsl:value-of select="$newline"/>
                        <xsl:text>&lt;!--</xsl:text>
                        <!-- this counts the remaining occurences -->
                        <xsl:value-of select="count(//*[name()=name(current())])"/>
                        <xsl:text> occurences</xsl:text>
                        <xsl:text>--&gt;</xsl:text>
                        <xsl:value-of select="$newline"/>
                        <xsl:text>&lt;/xsl:template></xsl:text>
                        <xsl:value-of select="$newline"/>
                        <xsl:value-of select="$newline"/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:for-each>
        <xsl:value-of select="$newline"/>
        <xsl:text>&lt;/xsl:stylesheet></xsl:text>
    </xsl:template>
</xsl:stylesheet>
----  

Back to content

Search my site

Sections

Current teaching

Recent changes to this site

Tags

anglo-saxon studies, caedmon, citation, citation practice, citations, composition, computers, digital humanities, digital pedagogy, exercises, grammar, history, moodle, old english, pedagogy, research, student employees, students, study tips, teaching, tips, tutorials, unessay, universities, university of lethbridge

See all...

Follow me on Twitter

At the dpod blog