photoblog
文件大小: unknow
源码售价: 5 个金币 积分规则     积分充值
资源说明:The Lithium + MongoDB photo blog tutorial demonstrates how to build a simple photo blog using MongoDB's GridFS to handle file storage.
## Building a Photo Blog with Lithium and MongoDB

This tutorial will demonstrate how to build a simple photo blog with the Lithium PHP framework, using [ MongoDB](http://mongodb.org/) and [ GridFS](http://www.mongodb.org/display/DOCS/GridFS) as a storage backend. GridFS is a protocol for storing filesystem objects in MongoDB collections. 

Additionally, this tutorial will explore Mongo's geospatial features, using [the `li3_geo` plugin](http://dev.lithify.me/li3_geo) to extract location data from photos and simplify the use of Mongo's geo-indexing and search.

This tutorial assumes you have Lithium and MongoDB installed (as well as the [Mongo PECL extension](http://pecl.php.net/package/mongo)), and that the `li3` command [is in your system path](http://lithify.me/docs/lithium/console).

### Setting up

To begin, open your system console and change to your web server's document root, then run the following:
{{{
li3 library extract photoblog
}}}

Then, by pointing your browser to `http://localhost/photoblog` (or wherever you extracted the new app), you should see something like the following:

![New application screen](http://img.skitch.com/20100617-byk75fr6h21pud3efhrxjqmwqb.jpg)

Next, we'll correct the errors noted in the startup screen. Run the following to set the correct permissions on the `resources/` directory:

{{{ chmod -R 777 resources/ }}}

Keep in mind, however, that this is just for local development. When deploying to production, you're going to want to tune your permissions to be more specific to what your application is doing. Follow the [principle of least privilege](http://en.wikipedia.org/wiki/Principle_of_least_privilege).

Finally, find the following in `config/bootstrap.php`:
{{{
/**
 * Include this file if your application uses a database connection.
 */
// require __DIR__ . '/bootstrap/connections.php';
}}}

Uncomment the `require` statement, and open `config/connections.php`. Delete any existing code, and add the following:
{{{ embed:config/bootstrap/connections.php::9-14 }}}

Note that as long as MongoDB is running on `localhost` on the default port, no other settings are required. Also note that the `photoblog` database need not be explicitly created, as Mongo will connect to it and create the database automatically.

When reloaded, our page should now look something like this:

![New application screen, updated](http://img.skitch.com/20100618-t1c9wn3aw3uebb65gmj9nf8gqk.jpg)

### Generating stub classes

Next, we'll create some application files in which to house our logic. In your console, change into the `photoblog` directory, and enter the following:
{{{
li3 create Photos
}}}

You should then see this output:

{{{
Photo created in app\models.
PhotosController created in app\controllers.
PhotoTest created in app\tests\cases\models.
PhotosControllerTest created in app\tests\cases\controllers.
}}}

You can then browse to `http://path/to/app/photos`, and assuming you have PHP configured to display errors, you should see an exception error message because Lithium was unable to find a template.

The URL requested is accessing the `index()` action of the `PhotosController` class, which looks like this:

{{{
$photos = Photo::all();
return compact('photos');
}}}

We're simply querying the `Photo` model for all photos, and sending that variable to the templating layer as the `$photos` variable.

### Building templates

To remove the error, go into the `views` directory, and create the file `views/photos/index.html.php`. Since there are no photos yet, add a simple check that displays a message, and a link to add a photo, as follows:

{{{ embed:views/photos/index.html.php::1-3 }}}

Refreshing the page shows our template with no photos. Clicking the link to add one will navigate us to `PhotosController::add()`, which will again render an error page, because we haven't created a template for it. Since we know our add and edit templates will be almost the same, we can save ourselves a bit of work and create one for both actions. First, create `views/photos/edit.html.php`
(leaving it empty for now is fine), then open `controllers/PhotosController.php` and look for the
`add()` method, which should look like
this:

{{{
public function add() {
	$photo = Photo::create();

	if (($this->request->data) && $photo->save($this->request->data)) {
		$this->redirect(array('Photos::view', 'args' => array($photo->id)));
	}
	return compact('photo');
}
}}}

Right before the `return` statement, add the following line:

{{{ embed:photoblog\controllers\PhotosController::add(6-6) }}}

This tells the templating layer to use the template for the `edit()` action, rather than looking for the default `add` template. Refreshing the page should show us a blank screen, with just the headers from the layout. Also, while we're in here, we can change the IDs to Mongo IDs in the calls to `redirect()`:

{{{ embed:photoblog\controllers\PhotosController::edit(7-7) }}}

Also, we can modify the matching patterns of the default routes in `config/routes.php` to accept MongoDB IDs instead of standard integers. At the bottom of the file are a series of catch-all routes that look like this:

{{{
Router::connect('/{:controller}/{:action}/{:id:[0-9]+}.{:type}', array('id' => null));
Router::connect('/{:controller}/{:action}/{:id:[0-9]+}');
Router::connect('/{:controller}/{:action}/{:args}');
}}}

Since route expressions are just regular expressions with a macro syntax for capture groups, we can just change the matching pattern for the `{:id}` group:

{{{ embed:config/routes.php::44-46 }}}

Getting back to our edit template, we start by creating a form, using the `$photo` object to bind to it. Binding `$photo` to the `Form` helper allows the `Form` helper to use `$photo` to automatically display certain things like error messages, and to make decisions about rendering certain input elements. Also, because we'll be using this form to upload photos, set the `'type'` to `'file'` in the `$options` parameter:

{{{
form->create($photo, array('type' => 'file')); ?>

form->end(); ?>
}}}

Next, we'll include some fields on the form: a title, and a lengthier description. Also, we'll include a photo upload field, but only when we're creating a new photo:

{{{
form->create($photo, array('type' => 'file')); ?>
	form->field('title'); ?>
	form->field('description'); ?>
	exists()) { ?>
		form->field('file', array('type' => 'file')); ?>
	
	form->submit('Save'); ?>
form->end(); ?>
}}}

The `field()` method will render a form input, a corresponding `

本源码包内暂不包含可直接显示的源代码文件,请下载源码包。