PHPackages                             laraish/laraish - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. laraish/laraish

ActiveProject[Framework](/categories/framework)

laraish/laraish
===============

The WordPress theme powered by the Laravel Framework.

v12.0.0(8mo ago)2372.8k34[14 issues](https://github.com/laraish/laraish/issues)[2 PRs](https://github.com/laraish/laraish/pulls)MITPHPPHP ^8.2

Since Jan 12Pushed 7mo ago12 watchersCompare

[ Source](https://github.com/laraish/laraish)[ Packagist](https://packagist.org/packages/laraish/laraish)[ RSS](/packages/laraish-laraish/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (9)Versions (27)Used By (0)

Laravel in WordPress Theme
==========================

[](#laravel-in-wordpress-theme)

Laravel is a web application framework with expressive, elegant syntax. It's one of the most popular PHP frameworks today.

Laraish brings the Laravel Framework into WordPress, which allows us to have all the benefits of Laravel. So you can create themes with less effort and more enjoyment!

Table of contents
-----------------

[](#table-of-contents)

- [Requirement](#requirement)
- [What Laraish is and is not](#what-laraish-is-and-is-not)
- [What's the difference between the original Laravel?](#whats-the-difference-between-the-original-laravel)
- [Get Started](#get-started)
    - [Installation](#installation)
    - [Routing](#routing)
        - [Route order](#route-order)
        - [Auto-Discovery Routing](#auto-discovery-routing)
            - [Use Auto-Discovery Routing in the route file.](#use-auto-discovery-routing-in-the-route-file)
            - [Use Auto-Discovery Routing in the Controller.](#use-auto-discovery-routing-in-the-controller)
        - [Regular Route](#regular-route)
    - [Models](#models)
        - [Cast Model to JSON](#cast-model-to-json)
    - [The `@loop` blade directive](#the-loop-blade-directive)
    - [Theme Options](#theme-options)
    - [WordPress Hooks](#wordpress-hooks)
        - [WordPress Hook Auto-Discovery System](#wordpress-hook-auto-discovery-system)
    - [Pagination](#pagination)
    - [Work with ACF](#work-with-acf)
        - [Get the value of custom field from model](#get-the-value-of-custom-field-from-model)
        - [Data Type Casting](#data-type-casting)
    - [The `ShareViewData` Middleware](#the-shareviewdata-middleware)
    - [Options page](#options-page)
    - [View debugger](#view-debugger)
    - [Run artisan command](#run-artisan-command)
    - [Security Concerns](#security-concerns)
- [Known Issue](#known-issue)
    - [Composer race condition](#composer-race-condition)

Requirement
-----------

[](#requirement)

The 99% of Laraish is just the regular full stack PHP Framework [Laravel](https://laravel.com/). So if you have never heard of it, you're going to want to take a look at it before you can go any further.

For those who are already familiar with Laravel, it should be a piece of cake for you to get started with Laraish.

What Laraish is and is not
--------------------------

[](#what-laraish-is-and-is-not)

**Laraish is not a framework for general purpose WordPress theme development.**

Yes, it is a framework but not for general WordPress theme development. Laraish is aimed at helping create "homemade theme" rather than general purpose theme. So if you want to create themes with a bunch of theme options for sales or just for free distribution, you probably want to take a look at the following frameworks instead.

- [Piklist](https://piklist.com/product/piklist/)
- [Gantry](http://gantry.org/)
- [Unyson](http://unyson.io/)

What's the difference between the original Laravel?
---------------------------------------------------

[](#whats-the-difference-between-the-original-laravel)

I'd say almost no differences there, except some additional tweaking, which gets Laravel to work well inside a WordPress theme. So basically you could do anything that you could do with Laravel, it's just the regular Laravel inside a WordPress theme. If you are curious about what exactly have been modified, taking a diff to the original Laravel would make sense for you.

**Note**: The current version of Laraish is built on **Laravel 12**, providing you with all the latest features, security updates, and performance improvements from the Laravel framework.

Get Started
===========

[](#get-started)

Installation
------------

[](#installation)

You can install Laraish by issuing the following command via [Composer](https://getcomposer.org/).

```
composer create-project --prefer-dist laraish/laraish
```

Note that **the MySQL server and the web server must be running before you can issue the `composer create-project` command** to install Laraish. Because after Composer finishes the installation, it's going to run an artisan command, which requires MySQL server and the web server that host the WordPress be running at the time you issuing the command.

Also, notice that if you are on Mac and use MAMP or similar application to create your local server environment you may need to change your `$PATH` environment variable to make Composer use the PHP binary that MAMP provides rather than the OS's built-in PHP binary.

To ensure the `asset()` function operates correctly, open the `.env` file and insert the `ASSET_URL` key. Assign it the value of ``. For instance:

```
ASSET_URL=/wp-content/themes/Laraish/public
```

Routing
-------

[](#routing)

Laraish replaced the original `UriValidator`(`Illuminate\Routing\Matching\UriValidator`) with its own one to allow you to specify WordPress specific routes, like "archive" or "page" or "custom post type" ex.

You define your **WordPress-specific-routes** in the `routes/wp.php` file.

For example:

```
use App\Http\Controllers\Wp\Home;
use App\Http\Controllers\Wp\Page;
use App\Http\Controllers\Wp\Post;
use App\Http\Controllers\Wp\NotFound;
use Laraish\Support\Facades\WpRoute;

// Regular post pages
WpRoute::post('post', [Post::class, 'index']);

// Post pages where post-type is 'movie'
WpRoute::post('movie', [Post::class, 'index']);

// The archive page of "movie" post type.
WpRoute::postArchive('movie', [Home::class, 'index']);

// The child page "works" of the "about" page.
WpRoute::page('about.works', [Page::class, 'index']);

// Any child pages of the "about" page.
WpRoute::page('about.*', [Page::class, 'index']);

// Any descendant pages of the "about" page.
WpRoute::page('about.**', [Page::class, 'index']);

// The "about" page ("about" is the slug of the page)
WpRoute::page('about', [Page::class, 'index']);

// The archive page of "foobar" term of "category" taxonomy.
WpRoute::taxonomy('category.foobar', [Home::class, 'index']);

// The archive page of "category" taxonomy.
WpRoute::taxonomy('category', [Home::class, 'index']);

// The archive page of author "jack".
WpRoute::author('jack', [Home::class, 'index']);

// The archive page for all authors.
WpRoute::author([Home::class, 'index']);

// The search result page
WpRoute::search([Home::class, 'index']);

// All pages
WpRoute::page([Page::class, 'index']);

// The home/front page.
WpRoute::home([Home::class, 'index']);

// All archive pages.
WpRoute::archive([Home::class, 'index']);

// The 404 page.
WpRoute::notFound([NotFound::class, 'index']);
```

Here are some notes you should keep in mind.

- You can use a "dot notation" to specify the hierarchy for pages and taxonomies.
- You can use the wild card to specify any child/descendant page/term of a parent/ancestor page/term.
- You should care about the order of your routes. Routes that has a higher specificity should be placed more above than the routes that have a lower specificity.

### Route order

[](#route-order)

The position of the route is very **important**.

Here is a bad example:

```
use App\Http\Controllers\Wp\Page;
use Laraish\Support\Facades\WpRoute;

WpRoute::page([Page::class, 'index']);
WpRoute::page('works', [Page::class, 'works']);
```

The problem of this code is that the second route will never get matched. Because the first route matches to any pages, so all routes after the first one will be simply ignored. That is, routes that has a higher specificity should be placed above the routes that have a lower specificity.

### Auto-Discovery Routing

[](#auto-discovery-routing)

If you don't like to specify a route manually, you could always use the auto-discovery strategy instead. By turning on auto discovery routing, Laraish resolves the controller or view automatically the way similar to WordPress.

#### Use Auto-Discovery Routing in the route file.

[](#use-auto-discovery-routing-in-the-route-file)

```
use App\Http\Controllers\Wp\Home;
use App\Http\Controllers\Wp\Page;
use Laraish\Support\Facades\WpRoute;

WpRoute::home([Home::class, 'index']);
WpRoute::page([Page::class, 'index']);

// Fallback to auto discovery routing.
WpRoute::autoDiscovery();
```

Notice that you should always place auto discovery routing in the last line of your route file.

With this featured turned on, Laraish will try to find a controller or view that matches to the following naming convention.

in the `/wp` directory:

- home.blade.php
- search.blade.php
- archive.blade.php
- post.blade.php
- post
    - {$post\_type}.blade.php
- post-archive
    - {$post\_type}.blade.php
- page.blade.php
- page
    - {$page\_slug}.blade.php
    - {$page\_slug}
        - {$child\_page}.blade.php
        - …
- template
    - {$template\_slug}.blade.php
- taxonomy.blade.php
- taxonomy
    - {$taxonomy}.blade.php
    - {$taxonomy}
        - {$term}.blade.php
        - {$term}
            - {$child\_term}.blade.php
            - …
- author.blade.php
    - {$nicename}.blade.php

Same rule applied to the controllers under the namespace `App\Http\Controllers\Wp`.

For example, If the coming request is for a page called "foo", it'll try to :

1. Find a controller action in the following order.
    - `App\Http\Controllers\Wp\Page\Foo@index`.
    - `App\Http\Controllers\Wp\Page@index`.
2. If no controller action found, try to find a view file in the following order (if any, pass the `$post` object as the view data).
    - `/wp/page/foo.blade.php`.
    - `/wp/page.blade.php`.

As you can see, the searching paths will follow the hierarchy of the queried object. In the above example queried object is the page `foo`. Same rule will be applied to taxonomy or post archive Etc.

If Laraish could resolve the route, it'll passes some default view data according to the type of queried object :

- **page**
    - `$post`
- **post archive**
    - `$posts`
- **taxonomy archive**
    - `$term`
    - `$posts`
- **home**
    - `$post` if it's a "frontpage", otherwise `$posts`

Where `$post` is a Post [model](#models) object, and `$posts` is a `Laraish\Support\Wp\Query\QueryResults` object contains a collection of posts.

By default, the post model will be `Laraish\Support\Wp\Model\Post`, but it'll try to locate a custom model in `\App\Models\Wp\Post` first.

For example, if the queried object is a custom post type "movie", it will try to use `\App\Models\Wp\Post\Movie` if such a class found. Same rule applied to the taxonomy too, but the searching path will be `\App\Models\Wp\Taxonomy` instead.

Notice that if you want to use templates for pages or posts, you should register them in [theme.php](https://github.com/laraish/laraish/blob/master/config/theme.php#L167-L176).

#### Use Auto-Discovery Routing in the Controller.

[](#use-auto-discovery-routing-in-the-controller)

Not only in the route file, you could also use the `resolveView` method in the controller to let Laraish resolve the view file automatically.

Here is an example that shows how you can utilize the `resolveView` in a controller.

In the `routes/wp.php` file :

```
use App\Http\Controllers\Wp\Page;
use Laraish\Support\Facades\WpRoute;

WpRoute::page([Page::class, 'index']);
```

In the controller :

```
namespace App\Http\Controllers\Wp;

use App\Http\Controllers\Controller;

class Page extends Controller
{
    public function index()
    {
        $data = [ 'foo' => 'bar' ];

        // Let Laraish figure out the view file.
        // 'wp.page' is the default view if no matched view found.
        return $this->resolveView('wp.page', $data);
    }
}
```

In the above example, if the coming request is for a page called "foo", it'll try to find a view file from the following paths:

- `/wp/page/foo.blade.php`.
- `/wp/page.blade.php`.

### Regular Route

[](#regular-route)

Along with the WordPress routes, you can even write your own routes by URI, and it just works. Just be careful do not write regular routes to the `routes/wp.php` file ( technically you could, but I would not recommend ). For instance, write them to the `routes/web.php` file.

```
use Illuminate\Support\Facades\Route;

// This will use the original UriValidator of Laravel.
Route::get('/my/endpoint', function () {
    return 'Magic!';
});
```

Keep in mind that routes in `routes/wp.php` has the lowest priority of all the routes in the `routes` directory.

Models
------

[](#models)

Laraish comes with some general purpose models like `Post` or `Term` model. Note that they are not an implementation of ORM like the Laravel's Eloquent Model. They are just a simple wrapper for WordPress's APIs that encapsulate some common logic to help you simplify your business logic.

You can find those models in `Laraish\Support\Wp\Model`. Because the `Post` model is the most frequently used model, for convenience, a `Post` Class that extends the `Laraish\Support\Wp\Model\Post` has brought to your `app/Models` directory already.

Let's take a look at an example.

Say you have a route like this :

```
WpRoute::archive('\App\Http\Controllers\Wp\Archive@index');
```

In your controller `app\Http\Controllers\Wp\Archive` :

```

```

where `$post` should be a `Post` model object.

Usually you don't want to use the `@loop` directive because it'll introduce some unnecessary overhead. Keep in mind that you should always prefer `@foreach` to `@loop`. Unless you want to access some properties like `content` or `excerpt` which must be retrieved within "The Loop", otherwise never use the `@loop` actively.

Theme Options
-------------

[](#theme-options)

Set up the custom post type, register the navigation menus... There are always some common tasks you have to deal with when you start to build a WordPress theme. The `app/config/theme.php` is where you define all your common tasks.

Some basic options are predefined for you. Take a look at the [config/theme.php](https://github.com/laraish/laraish/blob/master/config/theme.php).

Also, you can create your own options by adding new static methods to the `App\Providers\ThemeOptionsProvider`. The name of the method will become an option.

WordPress Hooks
---------------

[](#wordpress-hooks)

### WordPress Hook Auto-Discovery System

[](#wordpress-hook-auto-discovery-system)

Laraish provides an Auto-Discovery System that automatically scans the `app/WpListeners` directory and registers WordPress hooks based on class properties. This approach is similar to Laravel's EventServiceProvider but requires no manual configuration.

#### Creating Hook Listeners

[](#creating-hook-listeners)

Create classes that extend `WpHookListener` in the `app/WpListeners` directory:

```
